diff options
| author | Sebastiano Tronto <sebastiano@tronto.net> | 2023-05-01 12:48:55 +0200 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano@tronto.net> | 2023-05-01 12:48:55 +0200 |
| commit | 6f4313bc1ed5be794146e6ca2fd73f48c7906061 (patch) | |
| tree | a79c8be8613e8b4256d609477f98f440bfd7168c /src/solve.c | |
| parent | 1a5bfe9b08707b0aef748d7921a419ba4a046fba (diff) | |
| download | nissy-classic-6f4313bc1ed5be794146e6ca2fd73f48c7906061.tar.gz nissy-classic-6f4313bc1ed5be794146e6ca2fd73f48c7906061.zip | |
Reverted to 2.0.3
Diffstat (limited to '')
| -rw-r--r-- | src/solve.c | 538 |
1 files changed, 458 insertions, 80 deletions
diff --git a/src/solve.c b/src/solve.c index 2d0c94d..d4c0f18 100644 --- a/src/solve.c +++ b/src/solve.c | |||
| @@ -1,122 +1,500 @@ | |||
| 1 | #define SOLVE_C | ||
| 2 | |||
| 3 | #include "solve.h" | 1 | #include "solve.h" |
| 4 | 2 | ||
| 5 | void | 3 | /* Local functions ***********************************************************/ |
| 6 | dfs(DfsArg *arg, Solver *solver, Threader *threader) | 4 | |
| 5 | static bool allowed_next(Move move, DfsArg *arg); | ||
| 6 | static bool cancel_niss(DfsArg *arg); | ||
| 7 | static void copy_dfsarg(DfsArg *src, DfsArg *dst); | ||
| 8 | static void dfs(DfsArg *arg); | ||
| 9 | static void dfs_branch(DfsArg *arg); | ||
| 10 | static bool dfs_check_solved(DfsArg *arg); | ||
| 11 | static bool dfs_switch(DfsArg *arg); | ||
| 12 | static void dfs_niss(DfsArg *arg); | ||
| 13 | static bool dfs_stop(DfsArg *arg); | ||
| 14 | static void * instance_thread(void *arg); | ||
| 15 | static void invert_branch(DfsArg *arg); | ||
| 16 | static void multidfs(Cube c, Trans t, Step *s, SolveOptions *opts, | ||
| 17 | AlgList *sols, int d); | ||
| 18 | static bool niss_makes_sense(DfsArg *arg); | ||
| 19 | static bool solvestop(int d, int op, SolveOptions *opts, AlgList *sols); | ||
| 20 | |||
| 21 | /* Local functions ***********************************************************/ | ||
| 22 | |||
| 23 | static bool | ||
| 24 | allowed_next(Move m, DfsArg *arg) | ||
| 25 | { | ||
| 26 | bool bad, allowed, order; | ||
| 27 | uint64_t mbit; | ||
| 28 | |||
| 29 | mbit = ((uint64_t)1) << m; | ||
| 30 | bad = mbit & arg->badmoves; | ||
| 31 | allowed = mbit & arg->step->moveset->mask[arg->last2][arg->last1]; | ||
| 32 | order = !commute(arg->last1, m) || arg->last1 < m; | ||
| 33 | |||
| 34 | return allowed && !bad && order; | ||
| 35 | } | ||
| 36 | |||
| 37 | static bool | ||
| 38 | cancel_niss(DfsArg *arg) | ||
| 39 | { | ||
| 40 | Moveset *ms; | ||
| 41 | Move i1, i2; | ||
| 42 | bool p, p1, p2, q, q1, q2; | ||
| 43 | |||
| 44 | if (arg->last1inv == NULLMOVE) | ||
| 45 | return false; | ||
| 46 | |||
| 47 | ms = arg->step->moveset; | ||
| 48 | i1 = inverse_move(arg->last1inv); | ||
| 49 | i2 = inverse_move(arg->last2inv); | ||
| 50 | |||
| 51 | p1 = !ms->allowed_next(arg->last2, arg->last1, i1); | ||
| 52 | p2 = !ms->allowed_next(arg->last2, i1, arg->last1); | ||
| 53 | p = p1 || (commute(i1, arg->last1) && p2); | ||
| 54 | |||
| 55 | q1 = !ms->allowed_next(arg->last2, arg->last1, i2); | ||
| 56 | q2 = !ms->allowed_next(arg->last2, i2, arg->last1); | ||
| 57 | q = q1 || (commute(i2, arg->last1) && q2); | ||
| 58 | |||
| 59 | return p || (commute(i1, i2) && q); | ||
| 60 | } | ||
| 61 | |||
| 62 | static void | ||
| 63 | copy_dfsarg(DfsArg *src, DfsArg *dst) | ||
| 64 | { | ||
| 65 | dst->step = src->step; | ||
| 66 | dst->opts = src->opts; | ||
| 67 | dst->t = src->t; | ||
| 68 | dst->cube = src->cube; | ||
| 69 | dst->inverse = src->inverse; | ||
| 70 | dst->d = src->d; | ||
| 71 | dst->badmoves = src->badmoves; | ||
| 72 | dst->badmovesinv = src->badmovesinv; | ||
| 73 | dst->niss = src->niss; | ||
| 74 | dst->last1 = src->last1; | ||
| 75 | dst->last2 = src->last2; | ||
| 76 | dst->last1inv = src->last1inv; | ||
| 77 | dst->last2inv = src->last2inv; | ||
| 78 | dst->sols = src->sols; | ||
| 79 | dst->sols_mutex = src->sols_mutex; | ||
| 80 | dst->current_alg = src->current_alg; | ||
| 81 | |||
| 82 | copy_estimatedata(src->ed, dst->ed); | ||
| 83 | } | ||
| 84 | |||
| 85 | static void | ||
| 86 | dfs(DfsArg *arg) | ||
| 87 | { | ||
| 88 | bool sw = false; | ||
| 89 | |||
| 90 | if (dfs_stop(arg)) | ||
| 91 | return; | ||
| 92 | |||
| 93 | if (dfs_check_solved(arg)) | ||
| 94 | return; | ||
| 95 | |||
| 96 | if (arg->step->final && (sw = dfs_switch(arg))) | ||
| 97 | invert_branch(arg); | ||
| 98 | dfs_branch(arg); | ||
| 99 | |||
| 100 | if (arg->opts->can_niss && !arg->niss && niss_makes_sense(arg)) | ||
| 101 | dfs_niss(arg); | ||
| 102 | |||
| 103 | if (sw) | ||
| 104 | invert_branch(arg); | ||
| 105 | } | ||
| 106 | |||
| 107 | static void | ||
| 108 | dfs_branch(DfsArg *arg) | ||
| 7 | { | 109 | { |
| 8 | int i; | 110 | int i; |
| 9 | DfsArg newarg; | ||
| 10 | Alg *sol; | ||
| 11 | Move m; | 111 | Move m; |
| 112 | DfsArg *newarg; | ||
| 12 | 113 | ||
| 13 | if (arg->current_alg->len > arg->d) | 114 | newarg = malloc(sizeof(DfsArg)); |
| 14 | return; | 115 | newarg->ed = malloc(sizeof(EstimateData)); |
| 15 | 116 | ||
| 16 | if (solver->is_solved(solver->param, arg->cubedata)) { | 117 | for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) { |
| 17 | /* TODO: the "all" option should be re-implemented as setting | 118 | m = arg->step->moveset->sorted_moves[i]; |
| 18 | validate to null */ | 119 | if (allowed_next(m, arg)) { |
| 120 | copy_dfsarg(arg, newarg); | ||
| 121 | newarg->last2 = arg->last1; | ||
| 122 | newarg->last1 = m; | ||
| 123 | newarg->cube = apply_move(m, arg->cube); | ||
| 124 | append_move(arg->current_alg, m, newarg->niss); | ||
| 19 | 125 | ||
| 20 | /* TODO: we also have to check if cancel with NISS; | 126 | dfs(newarg); |
| 21 | we can't because we have no access to the s->final field | ||
| 22 | this should be done by the step's validator? */ | ||
| 23 | sol = solver->validate_solution(solver->param,arg->current_alg); | ||
| 24 | bool accepted = sol != NULL; | ||
| 25 | bool too_short = arg->current_alg->len != arg->d; | ||
| 26 | 127 | ||
| 27 | if (accepted && !too_short) { | 128 | arg->current_alg->len--; |
| 28 | /* TODO: arg->t got lost in refactoring */ | ||
| 29 | /* transform_alg(inverse_trans(arg->t), sol);*/ | ||
| 30 | if (arg->opts->verbose) | ||
| 31 | print_alg(sol, false); | ||
| 32 | threader->append_sol(sol, arg->threaddata); | ||
| 33 | } | 129 | } |
| 34 | return; | ||
| 35 | } | 130 | } |
| 36 | 131 | ||
| 37 | if (arg->current_alg->len == arg->d) | 132 | free(newarg->ed); |
| 38 | return; | 133 | free(newarg); |
| 134 | } | ||
| 135 | |||
| 136 | static bool | ||
| 137 | dfs_check_solved(DfsArg *arg) | ||
| 138 | { | ||
| 139 | if (!arg->step->is_done(arg->cube)) | ||
| 140 | return false; | ||
| 141 | |||
| 142 | if (arg->current_alg->len == arg->d) { | ||
| 143 | if ((arg->step->is_valid(arg->current_alg) || arg->opts->all) | ||
| 144 | && (!arg->step->final || !cancel_niss(arg))) { | ||
| 145 | |||
| 146 | pthread_mutex_lock(arg->sols_mutex); | ||
| 147 | |||
| 148 | if (arg->sols->len < arg->opts->max_solutions) { | ||
| 149 | append_alg(arg->sols, arg->current_alg); | ||
| 150 | |||
| 151 | transform_alg( | ||
| 152 | inverse_trans(arg->t), | ||
| 153 | arg->sols->last->alg | ||
| 154 | ); | ||
| 155 | if (arg->step->final) | ||
| 156 | inplace(unniss, arg->sols->last->alg); | ||
| 157 | |||
| 158 | if (arg->opts->verbose) | ||
| 159 | print_alg(arg->sols->last->alg, false); | ||
| 160 | } | ||
| 161 | |||
| 162 | pthread_mutex_unlock(arg->sols_mutex); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | return true; | ||
| 167 | } | ||
| 168 | |||
| 169 | static void | ||
| 170 | dfs_niss(DfsArg *arg) | ||
| 171 | { | ||
| 172 | DfsArg *newarg; | ||
| 173 | |||
| 174 | newarg = malloc(sizeof(DfsArg)); | ||
| 175 | newarg->ed = malloc(sizeof(EstimateData)); | ||
| 176 | |||
| 177 | copy_dfsarg(arg, newarg); | ||
| 178 | swapmove(&(newarg->last1), &(newarg->last1inv)); | ||
| 179 | swapmove(&(newarg->last2), &(newarg->last2inv)); | ||
| 180 | newarg->niss = !(arg->niss); | ||
| 181 | newarg->cube = inverse_cube(arg->cube); | ||
| 182 | |||
| 183 | dfs(newarg); | ||
| 184 | |||
| 185 | free(newarg->ed); | ||
| 186 | free(newarg); | ||
| 187 | } | ||
| 188 | |||
| 189 | static bool | ||
| 190 | dfs_stop(DfsArg *arg) | ||
| 191 | { | ||
| 192 | int lowerbound; | ||
| 193 | bool b; | ||
| 194 | |||
| 195 | lowerbound = arg->step->estimate(arg); | ||
| 196 | if (arg->opts->can_niss && !arg->niss) | ||
| 197 | lowerbound = MIN(1, lowerbound); | ||
| 198 | |||
| 199 | if (arg->current_alg->len + lowerbound > arg->d) { | ||
| 200 | b = 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 | } | ||
| 206 | |||
| 207 | return b; | ||
| 208 | } | ||
| 209 | |||
| 210 | static bool | ||
| 211 | dfs_switch(DfsArg *arg) | ||
| 212 | { | ||
| 213 | int i, bn, bi; | ||
| 214 | |||
| 215 | bn = 0; | ||
| 216 | for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) | ||
| 217 | if (allowed_next(arg->step->moveset->sorted_moves[i], arg)) | ||
| 218 | bn++; | ||
| 219 | |||
| 220 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 221 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 222 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 223 | |||
| 224 | bi = 0; | ||
| 225 | for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) | ||
| 226 | if (allowed_next(arg->step->moveset->sorted_moves[i], arg)) | ||
| 227 | bi++; | ||
| 228 | |||
| 229 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 230 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 231 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 232 | |||
| 233 | return bi < bn; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void * | ||
| 237 | instance_thread(void *arg) | ||
| 238 | { | ||
| 239 | bool b; | ||
| 240 | Cube c; | ||
| 241 | ThreadDataSolve *td; | ||
| 242 | AlgListNode *node; | ||
| 243 | DfsArg darg; | ||
| 244 | |||
| 245 | td = (ThreadDataSolve *)arg; | ||
| 246 | |||
| 247 | while (1) { | ||
| 248 | b = false; | ||
| 249 | |||
| 250 | pthread_mutex_lock(td->start_mutex); | ||
| 251 | if ((node = *(td->node)) == NULL) | ||
| 252 | b = true; | ||
| 253 | else | ||
| 254 | *(td->node) = (*(td->node))->next; | ||
| 255 | pthread_mutex_unlock(td->start_mutex); | ||
| 256 | |||
| 257 | if (b) | ||
| 258 | break; | ||
| 259 | |||
| 260 | c = node->alg->inv[0] ? | ||
| 261 | apply_move(node->alg->move[0], inverse_cube(td->cube)) : | ||
| 262 | apply_move(node->alg->move[0], td->cube); | ||
| 263 | |||
| 264 | darg.step = td->step; | ||
| 265 | darg.opts = td->opts; | ||
| 266 | darg.t = td->t; | ||
| 267 | darg.cube = c; | ||
| 268 | darg.d = td->depth; | ||
| 269 | darg.niss = node->alg->inv[0]; | ||
| 270 | darg.last1 = node->alg->move[0]; | ||
| 271 | darg.last2 = NULLMOVE; | ||
| 272 | darg.last1inv = NULLMOVE; | ||
| 273 | darg.last2inv = NULLMOVE; | ||
| 274 | darg.sols = td->sols; | ||
| 275 | darg.sols_mutex = td->sols_mutex; | ||
| 276 | darg.current_alg = new_alg(""); | ||
| 277 | append_move(darg.current_alg, node->alg->move[0], | ||
| 278 | node->alg->inv[0]); | ||
| 279 | darg.ed = malloc(sizeof(EstimateData)); | ||
| 280 | reset_estimatedata(darg.ed); | ||
| 281 | darg.badmoves = 0; | ||
| 282 | darg.badmovesinv = 0; | ||
| 283 | |||
| 284 | dfs(&darg); | ||
| 285 | |||
| 286 | free_alg(darg.current_alg); | ||
| 287 | free(darg.ed); | ||
| 288 | } | ||
| 289 | |||
| 290 | return NULL; | ||
| 291 | } | ||
| 292 | |||
| 293 | static void | ||
| 294 | invert_branch(DfsArg *arg) | ||
| 295 | { | ||
| 296 | Cube aux; | ||
| 297 | |||
| 298 | aux = arg->cube; | ||
| 299 | arg->cube = is_solved(arg->inverse) ? | ||
| 300 | inverse_cube(arg->cube) : arg->inverse; | ||
| 301 | arg->inverse = aux; | ||
| 302 | |||
| 303 | swapu64(&(arg->badmoves), &(arg->badmovesinv)); | ||
| 304 | arg->niss = !(arg->niss); | ||
| 305 | swapmove(&(arg->last1), &(arg->last1inv)); | ||
| 306 | swapmove(&(arg->last2), &(arg->last2inv)); | ||
| 307 | invert_estimatedata(arg->ed); | ||
| 308 | } | ||
| 309 | |||
| 310 | static void | ||
| 311 | multidfs(Cube c, Trans tr, Step *s, SolveOptions *opts, AlgList *sols, int d) | ||
| 312 | { | ||
| 313 | int i; | ||
| 314 | Alg *alg; | ||
| 315 | AlgList *start; | ||
| 316 | AlgListNode **node; | ||
| 317 | pthread_t t[opts->nthreads]; | ||
| 318 | ThreadDataSolve td[opts->nthreads]; | ||
| 319 | pthread_mutex_t *start_mutex, *sols_mutex; | ||
| 39 | 320 | ||
| 40 | /* TODO: do not alloc */ | 321 | node = malloc(sizeof(AlgListNode *)); |
| 41 | newarg.cubedata = solver->alloc_cubedata(solver->param); | 322 | start_mutex = malloc(sizeof(pthread_mutex_t)); |
| 42 | for (i = 0; solver->moveset->sorted_moves[i] != NULLMOVE; i++) { | 323 | sols_mutex = malloc(sizeof(pthread_mutex_t)); |
| 43 | m = solver->moveset->sorted_moves[i]; | ||
| 44 | if (solver->moveset->can_append(arg->current_alg, m, arg->niss) | ||
| 45 | && compare_last(arg->current_alg, m, arg->niss) >= 0) { | ||
| 46 | append_move(arg->current_alg, m, arg->niss); | ||
| 47 | 324 | ||
| 48 | solver->copy_cubedata( | 325 | start = new_alglist(); |
| 49 | solver->param, arg->cubedata, newarg.cubedata); | 326 | pthread_mutex_init(start_mutex, NULL); |
| 50 | newarg.threaddata = arg->threaddata; | 327 | pthread_mutex_init(sols_mutex, NULL); |
| 51 | newarg.opts = arg->opts; | ||
| 52 | newarg.d = arg->d; | ||
| 53 | newarg.niss = arg->niss; | ||
| 54 | newarg.current_alg = arg->current_alg; | ||
| 55 | if (!solver->move_check_stop( | ||
| 56 | solver->param, &newarg, threader)) | ||
| 57 | dfs(&newarg, solver, threader); | ||
| 58 | 328 | ||
| 59 | remove_last_move(arg->current_alg); | 329 | for (i = 0; s->moveset->sorted_moves[i] != NULLMOVE; i++) { |
| 330 | alg = new_alg(""); | ||
| 331 | append_move(alg, s->moveset->sorted_moves[i], false); | ||
| 332 | append_alg(start, alg); | ||
| 333 | if (opts->can_niss) { | ||
| 334 | alg->inv[0] = true; | ||
| 335 | append_alg(start, alg); | ||
| 60 | } | 336 | } |
| 337 | free_alg(alg); | ||
| 61 | } | 338 | } |
| 62 | solver->free_cubedata(solver->param, newarg.cubedata); | 339 | *node = start->first; |
| 63 | 340 | ||
| 64 | if (arg->opts->can_niss && !arg->niss && | 341 | for (i = 0; i < opts->nthreads; i++) { |
| 65 | solver->niss_makes_sense( | 342 | td[i].thid = i; |
| 66 | solver->param, arg->cubedata, arg->current_alg)) { | 343 | td[i].t = tr; |
| 67 | solver->invert_cube(solver->param, arg->cubedata); | 344 | td[i].cube = c; |
| 68 | arg->niss = true; | 345 | td[i].step = s; |
| 69 | dfs(arg, solver, threader); | 346 | td[i].depth = d; |
| 347 | td[i].opts = opts; | ||
| 348 | td[i].start = start; | ||
| 349 | td[i].node = node; | ||
| 350 | td[i].sols = sols; | ||
| 351 | td[i].start_mutex = start_mutex; | ||
| 352 | td[i].sols_mutex = sols_mutex; | ||
| 353 | pthread_create(&t[i], NULL, instance_thread, &td[i]); | ||
| 70 | } | 354 | } |
| 355 | |||
| 356 | for (i = 0; i < opts->nthreads; i++) | ||
| 357 | pthread_join(t[i], NULL); | ||
| 358 | |||
| 359 | free_alglist(start); | ||
| 360 | free(node); | ||
| 361 | free(start_mutex); | ||
| 362 | free(sols_mutex); | ||
| 363 | } | ||
| 364 | |||
| 365 | static bool | ||
| 366 | niss_makes_sense(DfsArg *arg) | ||
| 367 | { | ||
| 368 | Cube testcube; | ||
| 369 | |||
| 370 | testcube = apply_move(inverse_move(arg->last1), (Cube){0}); | ||
| 371 | return arg->current_alg->len == 0 || !arg->step->is_done(testcube); | ||
| 71 | } | 372 | } |
| 72 | 373 | ||
| 374 | static bool | ||
| 375 | solvestop(int d, int op, SolveOptions *opts, AlgList *sols) | ||
| 376 | { | ||
| 377 | bool opt_done, max_moves_exceeded, max_sols_exceeded; | ||
| 378 | |||
| 379 | opt_done = opts->optimal != -1 && op != -1 && d > opts->optimal + op; | ||
| 380 | max_moves_exceeded = d > opts->max_moves; | ||
| 381 | max_sols_exceeded = sols->len >= opts->max_solutions; | ||
| 382 | |||
| 383 | return opt_done || max_moves_exceeded || max_sols_exceeded; | ||
| 384 | } | ||
| 385 | |||
| 386 | /* Public functions **********************************************************/ | ||
| 387 | |||
| 73 | AlgList * | 388 | AlgList * |
| 74 | solve(Cube *cube, SolveOptions *opts, Solver **solver, Threader *threader) | 389 | solve(Cube cube, Step *step, SolveOptions *opts) |
| 75 | { | 390 | { |
| 76 | int i, d, optimal; | 391 | bool ready; |
| 77 | bool ready[MAX_SOLVERS], stop, one_ready; | 392 | int i, d, op, nt; |
| 78 | DfsArg arg[MAX_SOLVERS]; | ||
| 79 | AlgList *sols; | 393 | AlgList *sols; |
| 394 | Cube c; | ||
| 395 | Trans tt[NTRANS]; | ||
| 396 | |||
| 397 | prepare_step(step, opts); | ||
| 80 | 398 | ||
| 81 | one_ready = false; | 399 | if (step->detect != NULL) { |
| 82 | for (i = 0; solver[i] != NULL; i++) { | 400 | nt = step->detect(cube, tt); |
| 83 | arg[i].cubedata = | 401 | } else { |
| 84 | solver[i]->prepare_cube(solver[i]->param, cube); | 402 | tt[0] = step->pre_trans; |
| 85 | arg[i].opts = opts; | 403 | ready = step->ready == NULL || |
| 86 | ready[i] = arg[i].cubedata != NULL; | 404 | step->ready(apply_trans(tt[0], cube)); |
| 87 | one_ready = one_ready || ready[i]; | 405 | nt = ready ? 1 : 0; |
| 88 | } | 406 | } |
| 89 | 407 | ||
| 90 | sols = new_alglist(); | 408 | sols = new_alglist(); |
| 91 | if (!one_ready) { | 409 | |
| 92 | fprintf(stderr, "Cube not ready for solving\n"); | 410 | if (nt == 0) { |
| 411 | fprintf(stderr, "Cube not ready for solving step: "); | ||
| 412 | fprintf(stderr, "%s\n", step->ready_msg); | ||
| 93 | return sols; | 413 | return sols; |
| 94 | } | 414 | } |
| 95 | 415 | ||
| 96 | optimal = opts->max_moves; | 416 | if (opts->min_moves == 0) { |
| 97 | stop = false; | 417 | for (i = 0; i < nt; i++) { |
| 98 | for (d = opts->min_moves; d <= opts->max_moves && !stop; d++) { | 418 | c = apply_trans(tt[i], cube); |
| 419 | if (step->is_done(c)) { | ||
| 420 | append_alg(sols, new_alg("")); | ||
| 421 | return sols; | ||
| 422 | } | ||
| 423 | } | ||
| 424 | } | ||
| 425 | |||
| 426 | op = -1; | ||
| 427 | for (d = opts->min_moves; !solvestop(d, op, opts, sols); d++) { | ||
| 99 | if (opts->verbose) | 428 | if (opts->verbose) |
| 100 | fprintf(stderr, "Searching depth %d\n", d); | 429 | fprintf(stderr, "Searching depth %d\n", d); |
| 101 | 430 | ||
| 102 | for (i = 0; solver[i] != NULL && !stop; i++) { | 431 | for (i = 0; i < nt && !solvestop(d, op, opts, sols); i++) { |
| 103 | if (!ready[i]) | 432 | c = apply_trans(tt[i], cube); |
| 104 | continue; | 433 | multidfs(c, tt[i], step, opts, sols, d); |
| 434 | if (sols->len > 0 && op == -1) | ||
| 435 | op = d; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | return sols; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* TODO: make more general! */ | ||
| 443 | Alg * | ||
| 444 | solve_2phase(Cube cube, int nthreads) | ||
| 445 | { | ||
| 446 | int bestlen, newb; | ||
| 447 | Alg *bestalg, *ret; | ||
| 448 | AlgList *sols1, *sols2; | ||
| 449 | AlgListNode *i; | ||
| 450 | Cube c; | ||
| 451 | SolveOptions opts1, opts2; | ||
| 105 | 452 | ||
| 106 | arg[i].d = d; | 453 | opts1.min_moves = 0; |
| 107 | threader->dispatch(&arg[i], sols, solver[i], threader); | 454 | opts1.max_moves = 13; |
| 455 | opts1.max_solutions = 20; | ||
| 456 | opts1.nthreads = nthreads; | ||
| 457 | opts1.optimal = 3; | ||
| 458 | opts1.can_niss = false; | ||
| 459 | opts1.verbose = false; | ||
| 460 | opts1.all = true; | ||
| 108 | 461 | ||
| 109 | if (sols->len > 0) | 462 | opts2.min_moves = 0; |
| 110 | optimal = MIN(optimal, d); | 463 | opts2.max_moves = 19; |
| 464 | opts2.max_solutions = 1; | ||
| 465 | opts2.nthreads = nthreads; | ||
| 466 | opts2.can_niss = false; | ||
| 467 | opts2.verbose = false; | ||
| 111 | 468 | ||
| 112 | stop = sols->len >= opts->max_solutions; | 469 | /* We skip step1 if it is solved on any axis */ |
| 470 | if (drany_HTM.is_done(cube)) { | ||
| 471 | sols1 = new_alglist(); | ||
| 472 | append_alg(sols1, new_alg("")); | ||
| 473 | } else { | ||
| 474 | sols1 = solve(cube, &drany_HTM, &opts1); | ||
| 475 | } | ||
| 476 | bestalg = new_alg(""); | ||
| 477 | bestlen = 999; | ||
| 478 | for (i = sols1->first; i != NULL; i = i->next) { | ||
| 479 | c = apply_alg(i->alg, cube); | ||
| 480 | sols2 = solve(c, &dranyfin_DR, &opts2); | ||
| 481 | |||
| 482 | if (sols2->len > 0) { | ||
| 483 | newb = i->alg->len + sols2->first->alg->len; | ||
| 484 | if (newb < bestlen) { | ||
| 485 | bestlen = newb; | ||
| 486 | copy_alg(i->alg, bestalg); | ||
| 487 | compose_alg(bestalg, sols2->first->alg); | ||
| 488 | } | ||
| 113 | } | 489 | } |
| 114 | stop = stop || | 490 | |
| 115 | (opts->optimal != -1 && d >= opts->optimal + optimal); | 491 | free_alglist(sols2); |
| 116 | } | 492 | } |
| 117 | 493 | ||
| 118 | /* TODO: some cleanup (free cubedata) */ | 494 | free_alglist(sols1); |
| 119 | /* TODO: actually, preparation should be done somewhere else */ | ||
| 120 | 495 | ||
| 121 | return sols; | 496 | ret = cleanup(bestalg); |
| 497 | free_alg(bestalg); | ||
| 498 | |||
| 499 | return ret; | ||
| 122 | } | 500 | } |
