aboutsummaryrefslogtreecommitdiff
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
parent0df4f6f98101bb3be192ce892aa1452f2c6de1a4 (diff)
downloadnissy-a8c4da5b955eab2eed9ebb03ee4b1212ec6fe042.tar.gz
nissy-a8c4da5b955eab2eed9ebb03ee4b1212ec6fe042.zip
Multithreading seems to be working now, it was easier than expected!
Diffstat (limited to '')
-rw-r--r--Makefile6
-rw-r--r--TODO.md11
-rw-r--r--doc/nissy.18
-rw-r--r--nissy-2.0beta3.tar.gzbin0 -> 53146 bytes
-rw-r--r--src/commands.c34
-rw-r--r--src/cubetypes.h231
-rw-r--r--src/pruning.c10
-rw-r--r--src/solve.c193
-rw-r--r--src/steps.c13
-rw-r--r--src/steps.h2
10 files changed, 347 insertions, 161 deletions
diff --git a/Makefile b/Makefile
index cb7b898..4ffef70 100644
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,13 @@
1# See LICENSE file for copyright and license details. 1# See LICENSE file for copyright and license details.
2 2
3VERSION = 2.0beta2 3VERSION = 2.0beta3
4 4
5PREFIX = /usr/local 5PREFIX = /usr/local
6MANPREFIX = ${PREFIX}/share/man 6MANPREFIX = ${PREFIX}/share/man
7 7
8CPPFLAGS = -DVERSION=\"${VERSION}\" 8CPPFLAGS = -DVERSION=\"${VERSION}\"
9CFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -O3 ${CPPFLAGS} 9CFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -O3 ${CPPFLAGS}
10DBGFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -g ${CPPFLAGS} 10DBGFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -g ${CPPFLAGS}
11 11
12CC = cc 12CC = cc
13 13
diff --git a/TODO.md b/TODO.md
index 0172dd8..0ed9c21 100644
--- a/TODO.md
+++ b/TODO.md
@@ -3,6 +3,9 @@
3This is a list of things that I would like to add or change at some point. 3This is a list of things that I would like to add or change at some point.
4It's more of a personal reminder than anything else. 4It's more of a personal reminder than anything else.
5 5
6## Bugs
7* Segfault on "nissy solve -s 10U" (no space between 10 and U)
8
6## Commands 9## Commands
7 10
8### Commands that are available in nissy 1.0, but not in this version (yet): 11### Commands that are available in nissy 1.0, but not in this version (yet):
@@ -37,22 +40,14 @@ It's more of a personal reminder than anything else.
37* default to current directory for tables; this will work on any OS, up to 40* default to current directory for tables; this will work on any OS, up to
38 using the correct #ifdef guards to avoid checking for posix directories 41 using the correct #ifdef guards to avoid checking for posix directories
39 in non-posix systems 42 in non-posix systems
40* better internal help page for each command (take it from man page)
41* better man page 43* better man page
42* find a better way to distribute the large tables, especially khuge 44* find a better way to distribute the large tables, especially khuge
43 45
44## Technical stuff 46## Technical stuff
45 47
46### Small fixes
47* printf with stdint.h: use proper macros instead of %llu
48
49### Better pruning tables 48### Better pruning tables
50* Use pruning values mod 4 instead of mod 16 49* Use pruning values mod 4 instead of mod 16
51 50
52### Code simplification
53* Remove anti-indeces. I think I can do this by using an iterative deepening
54 dfs method for generating pruning tables, like I do in solve()
55
56### Memory management 51### Memory management
57* fail gracefully when there is not enough memory to load a large table 52* fail gracefully when there is not enough memory to load a large table
58* free tables from memory when not used 53* free tables from memory when not used
diff --git a/doc/nissy.1 b/doc/nissy.1
index ebabb0e..5bfa930 100644
--- a/doc/nissy.1
+++ b/doc/nissy.1
@@ -93,6 +93,14 @@ Only find solutions that require the minimum number of moves.
93.It Fl p 93.It Fl p
94Plain style: do not print the number of moves. 94Plain style: do not print the number of moves.
95. 95.
96.It Fl t Ar n
97Use
98.Ar n
99CPU threads. By default nissy uses only 1 thread. Using more than one
100thread will improve performance, but the optimal number depends on your
101machine and operating system. Generally, using one less than the number
102of threads of your CPU works quite well.
103.
96.It Fl v 104.It Fl v
97Verbose mode: print some information during the search and print each solution 105Verbose mode: print some information during the search and print each solution
98as it is found instead of only printing them all together at the end. 106as it is found instead of only printing them all together at the end.
diff --git a/nissy-2.0beta3.tar.gz b/nissy-2.0beta3.tar.gz
new file mode 100644
index 0000000..e35868f
--- /dev/null
+++ b/nissy-2.0beta3.tar.gz
Binary files differ
diff --git a/src/commands.c b/src/commands.c
index 10e4eb8..b089a1c 100644
--- a/src/commands.c
+++ b/src/commands.c
@@ -28,7 +28,7 @@ Command
28solve_cmd = { 28solve_cmd = {
29 .name = "solve", 29 .name = "solve",
30 .usage = "solve STEP [OPTIONS] SCRAMBLE", 30 .usage = "solve STEP [OPTIONS] SCRAMBLE",
31 .description = "Solve a step", 31 .description = "Solve a step; see command steps for a list of steps",
32 .parse_args = solve_parse_args, 32 .parse_args = solve_parse_args,
33 .exec = solve_exec 33 .exec = solve_exec
34}; 34};
@@ -116,6 +116,7 @@ solve_parse_args(int c, char **v)
116 a->opts->min_moves = 0; 116 a->opts->min_moves = 0;
117 a->opts->max_moves = 20; 117 a->opts->max_moves = 20;
118 a->opts->max_solutions = 1; 118 a->opts->max_solutions = 1;
119 a->opts->nthreads = 1;
119 a->opts->optimal_only = false; 120 a->opts->optimal_only = false;
120 a->opts->can_niss = false; 121 a->opts->can_niss = false;
121 a->opts->verbose = false; 122 a->opts->verbose = false;
@@ -127,7 +128,8 @@ solve_parse_args(int c, char **v)
127 val = strtol(v[++i], NULL, 10); 128 val = strtol(v[++i], NULL, 10);
128 if (val < 0 || val > 100) { 129 if (val < 0 || val > 100) {
129 fprintf(stderr, 130 fprintf(stderr,
130 "Invalid min number of moves.\n"); 131 "Invalid min number of moves"
132 "(0 <= m <= 100).\n");
131 return a; 133 return a;
132 } 134 }
133 a->opts->min_moves = val; 135 a->opts->min_moves = val;
@@ -135,10 +137,20 @@ solve_parse_args(int c, char **v)
135 val = strtol(v[++i], NULL, 10); 137 val = strtol(v[++i], NULL, 10);
136 if (val < 0 || val > 100) { 138 if (val < 0 || val > 100) {
137 fprintf(stderr, 139 fprintf(stderr,
138 "Invalid max number of moves.\n"); 140 "Invalid max number of moves"
141 "(0 <= M <= 100).\n");
139 return a; 142 return a;
140 } 143 }
141 a->opts->max_moves = val; 144 a->opts->max_moves = val;
145 } else if (!strcmp(v[i], "-t")) {
146 val = strtol(v[++i], NULL, 10);
147 if (val < 1 || val > 64) {
148 fprintf(stderr,
149 "Invalid number of threads."
150 "1 <= t <= 64\n");
151 return a;
152 }
153 a->opts->nthreads = val;
142 } else if (!strcmp(v[i], "-s")) { 154 } else if (!strcmp(v[i], "-s")) {
143 val = strtol(v[++i], NULL, 10); 155 val = strtol(v[++i], NULL, 10);
144 if (val < 1 || val > 1000000) { 156 if (val < 1 || val > 1000000) {
@@ -255,11 +267,19 @@ print_exec(CommandArgs *args)
255static void 267static void
256help_exec(CommandArgs *args) 268help_exec(CommandArgs *args)
257{ 269{
258 /* TODO: print full nissy manpage */
259 if (args->command == NULL) { 270 if (args->command == NULL) {
260 printf("Type help COMMAND for information on a "); 271 printf(
261 printf("specific command.\n"); 272 "Use the nissy command \"help COMMAND\" for a short "
262 printf("A more complete manual page is work in progress.\n"); 273 "description of a specific command.\n"
274 "Use the nissy command \"commands\" for a list of "
275 "available commands.\n"
276 "See the manual page for more details. The manual"
277 " page is available with \"man nissy\" on a UNIX"
278 " system (such a Linux or MacOS) or in pdf and html"
279 " format in the docs folder.\n"
280 "Nissy is available for free at "
281 "https://github.com/sebastianotronto/nissy"
282 );
263 } else { 283 } else {
264 printf("Command %s: %s\nusage: %s\n", args->command->name, 284 printf("Command %s: %s\nusage: %s\n", args->command->name,
265 args->command->description, args->command->usage); 285 args->command->description, args->command->usage);
diff --git a/src/cubetypes.h b/src/cubetypes.h
index 334662c..7eb803e 100644
--- a/src/cubetypes.h
+++ b/src/cubetypes.h
@@ -3,6 +3,7 @@
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include <inttypes.h> 5#include <inttypes.h>
6#include <pthread.h>
6 7
7#define NMOVES 55 /* Actually 55, but one is NULLMOVE */ 8#define NMOVES 55 /* Actually 55, but one is NULLMOVE */
8#define NTRANS 48 9#define NTRANS 48
@@ -87,6 +88,7 @@ typedef struct prunedata PruneData;
87typedef struct solveoptions SolveOptions; 88typedef struct solveoptions SolveOptions;
88typedef struct step Step; 89typedef struct step Step;
89typedef struct symdata SymData; 90typedef struct symdata SymData;
91typedef struct threaddata ThreadData;
90 92
91typedef Cube (*AntiIndexer) (uint64_t); 93typedef Cube (*AntiIndexer) (uint64_t);
92typedef bool (*Checker) (Cube); 94typedef bool (*Checker) (Cube);
@@ -104,186 +106,205 @@ typedef Trans (*TransDetector) (Cube);
104struct 106struct
105alg 107alg
106{ 108{
107 Move * move; 109 Move * move;
108 bool * inv; 110 bool * inv;
109 int len; 111 int len;
110 int allocated; 112 int allocated;
111}; 113};
112 114
113struct 115struct
114alglist 116alglist
115{ 117{
116 AlgListNode * first; 118 AlgListNode * first;
117 AlgListNode * last; 119 AlgListNode * last;
118 int len; 120 int len;
119}; 121};
120 122
121struct 123struct
122alglistnode 124alglistnode
123{ 125{
124 Alg * alg; 126 Alg * alg;
125 AlgListNode * next; 127 AlgListNode * next;
126}; 128};
127 129
128struct 130struct
129block 131block
130{ 132{
131 bool edge[12]; 133 bool edge[12];
132 bool corner[8]; 134 bool corner[8];
133 bool center[6]; 135 bool center[6];
134}; 136};
135 137
136struct 138struct
137command 139command
138{ 140{
139 char * name; 141 char * name;
140 char * usage; 142 char * usage;
141 char * description; 143 char * description;
142 ArgParser parse_args; 144 ArgParser parse_args;
143 Exec exec; 145 Exec exec;
144}; 146};
145 147
146struct 148struct
147commandargs 149commandargs
148{ 150{
149 bool success; 151 bool success;
150 Alg * scramble; 152 Alg * scramble;
151 SolveOptions * opts; 153 SolveOptions * opts;
152 Step * step; 154 Step * step;
153 Command * command; /* For help */ 155 Command * command; /* For help */
154}; 156};
155 157
156struct 158struct
157coordinate 159coordinate
158{ 160{
159 Indexer index; 161 Indexer index;
160 AntiIndexer cube; 162 AntiIndexer cube;
161 uint64_t max; 163 uint64_t max;
162 int ntrans; 164 int ntrans;
163 Trans * trans; 165 Trans * trans;
164}; 166};
165 167
166struct 168struct
167cube 169cube
168{ 170{
169 int epose; 171 int epose;
170 int eposs; 172 int eposs;
171 int eposm; 173 int eposm;
172 int eofb; 174 int eofb;
173 int eorl; 175 int eorl;
174 int eoud; 176 int eoud;
175 int cp; 177 int cp;
176 int coud; 178 int coud;
177 int cofb; 179 int cofb;
178 int corl; 180 int corl;
179 int cpos; 181 int cpos;
180}; 182};
181 183
182struct 184struct
183cubearray 185cubearray
184{ 186{
185 int * ep; 187 int * ep;
186 int * eofb; 188 int * eofb;
187 int * eorl; 189 int * eorl;
188 int * eoud; 190 int * eoud;
189 int * cp; 191 int * cp;
190 int * coud; 192 int * coud;
191 int * corl; 193 int * corl;
192 int * cofb; 194 int * cofb;
193 int * cpos; 195 int * cpos;
194}; 196};
195 197
196struct 198struct
197cubetarget 199cubetarget
198{ 200{
199 Cube cube; 201 Cube cube;
200 int target; 202 int target;
201}; 203};
202 204
203struct 205struct
204dfsdata 206dfsdata
205{ 207{
206 int d; 208 int d;
207 int m; 209 int m;
208 int lb; 210 int lb;
209 bool niss; 211 bool niss;
210 Move last1; 212 Move last1;
211 Move last2; 213 Move last2;
212 AlgList * sols; 214 AlgList * sols;
213 Alg * current_alg; 215 pthread_mutex_t * sols_mutex;
214 Move sorted_moves[NMOVES]; 216 Alg * current_alg;
215 int move_position[NMOVES]; 217 Move * sorted_moves;
216 uint8_t * visited; 218 int * move_position;
219 uint8_t * visited;
217}; 220};
218 221
219struct 222struct
220piecefilter 223piecefilter
221{ 224{
222 bool epose; 225 bool epose;
223 bool eposs; 226 bool eposs;
224 bool eposm; 227 bool eposm;
225 bool eofb; 228 bool eofb;
226 bool eorl; 229 bool eorl;
227 bool eoud; 230 bool eoud;
228 bool cp; 231 bool cp;
229 bool coud; 232 bool coud;
230 bool cofb; 233 bool cofb;
231 bool corl; 234 bool corl;
232 bool cpos; 235 bool cpos;
233}; 236};
234 237
235struct 238struct
236prunedata 239prunedata
237{ 240{
238 char * filename; 241 char * filename;
239 uint8_t * ptable; 242 uint8_t * ptable;
240 bool generated; 243 bool generated;
241 uint64_t n; 244 uint64_t n;
242 Coordinate * coord; 245 Coordinate * coord;
243 Moveset moveset; 246 Moveset moveset;
244}; 247};
245 248
246struct 249struct
247solveoptions 250solveoptions
248{ 251{
249 int min_moves; 252 int min_moves;
250 int max_moves; 253 int max_moves;
251 int max_solutions; 254 int max_solutions;
252 bool optimal_only; 255 int nthreads;
253 bool can_niss; 256 bool optimal_only;
254 bool verbose; 257 bool can_niss;
255 bool all; 258 bool verbose;
256 bool print_number; 259 bool all;
260 bool print_number;
257}; 261};
258 262
259struct 263struct
260step 264step
261{ 265{
262 char * shortname; 266 char * shortname;
263 char * name; 267 char * name;
264 Estimator estimate; 268 Estimator estimate;
265 Checker ready; 269 Checker ready;
266 char * ready_msg; 270 char * ready_msg;
267 Validator is_valid; 271 Validator is_valid;
268 Moveset moveset; 272 Moveset moveset;
269 Trans pre_trans; 273 Trans pre_trans;
270 TransDetector detect; 274 TransDetector detect;
271 int ntables; 275 int ntables;
272 PruneData * tables[10]; 276 PruneData * tables[10];
273}; 277};
274 278
275struct 279struct
276symdata 280symdata
277{ 281{
278 char * filename; 282 char * filename;
279 bool generated; 283 bool generated;
280 Coordinate * coord; 284 Coordinate * coord;
281 Coordinate * sym_coord; 285 Coordinate * sym_coord;
282 int ntrans; 286 int ntrans;
283 Trans * trans; 287 Trans * trans;
284 uint64_t * class; 288 uint64_t * class;
285 Cube * rep; 289 Cube * rep;
286 Trans * transtorep; 290 Trans * transtorep;
291};
292
293struct
294threaddata
295{
296 int thid;
297 Cube cube;
298 Step * step;
299 int depth;
300 Move * sorted_moves;
301 int * move_position;
302 SolveOptions * opts;
303 AlgList * start;
304 AlgListNode ** node;
305 AlgList * sols;
306 pthread_mutex_t * start_mutex;
307 pthread_mutex_t * sols_mutex;
287}; 308};
288 309
289#endif 310#endif
diff --git a/src/pruning.c b/src/pruning.c
index 1369892..2c6f348 100644
--- a/src/pruning.c
+++ b/src/pruning.c
@@ -95,7 +95,7 @@ pd_khuge_HTM = {
95void 95void
96genptable(PruneData *pd) 96genptable(PruneData *pd)
97{ 97{
98 Move ms[NMOVES]; 98 Move *ms;
99 uint64_t j, oldn; 99 uint64_t j, oldn;
100 DfsData dd; 100 DfsData dd;
101 101
@@ -112,6 +112,7 @@ genptable(PruneData *pd)
112 112
113 fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); 113 fprintf(stderr, "Cannot load %s, generating it\n", pd->filename);
114 114
115 ms = malloc(NMOVES * sizeof(Move));
115 moveset_to_list(pd->moveset, ms); 116 moveset_to_list(pd->moveset, ms);
116 117
117 for (j = 0; j < pd->coord->max; j++) 118 for (j = 0; j < pd->coord->max; j++)
@@ -119,6 +120,7 @@ genptable(PruneData *pd)
119 120
120 dd = (DfsData) { .m = 0 }; 121 dd = (DfsData) { .m = 0 };
121 dd.visited = malloc((ptablesize(pd)/4 + 1) * sizeof(uint8_t)); 122 dd.visited = malloc((ptablesize(pd)/4 + 1) * sizeof(uint8_t));
123 dd.sorted_moves = malloc(NMOVES * sizeof(Move));
122 moveset_to_list(pd->moveset, dd.sorted_moves); 124 moveset_to_list(pd->moveset, dd.sorted_moves);
123 oldn = 0; 125 oldn = 0;
124 pd->n = 0; 126 pd->n = 0;
@@ -136,14 +138,16 @@ genptable(PruneData *pd)
136 if (!write_ptable_file(pd)) 138 if (!write_ptable_file(pd))
137 fprintf(stderr, "Error writing ptable file\n"); 139 fprintf(stderr, "Error writing ptable file\n");
138 140
141 free(ms);
139 free(dd.visited); 142 free(dd.visited);
143 free(dd.sorted_moves);
140} 144}
141*/ 145*/
142 146
143void 147void
144genptable(PruneData *pd) 148genptable(PruneData *pd)
145{ 149{
146 Move ms[NMOVES]; 150 Move *ms;
147 int d; 151 int d;
148 uint64_t j, oldn; 152 uint64_t j, oldn;
149 153
@@ -161,6 +165,7 @@ genptable(PruneData *pd)
161 165
162 fprintf(stderr, "Cannot load %s, generating it\n", pd->filename); 166 fprintf(stderr, "Cannot load %s, generating it\n", pd->filename);
163 167
168 ms = malloc(NMOVES * sizeof(Move));
164 moveset_to_list(pd->moveset, ms); 169 moveset_to_list(pd->moveset, ms);
165 170
166 /* We use 4 bits per value, so any distance >= 15 is set to 15 */ 171 /* We use 4 bits per value, so any distance >= 15 is set to 15 */
@@ -186,6 +191,7 @@ genptable(PruneData *pd)
186 if (!write_ptable_file(pd)) 191 if (!write_ptable_file(pd))
187 fprintf(stderr, "Error writing ptable file\n"); 192 fprintf(stderr, "Error writing ptable file\n");
188 193
194 free(ms);
189} 195}
190 196
191/* 197/*
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}
diff --git a/src/steps.c b/src/steps.c
index 012e4cd..34ddcc2 100644
--- a/src/steps.c
+++ b/src/steps.c
@@ -1063,21 +1063,10 @@ detect_pretrans_drud(Cube cube)
1063/* Public functions **********************************************************/ 1063/* Public functions **********************************************************/
1064 1064
1065void 1065void
1066prepare_step(Step *step, DfsData *dd) 1066prepare_step(Step *step)
1067{ 1067{
1068 int i; 1068 int i;
1069 1069
1070 dd->m = 0;
1071 dd->niss = false;
1072 dd->lb = -1;
1073 dd->last1 = NULLMOVE;
1074 dd->last2 = NULLMOVE;
1075 dd->sols = new_alglist();
1076 dd->current_alg = new_alg("");
1077
1078 moveset_to_list(step->moveset, dd->sorted_moves);
1079 movelist_to_position(dd->sorted_moves, dd->move_position);
1080
1081 for (i = 0; i < step->ntables; i++) 1070 for (i = 0; i < step->ntables; i++)
1082 genptable(step->tables[i]); 1071 genptable(step->tables[i]);
1083} 1072}
diff --git a/src/steps.h b/src/steps.h
index 89ab168..4aedcee 100644
--- a/src/steps.h
+++ b/src/steps.h
@@ -7,6 +7,6 @@
7 7
8extern Step * steps[NSTEPS]; 8extern Step * steps[NSTEPS];
9 9
10void prepare_step(Step *step, DfsData *dd); 10void prepare_step(Step *step);
11 11
12#endif 12#endif

Generated with cgit - Back to sebastiano.tronto.net