diff options
| author | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-11-20 16:08:43 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-11-20 16:08:43 +0100 |
| commit | a8c4da5b955eab2eed9ebb03ee4b1212ec6fe042 (patch) | |
| tree | 3fe233ce2883545ec42d2c3cf5661fba3818fb9d | |
| parent | 0df4f6f98101bb3be192ce892aa1452f2c6de1a4 (diff) | |
| download | nissy-a8c4da5b955eab2eed9ebb03ee4b1212ec6fe042.tar.gz nissy-a8c4da5b955eab2eed9ebb03ee4b1212ec6fe042.zip | |
Multithreading seems to be working now, it was easier than expected!
Diffstat (limited to '')
| -rw-r--r-- | Makefile | 6 | ||||
| -rw-r--r-- | TODO.md | 11 | ||||
| -rw-r--r-- | doc/nissy.1 | 8 | ||||
| -rw-r--r-- | nissy-2.0beta3.tar.gz | bin | 0 -> 53146 bytes | |||
| -rw-r--r-- | src/commands.c | 34 | ||||
| -rw-r--r-- | src/cubetypes.h | 231 | ||||
| -rw-r--r-- | src/pruning.c | 10 | ||||
| -rw-r--r-- | src/solve.c | 193 | ||||
| -rw-r--r-- | src/steps.c | 13 | ||||
| -rw-r--r-- | src/steps.h | 2 |
10 files changed, 347 insertions, 161 deletions
| @@ -1,13 +1,13 @@ | |||
| 1 | # See LICENSE file for copyright and license details. | 1 | # See LICENSE file for copyright and license details. |
| 2 | 2 | ||
| 3 | VERSION = 2.0beta2 | 3 | VERSION = 2.0beta3 |
| 4 | 4 | ||
| 5 | PREFIX = /usr/local | 5 | PREFIX = /usr/local |
| 6 | MANPREFIX = ${PREFIX}/share/man | 6 | MANPREFIX = ${PREFIX}/share/man |
| 7 | 7 | ||
| 8 | CPPFLAGS = -DVERSION=\"${VERSION}\" | 8 | CPPFLAGS = -DVERSION=\"${VERSION}\" |
| 9 | CFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -O3 ${CPPFLAGS} | 9 | CFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -O3 ${CPPFLAGS} |
| 10 | DBGFLAGS = -std=c99 -pedantic -Wall -Wextra -Wno-unused-parameter -g ${CPPFLAGS} | 10 | DBGFLAGS = -std=c99 -pthread -pedantic -Wall -Wextra -Wno-unused-parameter -g ${CPPFLAGS} |
| 11 | 11 | ||
| 12 | CC = cc | 12 | CC = cc |
| 13 | 13 | ||
| @@ -3,6 +3,9 @@ | |||
| 3 | This is a list of things that I would like to add or change at some point. | 3 | This is a list of things that I would like to add or change at some point. |
| 4 | It's more of a personal reminder than anything else. | 4 | It'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 |
| 94 | Plain style: do not print the number of moves. | 94 | Plain style: do not print the number of moves. |
| 95 | . | 95 | . |
| 96 | .It Fl t Ar n | ||
| 97 | Use | ||
| 98 | .Ar n | ||
| 99 | CPU threads. By default nissy uses only 1 thread. Using more than one | ||
| 100 | thread will improve performance, but the optimal number depends on your | ||
| 101 | machine and operating system. Generally, using one less than the number | ||
| 102 | of threads of your CPU works quite well. | ||
| 103 | . | ||
| 96 | .It Fl v | 104 | .It Fl v |
| 97 | Verbose mode: print some information during the search and print each solution | 105 | Verbose mode: print some information during the search and print each solution |
| 98 | as it is found instead of only printing them all together at the end. | 106 | as 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 | |||
| 28 | solve_cmd = { | 28 | solve_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) | |||
| 255 | static void | 267 | static void |
| 256 | help_exec(CommandArgs *args) | 268 | help_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; | |||
| 87 | typedef struct solveoptions SolveOptions; | 88 | typedef struct solveoptions SolveOptions; |
| 88 | typedef struct step Step; | 89 | typedef struct step Step; |
| 89 | typedef struct symdata SymData; | 90 | typedef struct symdata SymData; |
| 91 | typedef struct threaddata ThreadData; | ||
| 90 | 92 | ||
| 91 | typedef Cube (*AntiIndexer) (uint64_t); | 93 | typedef Cube (*AntiIndexer) (uint64_t); |
| 92 | typedef bool (*Checker) (Cube); | 94 | typedef bool (*Checker) (Cube); |
| @@ -104,186 +106,205 @@ typedef Trans (*TransDetector) (Cube); | |||
| 104 | struct | 106 | struct |
| 105 | alg | 107 | alg |
| 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 | ||
| 113 | struct | 115 | struct |
| 114 | alglist | 116 | alglist |
| 115 | { | 117 | { |
| 116 | AlgListNode * first; | 118 | AlgListNode * first; |
| 117 | AlgListNode * last; | 119 | AlgListNode * last; |
| 118 | int len; | 120 | int len; |
| 119 | }; | 121 | }; |
| 120 | 122 | ||
| 121 | struct | 123 | struct |
| 122 | alglistnode | 124 | alglistnode |
| 123 | { | 125 | { |
| 124 | Alg * alg; | 126 | Alg * alg; |
| 125 | AlgListNode * next; | 127 | AlgListNode * next; |
| 126 | }; | 128 | }; |
| 127 | 129 | ||
| 128 | struct | 130 | struct |
| 129 | block | 131 | block |
| 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 | ||
| 136 | struct | 138 | struct |
| 137 | command | 139 | command |
| 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 | ||
| 146 | struct | 148 | struct |
| 147 | commandargs | 149 | commandargs |
| 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 | ||
| 156 | struct | 158 | struct |
| 157 | coordinate | 159 | coordinate |
| 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 | ||
| 166 | struct | 168 | struct |
| 167 | cube | 169 | cube |
| 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 | ||
| 182 | struct | 184 | struct |
| 183 | cubearray | 185 | cubearray |
| 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 | ||
| 196 | struct | 198 | struct |
| 197 | cubetarget | 199 | cubetarget |
| 198 | { | 200 | { |
| 199 | Cube cube; | 201 | Cube cube; |
| 200 | int target; | 202 | int target; |
| 201 | }; | 203 | }; |
| 202 | 204 | ||
| 203 | struct | 205 | struct |
| 204 | dfsdata | 206 | dfsdata |
| 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 | ||
| 219 | struct | 222 | struct |
| 220 | piecefilter | 223 | piecefilter |
| 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 | ||
| 235 | struct | 238 | struct |
| 236 | prunedata | 239 | prunedata |
| 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 | ||
| 246 | struct | 249 | struct |
| 247 | solveoptions | 250 | solveoptions |
| 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 | ||
| 259 | struct | 263 | struct |
| 260 | step | 264 | step |
| 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 | ||
| 275 | struct | 279 | struct |
| 276 | symdata | 280 | symdata |
| 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 | |||
| 293 | struct | ||
| 294 | threaddata | ||
| 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 = { | |||
| 95 | void | 95 | void |
| 96 | genptable(PruneData *pd) | 96 | genptable(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 | ||
| 143 | void | 147 | void |
| 144 | genptable(PruneData *pd) | 148 | genptable(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); | |||
| 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 | } |
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 | ||
| 1065 | void | 1065 | void |
| 1066 | prepare_step(Step *step, DfsData *dd) | 1066 | prepare_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 | ||
| 8 | extern Step * steps[NSTEPS]; | 8 | extern Step * steps[NSTEPS]; |
| 9 | 9 | ||
| 10 | void prepare_step(Step *step, DfsData *dd); | 10 | void prepare_step(Step *step); |
| 11 | 11 | ||
| 12 | #endif | 12 | #endif |
