diff options
| author | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-12-14 17:32:29 +0100 |
|---|---|---|
| committer | Sebastiano Tronto <sebastiano.tronto@gmail.com> | 2021-12-14 17:32:29 +0100 |
| commit | 25e0d5703367969170f8f47051c7adcf58f5c990 (patch) | |
| tree | bca61827af98a4fb23eb1ab5088a0154c39b193d | |
| parent | a9831ada32f9349b3d8973b07df3171455fbddcd (diff) | |
| download | nissy-25e0d5703367969170f8f47051c7adcf58f5c990.tar.gz nissy-25e0d5703367969170f8f47051c7adcf58f5c990.zip | |
Added light optimal solver - about 5 times slower but takes only 500Mb of RAM
| -rw-r--r-- | INSTALL | 7 | ||||
| -rw-r--r-- | README.md | 11 | ||||
| -rw-r--r-- | TODO.md | 3 | ||||
| -rwxr-xr-x | nissy | bin | 188520 -> 192888 bytes | |||
| -rw-r--r-- | src/steps.c | 126 |
5 files changed, 129 insertions, 18 deletions
| @@ -1,10 +1,11 @@ | |||
| 1 | # Requirements | 1 | # Requirements |
| 2 | 2 | ||
| 3 | A full installation of nissy requires a little more than 2Gb of space, | 3 | A full installation of nissy requires a little more than 2Gb of space, |
| 4 | of which 1.6Gb are occupied by the huge pruning table for optimal solving, | 4 | of which 1.6Gb are occupied by the huge pruning table for fast optimal solving, |
| 5 | and running it requires the same amount of RAM. | 5 | and running it requires the same amount of RAM. |
| 6 | One can choose to never use the optimal solver and not to install the relative | 6 | One can choose to never use this function and not to install the relative |
| 7 | pruning table. If so, about 500Mb should be enough. | 7 | pruning table. There is an alternative (about 5 times slower) |
| 8 | optimal solving function that uses about 500Mb of RAM. | ||
| 8 | 9 | ||
| 9 | # Installation | 10 | # Installation |
| 10 | 11 | ||
| @@ -20,11 +20,12 @@ solutions for EO/DR/HTR or similar substeps. | |||
| 20 | 20 | ||
| 21 | ## Requirements | 21 | ## Requirements |
| 22 | 22 | ||
| 23 | A full installation of nissy requires about 1.8Gb of space, of which 1.6Gb are | 23 | A full installation of nissy requires a little more than 2Gb of space, |
| 24 | occupied by the huge pruning table for optimal solving, and running it requires | 24 | of which 1.6Gb are occupied by the huge pruning table for fast optimal solving, |
| 25 | the same amount of RAM. | 25 | and running it requires the same amount of RAM. |
| 26 | One can choose to never use the optimal solver and not to install the relative | 26 | One can choose to never use this function and not to install the relative |
| 27 | pruning table. If so, about 200Mb should be enough. | 27 | pruning table. There is an alternative (about 5 times slower) |
| 28 | optimal solving function that uses about 500Mb of RAM. | ||
| 28 | 29 | ||
| 29 | ## Installation | 30 | ## Installation |
| 30 | 31 | ||
| @@ -14,9 +14,6 @@ It's more of a personal reminder than anything else. | |||
| 14 | * invert an alg | 14 | * invert an alg |
| 15 | 15 | ||
| 16 | ### More steps for `solve` | 16 | ### More steps for `solve` |
| 17 | * "slow" optimal solver, using drud table but all the tricks | ||
| 18 | of khuge (+ trick to avoid 180° moves when one of the inverse | ||
| 19 | probes returns exactly the target value) | ||
| 20 | * QTM optimal solving | 17 | * QTM optimal solving |
| 21 | * Block-building steps (cross, roux blocks, ...) | 18 | * Block-building steps (cross, roux blocks, ...) |
| 22 | * Other common steps (LSE, ...) | 19 | * Other common steps (LSE, ...) |
| Binary files differ | |||
diff --git a/src/steps.c b/src/steps.c index a56b47a..7478ce6 100644 --- a/src/steps.c +++ b/src/steps.c | |||
| @@ -36,6 +36,7 @@ static int estimate_drudfin_drud(DfsArg *arg); | |||
| 36 | static int estimate_htr_drud(DfsArg *arg); | 36 | static int estimate_htr_drud(DfsArg *arg); |
| 37 | static int estimate_htrfin_htr(DfsArg *arg); | 37 | static int estimate_htrfin_htr(DfsArg *arg); |
| 38 | static int estimate_optimal_HTM(DfsArg *arg); | 38 | static int estimate_optimal_HTM(DfsArg *arg); |
| 39 | static int estimate_light_HTM(DfsArg *arg); | ||
| 39 | 40 | ||
| 40 | static bool always_valid(Alg *alg); | 41 | static bool always_valid(Alg *alg); |
| 41 | static bool validate_singlecw_ending(Alg *alg); | 42 | static bool validate_singlecw_ending(Alg *alg); |
| @@ -55,6 +56,7 @@ static char check_drany_msg[100] = "DR must be solved on at least one axis"; | |||
| 55 | 56 | ||
| 56 | /* Steps *********************************************************************/ | 57 | /* Steps *********************************************************************/ |
| 57 | 58 | ||
| 59 | /* Optimal solvers *******************/ | ||
| 58 | Step | 60 | Step |
| 59 | optimal_HTM = { | 61 | optimal_HTM = { |
| 60 | .shortname = "optimal", | 62 | .shortname = "optimal", |
| @@ -74,6 +76,25 @@ optimal_HTM = { | |||
| 74 | .ntables = 2, | 76 | .ntables = 2, |
| 75 | }; | 77 | }; |
| 76 | 78 | ||
| 79 | Step | ||
| 80 | optimal_light_HTM = { | ||
| 81 | .shortname = "light", | ||
| 82 | .name = "Optimal solve (in HTM), small table (500Mb RAM total)", | ||
| 83 | |||
| 84 | .final = true, | ||
| 85 | .is_done = is_solved, | ||
| 86 | .estimate = estimate_light_HTM, | ||
| 87 | .ready = check_centers, | ||
| 88 | .ready_msg = check_centers_msg, | ||
| 89 | .is_valid = always_valid, | ||
| 90 | .moveset = moveset_HTM, | ||
| 91 | |||
| 92 | .pre_trans = uf, | ||
| 93 | |||
| 94 | .tables = {&pd_drud_sym16_HTM, &pd_corners_HTM}, | ||
| 95 | .ntables = 2, | ||
| 96 | }; | ||
| 97 | |||
| 77 | /* EO steps **************************/ | 98 | /* EO steps **************************/ |
| 78 | Step | 99 | Step |
| 79 | eoany_HTM = { | 100 | eoany_HTM = { |
| @@ -813,6 +834,7 @@ htrfin_htr = { | |||
| 813 | 834 | ||
| 814 | Step *steps[NSTEPS] = { | 835 | Step *steps[NSTEPS] = { |
| 815 | &optimal_HTM, /* first is default */ | 836 | &optimal_HTM, /* first is default */ |
| 837 | &optimal_light_HTM, | ||
| 816 | 838 | ||
| 817 | &eoany_HTM, | 839 | &eoany_HTM, |
| 818 | &eofb_HTM, | 840 | &eofb_HTM, |
| @@ -1162,7 +1184,6 @@ static int | |||
| 1162 | estimate_optimal_HTM(DfsArg *arg) | 1184 | estimate_optimal_HTM(DfsArg *arg) |
| 1163 | { | 1185 | { |
| 1164 | int target, ret; | 1186 | int target, ret; |
| 1165 | Move bl1; | ||
| 1166 | Cube aux; | 1187 | Cube aux; |
| 1167 | 1188 | ||
| 1168 | static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) | | 1189 | static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) | |
| @@ -1174,7 +1195,6 @@ estimate_optimal_HTM(DfsArg *arg) | |||
| 1174 | 1195 | ||
| 1175 | ret = -1; | 1196 | ret = -1; |
| 1176 | target = arg->d - arg->current_alg->len; | 1197 | target = arg->d - arg->current_alg->len; |
| 1177 | bl1 = base_move(arg->last1); | ||
| 1178 | arg->inverse = (Cube){0}; | 1198 | arg->inverse = (Cube){0}; |
| 1179 | arg->badmovesinv = 0; | 1199 | arg->badmovesinv = 0; |
| 1180 | arg->badmoves = 0; | 1200 | arg->badmoves = 0; |
| @@ -1204,17 +1224,17 @@ estimate_optimal_HTM(DfsArg *arg) | |||
| 1204 | } | 1224 | } |
| 1205 | 1225 | ||
| 1206 | /* Inverse probing */ | 1226 | /* Inverse probing */ |
| 1207 | arg->inverse = inverse_cube(arg->cube); | 1227 | aux = arg->inverse = inverse_cube(arg->cube); |
| 1208 | if ((bl1 != U && bl1 != D) || (arg->ed->inverse_ud == -1)) { | 1228 | if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) { |
| 1209 | arg->ed->inverse_ud = ptableval(&pd_khuge_HTM, arg->inverse); | 1229 | arg->ed->inverse_ud = ptableval(&pd_khuge_HTM, aux); |
| 1210 | } | 1230 | } |
| 1211 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); | 1231 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); |
| 1212 | if ((bl1 != F && bl1 != B) || (arg->ed->inverse_fb == -1)) { | 1232 | if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) { |
| 1213 | aux = apply_trans(fd, arg->inverse); | 1233 | aux = apply_trans(fd, arg->inverse); |
| 1214 | arg->ed->inverse_fb = ptableval(&pd_khuge_HTM, aux); | 1234 | arg->ed->inverse_fb = ptableval(&pd_khuge_HTM, aux); |
| 1215 | } | 1235 | } |
| 1216 | UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); | 1236 | UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); |
| 1217 | if ((bl1 != R && bl1 != L) || (arg->ed->inverse_rl == -1)) { | 1237 | if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) { |
| 1218 | aux = apply_trans(rf, arg->inverse); | 1238 | aux = apply_trans(rf, arg->inverse); |
| 1219 | arg->ed->inverse_rl = ptableval(&pd_khuge_HTM, aux); | 1239 | arg->ed->inverse_rl = ptableval(&pd_khuge_HTM, aux); |
| 1220 | } | 1240 | } |
| @@ -1244,6 +1264,98 @@ estimate_optimal_HTM(DfsArg *arg) | |||
| 1244 | return arg->ed->oldret = ret; | 1264 | return arg->ed->oldret = ret; |
| 1245 | } | 1265 | } |
| 1246 | 1266 | ||
| 1267 | static int | ||
| 1268 | estimate_light_HTM(DfsArg *arg) | ||
| 1269 | { | ||
| 1270 | int target, ret; | ||
| 1271 | Cube aux; | ||
| 1272 | |||
| 1273 | static const uint64_t udmask = (1<<U) | (1<<U2) | (1<<U3) | | ||
| 1274 | (1<<D) | (1<<D2) | (1<<D3); | ||
| 1275 | static const uint64_t rlmask = (1<<R) | (1<<R2) | (1<<R3) | | ||
| 1276 | (1<<L) | (1<<L2) | (1<<L3); | ||
| 1277 | static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | | ||
| 1278 | (1<<B) | (1<<B2) | (1<<B3); | ||
| 1279 | static const uint64_t htmask = (1<<U2) | (1<<D2) | | ||
| 1280 | (1<<R2) | (1<<L2) | | ||
| 1281 | (1<<F2) | (1<<B2); | ||
| 1282 | |||
| 1283 | ret = -1; | ||
| 1284 | target = arg->d - arg->current_alg->len; | ||
| 1285 | arg->inverse = (Cube){0}; | ||
| 1286 | arg->badmovesinv = 0; | ||
| 1287 | arg->badmoves = 0; | ||
| 1288 | |||
| 1289 | /* Corners */ | ||
| 1290 | arg->ed->corners = ptableval(&pd_corners_HTM, arg->cube); | ||
| 1291 | UPDATECHECKSTOP(ret, arg->ed->corners, target); | ||
| 1292 | |||
| 1293 | /* Normal probing */ | ||
| 1294 | arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube); | ||
| 1295 | UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); | ||
| 1296 | aux = apply_trans(fd, arg->cube); | ||
| 1297 | arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1298 | UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); | ||
| 1299 | aux = apply_trans(rf, arg->cube); | ||
| 1300 | arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1301 | UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); | ||
| 1302 | |||
| 1303 | /* If ret == 0, it's solved (corners + triple slice solved) */ | ||
| 1304 | if (ret == 0) | ||
| 1305 | return 0; | ||
| 1306 | |||
| 1307 | /* Michel de Bondt's trick*/ | ||
| 1308 | if (arg->ed->normal_ud == arg->ed->normal_fb && | ||
| 1309 | arg->ed->normal_fb == arg->ed->normal_rl) { | ||
| 1310 | UPDATECHECKSTOP(ret, arg->ed->normal_ud + 1, target); | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | /* Inverse probing */ | ||
| 1314 | if (!((1<<arg->last1) & htmask)) { | ||
| 1315 | aux = arg->inverse = inverse_cube(arg->cube); | ||
| 1316 | if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) { | ||
| 1317 | arg->ed->inverse_ud = | ||
| 1318 | ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1319 | } | ||
| 1320 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); | ||
| 1321 | if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) { | ||
| 1322 | aux = apply_trans(fd, arg->inverse); | ||
| 1323 | arg->ed->inverse_fb = | ||
| 1324 | ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1325 | } | ||
| 1326 | UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); | ||
| 1327 | if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) { | ||
| 1328 | aux = apply_trans(rf, arg->inverse); | ||
| 1329 | arg->ed->inverse_rl = | ||
| 1330 | ptableval(&pd_drud_sym16_HTM, aux); | ||
| 1331 | } | ||
| 1332 | UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); | ||
| 1333 | } | ||
| 1334 | |||
| 1335 | /* Michel de Bondt's trick*/ | ||
| 1336 | if (arg->ed->inverse_ud == arg->ed->inverse_fb && | ||
| 1337 | arg->ed->inverse_fb == arg->ed->inverse_rl) { | ||
| 1338 | UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | /* nxopt trick + half turn trick */ | ||
| 1342 | if (arg->ed->normal_ud == target) | ||
| 1343 | arg->badmovesinv |= udmask | htmask; | ||
| 1344 | if (arg->ed->normal_fb == target) | ||
| 1345 | arg->badmovesinv |= fbmask | htmask; | ||
| 1346 | if (arg->ed->normal_rl == target) | ||
| 1347 | arg->badmovesinv |= rlmask | htmask; | ||
| 1348 | |||
| 1349 | if (arg->ed->inverse_ud == target) | ||
| 1350 | arg->badmoves |= udmask | htmask; | ||
| 1351 | if (arg->ed->inverse_fb == target) | ||
| 1352 | arg->badmoves |= fbmask | htmask; | ||
| 1353 | if (arg->ed->inverse_rl == target) | ||
| 1354 | arg->badmoves |= rlmask | htmask; | ||
| 1355 | |||
| 1356 | return arg->ed->oldret = ret; | ||
| 1357 | } | ||
| 1358 | |||
| 1247 | static bool | 1359 | static bool |
| 1248 | always_valid(Alg *alg) | 1360 | always_valid(Alg *alg) |
| 1249 | { | 1361 | { |
