diff options
24 files changed, 309 insertions, 160 deletions
| @@ -46,3 +46,4 @@ tools/results | |||
| 46 | python/*.pyd | 46 | python/*.pyd |
| 47 | python/*.exp | 47 | python/*.exp |
| 48 | python/*.lib | 48 | python/*.lib |
| 49 | *.sketch | ||
diff --git a/benchmarks/benchmarks.md b/benchmarks/benchmarks.md index f84ddb3..33e8288 100644 --- a/benchmarks/benchmarks.md +++ b/benchmarks/benchmarks.md | |||
| @@ -71,9 +71,9 @@ Time per cube (in seconds, lower is better). | |||
| 71 | 71 | ||
| 72 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 72 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 73 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 73 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 74 | |H48 h11 k2|56.1GiB | 0.23 | 1.15 | 5.08 | 31.30 | 278.47 | | 74 | |H48 h11 k2|56.1GiB | 0.23 | 1.15 | 5.08 | 31.30 | 53.67 | |
| 75 | |vcube 404 |31.8GiB | 0.30 | 1.25 | 6.87 | 57.49 | 291.31 | | 75 | |vcube 404 |31.8GiB | 0.30 | 1.25 | 6.87 | 57.49 | 291.31 | |
| 76 | |H48 h10 k2|28.1GiB | 0.34 | 1.80 | 7.77 | | | | 76 | |H48 h10 k2|28.1GiB | 0.34 | 1.80 | 7.77 | | 81.89 | |
| 77 | |vcube 308 |21.2GiB | 0.20 | 1.11 | 6.92 | | | | 77 | |vcube 308 |21.2GiB | 0.20 | 1.11 | 6.92 | | | |
| 78 | |H48 h9 k2 |14.1GiB | 0.42 | 2.84 | 12.86 | | | | 78 | |H48 h9 k2 |14.1GiB | 0.42 | 2.84 | 12.86 | | | |
| 79 | |vcube 208 | 7.3GiB | 0.57 | 4.41 | 20.75 | | | | 79 | |vcube 208 | 7.3GiB | 0.57 | 4.41 | 20.75 | | | |
| @@ -86,9 +86,9 @@ Time per cube adjusted for tables size (in seconds \* GiB, lower is better). | |||
| 86 | 86 | ||
| 87 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 87 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 88 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 88 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 89 | |H48 h11 k2|56.1GiB | 12.90 | 64.51 | 284.99 |1755.93 |15622.17 | | 89 | |H48 h11 k2|56.1GiB | 12.90 | 64.51 | 284.99 |1755.93 | 3010.89 | |
| 90 | |vcube 404 |31.8GiB | 9.54 | 39.75 | 218.47 |1828.18 | 9263.66 | | 90 | |vcube 404 |31.8GiB | 9.54 | 39.75 | 218.47 |1828.18 | 9263.66 | |
| 91 | |H48 h10 k2|28.1GiB | 9.55 | 50.58 | 218.34 | | | | 91 | |H48 h10 k2|28.1GiB | 9.55 | 50.58 | 218.34 | | 2301.11 | |
| 92 | |vcube 308 |21.2GiB | 4.24 | 23.53 | 146.70 | | | | 92 | |vcube 308 |21.2GiB | 4.24 | 23.53 | 146.70 | | | |
| 93 | |H48 h9 k2 |14.1GiB | 5.92 | 40.04 | 181.33 | | | | 93 | |H48 h9 k2 |14.1GiB | 5.92 | 40.04 | 181.33 | | | |
| 94 | |vcube 208 | 7.3GiB | 4.16 | 32.19 | 151.48 | | | | 94 | |vcube 208 | 7.3GiB | 4.16 | 32.19 | 151.48 | | | |
| @@ -110,11 +110,11 @@ Time per cube (in seconds, lower is better). | |||
| 110 | 110 | ||
| 111 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 111 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 112 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 112 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 113 | |H48 h11 k2|56.1GiB | 0.06 | 0.31 | 1.31 | 7.96 | 77.81 | | 113 | |H48 h11 k2|56.1GiB | 0.06 | 0.31 | 1.31 | 7.96 | 14.01 | |
| 114 | |vcube 404 |31.8GiB | 0.10 | 0.38 | 1.88 | 16.98 | (a) | | 114 | |vcube 404 |31.8GiB | 0.10 | 0.38 | 1.88 | 16.98 | (a) | |
| 115 | |H48 h10 k2|28.1GiB | 0.10 | 0.47 | 2.00 | 13.54 | 114.35 | | 115 | |H48 h10 k2|28.1GiB | 0.10 | 0.47 | 2.00 | 13.54 | 21.96 | |
| 116 | |vcube 308 |21.2GiB | 0.06 | 0.42 | 1.95 | 17.73 | (a) | | 116 | |vcube 308 |21.2GiB | 0.06 | 0.42 | 1.95 | 17.73 | (a) | |
| 117 | |H48 h9 k2 |14.1GiB | 0.14 | 0.83 | 3.82 | 25.98 | 162.72 | | 117 | |H48 h9 k2 |14.1GiB | 0.14 | 0.83 | 3.82 | 25.98 | 31.68 | |
| 118 | |vcube 208 | 7.3GiB | 0.17 | 1.49 | 5.88 | | (a) | | 118 | |vcube 208 | 7.3GiB | 0.17 | 1.49 | 5.88 | | (a) | |
| 119 | |H48 h8 k2 | 7.1GiB | 0.27 | 2.02 | 7.94 | | | | 119 | |H48 h8 k2 | 7.1GiB | 0.27 | 2.02 | 7.94 | | | |
| 120 | |H48 h7 k2 | 3.6GiB | 0.35 | 2.59 | 12.41 | | | | 120 | |H48 h7 k2 | 3.6GiB | 0.35 | 2.59 | 12.41 | | | |
| @@ -125,11 +125,11 @@ Time per cube adjusted for tables size (in seconds \* GiB, lower is better). | |||
| 125 | 125 | ||
| 126 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 126 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 127 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 127 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 128 | |H48 h11 k2|56.1GiB | 3.37 | 17.39 | 73.49 | 446.56 | 4365.92 | | 128 | |H48 h11 k2|56.1GiB | 3.37 | 17.39 | 73.49 | 446.56 | 785.96 | |
| 129 | |vcube 404 |31.8GiB | 3.80 | 12.08 | 59.78 | 539.96 | (a) | | 129 | |vcube 404 |31.8GiB | 3.80 | 12.08 | 59.78 | 539.96 | (a) | |
| 130 | |H48 h10 k2|28.1GiB | 2.81 | 13.21 | 56.20 | 380.47 | 3213.24 | | 130 | |H48 h10 k2|28.1GiB | 2.81 | 13.21 | 56.20 | 380.47 | 617.08 | |
| 131 | |vcube 308 |21.2GiB | 1.27 | 8.90 | 41.34 | 375.88 | (a) | | 131 | |vcube 308 |21.2GiB | 1.27 | 8.90 | 41.34 | 375.88 | (a) | |
| 132 | |H48 h9 k2 |14.1GiB | 1.97 | 11.70 | 53.86 | 366.32 | 2294.35 | | 132 | |H48 h9 k2 |14.1GiB | 1.97 | 11.70 | 53.86 | 366.32 | 446.69 | |
| 133 | |vcube 208 | 7.3GiB | 1.24 | 10.88 | 42.92 | | (a) | | 133 | |vcube 208 | 7.3GiB | 1.24 | 10.88 | 42.92 | | (a) | |
| 134 | |H48 h8 k2 | 7.1GiB | 1.92 | 14.34 | 56.37 | | | | 134 | |H48 h8 k2 | 7.1GiB | 1.92 | 14.34 | 56.37 | | | |
| 135 | |H48 h7 k2 | 3.6GiB | 1.26 | 9.32 | 44.68 | | | | 135 | |H48 h7 k2 | 3.6GiB | 1.26 | 9.32 | 44.68 | | | |
| @@ -152,11 +152,11 @@ Time per cube (in seconds, lower is better). | |||
| 152 | 152 | ||
| 153 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 153 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 154 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 154 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 155 | |H48 h11 k2|56.1GiB | 0.02 | 0.10 | 0.43 | 2.48 | 26.29 | | 155 | |H48 h11 k2|56.1GiB | 0.02 | 0.10 | 0.43 | 2.48 | 5.67 | |
| 156 | |vcube 404 |31.8GiB | 0.03 | 0.16 | 0.67 | 6.36 | (a) | | 156 | |vcube 404 |31.8GiB | 0.03 | 0.16 | 0.67 | 6.36 | (a) | |
| 157 | |H48 h10 k2|28.1GiB | 0.03 | 0.16 | 0.74 | 4.43 | | | 157 | |H48 h10 k2|28.1GiB | 0.03 | 0.16 | 0.74 | 4.43 | 8.81 | |
| 158 | |vcube 308 |21.2GiB | 0.04 | 0.22 | 0.89 | 9.53 | (a) | | 158 | |vcube 308 |21.2GiB | 0.04 | 0.22 | 0.89 | 9.53 | (a) | |
| 159 | |H48 h9 k2 |14.1GiB | 0.04 | 0.26 | 1.18 | 8.31 | | | 159 | |H48 h9 k2 |14.1GiB | 0.04 | 0.26 | 1.18 | 8.31 | 13.20 | |
| 160 | |vcube 208 | 7.3GiB | 0.08 | 0.80 | 2.38 | | (a) | | 160 | |vcube 208 | 7.3GiB | 0.08 | 0.80 | 2.38 | | (a) | |
| 161 | |H48 h8 k2 | 7.1GiB | 0.08 | 0.60 | 2.48 | | | | 161 | |H48 h8 k2 | 7.1GiB | 0.08 | 0.60 | 2.48 | | | |
| 162 | |H48 h7 k2 | 3.6GiB | 0.11 | 0.81 | 3.91 | | | | 162 | |H48 h7 k2 | 3.6GiB | 0.11 | 0.81 | 3.91 | | | |
| @@ -167,11 +167,11 @@ Time per cube adjusted for tables size (in seconds \* GiB, lower is better). | |||
| 167 | 167 | ||
| 168 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| | 168 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 169 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| | 169 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 170 | |H48 h11 k2|56.1GiB | 1.12 | 5.61 | 24.12 | 139.13 | 1474.87 | | 170 | |H48 h11 k2|56.1GiB | 1.12 | 5.61 | 24.12 | 139.13 | 318.09 | |
| 171 | |vcube 404 |31.8GiB | 1.08 | 5.09 | 21.31 | 202.25 | (a) | | 171 | |vcube 404 |31.8GiB | 1.08 | 5.09 | 21.31 | 202.25 | (a) | |
| 172 | |H48 h10 k2|28.1GiB | 0.84 | 4.50 | 20.79 | 124.48 | | | 172 | |H48 h10 k2|28.1GiB | 0.84 | 4.50 | 20.79 | 124.48 | 247.56 | |
| 173 | |vcube 308 |21.2GiB | 0.85 | 4.66 | 18.87 | 202.04 | (a) | | 173 | |vcube 308 |21.2GiB | 0.85 | 4.66 | 18.87 | 202.04 | (a) | |
| 174 | |H48 h9 k2 |14.1GiB | 0.56 | 3.67 | 16.64 | 117.17 | | | 174 | |H48 h9 k2 |14.1GiB | 0.56 | 3.67 | 16.64 | 117.17 | 186.12 | |
| 175 | |vcube 208 | 7.3GiB | 0.58 | 5.84 | 17.37 | | (a) | | 175 | |vcube 208 | 7.3GiB | 0.58 | 5.84 | 17.37 | | (a) | |
| 176 | |H48 h8 k2 | 7.1GiB | 0.57 | 4.26 | 17.60 | | | | 176 | |H48 h8 k2 | 7.1GiB | 0.57 | 4.26 | 17.60 | | | |
| 177 | |H48 h7 k2 | 3.6GiB | 0.40 | 2.92 | 14.07 | | | | 177 | |H48 h7 k2 | 3.6GiB | 0.40 | 2.92 | 14.07 | | | |
| @@ -196,25 +196,25 @@ Average time for finding all optimal solutions. | |||
| 196 | 196 | ||
| 197 | Time per cube (in seconds, lower is better). | 197 | Time per cube (in seconds, lower is better). |
| 198 | 198 | ||
| 199 | | Solver | Size |17 moves|18 moves|19 moves|20 moves| | 199 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 200 | |:---------|:-------|-------:|-------:|-------:|-------:| | 200 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 201 | |H48 h11 k2|56.1GiB | 0.05 | 0.50 | 4.24 | 19.75 | | 201 | |H48 h11 k2|56.1GiB | 0.05 | 0.50 | 4.24 | 19.75 | 52.99 | |
| 202 | |H48 h10 k2|28.1GiB | 0.08 | 0.88 | 6.94 | | | 202 | |H48 h10 k2|28.1GiB | 0.08 | 0.88 | 6.94 | | | |
| 203 | |H48 h9 k2 |14.1GiB | 0.13 | 1.39 | 13.50 | | | 203 | |H48 h9 k2 |14.1GiB | 0.13 | 1.39 | 13.50 | | | |
| 204 | |H48 h8 k2 | 7.1GiB | 0.25 | 2.85 | | | | 204 | |H48 h8 k2 | 7.1GiB | 0.25 | 2.85 | | | | |
| 205 | |H48 h7 k2 | 3.6GiB | 0.36 | 4.24 | | | | 205 | |H48 h7 k2 | 3.6GiB | 0.36 | 4.24 | | | | |
| 206 | |H48 h6 k2 | 1.8GiB | 0.69 | 8.20 | | | | 206 | |H48 h6 k2 | 1.8GiB | 0.69 | 8.20 | | | | |
| 207 | 207 | ||
| 208 | Time per cube adjusted for tables size (in seconds \* GiB, lower is better). | 208 | Time per cube adjusted for tables size (in seconds \* GiB, lower is better). |
| 209 | 209 | ||
| 210 | | Solver | Size |17 moves|18 moves|19 moves|20 moves| | 210 | | Solver | Size |17 moves|18 moves|19 moves|20 moves|Superflip| |
| 211 | |:---------|:-------|-------:|-------:|-------:|-------:| | 211 | |:---------|:-------|-------:|-------:|-------:|-------:|--------:| |
| 212 | |H48 h11 k2|56.1GiB | 2.81 | 28.05 | 237.86 |1107.98 | | 212 | |H48 h11 k2|56.1GiB | 2.81 | 28.05 | 237.86 |1107.98 | 2972.74 | |
| 213 | |H48 h10 k2|28.1GiB | 2.25 | 24.73 | 195.01 | | | 213 | |H48 h10 k2|28.1GiB | 2.25 | 24.73 | 195.01 | | | |
| 214 | |H48 h9 k2 |14.1GiB | 1.83 | 19.60 | 190.35 | | | 214 | |H48 h9 k2 |14.1GiB | 1.83 | 19.60 | 190.35 | | | |
| 215 | |H48 h8 k2 | 7.1GiB | 1.77 | 20.24 | | | | 215 | |H48 h8 k2 | 7.1GiB | 1.77 | 20.24 | | | | |
| 216 | |H48 h7 k2 | 3.6GiB | 1.30 | 15.26 | | | | 216 | |H48 h7 k2 | 3.6GiB | 1.30 | 15.26 | | | | |
| 217 | |H48 h6 k2 | 1.8GiB | 1.24 | 14.76 | | | | 217 | |H48 h6 k2 | 1.8GiB | 1.24 | 14.76 | | | | |
| 218 | 218 | ||
| 219 | ## Comments on the results | 219 | ## Comments on the results |
| 220 | 220 | ||
diff --git a/src/solvers/coord/multisolve.h b/src/solvers/coord/multisolve.h index f3589e8..a45bd6a 100644 --- a/src/solvers/coord/multisolve.h +++ b/src/solvers/coord/multisolve.h | |||
| @@ -9,6 +9,7 @@ typedef struct { | |||
| 9 | uint8_t target_depth; | 9 | uint8_t target_depth; |
| 10 | solution_moves_t *solution_moves; | 10 | solution_moves_t *solution_moves; |
| 11 | solution_settings_t *solution_settings; | 11 | solution_settings_t *solution_settings; |
| 12 | uint64_t tmask; | ||
| 12 | solution_list_t *solution_list; | 13 | solution_list_t *solution_list; |
| 13 | multicoord_t *mcoord; | 14 | multicoord_t *mcoord; |
| 14 | const unsigned char *coord_data[MAX_MULTICOORD_NCOORDS]; | 15 | const unsigned char *coord_data[MAX_MULTICOORD_NCOORDS]; |
| @@ -87,7 +88,7 @@ solve_multicoord_dfs(dfsarg_solve_multicoord_t arg[static 1]) | |||
| 87 | /* All coordinates are solved */ | 88 | /* All coordinates are solved */ |
| 88 | if (!multicoord_solution_admissible(arg)) | 89 | if (!multicoord_solution_admissible(arg)) |
| 89 | return 0; | 90 | return 0; |
| 90 | return appendsolution(arg->solution_moves, | 91 | return appendsolution(arg->solution_moves, 1, &arg->tmask, |
| 91 | arg->solution_settings, arg->solution_list); | 92 | arg->solution_settings, arg->solution_list); |
| 92 | 93 | ||
| 93 | solve_multicoord_dfs_notsolved: | 94 | solve_multicoord_dfs_notsolved: |
| @@ -208,7 +209,6 @@ solve_multicoord( | |||
| 208 | solution_moves_reset(&solution_moves); | 209 | solution_moves_reset(&solution_moves); |
| 209 | 210 | ||
| 210 | solution_settings = (solution_settings_t) { | 211 | solution_settings = (solution_settings_t) { |
| 211 | .tmask = TM_SINGLE(inverse_trans(trans)), | ||
| 212 | .unniss = false, | 212 | .unniss = false, |
| 213 | .maxmoves = maxmoves, | 213 | .maxmoves = maxmoves, |
| 214 | .maxsolutions = maxsolutions, | 214 | .maxsolutions = maxsolutions, |
| @@ -222,6 +222,7 @@ solve_multicoord( | |||
| 222 | .mcoord = mcoord, | 222 | .mcoord = mcoord, |
| 223 | .solution_moves = &solution_moves, | 223 | .solution_moves = &solution_moves, |
| 224 | .solution_settings = &solution_settings, | 224 | .solution_settings = &solution_settings, |
| 225 | .tmask = TM_SINGLE(inverse_trans(trans)), | ||
| 225 | .solution_list = &solution_list, | 226 | .solution_list = &solution_list, |
| 226 | }; | 227 | }; |
| 227 | 228 | ||
| @@ -258,8 +259,8 @@ solve_multicoord( | |||
| 258 | } | 259 | } |
| 259 | 260 | ||
| 260 | /* All coordinates are solved */ | 261 | /* All coordinates are solved */ |
| 261 | if (minmoves == 0 && !appendsolution(&solution_moves, | 262 | if (minmoves == 0 && !appendsolution(&solution_moves, 1, |
| 262 | &solution_settings, &solution_list)) | 263 | &arg.tmask, &solution_settings, &solution_list)) |
| 263 | goto solve_multicoord_error_buffer; | 264 | goto solve_multicoord_error_buffer; |
| 264 | goto solve_multicoord_done; | 265 | goto solve_multicoord_done; |
| 265 | 266 | ||
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h index 54309b1..9ea6d1a 100644 --- a/src/solvers/coord/solve.h +++ b/src/solvers/coord/solve.h | |||
| @@ -3,6 +3,7 @@ typedef struct { | |||
| 3 | cube_t inverse; | 3 | cube_t inverse; |
| 4 | uint8_t target_depth; | 4 | uint8_t target_depth; |
| 5 | solution_moves_t *solution_moves; | 5 | solution_moves_t *solution_moves; |
| 6 | uint64_t tmask; | ||
| 6 | solution_settings_t *solution_settings; | 7 | solution_settings_t *solution_settings; |
| 7 | solution_list_t *solution_list; | 8 | solution_list_t *solution_list; |
| 8 | uint8_t nissflag; | 9 | uint8_t nissflag; |
| @@ -163,7 +164,7 @@ solve_coord_dfs(dfsarg_solve_coord_t arg[static 1]) | |||
| 163 | if (coord_is_solved(arg->coord, coord, arg->coord_data)) { | 164 | if (coord_is_solved(arg->coord, coord, arg->coord_data)) { |
| 164 | if (!coord_solution_admissible(arg)) | 165 | if (!coord_solution_admissible(arg)) |
| 165 | return 0; | 166 | return 0; |
| 166 | return appendsolution(arg->solution_moves, | 167 | return appendsolution(arg->solution_moves, 1, &arg->tmask, |
| 167 | arg->solution_settings, arg->solution_list); | 168 | arg->solution_settings, arg->solution_list); |
| 168 | } | 169 | } |
| 169 | 170 | ||
| @@ -339,7 +340,6 @@ solve_coord( | |||
| 339 | solution_moves_reset(&solution_moves); | 340 | solution_moves_reset(&solution_moves); |
| 340 | 341 | ||
| 341 | solution_settings = (solution_settings_t) { | 342 | solution_settings = (solution_settings_t) { |
| 342 | .tmask = TM_SINGLE(inverse_trans(trans)), | ||
| 343 | .unniss = false, | 343 | .unniss = false, |
| 344 | .maxmoves = maxmoves, | 344 | .maxmoves = maxmoves, |
| 345 | .maxsolutions = maxsolutions, | 345 | .maxsolutions = maxsolutions, |
| @@ -355,14 +355,15 @@ solve_coord( | |||
| 355 | .ptable = ptable, | 355 | .ptable = ptable, |
| 356 | .solution_moves = &solution_moves, | 356 | .solution_moves = &solution_moves, |
| 357 | .solution_settings = &solution_settings, | 357 | .solution_settings = &solution_settings, |
| 358 | .tmask = TM_SINGLE(inverse_trans(trans)), | ||
| 358 | .solution_list = &solution_list, | 359 | .solution_list = &solution_list, |
| 359 | .nissflag = nissflag, | 360 | .nissflag = nissflag, |
| 360 | }; | 361 | }; |
| 361 | 362 | ||
| 362 | i = coord->coord(c, coord_data); | 363 | i = coord->coord(c, coord_data); |
| 363 | if (coord_is_solved(coord, i, coord_data)) { | 364 | if (coord_is_solved(coord, i, coord_data)) { |
| 364 | if (minmoves == 0 && !appendsolution(&solution_moves, | 365 | if (minmoves == 0 && !appendsolution(&solution_moves, 1, |
| 365 | &solution_settings, &solution_list)) | 366 | &arg.tmask, &solution_settings, &solution_list)) |
| 366 | goto solve_coord_error_buffer; | 367 | goto solve_coord_error_buffer; |
| 367 | goto solve_coord_done; | 368 | goto solve_coord_done; |
| 368 | } | 369 | } |
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h index bf10723..ad66fd4 100644 --- a/src/solvers/h48/solve.h +++ b/src/solvers/h48/solve.h | |||
| @@ -13,6 +13,7 @@ typedef struct { | |||
| 13 | cube_t cube; | 13 | cube_t cube; |
| 14 | uint8_t moves[H48_STARTING_MOVES]; | 14 | uint8_t moves[H48_STARTING_MOVES]; |
| 15 | int64_t rank; | 15 | int64_t rank; |
| 16 | uint64_t tmask[H48_STARTING_MOVES]; | ||
| 16 | } solve_h48_task_t; | 17 | } solve_h48_task_t; |
| 17 | 18 | ||
| 18 | typedef struct { | 19 | typedef struct { |
| @@ -22,6 +23,7 @@ typedef struct { | |||
| 22 | int8_t target_depth; | 23 | int8_t target_depth; |
| 23 | solution_moves_t *solution_moves; | 24 | solution_moves_t *solution_moves; |
| 24 | solution_settings_t *solution_settings; | 25 | solution_settings_t *solution_settings; |
| 26 | const uint64_t *tmask; | ||
| 25 | solution_list_t *solution_list; | 27 | solution_list_t *solution_list; |
| 26 | int8_t lb_normal; | 28 | int8_t lb_normal; |
| 27 | int8_t lb_inverse; | 29 | int8_t lb_inverse; |
| @@ -55,6 +57,7 @@ typedef struct { | |||
| 55 | int8_t minmoves; | 57 | int8_t minmoves; |
| 56 | int8_t maxmoves; | 58 | int8_t maxmoves; |
| 57 | int8_t *shortest_sol; | 59 | int8_t *shortest_sol; |
| 60 | uint64_t tmask[H48_STARTING_MOVES]; | ||
| 58 | } dfsarg_solve_h48_maketasks_t; | 61 | } dfsarg_solve_h48_maketasks_t; |
| 59 | 62 | ||
| 60 | STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, | 63 | STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, |
| @@ -69,7 +72,7 @@ STATIC void *solve_h48_runthread(void *); | |||
| 69 | STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); | 72 | STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); |
| 70 | STATIC void solve_h48_log_solutions(solution_list_t [static 1], size_t); | 73 | STATIC void solve_h48_log_solutions(solution_list_t [static 1], size_t); |
| 71 | STATIC int solve_h48_compare_tasks(const void *, const void *); | 74 | STATIC int solve_h48_compare_tasks(const void *, const void *); |
| 72 | STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t, | 75 | STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint64_t, uint8_t, |
| 73 | uint8_t, uint64_t, const unsigned char *, size_t, char *, | 76 | uint8_t, uint64_t, const unsigned char *, size_t, char *, |
| 74 | long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); | 77 | long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *); |
| 75 | 78 | ||
| @@ -208,8 +211,8 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1]) | |||
| 208 | if (arg->target_depth != nm) | 211 | if (arg->target_depth != nm) |
| 209 | return 0; | 212 | return 0; |
| 210 | wrapthread_mutex_lock(arg->solutions_mutex); | 213 | wrapthread_mutex_lock(arg->solutions_mutex); |
| 211 | ret = appendsolution(arg->solution_moves, | 214 | ret = appendsolution(arg->solution_moves, H48_STARTING_MOVES, |
| 212 | arg->solution_settings, arg->solution_list); | 215 | arg->tmask, arg->solution_settings, arg->solution_list); |
| 213 | wrapthread_mutex_unlock(arg->solutions_mutex); | 216 | wrapthread_mutex_unlock(arg->solutions_mutex); |
| 214 | return ret; | 217 | return ret; |
| 215 | } | 218 | } |
| @@ -313,6 +316,7 @@ solve_h48_runthread(void *arg) | |||
| 313 | dfsarg->use_lb_inverse = false; | 316 | dfsarg->use_lb_inverse = false; |
| 314 | dfsarg->movemask_normal = MM18_ALLMOVES; | 317 | dfsarg->movemask_normal = MM18_ALLMOVES; |
| 315 | dfsarg->movemask_inverse = MM18_ALLMOVES; | 318 | dfsarg->movemask_inverse = MM18_ALLMOVES; |
| 319 | dfsarg->tmask = dfsarg->tasks[i].tmask; | ||
| 316 | 320 | ||
| 317 | solve_h48_dfs(dfsarg); | 321 | solve_h48_dfs(dfsarg); |
| 318 | 322 | ||
| @@ -341,7 +345,7 @@ solve_h48_runthread_end: | |||
| 341 | STATIC int64_t | 345 | STATIC int64_t |
| 342 | solve_h48_maketasks( | 346 | solve_h48_maketasks( |
| 343 | dfsarg_solve_h48_t solve_arg[static 1], | 347 | dfsarg_solve_h48_t solve_arg[static 1], |
| 344 | dfsarg_solve_h48_maketasks_t maketasks_arg[static 1], | 348 | dfsarg_solve_h48_maketasks_t mtarg[static 1], |
| 345 | solve_h48_task_t tasks[static H48_STARTING_CUBES], | 349 | solve_h48_task_t tasks[static H48_STARTING_CUBES], |
| 346 | int ntasks[static 1] | 350 | int ntasks[static 1] |
| 347 | ) | 351 | ) |
| @@ -353,59 +357,60 @@ solve_h48_maketasks( | |||
| 353 | cube_t backup_cube; | 357 | cube_t backup_cube; |
| 354 | solution_moves_t moves; | 358 | solution_moves_t moves; |
| 355 | 359 | ||
| 356 | if (equal(maketasks_arg->cube, SOLVED_CUBE)) { | 360 | if (equal(mtarg->cube, SOLVED_CUBE)) { |
| 357 | if (maketasks_arg->nmoves > maketasks_arg->maxmoves || | 361 | if (mtarg->nmoves > mtarg->maxmoves || |
| 358 | maketasks_arg->nmoves < maketasks_arg->minmoves || | 362 | mtarg->nmoves < mtarg->minmoves || |
| 359 | solutions_done(solve_arg->solution_list, | 363 | solutions_done(solve_arg->solution_list, |
| 360 | solve_arg->solution_settings, maketasks_arg->nmoves)) | 364 | solve_arg->solution_settings, mtarg->nmoves)) |
| 361 | return NISSY_OK; | 365 | return NISSY_OK; |
| 362 | 366 | ||
| 363 | solution_moves_reset(&moves); | 367 | solution_moves_reset(&moves); |
| 364 | moves.nmoves = maketasks_arg->nmoves; | 368 | moves.nmoves = mtarg->nmoves; |
| 365 | memcpy(moves.moves, | 369 | memcpy(moves.moves, mtarg->moves, mtarg->nmoves); |
| 366 | maketasks_arg->moves, maketasks_arg->nmoves); | ||
| 367 | 370 | ||
| 368 | appret = appendsolution(&moves, solve_arg->solution_settings, | 371 | appret = appendsolution(&moves, mtarg->nmoves, mtarg->tmask, |
| 369 | solve_arg->solution_list); | 372 | solve_arg->solution_settings, solve_arg->solution_list); |
| 370 | return appret < 0 ? appret : NISSY_OK; | 373 | return appret < 0 ? appret : NISSY_OK; |
| 371 | } | 374 | } |
| 372 | 375 | ||
| 373 | if (maketasks_arg->nmoves == H48_STARTING_MOVES) { | 376 | if (mtarg->nmoves == H48_STARTING_MOVES) { |
| 374 | tasks[*ntasks].cube = maketasks_arg->cube; | 377 | tasks[*ntasks].cube = mtarg->cube; |
| 375 | memcpy(tasks[*ntasks].moves, | 378 | memcpy(tasks[*ntasks].moves, mtarg->moves, |
| 376 | maketasks_arg->moves, H48_STARTING_MOVES); | 379 | H48_STARTING_MOVES * sizeof(uint8_t)); |
| 380 | memcpy(tasks[*ntasks].tmask, mtarg->tmask, | ||
| 381 | H48_STARTING_MOVES * sizeof(uint64_t)); | ||
| 377 | (*ntasks)++; | 382 | (*ntasks)++; |
| 378 | return NISSY_OK; | 383 | return NISSY_OK; |
| 379 | } | 384 | } |
| 380 | 385 | ||
| 381 | if (maketasks_arg->nmoves == 0) { | 386 | if (mtarg->nmoves == 0) { |
| 382 | mm = MM18_ALLMOVES; | 387 | mm = MM18_ALLMOVES; |
| 383 | } else { | 388 | } else { |
| 384 | m = maketasks_arg->moves[maketasks_arg->nmoves-1]; | 389 | m = mtarg->moves[mtarg->nmoves-1]; |
| 385 | mm = allowedmask[movebase(m)]; | 390 | mm = allowedmask[movebase(m)]; |
| 386 | } | 391 | } |
| 387 | 392 | ||
| 388 | maketasks_arg->nmoves++; | 393 | mtarg->tmask[mtarg->nmoves] = symmetry_mask(mtarg->cube); |
| 389 | backup_cube = maketasks_arg->cube; | 394 | |
| 395 | mtarg->nmoves++; | ||
| 396 | backup_cube = mtarg->cube; | ||
| 390 | for (m = 0; m < 18; m++) { | 397 | for (m = 0; m < 18; m++) { |
| 391 | if (!(mm & MM_SINGLE(m))) | 398 | if (!(mm & MM_SINGLE(m))) |
| 392 | continue; | 399 | continue; |
| 393 | maketasks_arg->moves[maketasks_arg->nmoves-1] = m; | 400 | |
| 394 | maketasks_arg->cube = move(backup_cube, m); | 401 | mtarg->moves[mtarg->nmoves-1] = m; |
| 395 | r = solve_h48_maketasks( | 402 | mtarg->cube = move(backup_cube, m); |
| 396 | solve_arg, maketasks_arg, tasks, ntasks); | 403 | r = solve_h48_maketasks(solve_arg, mtarg, tasks, ntasks); |
| 397 | if (r < 0) | 404 | if (r < 0) |
| 398 | return r; | 405 | return r; |
| 399 | 406 | ||
| 400 | /* Avoid symmetry-equivalent moves from the starting cube */ | 407 | /* Avoid symmetry-equivalent moves from the starting cube */ |
| 401 | if (maketasks_arg->nmoves == 1) | 408 | for (t = 0; t < NTRANS; t++) |
| 402 | for (t = 0; t < NTRANS; t++) | 409 | if (mtarg->tmask[mtarg->nmoves-1] & TM_SINGLE(t)) |
| 403 | if (solve_arg->solution_settings->tmask & | 410 | mm &= ~MM_SINGLE(transform_move(m, t)); |
| 404 | TM_SINGLE(t)) | ||
| 405 | mm &= ~MM_SINGLE(transform_move(m, t)); | ||
| 406 | } | 411 | } |
| 407 | maketasks_arg->nmoves--; | 412 | mtarg->nmoves--; |
| 408 | maketasks_arg->cube = backup_cube; | 413 | mtarg->cube = backup_cube; |
| 409 | 414 | ||
| 410 | return NISSY_OK; | 415 | return NISSY_OK; |
| 411 | } | 416 | } |
| @@ -441,7 +446,7 @@ solve_h48( | |||
| 441 | oriented_cube_t oc, | 446 | oriented_cube_t oc, |
| 442 | uint8_t minmoves, | 447 | uint8_t minmoves, |
| 443 | uint8_t maxmoves, | 448 | uint8_t maxmoves, |
| 444 | uint8_t maxsolutions, | 449 | uint64_t maxsolutions, |
| 445 | uint8_t optimal, | 450 | uint8_t optimal, |
| 446 | uint8_t threads, | 451 | uint8_t threads, |
| 447 | uint64_t data_size, | 452 | uint64_t data_size, |
| @@ -460,7 +465,7 @@ solve_h48( | |||
| 460 | int8_t d; | 465 | int8_t d; |
| 461 | dfsarg_solve_h48_t arg[THREADS]; | 466 | dfsarg_solve_h48_t arg[THREADS]; |
| 462 | solve_h48_task_t tasks[H48_STARTING_CUBES]; | 467 | solve_h48_task_t tasks[H48_STARTING_CUBES]; |
| 463 | dfsarg_solve_h48_maketasks_t maketasks_arg; | 468 | dfsarg_solve_h48_maketasks_t mtarg; |
| 464 | long double fallback_rate, lookups_per_node; | 469 | long double fallback_rate, lookups_per_node; |
| 465 | uint64_t offset; | 470 | uint64_t offset; |
| 466 | uint64_t nodes_visited, table_lookups, table_fallbacks; | 471 | uint64_t nodes_visited, table_lookups, table_fallbacks; |
| @@ -508,7 +513,6 @@ solve_h48( | |||
| 508 | fallback2 = h48data + offset; | 513 | fallback2 = h48data + offset; |
| 509 | 514 | ||
| 510 | settings = (solution_settings_t) { | 515 | settings = (solution_settings_t) { |
| 511 | .tmask = symmetry_mask(oc.cube), | ||
| 512 | .unniss = true, | 516 | .unniss = true, |
| 513 | .maxmoves = maxmoves, | 517 | .maxmoves = maxmoves, |
| 514 | .maxsolutions = maxsolutions, | 518 | .maxsolutions = maxsolutions, |
| @@ -543,14 +547,14 @@ solve_h48( | |||
| 543 | 547 | ||
| 544 | wrapthread_mutex_init(&solutions_mutex, NULL); | 548 | wrapthread_mutex_init(&solutions_mutex, NULL); |
| 545 | 549 | ||
| 546 | maketasks_arg = (dfsarg_solve_h48_maketasks_t) { | 550 | mtarg = (dfsarg_solve_h48_maketasks_t) { |
| 547 | .cube = oc.cube, | 551 | .cube = oc.cube, |
| 548 | .nmoves = 0, | 552 | .nmoves = 0, |
| 549 | .minmoves = minmoves, | 553 | .minmoves = minmoves, |
| 550 | .maxmoves = maxmoves, | 554 | .maxmoves = maxmoves, |
| 551 | }; | 555 | }; |
| 552 | ntasks = 0; | 556 | ntasks = 0; |
| 553 | solve_h48_maketasks(&arg[0], &maketasks_arg, tasks, &ntasks); | 557 | solve_h48_maketasks(&arg[0], &mtarg, tasks, &ntasks); |
| 554 | if (ntasks < 0) | 558 | if (ntasks < 0) |
| 555 | goto solve_h48_error_solutions_buffer; | 559 | goto solve_h48_error_solutions_buffer; |
| 556 | if (solutions_done(&sollist, &settings, | 560 | if (solutions_done(&sollist, &settings, |
diff --git a/src/solvers/solutions.h b/src/solvers/solutions.h index 9f209d1..d92d5ad 100644 --- a/src/solvers/solutions.h +++ b/src/solvers/solutions.h | |||
| @@ -1,17 +1,23 @@ | |||
| 1 | STATIC void solution_moves_reset(solution_moves_t [static 1]); | 1 | STATIC void solution_moves_reset(solution_moves_t [static 1]); |
| 2 | STATIC void solution_moves_transform(solution_moves_t [static 1], uint8_t); | 2 | STATIC void solution_moves_transform(solution_moves_t [static 1], size_t, |
| 3 | uint8_t); | ||
| 3 | STATIC void solution_moves_reorient(solution_moves_t [static 1], uint8_t); | 4 | STATIC void solution_moves_reorient(solution_moves_t [static 1], uint8_t); |
| 4 | STATIC bool solution_list_init(solution_list_t [static 1], size_t, char *); | 5 | STATIC bool solution_list_init(solution_list_t [static 1], size_t, char *); |
| 5 | STATIC bool solution_moves_equal( | 6 | STATIC bool solution_moves_equal( |
| 6 | const solution_moves_t [static 1], const solution_moves_t [static 1]); | 7 | const solution_moves_t [static 1], const solution_moves_t [static 1]); |
| 7 | STATIC bool solution_moves_is_duplicate(size_t, const solution_moves_t *); | 8 | STATIC bool last_solution_is_duplicate(const solution_list_t [static 1]); |
| 8 | STATIC bool appendchar(solution_list_t [static 1], char); | 9 | STATIC bool appendchar(solution_list_t [static 1], char); |
| 9 | STATIC bool appendnormal( | 10 | STATIC bool appendnormal( |
| 10 | const solution_moves_t [static 1], solution_list_t [static 1]); | 11 | const solution_moves_t [static 1], solution_list_t [static 1]); |
| 11 | STATIC bool appendinverse( | 12 | STATIC bool appendinverse( |
| 12 | const solution_moves_t [static 1], solution_list_t [static 1]); | 13 | const solution_moves_t [static 1], solution_list_t [static 1]); |
| 14 | STATIC void appendsolution_dfs(const solution_moves_t [static 1], size_t, | ||
| 15 | const uint64_t *, size_t, uint8_t *, const solution_settings_t [static 1], | ||
| 16 | solution_list_t [static 1], | ||
| 17 | solution_moves_t [static NTRANS * SOLUTION_MAXLEN], int64_t [static 1]); | ||
| 13 | STATIC int64_t appendsolution(const solution_moves_t [static 1], | 18 | STATIC int64_t appendsolution(const solution_moves_t [static 1], |
| 14 | const solution_settings_t [static 1], solution_list_t [static 1]); | 19 | size_t, const uint64_t *, const solution_settings_t [static 1], |
| 20 | solution_list_t [static 1]); | ||
| 15 | STATIC bool solutions_done(const solution_list_t [static 1], | 21 | STATIC bool solutions_done(const solution_list_t [static 1], |
| 16 | const solution_settings_t [static 1], int8_t depth); | 22 | const solution_settings_t [static 1], int8_t depth); |
| 17 | 23 | ||
| @@ -23,11 +29,11 @@ solution_moves_reset(solution_moves_t sol[static 1]) | |||
| 23 | } | 29 | } |
| 24 | 30 | ||
| 25 | STATIC void | 31 | STATIC void |
| 26 | solution_moves_transform(solution_moves_t moves[static 1], uint8_t t) | 32 | solution_moves_transform(solution_moves_t moves[static 1], size_t z, uint8_t t) |
| 27 | { | 33 | { |
| 28 | uint8_t i; | 34 | uint8_t i; |
| 29 | 35 | ||
| 30 | for (i = 0; i < moves->nmoves; i++) | 36 | for (i = z; i < moves->nmoves; i++) |
| 31 | moves->moves[i] = transform_move(moves->moves[i], t); | 37 | moves->moves[i] = transform_move(moves->moves[i], t); |
| 32 | 38 | ||
| 33 | for (i = 0; i < moves->npremoves; i++) | 39 | for (i = 0; i < moves->npremoves; i++) |
| @@ -87,13 +93,27 @@ solution_moves_equal( | |||
| 87 | } | 93 | } |
| 88 | 94 | ||
| 89 | STATIC bool | 95 | STATIC bool |
| 90 | solution_moves_is_duplicate(size_t n, const solution_moves_t *s) | 96 | last_solution_is_duplicate(const solution_list_t l[static 1]) |
| 91 | { | 97 | { |
| 92 | size_t i; | 98 | size_t i, j; |
| 99 | |||
| 100 | if (l->nsols == 1) | ||
| 101 | return false; | ||
| 93 | 102 | ||
| 94 | for (i = 0; i < n; i++) | 103 | /* We assume the list is newline-terminated */ |
| 95 | if (solution_moves_equal(&s[i], &s[n])) | 104 | j = l->used-2; |
| 96 | return true; | 105 | while (true) { |
| 106 | for ( ; l->buf[j] != '\n'; j--) | ||
| 107 | if (j == 0) return false; | ||
| 108 | j--; | ||
| 109 | for (i = l->used-2; l->buf[i] == l->buf[j]; i--, j--) { | ||
| 110 | if (l->buf[i-1] == '\n') { | ||
| 111 | if (l->buf[j-1] == '\n' || j == 0) | ||
| 112 | return true; | ||
| 113 | else break; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | } | ||
| 97 | 117 | ||
| 98 | return false; | 118 | return false; |
| 99 | } | 119 | } |
| @@ -150,97 +170,157 @@ appendinverse( | |||
| 150 | return appendchar(list, ')'); | 170 | return appendchar(list, ')'); |
| 151 | } | 171 | } |
| 152 | 172 | ||
| 153 | STATIC int64_t | 173 | STATIC void |
| 154 | appendsolution( | 174 | appendsolution_dfs( |
| 155 | const solution_moves_t moves[static 1], | 175 | const solution_moves_t moves[static 1], |
| 176 | size_t ntmask, | ||
| 177 | const uint64_t *tmask, | ||
| 178 | size_t itm, | ||
| 179 | uint8_t *tt, | ||
| 156 | const solution_settings_t settings[static 1], | 180 | const solution_settings_t settings[static 1], |
| 157 | solution_list_t list[static 1] | 181 | solution_list_t list[static 1], |
| 182 | solution_moves_t tsol[static NTRANS * SOLUTION_MAXLEN], | ||
| 183 | int64_t r[static 1] | ||
| 158 | ) | 184 | ) |
| 159 | { | 185 | { |
| 160 | int64_t r; | 186 | /* |
| 161 | int i; | 187 | The logic here is quit complex because we have to address H48 |
| 162 | uint8_t t; | 188 | solutions that may be reduced by symmetry in the first few moves. |
| 163 | solution_moves_t tsol[NTRANS]; | 189 | */ |
| 164 | 190 | ||
| 165 | if (moves->nmoves + moves->npremoves > SOLUTION_MAXLEN) | 191 | size_t i, last_start; |
| 166 | goto appendsolution_error_solution_length; | 192 | uint8_t t; |
| 193 | solution_moves_t moves_copy; | ||
| 167 | 194 | ||
| 168 | for ( | 195 | if (list->nsols >= settings->maxsolutions) |
| 169 | t = 0, r = 0; | 196 | return; |
| 170 | t < NTRANS && list->nsols < settings->maxsolutions; | ||
| 171 | t++ | ||
| 172 | ) { | ||
| 173 | if (!(settings->tmask & TM_SINGLE(t))) | ||
| 174 | continue; | ||
| 175 | 197 | ||
| 176 | tsol[r] = *moves; | 198 | if (ntmask == itm) { |
| 177 | if (settings->unniss) { | 199 | tsol[*r] = *moves; |
| 178 | tsol[r].nmoves += moves->npremoves; | ||
| 179 | tsol[r].npremoves = 0; | ||
| 180 | for (i = moves->npremoves-1; i >= 0; i--) | ||
| 181 | tsol[r].moves[tsol[r].nmoves - i - 1] = | ||
| 182 | inverse_move(moves->premoves[i]); | ||
| 183 | 200 | ||
| 184 | /* | 201 | for (i = ntmask; i > 0; i--) |
| 185 | This is a bit ugly: we have to sort now and then again | 202 | solution_moves_transform(&tsol[*r], i-1, tt[i-1]); |
| 186 | later, because the allowedmoves check would fail with | ||
| 187 | improperly sorted parallel moves, but then transforming | ||
| 188 | could swap the pairs the wrong way around. | ||
| 189 | */ | ||
| 190 | sortparallel_moves(tsol[r].nmoves, tsol[r].moves); | ||
| 191 | 203 | ||
| 192 | /* Check if unnissed premoves cancel with normal. */ | 204 | solution_moves_reorient(&tsol[*r], settings->orientation); |
| 193 | if (!allowedmoves(tsol[r].nmoves, tsol[r].moves)) | 205 | sortparallel_moves(tsol[*r].nmoves, tsol[*r].moves); |
| 194 | continue; | 206 | sortparallel_moves(tsol[*r].npremoves, tsol[*r].premoves); |
| 195 | } | ||
| 196 | solution_moves_transform(&tsol[r], t); | ||
| 197 | solution_moves_reorient(&tsol[r], settings->orientation); | ||
| 198 | sortparallel_moves(tsol[r].nmoves, tsol[r].moves); | ||
| 199 | sortparallel_moves(tsol[r].npremoves, tsol[r].premoves); | ||
| 200 | 207 | ||
| 201 | /* Skip duplicates that may appear after transforming */ | 208 | last_start = list->used; |
| 202 | if (solution_moves_is_duplicate(r, tsol)) | ||
| 203 | continue; | ||
| 204 | 209 | ||
| 205 | /* Append first the moves on the side that has more */ | 210 | /* Append first the moves on the side that has more */ |
| 206 | /* E.g. write (U L F) B instead of B (U L F) */ | 211 | /* E.g. write (U L F) B instead of B (U L F) */ |
| 207 | if (tsol[r].nmoves >= tsol[r].npremoves) { | 212 | if (tsol[*r].nmoves >= tsol[*r].npremoves) { |
| 208 | if (!appendnormal(&tsol[r], list)) | 213 | if (!appendnormal(&tsol[*r], list)) |
| 209 | goto appendsolution_error_buffer; | 214 | goto appendsolution_dfs_error_buffer; |
| 210 | 215 | ||
| 211 | if (tsol[r].nmoves > 0 && tsol[r].npremoves > 0) | 216 | if (tsol[*r].nmoves > 0 && tsol[*r].npremoves > 0) |
| 212 | if (!appendchar(list, ' ')) | 217 | if (!appendchar(list, ' ')) |
| 213 | return false; | 218 | goto appendsolution_dfs_error_buffer; |
| 214 | 219 | ||
| 215 | if (!appendinverse(&tsol[r], list)) | 220 | if (!appendinverse(&tsol[*r], list)) |
| 216 | goto appendsolution_error_buffer; | 221 | goto appendsolution_dfs_error_buffer; |
| 217 | } else { | 222 | } else { |
| 218 | if (!appendinverse(&tsol[r], list)) | 223 | if (!appendinverse(&tsol[*r], list)) |
| 219 | goto appendsolution_error_buffer; | 224 | goto appendsolution_dfs_error_buffer; |
| 220 | 225 | ||
| 221 | if (tsol[r].nmoves > 0 && tsol[r].npremoves > 0) | 226 | if (tsol[*r].nmoves > 0 && tsol[*r].npremoves > 0) |
| 222 | if (!appendchar(list, ' ')) | 227 | if (!appendchar(list, ' ')) |
| 223 | return false; | 228 | goto appendsolution_dfs_error_buffer; |
| 224 | 229 | ||
| 225 | if (!appendnormal(&tsol[r], list)) | 230 | if (!appendnormal(&tsol[*r], list)) |
| 226 | goto appendsolution_error_buffer; | 231 | goto appendsolution_dfs_error_buffer; |
| 227 | } | 232 | } |
| 228 | 233 | ||
| 229 | if (!appendchar(list, '\n')) | 234 | if (!appendchar(list, '\n')) |
| 230 | goto appendsolution_error_buffer; | 235 | goto appendsolution_dfs_error_buffer; |
| 231 | |||
| 232 | ++list->nsols; | 236 | ++list->nsols; |
| 237 | |||
| 238 | /* | ||
| 239 | Normaly, it would be enough to check for duplicates in the | ||
| 240 | current "pack" of transformation-equivalent solutions. | ||
| 241 | However, in rare cases, the H48 solver may produce equivalent | ||
| 242 | "packs" of solutions. It would be more elegant to filter out | ||
| 243 | the corresponding tasks in solve_h48_maketasks(), but doing so | ||
| 244 | is not trivial. In the end, duplicate solutions are never | ||
| 245 | desirable, so we might as well do this clean up here. | ||
| 246 | */ | ||
| 247 | if (last_solution_is_duplicate(list)) { | ||
| 248 | --list->nsols; | ||
| 249 | list->used = last_start; | ||
| 250 | return; | ||
| 251 | } | ||
| 252 | |||
| 233 | list->shortest_sol = MIN( | 253 | list->shortest_sol = MIN( |
| 234 | list->shortest_sol, tsol[r].nmoves + tsol[r].npremoves); | 254 | list->shortest_sol, tsol[*r].nmoves + tsol[*r].npremoves); |
| 235 | r++; | 255 | (*r)++; |
| 256 | } else { | ||
| 257 | for (t = 0; t < NTRANS; t++) { | ||
| 258 | if (!(tmask[itm] & TM_SINGLE(t))) | ||
| 259 | continue; | ||
| 260 | moves_copy = *moves; | ||
| 261 | tt[itm] = t; | ||
| 262 | appendsolution_dfs(&moves_copy, ntmask, tmask, | ||
| 263 | itm+1, tt, settings, list, tsol, r); | ||
| 264 | if (*r < 0) | ||
| 265 | return; | ||
| 266 | } | ||
| 236 | } | 267 | } |
| 237 | 268 | ||
| 238 | list->buf[list->used] = '\0'; | 269 | return; |
| 239 | return r; | ||
| 240 | 270 | ||
| 241 | appendsolution_error_buffer: | 271 | appendsolution_dfs_error_buffer: |
| 242 | list->buf[0] = '\0'; | 272 | list->buf[0] = '\0'; |
| 243 | return NISSY_ERROR_BUFFER_SIZE; | 273 | *r = NISSY_ERROR_BUFFER_SIZE; |
| 274 | return; | ||
| 275 | } | ||
| 276 | |||
| 277 | STATIC int64_t | ||
| 278 | appendsolution( | ||
| 279 | const solution_moves_t moves[static 1], | ||
| 280 | size_t ntmask, | ||
| 281 | const uint64_t *tmask, | ||
| 282 | const solution_settings_t settings[static 1], | ||
| 283 | solution_list_t list[static 1] | ||
| 284 | ) | ||
| 285 | { | ||
| 286 | int64_t r; | ||
| 287 | int i; | ||
| 288 | uint8_t tt[SOLUTION_MAXLEN]; | ||
| 289 | solution_moves_t moves_copy, tsol[NTRANS * SOLUTION_MAXLEN]; | ||
| 290 | |||
| 291 | if (moves->nmoves + moves->npremoves > SOLUTION_MAXLEN) | ||
| 292 | goto appendsolution_error_solution_length; | ||
| 293 | |||
| 294 | moves_copy = *moves; | ||
| 295 | if (settings->unniss) { | ||
| 296 | moves_copy.nmoves += moves->npremoves; | ||
| 297 | moves_copy.npremoves = 0; | ||
| 298 | for (i = moves->npremoves-1; i >= 0; i--) | ||
| 299 | moves_copy.moves[moves_copy.nmoves - i - 1] = | ||
| 300 | inverse_move(moves->premoves[i]); | ||
| 301 | |||
| 302 | /* | ||
| 303 | This is a bit ugly: we have to sort now and then again | ||
| 304 | later, because the allowedmoves check would fail with | ||
| 305 | improperly sorted parallel moves, but then transforming | ||
| 306 | could swap the pairs the wrong way around. | ||
| 307 | */ | ||
| 308 | sortparallel_moves(moves_copy.nmoves, moves_copy.moves); | ||
| 309 | |||
| 310 | /* Check if unnissed premoves cancel with normal. */ | ||
| 311 | if (!allowedmoves(moves_copy.nmoves, moves_copy.moves)) | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | r = 0; | ||
| 316 | memset(tt, TRANS_UFr, SOLUTION_MAXLEN); | ||
| 317 | appendsolution_dfs( | ||
| 318 | &moves_copy, ntmask, tmask, 0, tt, settings, list, tsol, &r); | ||
| 319 | if (r < 0) | ||
| 320 | return r; | ||
| 321 | |||
| 322 | list->buf[list->used] = '\0'; | ||
| 323 | return r; | ||
| 244 | 324 | ||
| 245 | appendsolution_error_solution_length: | 325 | appendsolution_error_solution_length: |
| 246 | list->buf[0] = '\0'; | 326 | list->buf[0] = '\0'; |
diff --git a/src/solvers/solutions_types_macros.h b/src/solvers/solutions_types_macros.h index c8efc0b..4727e5a 100644 --- a/src/solvers/solutions_types_macros.h +++ b/src/solvers/solutions_types_macros.h | |||
| @@ -8,7 +8,6 @@ typedef struct { | |||
| 8 | } solution_moves_t; | 8 | } solution_moves_t; |
| 9 | 9 | ||
| 10 | typedef struct { | 10 | typedef struct { |
| 11 | uint64_t tmask; | ||
| 12 | bool unniss; | 11 | bool unniss; |
| 13 | uint8_t maxmoves; | 12 | uint8_t maxmoves; |
| 14 | uint64_t maxsolutions; | 13 | uint64_t maxsolutions; |
diff --git a/test/140_appendsolution/00_empty.in b/test/140_appendsolution/00_empty.in index 1100b95..00546ef 100644 --- a/test/140_appendsolution/00_empty.in +++ b/test/140_appendsolution/00_empty.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | 1 | ||
| 2 | 0 | 2 | 0 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/01_simple_onlynormal_nounniss.in b/test/140_appendsolution/01_simple_onlynormal_nounniss.in index fb1eaed..84d16c0 100644 --- a/test/140_appendsolution/01_simple_onlynormal_nounniss.in +++ b/test/140_appendsolution/01_simple_onlynormal_nounniss.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | U F R D2 B' | 1 | U F R D2 B' |
| 2 | 0 | 2 | 0 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/02_simple_onlynormal_nounnis_multitrans.in b/test/140_appendsolution/02_simple_onlynormal_nounnis_multitrans.in index db5f074..15ff39e 100644 --- a/test/140_appendsolution/02_simple_onlynormal_nounnis_multitrans.in +++ b/test/140_appendsolution/02_simple_onlynormal_nounnis_multitrans.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | U F R | 1 | U F R |
| 2 | 0 | 2 | 0 |
| 3 | 1 | ||
| 3 | 4 | 4 | 4 |
| 4 | rotation UF | 5 | rotation UF |
| 5 | mirrored UR | 6 | mirrored UR |
diff --git a/test/140_appendsolution/03_simple_unniss.in b/test/140_appendsolution/03_simple_unniss.in index 2c5a331..ac6fe72 100644 --- a/test/140_appendsolution/03_simple_unniss.in +++ b/test/140_appendsolution/03_simple_unniss.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | U F B2 (R' F D) | 1 | U F B2 (R' F D) |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/04_niss_nounniss.in b/test/140_appendsolution/04_niss_nounniss.in index b07f970..cae1328 100644 --- a/test/140_appendsolution/04_niss_nounniss.in +++ b/test/140_appendsolution/04_niss_nounniss.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | U F B2 (R' F D) | 1 | U F B2 (R' F D) |
| 2 | 0 | 2 | 0 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/05_sort_parallel.in b/test/140_appendsolution/05_sort_parallel.in index bc1cf0f..85351b5 100644 --- a/test/140_appendsolution/05_sort_parallel.in +++ b/test/140_appendsolution/05_sort_parallel.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | L R' B2 F | 1 | L R' B2 F |
| 2 | 0 | 2 | 0 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/06_unniss_trans_sort.in b/test/140_appendsolution/06_unniss_trans_sort.in index 2ffab93..e6b7897 100644 --- a/test/140_appendsolution/06_unniss_trans_sort.in +++ b/test/140_appendsolution/06_unniss_trans_sort.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | B (R2 F2) | 1 | B (R2 F2) |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UR | 5 | rotation UR |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/07_unniss_cancel_nosol.in b/test/140_appendsolution/07_unniss_cancel_nosol.in index 6883d05..4faed6b 100644 --- a/test/140_appendsolution/07_unniss_cancel_nosol.in +++ b/test/140_appendsolution/07_unniss_cancel_nosol.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | B' F (R2 B2) | 1 | B' F (R2 B2) |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/08_unniss_cancel_nosol_v2.in b/test/140_appendsolution/08_unniss_cancel_nosol_v2.in index 3d461f0..741687a 100644 --- a/test/140_appendsolution/08_unniss_cancel_nosol_v2.in +++ b/test/140_appendsolution/08_unniss_cancel_nosol_v2.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | F' B (R2 F2) | 1 | F' B (R2 F2) |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/09_fullinverse_niss.in b/test/140_appendsolution/09_fullinverse_niss.in index bb2b640..e2e5f7b 100644 --- a/test/140_appendsolution/09_fullinverse_niss.in +++ b/test/140_appendsolution/09_fullinverse_niss.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | (F) | 1 | (F) |
| 2 | 0 | 2 | 0 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 0 | 6 | 0 |
diff --git a/test/140_appendsolution/10_rotated.in b/test/140_appendsolution/10_rotated.in index 5210cd5..947696f 100644 --- a/test/140_appendsolution/10_rotated.in +++ b/test/140_appendsolution/10_rotated.in | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | U2 F B L' | 1 | U2 F B L' |
| 2 | 1 | 2 | 1 |
| 3 | 1 | 3 | 1 |
| 4 | 1 | ||
| 4 | rotation UF | 5 | rotation UF |
| 5 | 7 | 6 | 7 |
diff --git a/test/140_appendsolution/11_multisym.in b/test/140_appendsolution/11_multisym.in new file mode 100644 index 0000000..947127f --- /dev/null +++ b/test/140_appendsolution/11_multisym.in | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | L U F | ||
| 2 | 0 | ||
| 3 | 2 | ||
| 4 | 2 | ||
| 5 | rotation UF | ||
| 6 | rotation UB | ||
| 7 | 2 | ||
| 8 | rotation UF | ||
| 9 | rotation DR | ||
| 10 | 0 | ||
diff --git a/test/140_appendsolution/11_multisym.out b/test/140_appendsolution/11_multisym.out new file mode 100644 index 0000000..9f1a312 --- /dev/null +++ b/test/140_appendsolution/11_multisym.out | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | L U F | ||
| 2 | L D R | ||
| 3 | R U B | ||
| 4 | R D L | ||
| 5 | Number of solutions: 4 | ||
| 6 | Shortest solution length: 3 | ||
| 7 | Used bytes: 24 | ||
diff --git a/test/140_appendsolution/appendsolution_tests.c b/test/140_appendsolution/appendsolution_tests.c index d4c2a1f..f9620ab 100644 --- a/test/140_appendsolution/appendsolution_tests.c +++ b/test/140_appendsolution/appendsolution_tests.c | |||
| @@ -3,8 +3,10 @@ Input format for appendsolution tests: | |||
| 3 | 3 | ||
| 4 | moves on normal (with NISS notation) | 4 | moves on normal (with NISS notation) |
| 5 | unniss flag (0=false, 1=true) | 5 | unniss flag (0=false, 1=true) |
| 6 | number of transformations | 6 | n = maximum number of moves for transformations + 1 (at most 20) |
| 7 | transformations, one per line | 7 | n times the following: |
| 8 | number of transformations | ||
| 9 | transformations, one per line | ||
| 8 | the orientation of the cube, as a number from 0 to 23 | 10 | the orientation of the cube, as a number from 0 to 23 |
| 9 | 11 | ||
| 10 | See below for the output format. | 12 | See below for the output format. |
| @@ -18,11 +20,13 @@ int64_t readmoves(const char *, size_t n, size_t m, | |||
| 18 | void solution_moves_reset(solution_moves_t [static 1]); | 20 | void solution_moves_reset(solution_moves_t [static 1]); |
| 19 | bool solution_list_init(solution_list_t [static 1], size_t n, char [n]); | 21 | bool solution_list_init(solution_list_t [static 1], size_t n, char [n]); |
| 20 | int64_t appendsolution(const solution_moves_t [static 1], | 22 | int64_t appendsolution(const solution_moves_t [static 1], |
| 21 | const solution_settings_t [static 1], solution_list_t [static 1]); | 23 | size_t, const uint64_t *, const solution_settings_t [static 1], |
| 24 | solution_list_t [static 1]); | ||
| 22 | 25 | ||
| 23 | void run(void) { | 26 | void run(void) { |
| 24 | int i, ntrans; | 27 | int i, j, nnt, ntrans; |
| 25 | int64_t tot; | 28 | int64_t tot; |
| 29 | uint64_t tmask[20]; | ||
| 26 | size_t nm, np; | 30 | size_t nm, np; |
| 27 | char str[STRLENMAX], buf[STRLENMAX]; | 31 | char str[STRLENMAX], buf[STRLENMAX]; |
| 28 | solution_moves_t moves; | 32 | solution_moves_t moves; |
| @@ -32,7 +36,6 @@ void run(void) { | |||
| 32 | solution_moves_reset(&moves); | 36 | solution_moves_reset(&moves); |
| 33 | solution_list_init(&list, STRLENMAX, buf); | 37 | solution_list_init(&list, STRLENMAX, buf); |
| 34 | settings = (solution_settings_t) { | 38 | settings = (solution_settings_t) { |
| 35 | .tmask = UINT64_C(0), | ||
| 36 | .unniss = false, | 39 | .unniss = false, |
| 37 | .maxmoves = 20, | 40 | .maxmoves = 20, |
| 38 | .maxsolutions = 100, | 41 | .maxsolutions = 100, |
| @@ -49,16 +52,21 @@ void run(void) { | |||
| 49 | moves.npremoves = np; | 52 | moves.npremoves = np; |
| 50 | fgets(str, STRLENMAX, stdin); | 53 | fgets(str, STRLENMAX, stdin); |
| 51 | settings.unniss = (bool)atoi(str); | 54 | settings.unniss = (bool)atoi(str); |
| 55 | |||
| 52 | fgets(str, STRLENMAX, stdin); | 56 | fgets(str, STRLENMAX, stdin); |
| 53 | ntrans = atoi(str); | 57 | nnt = atoi(str); |
| 54 | for (i = 0; i < ntrans; i++) { | 58 | for (j = 0; j < nnt; j++) { |
| 55 | fgets(str, STRLENMAX, stdin); | 59 | fgets(str, STRLENMAX, stdin); |
| 56 | settings.tmask |= UINT64_C(1) << (uint64_t)readtrans(str); | 60 | ntrans = atoi(str); |
| 61 | for (i = 0; i < ntrans; i++) { | ||
| 62 | fgets(str, STRLENMAX, stdin); | ||
| 63 | tmask[j] |= UINT64_C(1) << (uint64_t)readtrans(str); | ||
| 64 | } | ||
| 57 | } | 65 | } |
| 58 | fgets(str, STRLENMAX, stdin); | 66 | fgets(str, STRLENMAX, stdin); |
| 59 | settings.orientation = atoi(str); | 67 | settings.orientation = atoi(str); |
| 60 | 68 | ||
| 61 | appendsolution(&moves, &settings, &list); | 69 | appendsolution(&moves, nnt, tmask, &settings, &list); |
| 62 | 70 | ||
| 63 | printf("%s", list.buf); | 71 | printf("%s", list.buf); |
| 64 | printf("Number of solutions: %" PRIu64 "\n", list.nsols); | 72 | printf("Number of solutions: %" PRIu64 "\n", list.nsols); |
diff --git a/tools/301_solve_file/solve_file.c b/tools/301_solve_file/solve_file.c index a8f0925..ef9bf2c 100644 --- a/tools/301_solve_file/solve_file.c +++ b/tools/301_solve_file/solve_file.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | #include "../tool.h" | 1 | #include "../tool.h" |
| 2 | 2 | ||
| 3 | #define SOL_BUFFER_LEN 100000 | 3 | #define SOL_BUFFER_LEN 1000000 |
| 4 | #define MAX_SCR 10000 | 4 | #define MAX_SCR 10000 |
| 5 | #define MAX_SCR_LEN 250 | 5 | #define MAX_SCR_LEN 250 |
| 6 | 6 | ||
diff --git a/tools/420_solvetest_h48_symmetric/scrambles.h b/tools/420_solvetest_h48_symmetric/scrambles.h new file mode 100644 index 0000000..33f1643 --- /dev/null +++ b/tools/420_solvetest_h48_symmetric/scrambles.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | struct { | ||
| 2 | char *scramble; | ||
| 3 | char *solutions; | ||
| 4 | } s[] = { | ||
| 5 | [0] = { | ||
| 6 | .scramble = "M2 E2 S2", | ||
| 7 | .solutions = | ||
| 8 | "U2 D2 F2 B2 R2 L2\n" | ||
| 9 | "U2 D2 R2 L2 F2 B2\n" | ||
| 10 | "R2 L2 U2 D2 F2 B2\n" | ||
| 11 | "R2 L2 F2 B2 U2 D2\n" | ||
| 12 | "F2 B2 U2 D2 R2 L2\n" | ||
| 13 | "F2 B2 R2 L2 U2 D2\n" | ||
| 14 | }, | ||
| 15 | { | ||
| 16 | .scramble = "", /* End-of-list signal */ | ||
| 17 | } | ||
| 18 | }; | ||
diff --git a/tools/420_solvetest_h48_symmetric/solvetest.c b/tools/420_solvetest_h48_symmetric/solvetest.c new file mode 100644 index 0000000..245b7fe --- /dev/null +++ b/tools/420_solvetest_h48_symmetric/solvetest.c | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #define SOLVER "h48h3k2" | ||
| 2 | #define NISSFLAG NISSY_NISSFLAG_NORMAL | ||
| 3 | #define MINMOVES 0 | ||
| 4 | #define MAXMOVES 20 | ||
| 5 | #define MAXSOLUTIONS 500 | ||
| 6 | #define OPTIMAL 0 | ||
| 7 | |||
| 8 | #include "scrambles.h" | ||
| 9 | #include "../solvetest.h" | ||
