diff options
Diffstat (limited to 'src/solve.c')
| -rw-r--r-- | src/solve.c | 133 |
1 files changed, 76 insertions, 57 deletions
diff --git a/src/solve.c b/src/solve.c index 911d208..df15cca 100644 --- a/src/solve.c +++ b/src/solve.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | /* Local functions ***********************************************************/ | 5 | /* Local functions ***********************************************************/ |
| 6 | 6 | ||
| 7 | static bool allowed_next(Move move, StepAlt *sa, Move l0, Move l1); | 7 | static bool allowed_next(Move move, Step *s, Move l0, Move l1); |
| 8 | static bool cancel_niss(DfsArg *arg); | 8 | static bool cancel_niss(DfsArg *arg); |
| 9 | static void copy_dfsarg(DfsArg *src, DfsArg *dst); | 9 | static void copy_dfsarg(DfsArg *src, DfsArg *dst); |
| 10 | static void dfs(DfsArg *arg); | 10 | static void dfs(DfsArg *arg); |
| @@ -19,13 +19,13 @@ static bool solvestop(int d, int op, SolveOptions *opts, AlgList *sols); | |||
| 19 | /* Local functions ***********************************************************/ | 19 | /* Local functions ***********************************************************/ |
| 20 | 20 | ||
| 21 | static bool | 21 | static bool |
| 22 | allowed_next(Move m, StepAlt *sa, Move l0, Move l1) | 22 | allowed_next(Move m, Step *s, Move l0, Move l1) |
| 23 | { | 23 | { |
| 24 | bool allowed, order; | 24 | bool allowed, order; |
| 25 | uint64_t mbit; | 25 | uint64_t mbit; |
| 26 | 26 | ||
| 27 | mbit = ((uint64_t)1) << m; | 27 | mbit = ((uint64_t)1) << m; |
| 28 | allowed = mbit & sa->moveset->mask[l1][l0]; | 28 | allowed = mbit & s->moveset->mask[l1][l0]; |
| 29 | order = !commute(l0, m) || l0 < m; | 29 | order = !commute(l0, m) || l0 < m; |
| 30 | 30 | ||
| 31 | return allowed && order; | 31 | return allowed && order; |
| @@ -41,7 +41,7 @@ cancel_niss(DfsArg *arg) | |||
| 41 | if (arg->lastinv[0] == NULLMOVE) | 41 | if (arg->lastinv[0] == NULLMOVE) |
| 42 | return false; | 42 | return false; |
| 43 | 43 | ||
| 44 | ms = arg->sa->moveset; | 44 | ms = arg->s->moveset; |
| 45 | i1 = inverse_move(arg->lastinv[0]); | 45 | i1 = inverse_move(arg->lastinv[0]); |
| 46 | i2 = inverse_move(arg->lastinv[1]); | 46 | i2 = inverse_move(arg->lastinv[1]); |
| 47 | 47 | ||
| @@ -63,7 +63,7 @@ copy_dfsarg(DfsArg *src, DfsArg *dst) | |||
| 63 | 63 | ||
| 64 | dst->cube = src->cube; | 64 | dst->cube = src->cube; |
| 65 | dst->t = src->t; | 65 | dst->t = src->t; |
| 66 | dst->sa = src->sa; | 66 | dst->s = src->s; |
| 67 | dst->opts = src->opts; | 67 | dst->opts = src->opts; |
| 68 | dst->d = src->d; | 68 | dst->d = src->d; |
| 69 | dst->bound = src->bound; /* In theory not needed */ | 69 | dst->bound = src->bound; /* In theory not needed */ |
| @@ -77,10 +77,14 @@ copy_dfsarg(DfsArg *src, DfsArg *dst) | |||
| 77 | dst->lastinv[i] = src->lastinv[i]; | 77 | dst->lastinv[i] = src->lastinv[i]; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | for (i = 0; i < src->sa->n_coord; i++) { | 80 | for (i = 0; i < src->s->n_coord; i++) { |
| 81 | dst->ind[i].val = src->ind[i].val; | 81 | dst->ind[i].val = src->ind[i].val; |
| 82 | dst->ind[i].t = src->ind[i].t; | 82 | dst->ind[i].t = src->ind[i].t; |
| 83 | } | 83 | } |
| 84 | |||
| 85 | /* | ||
| 86 | src->s->copy_extra(src, dst); | ||
| 87 | */ | ||
| 84 | } | 88 | } |
| 85 | 89 | ||
| 86 | static void | 90 | static void |
| @@ -99,9 +103,9 @@ dfs(DfsArg *arg) | |||
| 99 | return; | 103 | return; |
| 100 | } | 104 | } |
| 101 | 105 | ||
| 102 | for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) { | 106 | for (i = 0; arg->s->moveset->sorted_moves[i] != NULLMOVE; i++) { |
| 103 | m = arg->sa->moveset->sorted_moves[i]; | 107 | m = arg->s->moveset->sorted_moves[i]; |
| 104 | if (allowed_next(m, arg->sa, arg->last[0], arg->last[1])) { | 108 | if (allowed_next(m, arg->s, arg->last[0], arg->last[1])) { |
| 105 | copy_dfsarg(arg, &newarg); | 109 | copy_dfsarg(arg, &newarg); |
| 106 | newarg.last[1] = arg->last[0]; | 110 | newarg.last[1] = arg->last[0]; |
| 107 | newarg.last[0] = m; | 111 | newarg.last[0] = m; |
| @@ -120,9 +124,9 @@ dfs_add_sol(DfsArg *arg) | |||
| 120 | { | 124 | { |
| 121 | bool valid, accepted, nisscanc; | 125 | bool valid, accepted, nisscanc; |
| 122 | 126 | ||
| 123 | valid = arg->sa->is_valid==NULL || arg->sa->is_valid(arg->current_alg); | 127 | valid = arg->s->is_valid==NULL || arg->s->is_valid(arg->current_alg); |
| 124 | accepted = valid || arg->opts->all; | 128 | accepted = valid || arg->opts->all; |
| 125 | nisscanc = arg->sa->final && cancel_niss(arg); | 129 | nisscanc = arg->s->final && cancel_niss(arg); |
| 126 | 130 | ||
| 127 | if (accepted && !nisscanc) { | 131 | if (accepted && !nisscanc) { |
| 128 | pthread_mutex_lock(arg->sols_mutex); | 132 | pthread_mutex_lock(arg->sols_mutex); |
| @@ -159,7 +163,7 @@ dfs_niss(DfsArg *arg) | |||
| 159 | compose(c, newarg.cube); | 163 | compose(c, newarg.cube); |
| 160 | 164 | ||
| 161 | /* New indexes */ | 165 | /* New indexes */ |
| 162 | compute_ind(newarg.sa, newarg.cube, newarg.ind); | 166 | compute_ind(newarg.s, newarg.cube, newarg.ind); |
| 163 | 167 | ||
| 164 | swapmove(&(newarg.last[0]), &(newarg.lastinv[0])); | 168 | swapmove(&(newarg.last[0]), &(newarg.lastinv[0])); |
| 165 | swapmove(&(newarg.last[1]), &(newarg.lastinv[1])); | 169 | swapmove(&(newarg.last[1]), &(newarg.lastinv[1])); |
| @@ -175,36 +179,35 @@ dfs_niss(DfsArg *arg) | |||
| 175 | static bool | 179 | static bool |
| 176 | dfs_move_checkstop(DfsArg *arg) | 180 | dfs_move_checkstop(DfsArg *arg) |
| 177 | { | 181 | { |
| 178 | bool b; | 182 | int i, goal, nsols; |
| 179 | int i, goal; | ||
| 180 | Move mm; | 183 | Move mm; |
| 181 | Trans tt = uf; /* Avoid uninitialized warning */ | 184 | Trans tt = uf; /* Avoid uninitialized warning */ |
| 182 | 185 | ||
| 183 | /* Moving */ | 186 | /* Moving and computing bound */ |
| 184 | if (arg->last[0] != NULLMOVE) { | 187 | arg->bound = 0; |
| 185 | for (i = 0; i < arg->sa->n_coord; i++) { | 188 | goal = arg->d - arg->current_alg->len; |
| 189 | for (i = 0; i < arg->s->n_coord; i++) { | ||
| 190 | if (arg->last[0] != NULLMOVE) { | ||
| 186 | mm = transform_move(arg->ind[i].t, arg->last[0]); | 191 | mm = transform_move(arg->ind[i].t, arg->last[0]); |
| 187 | arg->ind[i].val = move_coord(arg->sa->coord[i], | 192 | arg->ind[i].val = move_coord(arg->s->coord[i], |
| 188 | mm, arg->ind[i].val, &tt); | 193 | mm, arg->ind[i].val, &tt); |
| 189 | arg->ind[i].t = transform_trans(tt, arg->ind[i].t); | 194 | arg->ind[i].t = transform_trans(tt, arg->ind[i].t); |
| 190 | } | 195 | } |
| 191 | } | ||
| 192 | 196 | ||
| 193 | /* Computing bound for coordinates */ | 197 | arg->bound = |
| 194 | goal = arg->d - arg->current_alg->len; | 198 | MAX(arg->bound, ptableval(arg->s->pd[i], arg->ind[i].val)); |
| 195 | arg->bound = estimate_stepalt(arg->sa, arg->ind, goal); | 199 | if (arg->opts->can_niss && !arg->niss) |
| 196 | if (arg->opts->can_niss && !arg->niss) | 200 | arg->bound = MIN(1, arg->bound); |
| 197 | arg->bound = MIN(1, arg->bound); | ||
| 198 | 201 | ||
| 199 | if (arg->bound > goal) { | 202 | if (arg->bound > goal) |
| 200 | b = true; | 203 | return true; |
| 201 | } else { | ||
| 202 | pthread_mutex_lock(arg->sols_mutex); | ||
| 203 | b = arg->sols->len >= arg->opts->max_solutions; | ||
| 204 | pthread_mutex_unlock(arg->sols_mutex); | ||
| 205 | } | 204 | } |
| 206 | 205 | ||
| 207 | return b; | 206 | pthread_mutex_lock(arg->sols_mutex); |
| 207 | nsols = arg->sols->len; | ||
| 208 | pthread_mutex_unlock(arg->sols_mutex); | ||
| 209 | |||
| 210 | return nsols >= arg->opts->max_solutions; | ||
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | static void * | 213 | static void * |
| @@ -240,7 +243,7 @@ instance_thread(void *arg) | |||
| 240 | invert_cube(&c); | 243 | invert_cube(&c); |
| 241 | 244 | ||
| 242 | copy_dfsarg(&td->arg, &darg); | 245 | copy_dfsarg(&td->arg, &darg); |
| 243 | compute_ind(td->arg.sa, &c, darg.ind); | 246 | compute_ind(td->arg.s, &c, darg.ind); |
| 244 | darg.cube = &c; | 247 | darg.cube = &c; |
| 245 | 248 | ||
| 246 | darg.niss = inv; | 249 | darg.niss = inv; |
| @@ -279,11 +282,11 @@ multidfs(DfsArg *arg) | |||
| 279 | pthread_mutex_init(start_mutex, NULL); | 282 | pthread_mutex_init(start_mutex, NULL); |
| 280 | pthread_mutex_init(sols_mutex, NULL); | 283 | pthread_mutex_init(sols_mutex, NULL); |
| 281 | 284 | ||
| 282 | for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) { | 285 | for (i = 0; arg->s->moveset->sorted_moves[i] != NULLMOVE; i++) { |
| 283 | alg = new_alg(""); | 286 | alg = new_alg(""); |
| 284 | append_move(alg, arg->sa->moveset->sorted_moves[i], false); | 287 | append_move(alg, arg->s->moveset->sorted_moves[i], false); |
| 285 | append_alg(start, alg); | 288 | append_alg(start, alg); |
| 286 | if (arg->opts->can_niss && !arg->sa->final) { | 289 | if (arg->opts->can_niss && !arg->s->final) { |
| 287 | alg->inv[0] = true; | 290 | alg->inv[0] = true; |
| 288 | append_alg(start, alg); | 291 | append_alg(start, alg); |
| 289 | } | 292 | } |
| @@ -318,15 +321,25 @@ multidfs(DfsArg *arg) | |||
| 318 | static bool | 321 | static bool |
| 319 | niss_makes_sense(DfsArg *arg) | 322 | niss_makes_sense(DfsArg *arg) |
| 320 | { | 323 | { |
| 321 | Cube testcube; | 324 | Move m, mm; |
| 325 | uint64_t u; | ||
| 326 | int i; | ||
| 322 | 327 | ||
| 323 | if (arg->sa->final || arg->niss || !arg->opts->can_niss) | 328 | if (arg->s->final || arg->niss || !arg->opts->can_niss) |
| 324 | return false; | 329 | return false; |
| 325 | 330 | ||
| 326 | make_solved(&testcube); | 331 | if (arg->last[0] == NULLMOVE) |
| 327 | apply_move(inverse_move(arg->last[0]), &testcube); | 332 | return true; |
| 328 | return arg->current_alg->len == 0 || | 333 | |
| 329 | estimate_stepalt(arg->sa, arg->ind, 0) > 0; | 334 | m = inverse_move(arg->last[0]); |
| 335 | for (i = 0; i < arg->s->n_coord; i++) { | ||
| 336 | mm = transform_move(arg->ind[i].t, m); | ||
| 337 | u = move_coord(arg->s->coord[i], mm, 0, NULL); | ||
| 338 | if (ptableval(arg->s->pd[i], u) > 0) | ||
| 339 | return true; | ||
| 340 | } | ||
| 341 | |||
| 342 | return false; | ||
| 330 | } | 343 | } |
| 331 | 344 | ||
| 332 | static bool | 345 | static bool |
| @@ -344,38 +357,38 @@ solvestop(int d, int op, SolveOptions *opts, AlgList *sols) | |||
| 344 | /* Public functions **********************************************************/ | 357 | /* Public functions **********************************************************/ |
| 345 | 358 | ||
| 346 | AlgList * | 359 | AlgList * |
| 347 | solve(Cube *cube, Step *step, SolveOptions *opts) | 360 | solve(Cube *cube, ChoiceStep *cs, SolveOptions *opts) |
| 348 | { | 361 | { |
| 349 | int i, d, op; | 362 | int i, j, d, op, est; |
| 350 | bool ready[99], one_ready, zerosol; | 363 | bool ready[99], one_ready, zerosol; |
| 351 | Movable ind[99][10]; | 364 | Movable ind[99][10]; |
| 352 | AlgList *s; | 365 | AlgList *s; |
| 353 | Cube *c[99]; | 366 | Cube *c[99]; |
| 354 | DfsArg arg[99]; | 367 | DfsArg arg[99]; |
| 355 | 368 | ||
| 356 | prepare_step(step, opts); | 369 | prepare_cs(cs, opts); |
| 357 | s = new_alglist(); | 370 | s = new_alglist(); |
| 358 | 371 | ||
| 359 | for (i = 0, one_ready = false; step->alt[i] != NULL; i++) { | 372 | for (i = 0, one_ready = false; cs->step[i] != NULL; i++) { |
| 360 | c[i] = malloc(sizeof(Cube)); | 373 | c[i] = malloc(sizeof(Cube)); |
| 361 | copy_cube(cube, c[i]); | 374 | copy_cube(cube, c[i]); |
| 362 | apply_trans(step->t[i], c[i]); | 375 | apply_trans(cs->t[i], c[i]); |
| 363 | 376 | ||
| 364 | arg[i].cube = c[i]; | 377 | arg[i].cube = c[i]; |
| 365 | arg[i].t = step->t[i]; | 378 | arg[i].t = cs->t[i]; |
| 366 | arg[i].sa = step->alt[i]; | 379 | arg[i].s = cs->step[i]; |
| 367 | arg[i].opts = opts; | 380 | arg[i].opts = opts; |
| 368 | arg[i].sols = s; | 381 | arg[i].sols = s; |
| 369 | 382 | ||
| 370 | if ((ready[i] = step->alt[i]->ready(c[i]))) { | 383 | if ((ready[i] = cs->step[i]->ready(c[i]))) { |
| 371 | one_ready = true; | 384 | one_ready = true; |
| 372 | /* Only for local use for 0 moves solutions */ | 385 | /* Only for local use for 0 moves solutions */ |
| 373 | compute_ind(step->alt[i], c[i], ind[i]); | 386 | compute_ind(cs->step[i], c[i], ind[i]); |
| 374 | } | 387 | } |
| 375 | } | 388 | } |
| 376 | if (!one_ready) { | 389 | if (!one_ready) { |
| 377 | fprintf(stderr, "Cube not ready for solving step: "); | 390 | fprintf(stderr, "Cube not ready for solving step: "); |
| 378 | fprintf(stderr, "%s\n", step->ready_msg); | 391 | fprintf(stderr, "%s\n", cs->ready_msg); |
| 379 | return s; | 392 | return s; |
| 380 | } | 393 | } |
| 381 | 394 | ||
| @@ -383,10 +396,16 @@ solve(Cube *cube, Step *step, SolveOptions *opts) | |||
| 383 | * alternatives, all longer solutions will be discarded, so we may | 396 | * alternatives, all longer solutions will be discarded, so we may |
| 384 | * just set its ready[] value to false. If the solution is accepted | 397 | * just set its ready[] value to false. If the solution is accepted |
| 385 | * we append it and start searching from d = 1. */ | 398 | * we append it and start searching from d = 1. */ |
| 386 | for (i = 0, zerosol = false; step->alt[i] != NULL; i++) { | 399 | for (i = 0, zerosol = false; cs->step[i] != NULL; i++) { |
| 387 | if (ready[i] && estimate_stepalt(step->alt[i],ind[i],0) == 0) { | 400 | if (ready[i]) { |
| 388 | ready[i] = false; | 401 | est = 0; |
| 389 | zerosol = true; | 402 | for (j = 0; j < cs->step[i]->n_coord; j++) |
| 403 | est = MAX(est, ptableval(cs->step[i]->pd[j], | ||
| 404 | ind[i][j].val)); | ||
| 405 | if (est == 0) { | ||
| 406 | ready[i] = false; | ||
| 407 | zerosol = true; | ||
| 408 | } | ||
| 390 | } | 409 | } |
| 391 | } | 410 | } |
| 392 | if (zerosol && opts->min_moves == 0) { | 411 | if (zerosol && opts->min_moves == 0) { |
| @@ -401,7 +420,7 @@ solve(Cube *cube, Step *step, SolveOptions *opts) | |||
| 401 | if (opts->verbose) | 420 | if (opts->verbose) |
| 402 | fprintf(stderr, "Searching depth %d\n", d); | 421 | fprintf(stderr, "Searching depth %d\n", d); |
| 403 | 422 | ||
| 404 | for (i=0; step->alt[i]!=NULL && !solvestop(d,op,opts,s); i++) { | 423 | for (i=0; cs->step[i]!=NULL && !solvestop(d,op,opts,s); i++) { |
| 405 | if (!ready[i]) | 424 | if (!ready[i]) |
| 406 | continue; | 425 | continue; |
| 407 | 426 | ||
| @@ -413,7 +432,7 @@ solve(Cube *cube, Step *step, SolveOptions *opts) | |||
| 413 | } | 432 | } |
| 414 | } | 433 | } |
| 415 | 434 | ||
| 416 | for (i = 0; step->alt[i] != NULL; i++) | 435 | for (i = 0; cs->step[i] != NULL; i++) |
| 417 | free(c[i]); | 436 | free(c[i]); |
| 418 | 437 | ||
| 419 | return s; | 438 | return s; |
