nissy-fmc

A Rubik's cube FMC assistant
git clone https://git.tronto.net/nissy-fmc
Download | Log | Files | Refs | README | LICENSE

commit 2f924f942bd6e7126e8f1d8692e475c95bd9fe82
parent 4e2b4e603c7e84c7556f489d7d8dab06915b3a9b
Author: Sebastiano Tronto <sebastiano.tronto@gmail.com>
Date:   Thu, 16 Dec 2021 19:25:58 +0100

Added a new pruning table (equivalent to nxopt31). I have not tested it yet, it takes a while to generate.
Plus I have done a whole lot of refactoring in random places because I cannot focus on
one thing at the time.

Diffstat:
MTODO.md | 17++++++++---------
Mnissy | 0
Msrc/alg.c | 180++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/alg.h | 15+++++++++------
Msrc/commands.c | 2++
Msrc/coord.c | 86+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/coord.h | 2++
Msrc/cubetypes.h | 23++++++++++++++---------
Msrc/moves.c | 51---------------------------------------------------
Msrc/moves.h | 2--
Msrc/pruning.c | 95+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/pruning.h | 1+
Msrc/solve.c | 80++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/steps.c | 246+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/symcoord.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Msrc/symcoord.h | 2+-
16 files changed, 555 insertions(+), 332 deletions(-)

diff --git a/TODO.md b/TODO.md @@ -14,13 +14,11 @@ It's more of a personal reminder than anything else. * invert an alg ### More steps for `solve` -* QTM optimal solving +* QTM optimal solving (important: fix possible_next, which works only for HTM now) * Block-building steps (cross, roux blocks, ...) * Other common steps (LSE, ...) ### Improvements to currently implemented commands -* batch mode: add separator / info on which command it is executing -(also change man page for this) * solve should re-orient first if needed and not just give up if centers are off * solve should try up to a small bound without loading the large pruning table * drfin for HTR scrambles should try all 3 axis and pick the best solutions; @@ -42,7 +40,12 @@ It's more of a personal reminder than anything else. ## Technical stuff -## Performance +### Memory management +* Check if memory is enough for loading pruning tables; if not, abort +* For optimal solver: choose largest that fits in memory between + khuge, shug6 and light + +### Performance * solve (allow_next): filter out based on base_move; only check once for each triple of moves; how to deal with different movesets? * try htr corners + edges in slice but not oriented (300Mb table); @@ -51,12 +54,8 @@ It's more of a personal reminder than anything else. (like in light optimal solver) * Another idea: DR + cornershtr (5Gb table); same as above, de Bondt's trick does not work but I can use half-turn trick -* On the contrary: DR + separate UD corners allow dB's trick, but no ht-trick -## Coordinates, symmetries, pruning tables -* Cleanup symcoord.c: some coordinates and symdata are never actually used; -remove also sd_eofbepos and just use sd_coud for khuge (this changes the -coordinate so the whole table must be generated again!) or viceversa +### Coordinates, symmetries, pruning tables * Use pruning values mod 4 instead of mod 16 (or maybe not, I like the current system) diff --git a/nissy b/nissy Binary files differ. diff --git a/src/alg.c b/src/alg.c @@ -2,27 +2,76 @@ /* Local functions ***********************************************************/ +static bool allowed_HTM(Move m); +static bool allowed_URF(Move m); +static bool allowed_eofb(Move m); +static bool allowed_drud(Move m); +static bool allowed_htr(Move m); +static bool allowed_next_HTM(Move l2, Move l1, Move m); +static int axis(Move m); + static void free_alglistnode(AlgListNode *aln); static void realloc_alg(Alg *alg, int n); /* Movesets ******************************************************************/ -bool -moveset_HTM(Move m) +Moveset +moveset_HTM = { + .allowed = allowed_HTM, + .allowed_next = allowed_next_HTM, +}; + +Moveset +moveset_URF = { + .allowed = allowed_URF, + .allowed_next = allowed_next_HTM, +}; + +Moveset +moveset_eofb = { + .allowed = allowed_eofb, + .allowed_next = allowed_next_HTM, +}; + +Moveset +moveset_drud = { + .allowed = allowed_drud, + .allowed_next = allowed_next_HTM, +}; + +Moveset +moveset_htr = { + .allowed = allowed_htr, + .allowed_next = allowed_next_HTM, +}; + +static int nmoveset = 5; +static Moveset * all_ms[] = { + &moveset_HTM, + &moveset_URF, + &moveset_eofb, + &moveset_drud, + &moveset_htr, +}; + +/* Functions *****************************************************************/ + +static bool +allowed_HTM(Move m) { return m >= U && m <= B3; } -bool -moveset_URF(Move m) +static bool +allowed_URF(Move m) { Move b = base_move(m); return b == U || b == R || b == F; } -bool -moveset_eofb(Move m) +static bool +allowed_eofb(Move m) { Move b = base_move(m); @@ -30,8 +79,8 @@ moveset_eofb(Move m) ((b == F || b == B) && m == b+1); } -bool -moveset_drud(Move m) +static bool +allowed_drud(Move m) { Move b = base_move(m); @@ -39,16 +88,65 @@ moveset_drud(Move m) ((b == R || b == L || b == F || b == B) && m == b + 1); } -bool -moveset_htr(Move m) +static bool +allowed_htr(Move m) { Move b = base_move(m); - return moveset_HTM(m) && m == b + 1; + return moveset_HTM.allowed(m) && m == b + 1; } +static bool +allowed_next_HTM(Move l2, Move l1, Move m) +{ + bool p, q; -/* Functions *****************************************************************/ + p = l1 != NULLMOVE && base_move(l1) == base_move(m); + q = l2 != NULLMOVE && base_move(l2) == base_move(m); + + return !(p || (commute(l1, l2) && q)); +} + +static int +axis(Move m) +{ + Move i; + + static bool initialized = false; + static int aux[NMOVES]; + + if (!initialized) { + for (i = 0; i < NMOVES; i++) { + if (i == NULLMOVE) + aux[i] = 0; + + if (i >= U && i <= B3) + aux[i] = (i-1)/6 + 1; + + if (i >= Uw && i <= Bw3) + aux[i] = (i-1)/6 - 2; + + if (base_move(i) == E || base_move(i) == y) + aux[i] = 1; + + if (base_move(i) == M || base_move(i) == x) + aux[i] = 2; + + if (base_move(i) == S || base_move(i) == z) + aux[i] = 3; + } + + initialized = true; + } + + return aux[m]; +} + +bool +commute(Move m1, Move m2) +{ + return axis(m1) == axis(m2); +} void append_alg(AlgList *l, Alg *alg) @@ -171,33 +269,6 @@ move_string(Move m) return move_string_aux[m]; } -void -movelist_to_position(Move *movelist, int *position) -{ - Move m; - - for (m = 0; m < NMOVES && movelist[m] != NULLMOVE; m++) - position[movelist[m]] = m; -} - -void -moveset_to_list(Moveset ms, Move *r) -{ - int n = 0; - Move i; - - if (ms == NULL) { - fprintf(stderr, "Error: no moveset given\n"); - return; - } - - for (i = U; i < NMOVES; i++) - if (ms(i)) - r[n++] = i; - - r[n] = NULLMOVE; -} - Alg * new_alg(char *str) { @@ -405,3 +476,34 @@ unniss(Alg *alg) } free(aux); } + +void +init_movesets() +{ + int i, j; + uint64_t l, one; + Move m, l2, l1; + Moveset *ms; + + one = 1; + + for (i = 0; i < nmoveset; i++) { + ms = all_ms[i]; + + for (j = 0, m = U; m < NMOVES; m++) + if (ms->allowed(m)) + ms->sorted_moves[j++] = m; + ms->sorted_moves[j] = NULLMOVE; + + for (l1 = 0; l1 < NMOVES; l1++) { + for (l2 = 0; l2 < NMOVES; l2++) { + ms->mask[l2][l1] = 0; + for (l=0; ms->sorted_moves[l]!=NULLMOVE; l++) { + m = ms->sorted_moves[l]; + if (ms->allowed_next(l2, l1, m)) + ms->mask[l2][l1] |= (one<<m); + } + } + } + } +} diff --git a/src/alg.h b/src/alg.h @@ -8,16 +8,17 @@ #include "cubetypes.h" #include "utils.h" -bool moveset_HTM(Move m); -bool moveset_URF(Move m); -bool moveset_eofb(Move m); -bool moveset_drud(Move m); -bool moveset_htr(Move m); +extern Moveset moveset_HTM; +extern Moveset moveset_URF; +extern Moveset moveset_eofb; +extern Moveset moveset_drud; +extern Moveset moveset_htr; void append_alg(AlgList *l, Alg *alg); void append_move(Alg *alg, Move m, bool inverse); -void compose_alg(Alg *alg1, Alg *alg2); Move base_move(Move m); +void compose_alg(Alg *alg1, Alg *alg2); +bool commute(Move m1, Move m2); void free_alg(Alg *alg); void free_alglist(AlgList *l); Alg * inverse_alg(Alg *alg); @@ -33,5 +34,7 @@ void print_alglist(AlgList *al, bool l); void swapmove(Move *m1, Move *m2); void unniss(Alg *alg); +void init_movesets(); + #endif diff --git a/src/commands.c b/src/commands.c @@ -259,6 +259,7 @@ solve_exec(CommandArgs *args) Cube c; AlgList *sols; + init_movesets(); init_symcoord(); c = apply_alg(args->scramble, (Cube){0}); @@ -274,6 +275,7 @@ gen_exec(CommandArgs *args) int i; fprintf(stderr, "Generating coordinates...\n"); + init_movesets(); init_symcoord(); fprintf(stderr, "Generating pruning tables...\n"); diff --git a/src/coord.c b/src/coord.c @@ -13,6 +13,7 @@ static Cube antindex_drud(uint64_t ind); static Cube antindex_drud_eofb(uint64_t ind); static Cube antindex_htr_drud(uint64_t ind); static Cube antindex_htrfin(uint64_t ind); +static Cube antindex_cpud_separate(uint64_t ind); static uint64_t index_eofb(Cube cube); static uint64_t index_eofbepos(Cube cube); @@ -27,6 +28,7 @@ static uint64_t index_drud(Cube cube); static uint64_t index_drud_eofb(Cube cube); static uint64_t index_htr_drud(Cube cube); static uint64_t index_htrfin(Cube cube); +static uint64_t index_cpud_separate(Cube cube); static void init_cphtr_cosets(); static void init_cphtr_left_cosets_bfs(int i, int c); @@ -135,6 +137,13 @@ coord_drud_eofb = { .max = POW3TO7 * BINOM12ON4, }; +Coordinate +coord_cpud_separate = { + .index = index_cpud_separate, + .cube = antindex_cpud_separate, + .max = BINOM8ON4, +}; + /* Antindexers ***************************************************************/ static Cube @@ -356,6 +365,31 @@ antindex_htrfin(uint64_t ind) return ret; } +static Cube +antindex_cpud_separate(uint64_t ind) +{ + /* Not consistent because of side corner orientations and cp */ + unsigned int ui; + int i, co[8], cp[8]; + Corner u, d; + + static Cube aux[BINOM8ON4]; + static bool initialized = false; + + if (!initialized) { + for (ui = 0; ui < BINOM8ON4; ui++) { + index_to_subset(ui, 8, 4, co); + for (i = 0, u = UFR, d = DFR; i < 8; i++) + cp[i] = co[i] ? d++ : u++; + aux[ui] = (Cube){.cp = perm_to_index(cp, 8)}; + } + + initialized = true; + } + + return aux[ind]; +} + /* Indexers ******************************************************************/ static uint64_t @@ -477,6 +511,29 @@ index_htrfin(Cube cube) return cp * 24 * 24 * 24 + ep; } +static uint64_t +index_cpud_separate(Cube cube) +{ + unsigned int ui; + int i, co[8]; + + static int aux[FACTORIAL8]; + static bool initialized = false; + + if (!initialized) { + for (ui = 0; ui < FACTORIAL8; ui++) { + for (i = 0; i < 8; i++) + co[i] = what_corner_at((Cube){.cp=ui},i)>UBR ? + 1 : 0; + aux[ui] = subset_to_index(co, 8, 4); + } + + initialized = true; + } + + return aux[cube.cp]; +} + /* Init functions implementation *********************************************/ /* @@ -528,7 +585,7 @@ init_cphtr_left_cosets_bfs(int i, int c) while (n != 0) { for (j = 0, n2 = 0; j < n; j++) { for (k = U2; k < B3; k++) { - if (!moveset_htr(k)) + if (!moveset_htr.allowed(k)) continue; jj = apply_move(k, (Cube){ .cp = next[j] }).cp; @@ -578,7 +635,7 @@ init_cornershtrfin() if (cornershtrfin_ind[j] == -1) continue; for (m = U; m < NMOVES; m++) { - if (moveset_htr(m)) { + if (moveset_htr.allowed(m)) { c = apply_move(m, (Cube){.cp = j}).cp; if (cornershtrfin_ind[c] == -1) { cornershtrfin_ind[c] = n; @@ -592,6 +649,31 @@ init_cornershtrfin() } void +test_coord(Coordinate *coord) +{ + bool passed; + uint64_t ui, failcount; + + if (!(passed = (coord->index((Cube){0}) == 0))) { + printf("Failed: coordinate of solved cube is " + "%" PRIu64 "\n", coord->index((Cube){0})); + } + + printf("Testing %" PRIu64 " coordinates\n", coord->max); + for (failcount = 0, ui = 0; ui < coord->max; ui++) { + if (!(passed = (coord->index(coord->cube(ui)) == ui))) { + printf("Failed at %" PRIu64 "\n", ui); + failcount++; + } + } + + if (passed) + printf("Ok\n"); + else + printf("Test failed in %" PRIu64 " cases\n", failcount); +} + +void init_coord() { static bool initialized = false; diff --git a/src/coord.h b/src/coord.h @@ -16,7 +16,9 @@ extern Coordinate coord_drud; extern Coordinate coord_drud_eofb; extern Coordinate coord_htr_drud; extern Coordinate coord_htrfin; +extern Coordinate coord_cpud_separate; +void test_coord(Coordinate *coord); void init_coord(); #endif diff --git a/src/cubetypes.h b/src/cubetypes.h @@ -8,6 +8,7 @@ #define NMOVES 55 /* Actually 54, but one is NULLMOVE */ #define NTRANS 48 #define NROTATIONS 24 +#define entry_group_t uint8_t /* For pruning tables */ /* Enums *********************************************************************/ @@ -83,6 +84,7 @@ typedef struct cube Cube; typedef struct cubearray CubeArray; typedef struct dfsarg DfsArg; typedef struct estimatedata EstimateData; +typedef struct moveset Moveset; typedef struct piecefilter PieceFilter; typedef struct prunedata PruneData; typedef struct solveoptions SolveOptions; @@ -97,7 +99,6 @@ typedef int (*Estimator) (DfsArg *); typedef bool (*Validator) (Alg *); typedef void (*Exec) (CommandArgs *); typedef uint64_t (*Indexer) (Cube); -typedef bool (*Moveset) (Move); typedef CommandArgs * (*ArgParser) (int, char **); typedef Trans (*TransDetector) (Cube); typedef int (*TransFinder) (uint64_t, Trans *); @@ -215,8 +216,6 @@ dfsarg AlgList * sols; pthread_mutex_t * sols_mutex; Alg * current_alg; - Move * sorted_moves; - int * move_position; }; struct @@ -233,6 +232,15 @@ estimatedata }; struct +moveset +{ + bool (*allowed)(Move); + bool (*allowed_next)(Move, Move, Move); + Move sorted_moves[NMOVES+1]; + uint64_t mask[NMOVES][NMOVES]; +}; + +struct piecefilter { bool epose; @@ -252,11 +260,11 @@ struct prunedata { char * filename; - uint8_t * ptable; + entry_group_t * ptable; bool generated; uint64_t n; Coordinate * coord; - Moveset moveset; + Moveset * moveset; }; struct @@ -284,7 +292,7 @@ step Checker ready; char * ready_msg; Validator is_valid; - Moveset moveset; + Moveset * moveset; Trans pre_trans; TransDetector detect; int ntables; @@ -312,8 +320,6 @@ threaddatasolve Cube cube; Step * step; int depth; - Move * sorted_moves; - int * move_position; SolveOptions * opts; AlgList * start; AlgListNode ** node; @@ -329,7 +335,6 @@ threaddatagenpt int nthreads; PruneData * pd; int d; - Move * ms; int nchunks; pthread_mutex_t ** mutex; pthread_mutex_t * upmutex; diff --git a/src/moves.c b/src/moves.c @@ -319,57 +319,6 @@ write_mtables_file() return r; } -bool -commute(Move m1, Move m2) -{ - static bool initialized = false; - static bool commute_aux[NMOVES][NMOVES]; - - if (!initialized) { - Cube c1, c2; - int i, j; - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - c1 = apply_move(i, apply_move(j, (Cube){0})); - c2 = apply_move(j, apply_move(i, (Cube){0})); - commute_aux[i][j] = equal(c1, c2) && i && j; - } - } - - initialized = true; - } - - return commute_aux[m1][m2]; -} - -bool -possible_next(Move m1, Move m2, Move m3) -{ - static bool initialized = false; - static bool paux[NMOVES][NMOVES][NMOVES]; - - if (!initialized) { - int i, j, k; - bool p, q, c; - - for (i = 0; i < NMOVES; i++) { - for (j = 0; j < NMOVES; j++) { - for (k = 0; k < NMOVES; k++) { - p = j && base_move(j) == base_move(k); - q = i && base_move(i) == base_move(k); - c = commute(i, j); - paux[i][j][k] = !(p || (c && q)); - } - } - } - - initialized = true; - } - - return paux[m1][m2][m3]; -} - void init_moves() { static bool initialized = false; diff --git a/src/moves.h b/src/moves.h @@ -8,8 +8,6 @@ Cube apply_alg(Alg *alg, Cube cube); Cube apply_alg_generic(Alg *alg, Cube c, PieceFilter f, bool a); Cube apply_move(Move m, Cube cube); -bool commute(Move m1, Move m2); -bool possible_next(Move m1, Move m2, Move m3); void init_moves(); diff --git a/src/pruning.c b/src/pruning.c @@ -1,11 +1,10 @@ #include "pruning.h" -/* Chunks for multithreading */ -/* TODO: try smaller */ -#define NCHUNKS 100000 +#define NCHUNKS 100000 +#define ENTRIES_PER_GROUP (2*sizeof(entry_group_t)) static int findchunk(PruneData *pd, int nchunks, uint64_t i); -static void genptable_bfs(PruneData *pd,int d,Move *ms,int nt,int nc); +static void genptable_bfs(PruneData *pd, int d, int nt, int nc); static void genptable_fixnasty(PruneData *pd, int d); static void * instance_bfs(void *arg); static void ptable_update(PruneData *pd, Cube cube, int m); @@ -18,70 +17,77 @@ PruneData pd_eofb_HTM = { .filename = "pt_eofb_HTM", .coord = &coord_eofb, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, }; PruneData pd_coud_HTM = { .filename = "pt_coud_HTM", .coord = &coord_coud, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, }; PruneData pd_cornershtr_HTM = { .filename = "pt_cornershtr_HTM", .coord = &coord_cornershtr, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, }; PruneData pd_corners_HTM = { .filename = "pt_corners_HTM", .coord = &coord_corners, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, }; PruneData pd_drud_sym16_HTM = { .filename = "pt_drud_sym16_HTM", .coord = &coord_drud_sym16, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, }; PruneData pd_drud_eofb = { .filename = "pt_drud_eofb", .coord = &coord_drud_eofb, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, }; PruneData pd_drudfin_noE_sym16_drud = { .filename = "pt_drudfin_noE_sym16_drud", .coord = &coord_drudfin_noE_sym16, - .moveset = moveset_drud, + .moveset = &moveset_drud, }; PruneData pd_htr_drud = { .filename = "pt_htr_drud", .coord = &coord_htr_drud, - .moveset = moveset_drud, + .moveset = &moveset_drud, }; PruneData pd_htrfin_htr = { .filename = "pt_htrfin_htr", .coord = &coord_htrfin, - .moveset = moveset_htr, + .moveset = &moveset_htr, }; PruneData pd_khuge_HTM = { .filename = "pt_khuge_HTM", .coord = &coord_khuge, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, +}; + +PruneData +pd_nxopt31_HTM = { + .filename = "pt_nxopt31_HTM", + .coord = &coord_nxopt31, + .moveset = &moveset_HTM, }; PruneData * allpd[NPTABLES] = { @@ -95,6 +101,7 @@ PruneData * allpd[NPTABLES] = { &pd_htr_drud, &pd_htrfin_htr, &pd_khuge_HTM, + &pd_nxopt31_HTM, }; /* Functions *****************************************************************/ @@ -105,8 +112,7 @@ findchunk(PruneData *pd, int nchunks, uint64_t i) uint64_t chunksize; chunksize = pd->coord->max / (uint64_t)nchunks; - if (chunksize % 2 != 0) - chunksize++; + chunksize += ENTRIES_PER_GROUP - (chunksize % ENTRIES_PER_GROUP); return MIN(nchunks-1, (int)(i / chunksize)); } @@ -114,15 +120,14 @@ findchunk(PruneData *pd, int nchunks, uint64_t i) void genptable(PruneData *pd, int nthreads) { - Move *ms; int d, nchunks; - uint64_t j, oldn; + uint64_t oldn; if (pd->generated) return; /* TODO: check if memory is enough, otherwise maybe exit gracefully? */ - pd->ptable = malloc(ptablesize(pd) * sizeof(uint8_t)); + pd->ptable = malloc(ptablesize(pd) * sizeof(entry_group_t)); if (read_ptable_file(pd)) { pd->generated = true; @@ -130,17 +135,12 @@ genptable(PruneData *pd, int nthreads) } pd->generated = true; - nchunks = MIN(pd->coord->max/2, NCHUNKS); + nchunks = MIN(pd->coord->max/ENTRIES_PER_GROUP, NCHUNKS); fprintf(stderr, "Cannot load %s, generating it " "with %d threads and %d chunks\n", pd->filename, nthreads, nchunks); - ms = malloc(NMOVES * sizeof(Move)); - moveset_to_list(pd->moveset, ms); - - /* We use 4 bits per value, so any distance >= 15 is set to 15 */ - for (j = 0; j < pd->coord->max; j++) - ptable_update_index(pd, j, 15); + memset(pd->ptable, ~(uint8_t)0, ptablesize(pd)*sizeof(entry_group_t)); ptable_update(pd, (Cube){0}, 0); pd->n = 1; @@ -151,7 +151,7 @@ genptable(PruneData *pd, int nthreads) 0, pd->n - oldn, pd->n, pd->coord->max); oldn = pd->n; for (d = 0; d < 15 && pd->n < pd->coord->max; d++) { - genptable_bfs(pd, d, ms, nthreads, nchunks); + genptable_bfs(pd, d, nthreads, nchunks); genptable_fixnasty(pd, d+1); fprintf(stderr, "Depth %d done, generated %" PRIu64 "\t(%" PRIu64 "/%" PRIu64 ")\n", @@ -162,12 +162,10 @@ genptable(PruneData *pd, int nthreads) if (!write_ptable_file(pd)) fprintf(stderr, "Error writing ptable file\n"); - - free(ms); } static void -genptable_bfs(PruneData *pd, int d, Move *ms, int nthreads, int nchunks) +genptable_bfs(PruneData *pd, int d, int nthreads, int nchunks) { int i; pthread_t t[nthreads]; @@ -186,7 +184,6 @@ genptable_bfs(PruneData *pd, int d, Move *ms, int nthreads, int nchunks) td[i].nthreads = nthreads; td[i].pd = pd; td[i].d = d; - td[i].ms = ms; td[i].nchunks = nchunks; td[i].mutex = mtx; td[i].upmutex = upmtx; @@ -237,8 +234,10 @@ instance_bfs(void *arg) uint64_t i, ii, blocksize, rmin, rmax, updated; int j, pval, ichunk; Cube c, cc; + Move *ms; td = (ThreadDataGenpt *)arg; + ms = td->pd->moveset->sorted_moves; blocksize = td->pd->coord->max / (uint64_t)td->nthreads; rmin = ((uint64_t)td->thid) * blocksize; rmax = td->thid == td->nthreads - 1 ? @@ -253,8 +252,8 @@ instance_bfs(void *arg) pthread_mutex_unlock(td->mutex[ichunk]); if (pval == td->d) { c = td->pd->coord->cube(i); - for (j = 0; td->ms[j] != NULLMOVE; j++) { - cc = apply_move(td->ms[j], c); + for (j = 0; ms[j] != NULLMOVE; j++) { + cc = apply_move(ms[j], c); ii = td->pd->coord->index(cc); ichunk = findchunk(td->pd, td->nchunks, ii); pthread_mutex_lock(td->mutex[ichunk]); @@ -296,7 +295,7 @@ print_ptable(PruneData *pd) uint64_t ptablesize(PruneData *pd) { - return (pd->coord->max + 1) / 2; + return (pd->coord->max + ENTRIES_PER_GROUP - 1) / ENTRIES_PER_GROUP; } static void @@ -308,14 +307,16 @@ ptable_update(PruneData *pd, Cube cube, int n) static void ptable_update_index(PruneData *pd, uint64_t ind, int n) { - uint8_t oldval2; - int other; + int sh; + entry_group_t mask; + uint64_t i; - oldval2 = pd->ptable[ind/2]; - other = (ind % 2) ? oldval2 % 16 : oldval2 / 16; + sh = 4 * (ind % ENTRIES_PER_GROUP); + mask = ((entry_group_t)15) << sh; + i = ind/ENTRIES_PER_GROUP; - pd->ptable[ind/2] = (ind % 2) ? 16*n + other : 16*other + n; - /*pd->n++;*/ + pd->ptable[i] &= ~mask; + pd->ptable[i] |= (((entry_group_t)n)&15) << sh; } int @@ -327,6 +328,10 @@ ptableval(PruneData *pd, Cube cube) static int ptableval_index(PruneData *pd, uint64_t ind) { + int sh; + entry_group_t mask; + uint64_t i; + if (!pd->generated) { fprintf(stderr, "Warning: request pruning table value" " for uninitialized table %s.\n It's fine, but it" @@ -335,7 +340,11 @@ ptableval_index(PruneData *pd, uint64_t ind) genptable(pd, 1); /* TODO: set default or remove this case */ } - return (ind % 2) ? pd->ptable[ind/2] / 16 : pd->ptable[ind/2] % 16; + sh = 4 * (ind % ENTRIES_PER_GROUP); + mask = ((entry_group_t)15) << sh; + i = ind/ENTRIES_PER_GROUP; + + return (pd->ptable[i] & mask) >> sh; } static bool @@ -354,7 +363,7 @@ read_ptable_file(PruneData *pd) if ((f = fopen(fname, "rb")) == NULL) return false; - r = fread(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); + r = fread(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f); fclose(f); return r == ptablesize(pd); @@ -376,7 +385,7 @@ write_ptable_file(PruneData *pd) if ((f = fopen(fname, "wb")) == NULL) return false; - written = fwrite(pd->ptable, sizeof(uint8_t), ptablesize(pd), f); + written = fwrite(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f); fclose(f); return written == ptablesize(pd); diff --git a/src/pruning.h b/src/pruning.h @@ -15,6 +15,7 @@ extern PruneData pd_drudfin_noE_sym16_drud; extern PruneData pd_htr_drud; extern PruneData pd_htrfin_htr; extern PruneData pd_khuge_HTM; +extern PruneData pd_nxopt31_HTM; extern PruneData * allpd[NPTABLES]; diff --git a/src/solve.c b/src/solve.c @@ -8,7 +8,7 @@ static void copy_dfsarg(DfsArg *src, DfsArg *dst); static void dfs(DfsArg *arg); static void dfs_branch(DfsArg *arg); static bool dfs_check_solved(DfsArg *arg); -static bool dfs_switch_final(DfsArg *arg); +static bool dfs_switch(DfsArg *arg); static void dfs_niss(DfsArg *arg); static bool dfs_stop(DfsArg *arg); static void * instance_thread(void *arg); @@ -21,25 +21,43 @@ static bool niss_makes_sense(DfsArg *arg); static bool allowed_next(Move m, DfsArg *arg) { - if ((1 << m) & arg->badmoves) - return false; + bool bad, allowed, order; + uint64_t mbit; - if (!possible_next(arg->last2, arg->last1, m)) - return false; + if (arg->last1 == NULLMOVE) + return true; - if (commute(arg->last1, m)) - return arg->move_position[arg->last1] < arg->move_position[m]; + mbit = ((uint64_t)1) << m; + bad = mbit & arg->badmoves; + allowed = mbit & arg->step->moveset->mask[arg->last2][arg->last1]; + order = !commute(arg->last1, m) || arg->last1 < m; - return true; + return allowed && !bad && order; } static bool cancel_niss(DfsArg *arg) { - return !possible_next(arg->last2, arg->last1, arg->last1inv) && - !(commute(arg->last1inv, arg->last2inv) && - arg->last2inv != NULLMOVE && - possible_next(arg->last2, arg->last1, arg->last2inv)); + Moveset *ms; + Move i1, i2; + bool p, p1, p2, q, q1, q2; + + if (arg->last1inv == NULLMOVE) + return false; + + ms = arg->step->moveset; + i1 = inverse_move(arg->last1inv); + i2 = inverse_move(arg->last2inv); + + p1 = !ms->allowed_next(arg->last2, arg->last1, i1); + p2 = !ms->allowed_next(arg->last2, i1, arg->last1); + p = p1 || (commute(i1, arg->last1) && p2); + + q1 = !ms->allowed_next(arg->last2, arg->last1, i2); + q2 = !ms->allowed_next(arg->last2, i2, arg->last1); + q = q1 || (commute(i2, arg->last1) && q2); + + return p || (commute(i1, i2) && q); } static void @@ -60,8 +78,6 @@ copy_dfsarg(DfsArg *src, DfsArg *dst) dst->sols = src->sols; dst->sols_mutex = src->sols_mutex; dst->current_alg = src->current_alg; - dst->sorted_moves = src->sorted_moves; - dst->move_position = src->move_position; copy_estimatedata(src->ed, dst->ed); } @@ -77,7 +93,7 @@ dfs(DfsArg *arg) if (dfs_check_solved(arg)) return; - if (arg->step->final && (sw = dfs_switch_final(arg))) + if (arg->step->final && (sw = dfs_switch(arg))) invert_branch(arg); dfs_branch(arg); @@ -98,8 +114,8 @@ dfs_branch(DfsArg *arg) newarg = malloc(sizeof(DfsArg)); newarg->ed = malloc(sizeof(EstimateData)); - for (i = 0; arg->sorted_moves[i] != NULLMOVE; i++) { - m = arg->sorted_moves[i]; + for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) { + m = arg->step->moveset->sorted_moves[i]; if (allowed_next(m, arg)) { copy_dfsarg(arg, newarg); newarg->last2 = arg->last1; @@ -181,20 +197,22 @@ dfs_stop(DfsArg *arg) } static bool -dfs_switch_final(DfsArg *arg) +dfs_switch(DfsArg *arg) { int i, bn, bi; - for (bn = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) - if (allowed_next(arg->sorted_moves[i], arg)) + bn = 0; + for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) + if (allowed_next(arg->step->moveset->sorted_moves[i], arg)) bn++; swapmove(&(arg->last1), &(arg->last1inv)); swapmove(&(arg->last2), &(arg->last2inv)); swapu64(&(arg->badmoves), &(arg->badmovesinv)); - for (bi = 0, i = 0; arg->sorted_moves[i] != NULLMOVE; i++) - if (allowed_next(arg->sorted_moves[i], arg)) + bi = 0; + for (i = 0; arg->step->moveset->sorted_moves[i] != NULLMOVE; i++) + if (allowed_next(arg->step->moveset->sorted_moves[i], arg)) bi++; swapmove(&(arg->last1), &(arg->last1inv)); @@ -246,8 +264,6 @@ instance_thread(void *arg) darg.current_alg = new_alg(""); append_move(darg.current_alg, node->alg->move[0], node->alg->inv[0]); - darg.sorted_moves = td->sorted_moves; - darg.move_position = td->move_position; darg.ed = new_estimatedata(); darg.badmoves = 0; darg.badmovesinv = 0; @@ -281,8 +297,7 @@ invert_branch(DfsArg *arg) static void multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) { - int i, *move_position; - Move *sorted_moves; + int i; Alg *alg; AlgList *start; AlgListNode **node; @@ -290,8 +305,6 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) ThreadDataSolve td[opts->nthreads]; pthread_mutex_t *start_mutex, *sols_mutex; - move_position = malloc(NMOVES * sizeof(int)); - sorted_moves = malloc(NMOVES * sizeof(Move)); node = malloc(sizeof(AlgListNode *)); start_mutex = malloc(sizeof(pthread_mutex_t)); sols_mutex = malloc(sizeof(pthread_mutex_t)); @@ -300,14 +313,11 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) pthread_mutex_init(start_mutex, NULL); pthread_mutex_init(sols_mutex, NULL); - moveset_to_list(s->moveset, sorted_moves); - movelist_to_position(sorted_moves, move_position); - - for (i = 0; sorted_moves[i] != NULLMOVE; i++) { + for (i = 0; s->moveset->sorted_moves[i] != NULLMOVE; i++) { alg = new_alg(""); /* TODO: start on inverse also in case of final step and ed->sw true */ - append_move(alg, sorted_moves[i], false); + append_move(alg, s->moveset->sorted_moves[i], false); append_alg(start, alg); if (opts->can_niss) { alg->inv[0] = true; @@ -322,8 +332,6 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) td[i].cube = c; td[i].step = s; td[i].depth = d; - td[i].sorted_moves = sorted_moves; - td[i].move_position = move_position; td[i].opts = opts; td[i].start = start; td[i].node = node; @@ -340,8 +348,6 @@ multidfs(Cube c, Step *s, SolveOptions *opts, AlgList *sols, int d) free(node); free(start_mutex); free(sols_mutex); - free(move_position); - free(sorted_moves); } static bool diff --git a/src/steps.c b/src/steps.c @@ -36,8 +36,11 @@ static int estimate_drudfin_drud(DfsArg *arg); static int estimate_htr_drud(DfsArg *arg); static int estimate_htrfin_htr(DfsArg *arg); static int estimate_optimal_HTM(DfsArg *arg); +static int estimate_nxopt31_HTM(DfsArg *arg); static int estimate_light_HTM(DfsArg *arg); +static int estimate_nxoptlike(DfsArg *arg, PruneData *pd); + static bool always_valid(Alg *alg); static bool validate_singlecw_ending(Alg *alg); @@ -68,7 +71,7 @@ optimal_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = always_valid, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -77,6 +80,25 @@ optimal_HTM = { }; Step +optimal_nxopt31_HTM = { + .shortname = "nxopt31", + .name = "Optimal solve (in HTM), nxopt31 table", + + .final = true, + .is_done = is_solved, + .estimate = estimate_nxopt31_HTM, + .ready = check_centers, + .ready_msg = check_centers_msg, + .is_valid = always_valid, + .moveset = &moveset_HTM, + + .pre_trans = uf, + + .tables = {&pd_nxopt31_HTM, &pd_corners_HTM}, + .ntables = 2, +}; + +Step optimal_light_HTM = { .shortname = "light", .name = "Optimal solve (in HTM), small table (500Mb RAM total)", @@ -87,7 +109,7 @@ optimal_light_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = always_valid, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -107,7 +129,7 @@ eoany_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -126,7 +148,7 @@ eofb_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -145,7 +167,7 @@ eorl_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = ur, @@ -164,7 +186,7 @@ eoud_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = fd, @@ -183,7 +205,7 @@ coany_HTM = { .estimate = estimate_coany_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -201,7 +223,7 @@ coud_HTM = { .estimate = estimate_coud_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -219,7 +241,7 @@ corl_HTM = { .estimate = estimate_coud_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = rf, @@ -237,7 +259,7 @@ cofb_HTM = { .estimate = estimate_coud_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = fd, @@ -255,7 +277,7 @@ coany_URF = { .estimate = estimate_coany_URF, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, + .moveset = &moveset_URF, .pre_trans = uf, @@ -273,7 +295,7 @@ coud_URF = { .estimate = estimate_coud_URF, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, + .moveset = &moveset_URF, .pre_trans = uf, @@ -291,7 +313,7 @@ corl_URF = { .estimate = estimate_coud_URF, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, + .moveset = &moveset_URF, .pre_trans = rf, @@ -309,7 +331,7 @@ cofb_URF = { .estimate = estimate_coud_URF, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, + .moveset = &moveset_URF, .pre_trans = fd, @@ -328,7 +350,7 @@ cornershtr_HTM = { .estimate = estimate_cornershtr_HTM, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -346,7 +368,7 @@ cornershtr_URF = { .estimate = estimate_cornershtr_URF, .ready = NULL, .is_valid = validate_singlecw_ending, - .moveset = moveset_URF, + .moveset = &moveset_URF, .pre_trans = uf, @@ -364,7 +386,7 @@ corners_HTM = { .estimate = estimate_corners_HTM, .ready = NULL, .is_valid = always_valid, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -382,7 +404,7 @@ corners_URF = { .estimate = estimate_corners_URF, .ready = NULL, .is_valid = always_valid, - .moveset = moveset_URF, + .moveset = &moveset_URF, .pre_trans = uf, @@ -402,7 +424,7 @@ drany_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -421,7 +443,7 @@ drud_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = uf, @@ -440,7 +462,7 @@ drrl_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = rf, @@ -459,7 +481,7 @@ drfb_HTM = { .ready = check_centers, .ready_msg = check_centers_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_HTM, + .moveset = &moveset_HTM, .pre_trans = fd, @@ -479,7 +501,7 @@ dr_eo = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .detect = detect_pretrans_eofb, @@ -498,7 +520,7 @@ dr_eofb = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = uf, @@ -517,7 +539,7 @@ dr_eorl = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = ur, @@ -536,7 +558,7 @@ dr_eoud = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = fd, @@ -555,7 +577,7 @@ drud_eofb = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = uf, @@ -574,7 +596,7 @@ drrl_eofb = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = rf, @@ -593,7 +615,7 @@ drud_eorl = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = ur, @@ -612,7 +634,7 @@ drfb_eorl = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = fr, @@ -631,7 +653,7 @@ drfb_eoud = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = fd, @@ -650,7 +672,7 @@ drrl_eoud = { .ready = check_eofb, .ready_msg = check_eo_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_eofb, + .moveset = &moveset_eofb, .pre_trans = rd, @@ -670,7 +692,7 @@ dranyfin_DR = { .ready = check_drud, .ready_msg = check_drany_msg, .is_valid = always_valid, - .moveset = moveset_drud, + .moveset = &moveset_drud, .detect = detect_pretrans_drud, @@ -689,7 +711,7 @@ drudfin_drud = { .ready = check_drud, .ready_msg = check_dr_msg, .is_valid = always_valid, - .moveset = moveset_drud, + .moveset = &moveset_drud, .pre_trans = uf, @@ -708,7 +730,7 @@ drrlfin_drrl = { .ready = check_drud, .ready_msg = check_dr_msg, .is_valid = always_valid, - .moveset = moveset_drud, + .moveset = &moveset_drud, .pre_trans = rf, @@ -727,7 +749,7 @@ drfbfin_drfb = { .ready = check_drud, .ready_msg = check_dr_msg, .is_valid = always_valid, - .moveset = moveset_drud, + .moveset = &moveset_drud, .pre_trans = fd, @@ -747,7 +769,7 @@ htr_any = { .ready = check_drud, .ready_msg = check_drany_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, + .moveset = &moveset_drud, .detect = detect_pretrans_drud, @@ -766,7 +788,7 @@ htr_drud = { .ready = check_drud, .ready_msg = check_dr_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, + .moveset = &moveset_drud, .pre_trans = uf, @@ -785,7 +807,7 @@ htr_drrl = { .ready = check_drud, .ready_msg = check_dr_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, + .moveset = &moveset_drud, .pre_trans = rf, @@ -804,7 +826,7 @@ htr_drfb = { .ready = check_drud, .ready_msg = check_dr_msg, .is_valid = validate_singlecw_ending, - .moveset = moveset_drud, + .moveset = &moveset_drud, .pre_trans = fd, @@ -824,7 +846,7 @@ htrfin_htr = { .ready = check_htr, .ready_msg = check_htr_msg, .is_valid = always_valid, - .moveset = moveset_htr, + .moveset = &moveset_htr, .pre_trans = uf, @@ -834,6 +856,7 @@ htrfin_htr = { Step *steps[NSTEPS] = { &optimal_HTM, /* first is default */ + &optimal_nxopt31_HTM, &optimal_light_HTM, &eoany_HTM, @@ -1183,6 +1206,19 @@ estimate_htrfin_htr(DfsArg *arg) static int estimate_optimal_HTM(DfsArg *arg) { + return estimate_nxoptlike(arg, &pd_khuge_HTM); +} + +static int +estimate_nxopt31_HTM(DfsArg *arg) +{ + return estimate_nxoptlike(arg, &pd_nxopt31_HTM); +} + +/* TODO: also use generic procedure for this */ +static int +estimate_light_HTM(DfsArg *arg) +{ int target, ret; Cube aux; @@ -1192,6 +1228,9 @@ estimate_optimal_HTM(DfsArg *arg) (1<<L) | (1<<L2) | (1<<L3); static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | (1<<B) | (1<<B2) | (1<<B3); + static const uint64_t htmask = (1<<U2) | (1<<D2) | + (1<<R2) | (1<<L2) | + (1<<F2) | (1<<B2); ret = -1; target = arg->d - arg->current_alg->len; @@ -1204,18 +1243,18 @@ estimate_optimal_HTM(DfsArg *arg) UPDATECHECKSTOP(ret, arg->ed->corners, target); /* Normal probing */ - arg->ed->normal_ud = ptableval(&pd_khuge_HTM, arg->cube); + arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube); UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); aux = apply_trans(fd, arg->cube); - arg->ed->normal_fb = ptableval(&pd_khuge_HTM, aux); + arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux); UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); aux = apply_trans(rf, arg->cube); - arg->ed->normal_rl = ptableval(&pd_khuge_HTM, aux); + arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux); UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); /* If ret == 0, it's solved (corners + triple slice solved) */ if (ret == 0) - return 0; + return is_solved(arg->cube) ? 0 : 1; /* Michel de Bondt's trick*/ if (arg->ed->normal_ud == arg->ed->normal_fb && @@ -1224,21 +1263,30 @@ estimate_optimal_HTM(DfsArg *arg) } /* Inverse probing */ - aux = arg->inverse = inverse_cube(arg->cube); - if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) { - arg->ed->inverse_ud = ptableval(&pd_khuge_HTM, aux); - } - UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); - if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) { - aux = apply_trans(fd, arg->inverse); - arg->ed->inverse_fb = ptableval(&pd_khuge_HTM, aux); - } - UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); - if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) { - aux = apply_trans(rf, arg->inverse); - arg->ed->inverse_rl = ptableval(&pd_khuge_HTM, aux); + if (!((1<<arg->last1) & htmask)) { + aux = arg->inverse = inverse_cube(arg->cube); + if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) { + arg->ed->inverse_ud = + ptableval(&pd_drud_sym16_HTM, aux); + } + UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); + if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) { + aux = apply_trans(fd, arg->inverse); + arg->ed->inverse_fb = + ptableval(&pd_drud_sym16_HTM, aux); + } + UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); + if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) { + aux = apply_trans(rf, arg->inverse); + arg->ed->inverse_rl = + ptableval(&pd_drud_sym16_HTM, aux); + } + UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); + } else { + UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); + UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); + UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); } - UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); /* Michel de Bondt's trick*/ if (arg->ed->inverse_ud == arg->ed->inverse_fb && @@ -1246,26 +1294,26 @@ estimate_optimal_HTM(DfsArg *arg) UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); } - /* nxopt trick */ + /* nxopt trick + half turn trick */ if (arg->ed->normal_ud == target) - arg->badmovesinv |= udmask; + arg->badmovesinv |= udmask | htmask; if (arg->ed->normal_fb == target) - arg->badmovesinv |= fbmask; + arg->badmovesinv |= fbmask | htmask; if (arg->ed->normal_rl == target) - arg->badmovesinv |= rlmask; + arg->badmovesinv |= rlmask | htmask; if (arg->ed->inverse_ud == target) - arg->badmoves |= udmask; + arg->badmoves |= udmask | htmask; if (arg->ed->inverse_fb == target) - arg->badmoves |= fbmask; + arg->badmoves |= fbmask | htmask; if (arg->ed->inverse_rl == target) - arg->badmoves |= rlmask; + arg->badmoves |= rlmask | htmask; return arg->ed->oldret = ret; } static int -estimate_light_HTM(DfsArg *arg) +estimate_nxoptlike(DfsArg *arg, PruneData *pd) { int target, ret; Cube aux; @@ -1276,9 +1324,6 @@ estimate_light_HTM(DfsArg *arg) (1<<L) | (1<<L2) | (1<<L3); static const uint64_t fbmask = (1<<F) | (1<<F2) | (1<<F3) | (1<<B) | (1<<B2) | (1<<B3); - static const uint64_t htmask = (1<<U2) | (1<<D2) | - (1<<R2) | (1<<L2) | - (1<<F2) | (1<<B2); ret = -1; target = arg->d - arg->current_alg->len; @@ -1291,18 +1336,17 @@ estimate_light_HTM(DfsArg *arg) UPDATECHECKSTOP(ret, arg->ed->corners, target); /* Normal probing */ - arg->ed->normal_ud = ptableval(&pd_drud_sym16_HTM, arg->cube); + arg->ed->normal_ud = ptableval(pd, arg->cube); UPDATECHECKSTOP(ret, arg->ed->normal_ud, target); aux = apply_trans(fd, arg->cube); - arg->ed->normal_fb = ptableval(&pd_drud_sym16_HTM, aux); + arg->ed->normal_fb = ptableval(pd, aux); UPDATECHECKSTOP(ret, arg->ed->normal_fb, target); aux = apply_trans(rf, arg->cube); - arg->ed->normal_rl = ptableval(&pd_drud_sym16_HTM, aux); + arg->ed->normal_rl = ptableval(pd, aux); UPDATECHECKSTOP(ret, arg->ed->normal_rl, target); - /* If ret == 0, it's solved (corners + triple slice solved) */ if (ret == 0) - return 0; + return arg->step->is_done(arg->cube) ? 0 : 1; /* Michel de Bondt's trick*/ if (arg->ed->normal_ud == arg->ed->normal_fb && @@ -1311,30 +1355,21 @@ estimate_light_HTM(DfsArg *arg) } /* Inverse probing */ - if (!((1<<arg->last1) & htmask)) { - aux = arg->inverse = inverse_cube(arg->cube); - if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud==-1)) { - arg->ed->inverse_ud = - ptableval(&pd_drud_sym16_HTM, aux); - } - UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); - if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb==-1)) { - aux = apply_trans(fd, arg->inverse); - arg->ed->inverse_fb = - ptableval(&pd_drud_sym16_HTM, aux); - } - UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); - if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl==-1)) { - aux = apply_trans(rf, arg->inverse); - arg->ed->inverse_rl = - ptableval(&pd_drud_sym16_HTM, aux); - } - UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); - } else { - UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); - UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); - UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); + aux = arg->inverse = inverse_cube(arg->cube); + if (!((1<<arg->last1) & udmask) || (arg->ed->inverse_ud == -1)) { + arg->ed->inverse_ud = ptableval(pd, aux); + } + UPDATECHECKSTOP(ret, arg->ed->inverse_ud, target); + if (!((1<<arg->last1) & fbmask) || (arg->ed->inverse_fb == -1)) { + aux = apply_trans(fd, arg->inverse); + arg->ed->inverse_fb = ptableval(pd, aux); + } + UPDATECHECKSTOP(ret, arg->ed->inverse_fb, target); + if (!((1<<arg->last1) & rlmask) || (arg->ed->inverse_rl == -1)) { + aux = apply_trans(rf, arg->inverse); + arg->ed->inverse_rl = ptableval(pd, aux); } + UPDATECHECKSTOP(ret, arg->ed->inverse_rl, target); /* Michel de Bondt's trick*/ if (arg->ed->inverse_ud == arg->ed->inverse_fb && @@ -1342,24 +1377,25 @@ estimate_light_HTM(DfsArg *arg) UPDATECHECKSTOP(ret, arg->ed->inverse_ud + 1, target); } - /* nxopt trick + half turn trick */ + /* nxopt trick */ if (arg->ed->normal_ud == target) - arg->badmovesinv |= udmask | htmask; + arg->badmovesinv |= udmask; if (arg->ed->normal_fb == target) - arg->badmovesinv |= fbmask | htmask; + arg->badmovesinv |= fbmask; if (arg->ed->normal_rl == target) - arg->badmovesinv |= rlmask | htmask; + arg->badmovesinv |= rlmask; if (arg->ed->inverse_ud == target) - arg->badmoves |= udmask | htmask; + arg->badmoves |= udmask; if (arg->ed->inverse_fb == target) - arg->badmoves |= fbmask | htmask; + arg->badmoves |= fbmask; if (arg->ed->inverse_rl == target) - arg->badmoves |= rlmask | htmask; + arg->badmoves |= rlmask; return arg->ed->oldret = ret; } + static bool always_valid(Alg *alg) { diff --git a/src/symcoord.c b/src/symcoord.c @@ -4,23 +4,24 @@ #define CLASSES_CP_16 2768 #define CLASSES_EOFBEPOS_16 64430 -static Cube antindex_coud_sym16(uint64_t ind); static Cube antindex_cp_sym16(uint64_t ind); static Cube antindex_eofbepos_sym16(uint64_t ind); static Cube antindex_drud_sym16(uint64_t ind); static Cube antindex_drudfin_noE_sym16(uint64_t ind); static Cube antindex_khuge(uint64_t ind); +static Cube antindex_nxopt31(uint64_t ind); -static uint64_t index_coud_sym16(Cube cube); static uint64_t index_cp_sym16(Cube cube); static uint64_t index_eofbepos_sym16(Cube cube); static uint64_t index_drud_sym16(Cube cube); static uint64_t index_drudfin_noE_sym16(Cube cube); static uint64_t index_khuge(Cube cube); +static uint64_t index_nxopt31(Cube cube); static int transfinder_drud_sym16(uint64_t ind, Trans *ret); static int transfinder_drudfin_noE_sym16(uint64_t ind, Trans *ret); static int transfinder_khuge(uint64_t ind, Trans *ret); +static int transfinder_nxopt31(uint64_t ind, Trans *ret); static void gensym(SymData *sd); static bool read_symdata_file(SymData *sd); @@ -38,15 +39,6 @@ trans_group_udfix[16] = { }; static SymData -sd_coud_16 = { - .filename = "sd_coud_16", - .coord = &coord_coud, - .sym_coord = &coord_coud_sym16, - .ntrans = 16, - .trans = trans_group_udfix -}; - -static SymData sd_cp_16 = { .filename = "sd_cp_16", .coord = &coord_cp, @@ -64,9 +56,8 @@ sd_eofbepos_16 = { .trans = trans_group_udfix }; -static int nsymdata = 3; +static int nsymdata = 2; static SymData * all_sd[] = { - &sd_coud_16, &sd_cp_16, &sd_eofbepos_16, }; @@ -81,12 +72,6 @@ coord_eofbepos_sym16 = { }; Coordinate -coord_coud_sym16 = { - .index = index_coud_sym16, - .cube = antindex_coud_sym16, -}; - -Coordinate coord_cp_sym16 = { .index = index_cp_sym16, .cube = antindex_cp_sym16, @@ -116,13 +101,15 @@ coord_khuge = { .trans = transfinder_khuge, }; -/* Functions *****************************************************************/ +Coordinate +coord_nxopt31 = { + .index = index_nxopt31, + .cube = antindex_nxopt31, + .max = POW3TO7 * BINOM8ON4 * CLASSES_EOFBEPOS_16 , + .trans = transfinder_nxopt31, +}; -static Cube -antindex_coud_sym16(uint64_t ind) -{ - return sd_coud_16.rep[ind]; -} +/* Functions *****************************************************************/ static Cube antindex_cp_sym16(uint64_t ind) @@ -173,10 +160,16 @@ antindex_khuge(uint64_t ind) return c; } -static uint64_t -index_coud_sym16(Cube cube) +static Cube +antindex_nxopt31(uint64_t ind) { - return sd_coud_16.class[coord_coud.index(cube)]; + Cube c; + + c = antindex_eofbepos_sym16(ind/(BINOM8ON4*POW3TO7)); + c.cp = coord_cpud_separate.cube((ind/POW3TO7)%BINOM8ON4).cp; + c.coud = ind % POW3TO7; + + return c; } static uint64_t @@ -229,6 +222,20 @@ index_khuge(Cube cube) return a * POW3TO7 + c.coud; } +static uint64_t +index_nxopt31(Cube cube) +{ + Trans t; + Cube c; + uint64_t a; + + t = sd_eofbepos_16.transtorep[coord_eofbepos.index(cube)]; + c = apply_trans(t, cube); + a = (index_eofbepos_sym16(c)*BINOM8ON4) + coord_cpud_separate.index(c); + + return a * POW3TO7 + c.coud; +} + static int transfinder_drud_sym16(uint64_t ind, Trans *ret) { @@ -295,6 +302,28 @@ transfinder_khuge(uint64_t ind, Trans *ret) return naux[trueind]; } +static int +transfinder_nxopt31(uint64_t ind, Trans *ret) +{ + uint64_t i, trueind; + int j; + static bool initialized = false; + static int naux[CLASSES_EOFBEPOS_16]; + static Trans retaux[CLASSES_EOFBEPOS_16][NTRANS]; + + if (!initialized) { + for (i = 0; i < CLASSES_EOFBEPOS_16; i++) + naux[i] = selfsims(&sd_eofbepos_16, i, retaux[i]); + + initialized = true; + } + + trueind = ind/(BINOM8ON4*POW3TO7); + for (j = 0; j < naux[trueind]; j++) + ret[j] = retaux[trueind][j]; + return naux[trueind]; +} + /* Other functions ***********************************************************/ static void diff --git a/src/symcoord.h b/src/symcoord.h @@ -3,12 +3,12 @@ #include "coord.h" -extern Coordinate coord_coud_sym16; extern Coordinate coord_cp_sym16; extern Coordinate coord_eofbepos_sym16; extern Coordinate coord_drud_sym16; extern Coordinate coord_drudfin_noE_sym16; extern Coordinate coord_khuge; +extern Coordinate coord_nxopt31; void init_symcoord();