aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2025-11-23 16:16:31 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2025-11-24 16:32:11 +0100
commit147b0c3c4615c32478a4923242909b8ae5a30d03 (patch)
tree5294d9b3655031535085a5163c2c5b5cbe7413b1
parent78ec0d22d927bc4287aa090469d5ba5f84e8780b (diff)
downloadnissy-core-147b0c3c4615c32478a4923242909b8ae5a30d03.tar.gz
nissy-core-147b0c3c4615c32478a4923242909b8ae5a30d03.zip
Fix duplicate solutions, overflow in maxsols and improve symmetry reduction for H48.
This commit fixes two bugs: - A bug that caused duplicates solutions for symmetric scrambles. - An overflow in the maxsols parameter for the H48 solver, which caused it to find much fewer solutions than existed. Moreover, the H48 solvers has been improved by reducing by symmetry not only from the starting position, but also up to the first 4 moves.
-rw-r--r--.gitignore1
-rw-r--r--benchmarks/benchmarks.md64
-rw-r--r--src/solvers/coord/multisolve.h9
-rw-r--r--src/solvers/coord/solve.h9
-rw-r--r--src/solvers/h48/solve.h78
-rw-r--r--src/solvers/solutions.h224
-rw-r--r--src/solvers/solutions_types_macros.h1
-rw-r--r--test/140_appendsolution/00_empty.in1
-rw-r--r--test/140_appendsolution/01_simple_onlynormal_nounniss.in1
-rw-r--r--test/140_appendsolution/02_simple_onlynormal_nounnis_multitrans.in1
-rw-r--r--test/140_appendsolution/03_simple_unniss.in1
-rw-r--r--test/140_appendsolution/04_niss_nounniss.in1
-rw-r--r--test/140_appendsolution/05_sort_parallel.in1
-rw-r--r--test/140_appendsolution/06_unniss_trans_sort.in1
-rw-r--r--test/140_appendsolution/07_unniss_cancel_nosol.in1
-rw-r--r--test/140_appendsolution/08_unniss_cancel_nosol_v2.in1
-rw-r--r--test/140_appendsolution/09_fullinverse_niss.in1
-rw-r--r--test/140_appendsolution/10_rotated.in1
-rw-r--r--test/140_appendsolution/11_multisym.in10
-rw-r--r--test/140_appendsolution/11_multisym.out7
-rw-r--r--test/140_appendsolution/appendsolution_tests.c26
-rw-r--r--tools/301_solve_file/solve_file.c2
-rw-r--r--tools/420_solvetest_h48_symmetric/scrambles.h18
-rw-r--r--tools/420_solvetest_h48_symmetric/solvetest.c9
24 files changed, 309 insertions, 160 deletions
diff --git a/.gitignore b/.gitignore
index de7c8b6..3918e43 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,3 +46,4 @@ tools/results
46python/*.pyd 46python/*.pyd
47python/*.exp 47python/*.exp
48python/*.lib 48python/*.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
197Time per cube (in seconds, lower is better). 197Time 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
208Time per cube adjusted for tables size (in seconds \* GiB, lower is better). 208Time 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
93solve_multicoord_dfs_notsolved: 94solve_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
18typedef struct { 19typedef 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
60STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned, 63STATIC long long solve_h48_dispatch(oriented_cube_t, const char *, unsigned,
@@ -69,7 +72,7 @@ STATIC void *solve_h48_runthread(void *);
69STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); 72STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]);
70STATIC void solve_h48_log_solutions(solution_list_t [static 1], size_t); 73STATIC void solve_h48_log_solutions(solution_list_t [static 1], size_t);
71STATIC int solve_h48_compare_tasks(const void *, const void *); 74STATIC int solve_h48_compare_tasks(const void *, const void *);
72STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t, 75STATIC 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:
341STATIC int64_t 345STATIC int64_t
342solve_h48_maketasks( 346solve_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 @@
1STATIC void solution_moves_reset(solution_moves_t [static 1]); 1STATIC void solution_moves_reset(solution_moves_t [static 1]);
2STATIC void solution_moves_transform(solution_moves_t [static 1], uint8_t); 2STATIC void solution_moves_transform(solution_moves_t [static 1], size_t,
3 uint8_t);
3STATIC void solution_moves_reorient(solution_moves_t [static 1], uint8_t); 4STATIC void solution_moves_reorient(solution_moves_t [static 1], uint8_t);
4STATIC bool solution_list_init(solution_list_t [static 1], size_t, char *); 5STATIC bool solution_list_init(solution_list_t [static 1], size_t, char *);
5STATIC bool solution_moves_equal( 6STATIC 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]);
7STATIC bool solution_moves_is_duplicate(size_t, const solution_moves_t *); 8STATIC bool last_solution_is_duplicate(const solution_list_t [static 1]);
8STATIC bool appendchar(solution_list_t [static 1], char); 9STATIC bool appendchar(solution_list_t [static 1], char);
9STATIC bool appendnormal( 10STATIC 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]);
11STATIC bool appendinverse( 12STATIC 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]);
14STATIC 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]);
13STATIC int64_t appendsolution(const solution_moves_t [static 1], 18STATIC 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]);
15STATIC bool solutions_done(const solution_list_t [static 1], 21STATIC 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
25STATIC void 31STATIC void
26solution_moves_transform(solution_moves_t moves[static 1], uint8_t t) 32solution_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
89STATIC bool 95STATIC bool
90solution_moves_is_duplicate(size_t n, const solution_moves_t *s) 96last_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
153STATIC int64_t 173STATIC void
154appendsolution( 174appendsolution_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
241appendsolution_error_buffer: 271appendsolution_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
277STATIC int64_t
278appendsolution(
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
245appendsolution_error_solution_length: 325appendsolution_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
10typedef struct { 10typedef 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
20 20
31 31
41
4rotation UF 5rotation UF
50 60
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 @@
1U F R D2 B' 1U F R D2 B'
20 20
31 31
41
4rotation UF 5rotation UF
50 60
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 @@
1U F R 1U F R
20 20
31
34 44
4rotation UF 5rotation UF
5mirrored UR 6mirrored 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 @@
1U F B2 (R' F D) 1U F B2 (R' F D)
21 21
31 31
41
4rotation UF 5rotation UF
50 60
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 @@
1U F B2 (R' F D) 1U F B2 (R' F D)
20 20
31 31
41
4rotation UF 5rotation UF
50 60
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 @@
1L R' B2 F 1L R' B2 F
20 20
31 31
41
4rotation UF 5rotation UF
50 60
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 @@
1B (R2 F2) 1B (R2 F2)
21 21
31 31
41
4rotation UR 5rotation UR
50 60
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 @@
1B' F (R2 B2) 1B' F (R2 B2)
21 21
31 31
41
4rotation UF 5rotation UF
50 60
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 @@
1F' B (R2 F2) 1F' B (R2 F2)
21 21
31 31
41
4rotation UF 5rotation UF
50 60
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)
20 20
31 31
41
4rotation UF 5rotation UF
50 60
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 @@
1U2 F B L' 1U2 F B L'
21 21
31 31
41
4rotation UF 5rotation UF
57 67
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 @@
1L U F
20
32
42
5rotation UF
6rotation UB
72
8rotation UF
9rotation DR
100
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 @@
1L U F
2L D R
3R U B
4R D L
5Number of solutions: 4
6Shortest solution length: 3
7Used 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
4moves on normal (with NISS notation) 4moves on normal (with NISS notation)
5unniss flag (0=false, 1=true) 5unniss flag (0=false, 1=true)
6number of transformations 6n = maximum number of moves for transformations + 1 (at most 20)
7transformations, one per line 7n times the following:
8 number of transformations
9 transformations, one per line
8the orientation of the cube, as a number from 0 to 23 10the orientation of the cube, as a number from 0 to 23
9 11
10See below for the output format. 12See below for the output format.
@@ -18,11 +20,13 @@ int64_t readmoves(const char *, size_t n, size_t m,
18void solution_moves_reset(solution_moves_t [static 1]); 20void solution_moves_reset(solution_moves_t [static 1]);
19bool solution_list_init(solution_list_t [static 1], size_t n, char [n]); 21bool solution_list_init(solution_list_t [static 1], size_t n, char [n]);
20int64_t appendsolution(const solution_moves_t [static 1], 22int64_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
23void run(void) { 26void 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 @@
1struct {
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"

Generated with cgit - Back to sebastiano.tronto.net