diff options
Diffstat (limited to 'src/solve.c')
| -rw-r--r-- | src/solve.c | 193 |
1 files changed, 170 insertions, 23 deletions
diff --git a/src/solve.c b/src/solve.c index 29f614b..a35a837 100644 --- a/src/solve.c +++ b/src/solve.c | |||
| @@ -8,6 +8,8 @@ static void dfs_branch(Cube c, Step *s, SolveOptions *os, DfsData *dd); | |||
| 8 | static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); | 8 | static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); |
| 9 | static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | 9 | static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); |
| 10 | static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); | 10 | static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); |
| 11 | static void * instance_thread(void *arg); | ||
| 12 | static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d); | ||
| 11 | 13 | ||
| 12 | /* Local functions ***********************************************************/ | 14 | /* Local functions ***********************************************************/ |
| 13 | 15 | ||
| @@ -41,12 +43,24 @@ dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | |||
| 41 | static void | 43 | static void |
| 42 | dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | 44 | dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) |
| 43 | { | 45 | { |
| 44 | Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves; | 46 | bool b = false; |
| 47 | int i; | ||
| 48 | Move m, l1, l2; | ||
| 45 | 49 | ||
| 46 | int i, maxnsol = opts->max_solutions; | 50 | l1 = dd->last1; |
| 51 | l2 = dd->last2; | ||
| 47 | 52 | ||
| 48 | for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) { | 53 | for (i = 0; dd->sorted_moves[i] != NULLMOVE; i++) { |
| 49 | m = moves[i]; | 54 | /* |
| 55 | pthread_mutex_lock(dd->sols_mutex); | ||
| 56 | b = dd->sols->len >= opts->max_solutions; | ||
| 57 | pthread_mutex_unlock(dd->sols_mutex); | ||
| 58 | */ | ||
| 59 | |||
| 60 | if (b) | ||
| 61 | break; | ||
| 62 | |||
| 63 | m = dd->sorted_moves[i]; | ||
| 50 | if (allowed_next(m, dd)) { | 64 | if (allowed_next(m, dd)) { |
| 51 | dd->last2 = dd->last1; | 65 | dd->last2 = dd->last1; |
| 52 | dd->last1 = m; | 66 | dd->last1 = m; |
| @@ -68,8 +82,12 @@ dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd) | |||
| 68 | return false; | 82 | return false; |
| 69 | 83 | ||
| 70 | if (dd->current_alg->len == dd->d) { | 84 | if (dd->current_alg->len == dd->d) { |
| 71 | if (s->is_valid(dd->current_alg) || opts->all) | 85 | if (s->is_valid(dd->current_alg) || opts->all) { |
| 72 | append_alg(dd->sols, dd->current_alg); | 86 | pthread_mutex_lock(dd->sols_mutex); |
| 87 | if (dd->sols->len < opts->max_solutions) | ||
| 88 | append_alg(dd->sols, dd->current_alg); | ||
| 89 | pthread_mutex_unlock(dd->sols_mutex); | ||
| 90 | } | ||
| 73 | 91 | ||
| 74 | if (opts->verbose) | 92 | if (opts->verbose) |
| 75 | print_alg(dd->current_alg, false); | 93 | print_alg(dd->current_alg, false); |
| @@ -103,14 +121,13 @@ dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | |||
| 103 | static bool | 121 | static bool |
| 104 | dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | 122 | dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) |
| 105 | { | 123 | { |
| 124 | bool b = false; | ||
| 125 | |||
| 106 | CubeTarget ct = { | 126 | CubeTarget ct = { |
| 107 | .cube = c, | 127 | .cube = c, |
| 108 | .target = dd->d - dd->current_alg->len | 128 | .target = dd->d - dd->current_alg->len |
| 109 | }; | 129 | }; |
| 110 | 130 | ||
| 111 | if (dd->sols->len >= opts->max_solutions) | ||
| 112 | return true; | ||
| 113 | |||
| 114 | dd->lb = s->estimate(ct); | 131 | dd->lb = s->estimate(ct); |
| 115 | if (opts->can_niss && !dd->niss) | 132 | if (opts->can_niss && !dd->niss) |
| 116 | dd->lb = MIN(1, dd->lb); | 133 | dd->lb = MIN(1, dd->lb); |
| @@ -118,7 +135,131 @@ dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | |||
| 118 | if (dd->current_alg->len + dd->lb > dd->d) | 135 | if (dd->current_alg->len + dd->lb > dd->d) |
| 119 | return true; | 136 | return true; |
| 120 | 137 | ||
| 121 | return false; | 138 | pthread_mutex_lock(dd->sols_mutex); |
| 139 | b = dd->sols->len >= opts->max_solutions; | ||
| 140 | pthread_mutex_unlock(dd->sols_mutex); | ||
| 141 | |||
| 142 | return b; | ||
| 143 | } | ||
| 144 | |||
| 145 | static void * | ||
| 146 | instance_thread(void *arg) | ||
| 147 | { | ||
| 148 | bool b; | ||
| 149 | Cube c; | ||
| 150 | ThreadData *td; | ||
| 151 | AlgListNode *node; | ||
| 152 | DfsData dd; | ||
| 153 | |||
| 154 | td = (ThreadData *)arg; | ||
| 155 | |||
| 156 | while (1) { | ||
| 157 | b = false; | ||
| 158 | |||
| 159 | pthread_mutex_lock(td->start_mutex); | ||
| 160 | if ((node = *(td->node)) == NULL) | ||
| 161 | b = true; | ||
| 162 | else | ||
| 163 | *(td->node) = (*(td->node))->next; | ||
| 164 | pthread_mutex_unlock(td->start_mutex); | ||
| 165 | |||
| 166 | if (b) | ||
| 167 | break; | ||
| 168 | |||
| 169 | c = node->alg->inv[0] ? | ||
| 170 | apply_move(node->alg->move[0], inverse_cube(td->cube)) : | ||
| 171 | apply_move(node->alg->move[0], td->cube); | ||
| 172 | |||
| 173 | dd.d = td->depth; | ||
| 174 | dd.m = 1; | ||
| 175 | dd.niss = node->alg->inv[0]; | ||
| 176 | dd.lb = -1; | ||
| 177 | dd.last1 = node->alg->move[0]; | ||
| 178 | dd.last2 = NULLMOVE; | ||
| 179 | dd.sols = td->sols; | ||
| 180 | dd.sols_mutex = td->sols_mutex; | ||
| 181 | dd.current_alg = new_alg(""); | ||
| 182 | append_move(dd.current_alg, node->alg->move[0], | ||
| 183 | node->alg->inv[0]); | ||
| 184 | dd.sorted_moves = td->sorted_moves; | ||
| 185 | dd.move_position = td->move_position; | ||
| 186 | |||
| 187 | /* | ||
| 188 | pthread_mutex_lock(td->sols_mutex); | ||
| 189 | printf("Starting thread %d with move: ", td->thid); | ||
| 190 | print_alg(dd.current_alg, false); | ||
| 191 | pthread_mutex_unlock(td->sols_mutex); | ||
| 192 | */ | ||
| 193 | |||
| 194 | dfs(c, td->step, td->opts, &dd); | ||
| 195 | |||
| 196 | free_alg(dd.current_alg); | ||
| 197 | } | ||
| 198 | |||
| 199 | return NULL; | ||
| 200 | } | ||
| 201 | |||
| 202 | static void | ||
| 203 | multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) | ||
| 204 | { | ||
| 205 | int i, *move_position; | ||
| 206 | Move *sorted_moves; | ||
| 207 | Alg *alg; | ||
| 208 | AlgList *start; | ||
| 209 | AlgListNode **node; | ||
| 210 | pthread_t t[opts->nthreads]; | ||
| 211 | ThreadData td[opts->nthreads]; | ||
| 212 | pthread_mutex_t *start_mutex, *sols_mutex; | ||
| 213 | |||
| 214 | move_position = malloc(NMOVES * sizeof(int)); | ||
| 215 | sorted_moves = malloc(NMOVES * sizeof(Move)); | ||
| 216 | node = malloc(sizeof(AlgListNode *)); | ||
| 217 | start_mutex = malloc(sizeof(pthread_mutex_t)); | ||
| 218 | sols_mutex = malloc(sizeof(pthread_mutex_t)); | ||
| 219 | |||
| 220 | start = new_alglist(); | ||
| 221 | pthread_mutex_init(start_mutex, NULL); | ||
| 222 | pthread_mutex_init(sols_mutex, NULL); | ||
| 223 | |||
| 224 | moveset_to_list(s->moveset, sorted_moves); | ||
| 225 | movelist_to_position(sorted_moves, move_position); | ||
| 226 | for (i = 0; sorted_moves[i] != NULLMOVE; i++) { | ||
| 227 | alg = new_alg(""); | ||
| 228 | append_move(alg, sorted_moves[i], false); | ||
| 229 | append_alg(start, alg); | ||
| 230 | if (opts->can_niss) { | ||
| 231 | alg->inv[0] = true; | ||
| 232 | append_alg(start, alg); | ||
| 233 | } | ||
| 234 | free_alg(alg); | ||
| 235 | } | ||
| 236 | *node = start->first; | ||
| 237 | |||
| 238 | for (i = 0; i < opts->nthreads; i++) { | ||
| 239 | td[i].thid = i; | ||
| 240 | td[i].cube = c; | ||
| 241 | td[i].step = s; | ||
| 242 | td[i].depth = d; | ||
| 243 | td[i].sorted_moves = sorted_moves; | ||
| 244 | td[i].move_position = move_position; | ||
| 245 | td[i].opts = opts; | ||
| 246 | td[i].start = start; | ||
| 247 | td[i].node = node; | ||
| 248 | td[i].sols = sols; | ||
| 249 | td[i].start_mutex = start_mutex; | ||
| 250 | td[i].sols_mutex = sols_mutex; | ||
| 251 | pthread_create(&t[i], NULL, instance_thread, &td[i]); | ||
| 252 | } | ||
| 253 | |||
| 254 | for (i = 0; i < opts->nthreads; i++) | ||
| 255 | pthread_join(t[i], NULL); | ||
| 256 | |||
| 257 | free_alglist(start); | ||
| 258 | free(node); | ||
| 259 | free(start_mutex); | ||
| 260 | free(sols_mutex); | ||
| 261 | free(move_position); | ||
| 262 | free(sorted_moves); | ||
| 122 | } | 263 | } |
| 123 | 264 | ||
| 124 | /* Public functions **********************************************************/ | 265 | /* Public functions **********************************************************/ |
| @@ -126,11 +267,12 @@ dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) | |||
| 126 | AlgList * | 267 | AlgList * |
| 127 | solve(Cube cube, Step *step, SolveOptions *opts) | 268 | solve(Cube cube, Step *step, SolveOptions *opts) |
| 128 | { | 269 | { |
| 270 | int d; | ||
| 271 | AlgList *sols = new_alglist(); | ||
| 129 | AlgListNode *node; | 272 | AlgListNode *node; |
| 130 | DfsData dd; | ||
| 131 | Cube c; | 273 | Cube c; |
| 132 | 274 | ||
| 133 | prepare_step(step, &dd); | 275 | prepare_step(step); |
| 134 | 276 | ||
| 135 | if (step->detect != NULL) | 277 | if (step->detect != NULL) |
| 136 | step->pre_trans = step->detect(cube); | 278 | step->pre_trans = step->detect(cube); |
| @@ -139,24 +281,29 @@ solve(Cube cube, Step *step, SolveOptions *opts) | |||
| 139 | if (step->ready != NULL && !step->ready(c)) { | 281 | if (step->ready != NULL && !step->ready(c)) { |
| 140 | fprintf(stderr, "Cube not ready for solving step: "); | 282 | fprintf(stderr, "Cube not ready for solving step: "); |
| 141 | fprintf(stderr, "%s\n", step->ready_msg); | 283 | fprintf(stderr, "%s\n", step->ready_msg); |
| 142 | return dd.sols; | 284 | return sols; |
| 285 | } | ||
| 286 | |||
| 287 | if (step->estimate((CubeTarget){.cube = c, .target = 0}) == 0 && | ||
| 288 | opts->min_moves == 0) { | ||
| 289 | append_alg(sols, new_alg("")); | ||
| 290 | return sols; | ||
| 143 | } | 291 | } |
| 144 | 292 | ||
| 145 | for (dd.d = opts->min_moves; | 293 | for (d = MAX(1, opts->min_moves); |
| 146 | dd.d <= opts->max_moves && | 294 | d <= opts->max_moves && |
| 147 | !(dd.sols->len && opts->optimal_only) && | 295 | !(sols->len && opts->optimal_only) && |
| 148 | dd.sols->len < opts->max_solutions; | 296 | sols->len < opts->max_solutions; |
| 149 | dd.d++) { | 297 | d++) { |
| 150 | if (opts->verbose) | 298 | if (opts->verbose) |
| 151 | fprintf(stderr, | 299 | fprintf(stderr, |
| 152 | "Found %d solutions, searching depth %d...\n", | 300 | "Found %d solutions, searching depth %d...\n", |
| 153 | dd.sols->len, dd.d); | 301 | sols->len, d); |
| 154 | dfs(c, step, opts, &dd); | 302 | multidfs(c, step, opts, sols, d); |
| 155 | } | 303 | } |
| 156 | 304 | ||
| 157 | for (node = dd.sols->first; node != NULL; node = node->next) | 305 | for (node = sols->first; node != NULL; node = node->next) |
| 158 | transform_alg(inverse_trans(step->pre_trans), node->alg); | 306 | transform_alg(inverse_trans(step->pre_trans), node->alg); |
| 159 | 307 | ||
| 160 | free_alg(dd.current_alg); | 308 | return sols; |
| 161 | return dd.sols; | ||
| 162 | } | 309 | } |
