aboutsummaryrefslogtreecommitdiff
path: root/src/solve.c
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano.tronto@gmail.com>2021-11-20 16:08:43 +0100
committerSebastiano Tronto <sebastiano.tronto@gmail.com>2021-11-20 16:08:43 +0100
commita8c4da5b955eab2eed9ebb03ee4b1212ec6fe042 (patch)
tree3fe233ce2883545ec42d2c3cf5661fba3818fb9d /src/solve.c
parent0df4f6f98101bb3be192ce892aa1452f2c6de1a4 (diff)
downloadnissy-a8c4da5b955eab2eed9ebb03ee4b1212ec6fe042.tar.gz
nissy-a8c4da5b955eab2eed9ebb03ee4b1212ec6fe042.zip
Multithreading seems to be working now, it was easier than expected!
Diffstat (limited to 'src/solve.c')
-rw-r--r--src/solve.c193
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);
8static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd); 8static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd);
9static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd); 9static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd);
10static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd); 10static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd);
11static void * instance_thread(void *arg);
12static 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)
41static void 43static void
42dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd) 44dfs_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)
103static bool 121static bool
104dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd) 122dfs_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
145static void *
146instance_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
202static void
203multidfs(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)
126AlgList * 267AlgList *
127solve(Cube cube, Step *step, SolveOptions *opts) 268solve(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}

Generated with cgit - Back to sebastiano.tronto.net