commit 569983380edfb3744192b5a652e2ac038840e53d
parent a125e69c8ce0a2764b1e50b2dad0a4fa9d141ef4
Author: Sebastiano Tronto <sebastiano@tronto.net>
Date: Tue, 6 Sep 2022 23:25:31 +0200
Removed some code preparing for moving optimal solver away from general coordinate solving.
Kept symcoord for coordinate solving.
Diffstat:
M | TODO.md | | | 36 | +++++++++++++++++++++--------------- |
M | src/commands.c | | | 20 | ++++++++++---------- |
M | src/cubetypes.h | | | 64 | ++++++++++++++-------------------------------------------------- |
M | src/pruning.c | | | 99 | +++++++++---------------------------------------------------------------------- |
M | src/solve.c | | | 133 | +++++++++++++++++++++++++++++++++++++++++++++---------------------------------- |
M | src/solve.h | | | 2 | +- |
M | src/steps.c | | | 78 | ++++++++++++++---------------------------------------------------------------- |
M | src/steps.h | | | 148 | +++++++++++++++++++++++++++++++------------------------------------------------ |
8 files changed, 204 insertions(+), 376 deletions(-)
diff --git a/TODO.md b/TODO.md
@@ -3,20 +3,28 @@
This is a list of things that I would like to add or change at some point.
It's more of a personal reminder than anything else.
+## After symcoord
+### Solving standard coordinates
+* add Void * extradata to DfsArg and a custom move function
+* add optional custom pre-process for generating special table (nx)
+* copy_dfsdata should copy extra too!
+* Pruning: remove base value?
+### nx.c
+* implement nxopt with all tables and all tricks
+ (maybe compile time variable for maximum memory to use?)
+* custom pruning table, copy some code from pruning.h
+* generate compressed: hard-code the base value, doable!
+* special type of pruning table with fallback and whatnot
+* is_valid should also unniss / cleanup the alg
+### fst_cube
+* slightly different from cube in v2.0.2: each "side" coordinate
+ is a transformation of the other, not an eorl or similar (changes
+ the permutation!)
+* add fst_index for some coordinates?
+* inverse: for edges, just generate ep[12] and convert back
+* corners: big table (150Mb if 16bit integers are used)
+
## For version 2.1
-### Slow: it is slower than the old nissy 2.0.2 :(
-* nxopt's trick (switching to reduce branching) actually saves about 50%!
-* Another factor is estimating *while* moving (i.e. do not move all
- coordinates if the first one already gives a high value!)
-* simplify solve, remove everything that is used only by optimal solvers
-* Good compromise: each stepalt offers one of two alternatives: either solve
- by simply using pruning tables and moving coordinates, or using a custom
- estimator and moving a cube (or fast_cube) and computing coordinates
- in the estimator
-* is there really no way to use inverse branching trick with current system?
-* new file optimal.c with the old solve logic; try first with the simple
- cube implementation and the new indexers, if it is still slow change
- to fast_cube (intermediate nissy v2.0.2 implementation)
### Changes to Step and Solve
* remove cube from dfsarg? (i still need to save the scramble somewhere,
but I really only use it in dfs_niss)
@@ -24,8 +32,6 @@ It's more of a personal reminder than anything else.
* steps.c: checkers (use coordinates), all stepalt and steps (WIP...)
* commands gen and freemem
* commands.c: twophase, ...?
-* Coordinate should have a moveset field? No, at worst there are some garbage
- values in mtable, but no risk for errors
### Rotate, not transform, before solving
* solve should re-orient first if needed and not just give up if centers are off
### Documentation
diff --git a/src/commands.c b/src/commands.c
@@ -2,7 +2,7 @@
#include "commands.h"
-static bool read_step(CommandArgs *args, char *str);
+static bool read_cs(CommandArgs *args, char *str);
static bool read_scrtype(CommandArgs *args, char *str);
static bool read_scramble(int c, char **v, CommandArgs *args);
@@ -95,7 +95,7 @@ solve_parse_args(int c, char **v)
a->opts->print_number = false;
} else if (!strcmp(v[i], "-c")) {
a->opts->count_only = true;
- } else if (!read_step(a, v[i])) {
+ } else if (!read_cs(a, v[i])) {
break;
}
}
@@ -218,7 +218,7 @@ solve_exec(CommandArgs *args)
make_solved(&c);
apply_alg(args->scramble, &c);
- sols = solve(&c, args->step, args->opts);
+ sols = solve(&c, args->cs, args->opts);
if (args->opts->count_only)
printf("%d\n", sols->len);
@@ -345,8 +345,8 @@ steps_exec(CommandArgs *args)
{
int i;
- for (i = 0; steps[i] != NULL; i++)
- printf("%-15s %s\n", steps[i]->shortname, steps[i]->name);
+ for (i = 0; csteps[i] != NULL; i++)
+ printf("%-15s %s\n", csteps[i]->shortname, csteps[i]->name);
}
void
@@ -503,13 +503,13 @@ read_scrtype(CommandArgs *args, char *str)
}
static bool
-read_step(CommandArgs *args, char *str)
+read_cs(CommandArgs *args, char *str)
{
int i;
- for (i = 0; steps[i] != NULL; i++) {
- if (!strcmp(steps[i]->shortname, str)) {
- args->step = steps[i];
+ for (i = 0; csteps[i] != NULL; i++) {
+ if (!strcmp(csteps[i]->shortname, str)) {
+ args->cs = csteps[i];
return true;
}
}
@@ -546,7 +546,7 @@ new_args()
args->opts = malloc(sizeof(SolveOptions));
/* step and command are static */
- args->step = steps[0]; /* default: first step in list */
+ args->cs = csteps[0]; /* default: first step in list */
args->command = NULL;
return args;
diff --git a/src/cubetypes.h b/src/cubetypes.h
@@ -84,7 +84,7 @@ trans
typedef struct alg Alg;
typedef struct alglist AlgList;
typedef struct alglistnode AlgListNode;
-typedef struct block Block;
+typedef struct choicestep ChoiceStep;
typedef struct command Command;
typedef struct commandargs CommandArgs;
typedef struct coordinate Coordinate;
@@ -97,13 +97,14 @@ typedef struct pdgendata PDGenData;
typedef struct prunedata PruneData;
typedef struct solveoptions SolveOptions;
typedef struct step Step;
-typedef struct stepalt StepAlt;
typedef struct symdata SymData;
typedef struct threaddatasolve ThreadDataSolve;
typedef struct threaddatagenpt ThreadDataGenpt;
typedef struct transgroup TransGroup;
typedef bool (*Checker) (Cube *);
+typedef bool (*DfsMover) (DfsArg *);
+typedef void (*DfsExtraCopier) (void *, void *);
typedef bool (*Validator) (Alg *);
typedef void (*Exec) (CommandArgs *);
typedef CommandArgs * (*ArgParser) (int, char **);
@@ -137,11 +138,13 @@ alglistnode
};
struct
-block
+choicestep
{
- bool edge[12];
- bool corner[8];
- bool center[6];
+ char * shortname;
+ char * name;
+ Step * step[99];
+ Trans t[99];
+ char * ready_msg;
};
struct
@@ -160,7 +163,7 @@ commandargs
bool success;
Alg * scramble;
SolveOptions * opts;
- Step * step;
+ ChoiceStep * cs;
Command * command; /* For help */
int n;
char scrtype[20];
@@ -210,7 +213,7 @@ dfsarg
Cube * cube;
Movable ind[MAX_N_COORD];
Trans t;
- StepAlt * sa;
+ Step * s;
SolveOptions * opts;
int d;
int bound;
@@ -220,6 +223,7 @@ dfsarg
AlgList * sols;
pthread_mutex_t * sols_mutex;
Alg * current_alg;
+ void * extra;
};
struct
@@ -245,7 +249,6 @@ pdgendata
{
Coordinate * coord;
Moveset * moveset;
- bool compact;
PruneData * pd;
};
@@ -256,10 +259,7 @@ prunedata
uint64_t n;
Coordinate * coord;
Moveset * moveset;
- bool compact;
- int base;
uint64_t count[16];
- uint64_t fbmod;
};
struct
@@ -280,54 +280,18 @@ solveoptions
struct
step
{
- char * shortname;
- char * name;
- StepAlt * alt[99];
- Trans t[99];
- char * ready_msg;
-};
-
-struct
-stepalt
-{
Checker ready;
bool final;
Moveset * moveset;
- /* Just a comment, (TODO: remove this): moveset is really a stepalt
- * property, because for example we may want to define a "fingertrick
- * friendly ZBLL" step, where we allow either <R U D> or <R U F> as
- * movesets (or similar) */
int n_coord;
Coordinate * coord[MAX_N_COORD];
Trans coord_trans[MAX_N_COORD];
PruneData * pd[MAX_N_COORD];
- bool compact_pd[MAX_N_COORD];
- Coordinate * fallback_coord[MAX_N_COORD];
- PruneData * fallback_pd[MAX_N_COORD];
- uint64_t fbmod[MAX_N_COORD];
- int n_dbtrick;
- int dbtrick[MAX_N_COORD][3];
Validator is_valid;
+ DfsMover custom_move_checkstop;
+ DfsExtraCopier copy_extra;
};
-/*
-struct
-symdata
-{
- char * filename;
- bool generated;
- Coordinate * coord;
- Coordinate * sym_coord;
- int ntrans;
- Trans * trans;
- uint64_t * class;
- uint64_t * unsym;
- Trans * transtorep;
- uint64_t * selfsim;
-};
-*/
-
-
struct
threaddatasolve
{
diff --git a/src/pruning.c b/src/pruning.c
@@ -3,13 +3,10 @@
#include "pruning.h"
#define ENTRIES_PER_GROUP (2*sizeof(entry_group_t))
-#define ENTRIES_PER_GROUP_COMPACT (4*sizeof(entry_group_t))
static int findchunk(PruneData *pd, int nchunks, uint64_t i);
static void genptable_bfs(PruneData *pd, int d, int nt, int nc);
-static void genptable_compress(PruneData *pd);
static void genptable_fixnasty(PruneData *pd, int d, int nthreads);
-static void genptable_setbase(PruneData *pd);
static void * instance_bfs(void *arg);
static void * instance_fixnasty(void *arg);
static void ptable_update(PruneData *pd, uint64_t ind, int m);
@@ -32,16 +29,13 @@ findchunk(PruneData *pd, int nchunks, uint64_t i)
PruneData *
genptable(PDGenData *pdg, int nthreads)
{
- bool compact;
int d, nchunks, i;
- uint64_t oldn, sz;
+ uint64_t oldn;
PruneData *pd;
for (i = 0; active_pdg[i] != NULL; i++) {
pd = active_pdg[i]->pd;
- if (pd->coord == pdg->coord &&
- pd->moveset == pdg->moveset &&
- pd->compact == pdg->compact)
+ if (pd->coord == pdg->coord && pd->moveset == pdg->moveset)
return pd;
}
@@ -49,10 +43,7 @@ genptable(PDGenData *pdg, int nthreads)
pdg->pd = pd;
pd->coord = pdg->coord;
pd->moveset = pdg->moveset;
- pd->compact = pdg->compact;
-
- sz = ptablesize(pd) * (pd->compact ? 2 : 1);
- pd->ptable = malloc(sz * sizeof(entry_group_t));
+ pd->ptable = malloc(ptablesize(pd) * sizeof(entry_group_t));
gen_coord(pd->coord);
@@ -70,11 +61,6 @@ genptable(PDGenData *pdg, int nthreads)
);
}
-
- /* For the first steps we proceed the same way for compact and not */
- compact = pd->compact;
- pd->compact = false;
-
nchunks = MIN(ptablesize(pd), 100000);
fprintf(stderr, "Generating pt_%s_%s with %d threads\n",
pd->coord->name, pd->moveset->name, nthreads);
@@ -102,10 +88,6 @@ genptable(PDGenData *pdg, int nthreads)
oldn = pd->n;
}
fprintf(stderr, "Pruning table generated!\n");
-
- genptable_setbase(pd);
- if (compact)
- genptable_compress(pd);
if (!write_ptable_file(pd))
fprintf(stderr, "Error writing ptable file\n");
@@ -115,7 +97,6 @@ genptable_done:
active_pdg[i] = malloc(sizeof(PDGenData));
active_pdg[i]->coord = pdg->coord;
active_pdg[i]->moveset = pdg->moveset;
- active_pdg[i]->compact = pdg->compact;
active_pdg[i]->pd = pd;
return pd;
@@ -156,31 +137,6 @@ genptable_bfs(PruneData *pd, int d, int nthreads, int nchunks)
}
static void
-genptable_compress(PruneData *pd)
-{
- int val;
- uint64_t i, j;
- entry_group_t mask, v;
-
- fprintf(stderr, "Compressing table to 2 bits per entry\n");
-
- for (i = 0; i < pd->coord->max; i += ENTRIES_PER_GROUP_COMPACT) {
- mask = (entry_group_t)0;
- for (j = 0; j < ENTRIES_PER_GROUP_COMPACT; j++) {
- if (i+j >= pd->coord->max)
- break;
- val = ptableval(pd, i+j) - pd->base;
- v = (entry_group_t)MIN(3, MAX(0, val));
- mask |= v << (2*j);
- }
- pd->ptable[i/ENTRIES_PER_GROUP_COMPACT] = mask;
- }
-
- pd->compact = true;
- pd->ptable = realloc(pd->ptable, sizeof(entry_group_t)*ptablesize(pd));
-}
-
-static void
genptable_fixnasty(PruneData *pd, int d, int nthreads)
{
int i;
@@ -208,22 +164,6 @@ genptable_fixnasty(PruneData *pd, int d, int nthreads)
free(upmtx);
}
-static void
-genptable_setbase(PruneData *pd)
-{
- int i;
- uint64_t sum, newsum;
-
- pd->base = 0;
- sum = pd->count[0] + pd->count[1] + pd->count[2];
- for (i = 3; i < 16; i++) {
- newsum = sum + pd->count[i] - pd->count[i-3];
- if (newsum > sum)
- pd->base = i-3;
- sum = newsum;
- }
-}
-
static void *
instance_bfs(void *arg)
{
@@ -317,7 +257,6 @@ print_ptable(PruneData *pd)
uint64_t i;
printf("Table %s_%s\n", pd->coord->name, pd->moveset->name);
- printf("Base value: %d\n", pd->base);
for (i = 0; i < 16; i++)
printf("%2" PRIu64 "\t%10" PRIu64 "\n", i, pd->count[i]);
}
@@ -325,11 +264,7 @@ print_ptable(PruneData *pd)
uint64_t
ptablesize(PruneData *pd)
{
- uint64_t e;
-
- e = pd->compact ? ENTRIES_PER_GROUP_COMPACT : ENTRIES_PER_GROUP;
-
- return (pd->coord->max + e - 1) / e;
+ return (pd->coord->max + ENTRIES_PER_GROUP - 1) / ENTRIES_PER_GROUP;
}
static void
@@ -350,23 +285,11 @@ ptable_update(PruneData *pd, uint64_t ind, int n)
int
ptableval(PruneData *pd, uint64_t ind)
{
- int sh, ret;
- uint64_t e;
- entry_group_t m;
-
- if (pd->compact) {
- e = ENTRIES_PER_GROUP_COMPACT;
- m = 3;
- sh = (ind % e) * 2;
- } else {
- e = ENTRIES_PER_GROUP;
- m = 15;
- sh = (ind % e) * 4;
- }
+ int sh;
- ret = (pd->ptable[ind/e] & (m << sh)) >> sh;
+ sh = (ind % ENTRIES_PER_GROUP) * 4;
- return pd->compact ? ret + pd->base : ret;
+ return (pd->ptable[ind/ENTRIES_PER_GROUP] & (15 << sh)) >> sh;
}
static bool
@@ -376,7 +299,7 @@ read_ptable_file(PruneData *pd)
FILE *f;
char fname[strlen(tabledir)+256];
- int i;
+ int i, phony;
uint64_t r;
strcpy(fname, tabledir);
@@ -388,7 +311,7 @@ read_ptable_file(PruneData *pd)
if ((f = fopen(fname, "rb")) == NULL)
return false;
- r = fread(&(pd->base), sizeof(int), 1, f);
+ r = fread(&phony, sizeof(int), 1, f);
for (i = 0; i < 16; i++)
r += fread(&(pd->count[i]), sizeof(uint64_t), 1, f);
r += fread(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f);
@@ -405,7 +328,7 @@ write_ptable_file(PruneData *pd)
FILE *f;
char fname[strlen(tabledir)+256];
- int i;
+ int i, phony = 0;
uint64_t w;
strcpy(fname, tabledir);
@@ -417,7 +340,7 @@ write_ptable_file(PruneData *pd)
if ((f = fopen(fname, "wb")) == NULL)
return false;
- w = fwrite(&(pd->base), sizeof(int), 1, f);
+ w = fwrite(&phony, sizeof(int), 1, f); /* phony replace base */
for (i = 0; i < 16; i++)
w += fwrite(&(pd->count[i]), sizeof(uint64_t), 1, f);
w += fwrite(pd->ptable, sizeof(entry_group_t), ptablesize(pd), f);
diff --git a/src/solve.c b/src/solve.c
@@ -4,7 +4,7 @@
/* Local functions ***********************************************************/
-static bool allowed_next(Move move, StepAlt *sa, Move l0, Move l1);
+static bool allowed_next(Move move, Step *s, Move l0, Move l1);
static bool cancel_niss(DfsArg *arg);
static void copy_dfsarg(DfsArg *src, DfsArg *dst);
static void dfs(DfsArg *arg);
@@ -19,13 +19,13 @@ static bool solvestop(int d, int op, SolveOptions *opts, AlgList *sols);
/* Local functions ***********************************************************/
static bool
-allowed_next(Move m, StepAlt *sa, Move l0, Move l1)
+allowed_next(Move m, Step *s, Move l0, Move l1)
{
bool allowed, order;
uint64_t mbit;
mbit = ((uint64_t)1) << m;
- allowed = mbit & sa->moveset->mask[l1][l0];
+ allowed = mbit & s->moveset->mask[l1][l0];
order = !commute(l0, m) || l0 < m;
return allowed && order;
@@ -41,7 +41,7 @@ cancel_niss(DfsArg *arg)
if (arg->lastinv[0] == NULLMOVE)
return false;
- ms = arg->sa->moveset;
+ ms = arg->s->moveset;
i1 = inverse_move(arg->lastinv[0]);
i2 = inverse_move(arg->lastinv[1]);
@@ -63,7 +63,7 @@ copy_dfsarg(DfsArg *src, DfsArg *dst)
dst->cube = src->cube;
dst->t = src->t;
- dst->sa = src->sa;
+ dst->s = src->s;
dst->opts = src->opts;
dst->d = src->d;
dst->bound = src->bound; /* In theory not needed */
@@ -77,10 +77,14 @@ copy_dfsarg(DfsArg *src, DfsArg *dst)
dst->lastinv[i] = src->lastinv[i];
}
- for (i = 0; i < src->sa->n_coord; i++) {
+ for (i = 0; i < src->s->n_coord; i++) {
dst->ind[i].val = src->ind[i].val;
dst->ind[i].t = src->ind[i].t;
}
+
+/*
+ src->s->copy_extra(src, dst);
+*/
}
static void
@@ -99,9 +103,9 @@ dfs(DfsArg *arg)
return;
}
- for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) {
- m = arg->sa->moveset->sorted_moves[i];
- if (allowed_next(m, arg->sa, arg->last[0], arg->last[1])) {
+ for (i = 0; arg->s->moveset->sorted_moves[i] != NULLMOVE; i++) {
+ m = arg->s->moveset->sorted_moves[i];
+ if (allowed_next(m, arg->s, arg->last[0], arg->last[1])) {
copy_dfsarg(arg, &newarg);
newarg.last[1] = arg->last[0];
newarg.last[0] = m;
@@ -120,9 +124,9 @@ dfs_add_sol(DfsArg *arg)
{
bool valid, accepted, nisscanc;
- valid = arg->sa->is_valid==NULL || arg->sa->is_valid(arg->current_alg);
+ valid = arg->s->is_valid==NULL || arg->s->is_valid(arg->current_alg);
accepted = valid || arg->opts->all;
- nisscanc = arg->sa->final && cancel_niss(arg);
+ nisscanc = arg->s->final && cancel_niss(arg);
if (accepted && !nisscanc) {
pthread_mutex_lock(arg->sols_mutex);
@@ -159,7 +163,7 @@ dfs_niss(DfsArg *arg)
compose(c, newarg.cube);
/* New indexes */
- compute_ind(newarg.sa, newarg.cube, newarg.ind);
+ compute_ind(newarg.s, newarg.cube, newarg.ind);
swapmove(&(newarg.last[0]), &(newarg.lastinv[0]));
swapmove(&(newarg.last[1]), &(newarg.lastinv[1]));
@@ -175,36 +179,35 @@ dfs_niss(DfsArg *arg)
static bool
dfs_move_checkstop(DfsArg *arg)
{
- bool b;
- int i, goal;
+ int i, goal, nsols;
Move mm;
Trans tt = uf; /* Avoid uninitialized warning */
- /* Moving */
- if (arg->last[0] != NULLMOVE) {
- for (i = 0; i < arg->sa->n_coord; i++) {
+ /* Moving and computing bound */
+ arg->bound = 0;
+ goal = arg->d - arg->current_alg->len;
+ for (i = 0; i < arg->s->n_coord; i++) {
+ if (arg->last[0] != NULLMOVE) {
mm = transform_move(arg->ind[i].t, arg->last[0]);
- arg->ind[i].val = move_coord(arg->sa->coord[i],
+ arg->ind[i].val = move_coord(arg->s->coord[i],
mm, arg->ind[i].val, &tt);
arg->ind[i].t = transform_trans(tt, arg->ind[i].t);
}
- }
- /* Computing bound for coordinates */
- goal = arg->d - arg->current_alg->len;
- arg->bound = estimate_stepalt(arg->sa, arg->ind, goal);
- if (arg->opts->can_niss && !arg->niss)
- arg->bound = MIN(1, arg->bound);
+ arg->bound =
+ MAX(arg->bound, ptableval(arg->s->pd[i], arg->ind[i].val));
+ if (arg->opts->can_niss && !arg->niss)
+ arg->bound = MIN(1, arg->bound);
- if (arg->bound > goal) {
- b = true;
- } else {
- pthread_mutex_lock(arg->sols_mutex);
- b = arg->sols->len >= arg->opts->max_solutions;
- pthread_mutex_unlock(arg->sols_mutex);
+ if (arg->bound > goal)
+ return true;
}
- return b;
+ pthread_mutex_lock(arg->sols_mutex);
+ nsols = arg->sols->len;
+ pthread_mutex_unlock(arg->sols_mutex);
+
+ return nsols >= arg->opts->max_solutions;
}
static void *
@@ -240,7 +243,7 @@ instance_thread(void *arg)
invert_cube(&c);
copy_dfsarg(&td->arg, &darg);
- compute_ind(td->arg.sa, &c, darg.ind);
+ compute_ind(td->arg.s, &c, darg.ind);
darg.cube = &c;
darg.niss = inv;
@@ -279,11 +282,11 @@ multidfs(DfsArg *arg)
pthread_mutex_init(start_mutex, NULL);
pthread_mutex_init(sols_mutex, NULL);
- for (i = 0; arg->sa->moveset->sorted_moves[i] != NULLMOVE; i++) {
+ for (i = 0; arg->s->moveset->sorted_moves[i] != NULLMOVE; i++) {
alg = new_alg("");
- append_move(alg, arg->sa->moveset->sorted_moves[i], false);
+ append_move(alg, arg->s->moveset->sorted_moves[i], false);
append_alg(start, alg);
- if (arg->opts->can_niss && !arg->sa->final) {
+ if (arg->opts->can_niss && !arg->s->final) {
alg->inv[0] = true;
append_alg(start, alg);
}
@@ -318,15 +321,25 @@ multidfs(DfsArg *arg)
static bool
niss_makes_sense(DfsArg *arg)
{
- Cube testcube;
+ Move m, mm;
+ uint64_t u;
+ int i;
- if (arg->sa->final || arg->niss || !arg->opts->can_niss)
+ if (arg->s->final || arg->niss || !arg->opts->can_niss)
return false;
- make_solved(&testcube);
- apply_move(inverse_move(arg->last[0]), &testcube);
- return arg->current_alg->len == 0 ||
- estimate_stepalt(arg->sa, arg->ind, 0) > 0;
+ if (arg->last[0] == NULLMOVE)
+ return true;
+
+ m = inverse_move(arg->last[0]);
+ for (i = 0; i < arg->s->n_coord; i++) {
+ mm = transform_move(arg->ind[i].t, m);
+ u = move_coord(arg->s->coord[i], mm, 0, NULL);
+ if (ptableval(arg->s->pd[i], u) > 0)
+ return true;
+ }
+
+ return false;
}
static bool
@@ -344,38 +357,38 @@ solvestop(int d, int op, SolveOptions *opts, AlgList *sols)
/* Public functions **********************************************************/
AlgList *
-solve(Cube *cube, Step *step, SolveOptions *opts)
+solve(Cube *cube, ChoiceStep *cs, SolveOptions *opts)
{
- int i, d, op;
+ int i, j, d, op, est;
bool ready[99], one_ready, zerosol;
Movable ind[99][10];
AlgList *s;
Cube *c[99];
DfsArg arg[99];
- prepare_step(step, opts);
+ prepare_cs(cs, opts);
s = new_alglist();
- for (i = 0, one_ready = false; step->alt[i] != NULL; i++) {
+ for (i = 0, one_ready = false; cs->step[i] != NULL; i++) {
c[i] = malloc(sizeof(Cube));
copy_cube(cube, c[i]);
- apply_trans(step->t[i], c[i]);
+ apply_trans(cs->t[i], c[i]);
arg[i].cube = c[i];
- arg[i].t = step->t[i];
- arg[i].sa = step->alt[i];
+ arg[i].t = cs->t[i];
+ arg[i].s = cs->step[i];
arg[i].opts = opts;
arg[i].sols = s;
- if ((ready[i] = step->alt[i]->ready(c[i]))) {
+ if ((ready[i] = cs->step[i]->ready(c[i]))) {
one_ready = true;
/* Only for local use for 0 moves solutions */
- compute_ind(step->alt[i], c[i], ind[i]);
+ compute_ind(cs->step[i], c[i], ind[i]);
}
}
if (!one_ready) {
fprintf(stderr, "Cube not ready for solving step: ");
- fprintf(stderr, "%s\n", step->ready_msg);
+ fprintf(stderr, "%s\n", cs->ready_msg);
return s;
}
@@ -383,10 +396,16 @@ solve(Cube *cube, Step *step, SolveOptions *opts)
* alternatives, all longer solutions will be discarded, so we may
* just set its ready[] value to false. If the solution is accepted
* we append it and start searching from d = 1. */
- for (i = 0, zerosol = false; step->alt[i] != NULL; i++) {
- if (ready[i] && estimate_stepalt(step->alt[i],ind[i],0) == 0) {
- ready[i] = false;
- zerosol = true;
+ for (i = 0, zerosol = false; cs->step[i] != NULL; i++) {
+ if (ready[i]) {
+ est = 0;
+ for (j = 0; j < cs->step[i]->n_coord; j++)
+ est = MAX(est, ptableval(cs->step[i]->pd[j],
+ ind[i][j].val));
+ if (est == 0) {
+ ready[i] = false;
+ zerosol = true;
+ }
}
}
if (zerosol && opts->min_moves == 0) {
@@ -401,7 +420,7 @@ solve(Cube *cube, Step *step, SolveOptions *opts)
if (opts->verbose)
fprintf(stderr, "Searching depth %d\n", d);
- for (i=0; step->alt[i]!=NULL && !solvestop(d,op,opts,s); i++) {
+ for (i=0; cs->step[i]!=NULL && !solvestop(d,op,opts,s); i++) {
if (!ready[i])
continue;
@@ -413,7 +432,7 @@ solve(Cube *cube, Step *step, SolveOptions *opts)
}
}
- for (i = 0; step->alt[i] != NULL; i++)
+ for (i = 0; cs->step[i] != NULL; i++)
free(c[i]);
return s;
diff --git a/src/solve.h b/src/solve.h
@@ -5,7 +5,7 @@
#include "steps.h"
#include "trans.h"
-AlgList * solve(Cube *cube, Step *step, SolveOptions *opts);
+AlgList * solve(Cube *cube, ChoiceStep *cs, SolveOptions *opts);
Alg * solve_2phase(Cube *cube, int nthreads);
#endif
diff --git a/src/steps.c b/src/steps.c
@@ -132,90 +132,40 @@ validate_singlecw_ending(Alg *alg)
/* Public functions **********************************************************/
void
-compute_ind(StepAlt *a, Cube *cube, Movable *ind)
+compute_ind(Step *s, Cube *cube, Movable *ind)
{
int i;
Cube mvd;
Trans t, tt;
- for (i = 0; i < a->n_coord; i++) {
- t = a->coord_trans[i];
+ for (i = 0; i < s->n_coord; i++) {
+ t = s->coord_trans[i];
copy_cube(cube, &mvd);
apply_trans(t, &mvd);
- ind[i].val = index_coord(a->coord[i], &mvd, &tt);
+ ind[i].val = index_coord(s->coord[i], &mvd, &tt);
ind[i].t = transform_trans(tt, t);
}
}
-int
-estimate_stepalt(StepAlt *a, Movable *ind, int goal)
-{
- int i, ret, est[a->n_coord];
-
- for (i = 0; i < a->n_coord; i++) {
- est[i] = ptableval(a->pd[i], ind[i].val);
- if (est[i] == a->pd[i]->base && a->compact_pd[i])
- est[i] = ptableval(a->fallback_pd[i],
- ind[i].val/a->fbmod[i]);
- if (ind[i].val != 0 && est[i] == 0) /* est == 0 iff solved */
- est[i] = 1;
-/*
-TODO: remove this debug code
-printf("%d: est=%d | ", i, est[i]);
-*/
-
- if (est[i] > goal)
- return est[i];
- }
-
- for (i = 0; i < a->n_dbtrick; i++)
- if (est[a->dbtrick[i][0]] > 0 &&
- est[a->dbtrick[i][0]] == est[a->dbtrick[i][1]] &&
- est[a->dbtrick[i][0]] == est[a->dbtrick[i][2]])
- est[a->dbtrick[i][0]] += 1;
-
- for (i = 0, ret = -1; i < a->n_coord; i++)
- ret = MAX(ret, est[i]);
-
-/*
-TODO: remove this debug code
-printf("Final estimate: %d\n", ret);
-*/
-
- return ret;
-}
-
void
-prepare_step(Step *step, SolveOptions *opts)
+prepare_cs(ChoiceStep *cs, SolveOptions *opts)
{
int i, j;
PDGenData pdg;
- StepAlt *a;
+ Step *s;
- for (i = 0; step->alt[i] != NULL; i++) {
- a = step->alt[i];
- init_moveset(a->moveset);
- pdg.moveset = a->moveset;
- for (j = 0; j < a->n_coord; j++) {
- gen_coord(a->coord[j]);
+ for (i = 0; cs->step[i] != NULL; i++) {
+ s = cs->step[i];
+ init_moveset(s->moveset);
+ pdg.moveset = s->moveset;
+ for (j = 0; j < s->n_coord; j++) {
+ gen_coord(s->coord[j]);
- pdg.coord = a->coord[j];
- pdg.compact = a->compact_pd[j];
+ pdg.coord = s->coord[j];
pdg.pd = NULL;
- a->pd[j] = genptable(&pdg, opts->nthreads);
-
- if (a->compact_pd[j]) {
- gen_coord(a->fallback_coord[j]);
-
- pdg.coord = a->fallback_coord[j];
- pdg.compact = false;
- pdg.pd = NULL;
-
- a->fallback_pd[j] =
- genptable(&pdg, opts->nthreads);
- }
+ s->pd[j] = genptable(&pdg, opts->nthreads);
}
}
}
diff --git a/src/steps.h b/src/steps.h
@@ -13,9 +13,8 @@ bool check_cornershtr(Cube *cube);
bool check_eofb(Cube *cube);
bool check_drud(Cube *cube);
bool check_htr(Cube *cube);
-void compute_ind(StepAlt *a, Cube *cube, Movable *ind);
-int estimate_stepalt(StepAlt *a, Movable *ind, int goal);
-void prepare_step(Step *step, SolveOptions *opts);
+void compute_ind(Step *a, Cube *cube, Movable *ind);
+void prepare_cs(ChoiceStep *cs, SolveOptions *opts);
bool always_valid(Alg *alg);
bool validate_singlecw_ending(Alg *alg);
@@ -27,26 +26,25 @@ extern char check_dr_msg[100];
extern char check_htr_msg[100];
extern char check_drany_msg[100];
-extern StepAlt sa_nxopt31_HTM;
-extern StepAlt sa_eofb_HTM;
-extern StepAlt sa_drud_HTM;
-extern StepAlt sa_drfin_drud;
-
-extern Step optimal_HTM;
-extern Step eoany_HTM;
-extern Step eofb_HTM;
-extern Step eorl_HTM;
-extern Step eoud_HTM;
-extern Step drany_HTM;
-extern Step drud_HTM;
-extern Step drrl_HTM;
-extern Step drfb_HTM;
-extern Step dranyfin_DR;
-extern Step drudfin_drud;
-extern Step drrlfin_drrl;
-extern Step drfbfin_drfb;
-
-extern Step *steps[];
+extern Step step_eofb_HTM;
+extern Step step_drud_HTM;
+extern Step step_drfin_drud;
+
+extern ChoiceStep optimal_HTM;
+extern ChoiceStep eoany_HTM;
+extern ChoiceStep eofb_HTM;
+extern ChoiceStep eorl_HTM;
+extern ChoiceStep eoud_HTM;
+extern ChoiceStep drany_HTM;
+extern ChoiceStep drud_HTM;
+extern ChoiceStep drrl_HTM;
+extern ChoiceStep drfb_HTM;
+extern ChoiceStep dranyfin_DR;
+extern ChoiceStep drudfin_drud;
+extern ChoiceStep drrlfin_drrl;
+extern ChoiceStep drfbfin_drfb;
+
+extern ChoiceStep *csteps[];
#else
@@ -56,83 +54,51 @@ char check_dr_msg[100] = "DR must be solved on given axis";
char check_htr_msg[100] = "HTR must be solved";
char check_drany_msg[100] = "DR must be solved on at least one axis";
-/* Optimal solvers *******************/
-/* TODO: build options for smaller optimal solvers */
-
-StepAlt
-sa_nxopt31_HTM = {
- .ready = check_centers,
- .final = true,
- .moveset = &moveset_HTM,
- .n_coord = 6,
- .coord = {&coord_nxopt31, &coord_nxopt31, &coord_nxopt31,
- &coord_eposepe, &coord_eposepe, &coord_eposepe},
- /* TODO: use khuge as fallback? */
- .coord_trans = {uf, rd, bl, uf, rd, bl},
- .compact_pd = {true, true, true, false, false, false},
- .fallback_coord = {&coord_drud_sym16, &coord_drud_sym16,
- &coord_drud_sym16},
- .fbmod = {BINOM8ON4, BINOM8ON4, BINOM8ON4},
- .n_dbtrick = 1, /* TODO: change to 2 when khuge */
- .dbtrick = {{0, 1, 2}},
- .is_valid = NULL,
-};
-Step
-optimal_HTM = {
- .shortname = "optimal",
- .name = "Optimal solve (in HTM)",
- .alt = {&sa_nxopt31_HTM, NULL},
- .t = {uf},
- .ready_msg = check_centers_msg,
-};
-
/* Optimal after EO ******************/
/* TODO: eofin_eo (generic), eofbfin_eofb, eorlfin_eorl, eoudfin_eoud */
/* EO steps **************************/
/* TODO: eoany_HTM (generic), eofb_HTM, eorl_HTM, eoud_HTM */
-StepAlt
-sa_eofb_HTM = {
+Step
+step_eofb_HTM = {
.ready = check_centers,
.final = false,
.moveset = &moveset_HTM,
.n_coord = 1,
.coord = {&coord_eofb},
.coord_trans = {uf},
- .compact_pd = {false},
- .n_dbtrick = 0,
.is_valid = validate_singlecw_ending,
};
-Step
+ChoiceStep
eoany_HTM = {
.shortname = "eo",
.name = "EO on any axis",
- .alt = {&sa_eofb_HTM, &sa_eofb_HTM, &sa_eofb_HTM, NULL},
+ .step = {&step_eofb_HTM, &step_eofb_HTM, &step_eofb_HTM, NULL},
.t = {uf, ur, fd},
.ready_msg = check_centers_msg,
};
-Step
+ChoiceStep
eofb_HTM = {
.shortname = "eofb",
.name = "EO on F/B",
- .alt = {&sa_eofb_HTM, NULL},
+ .step = {&step_eofb_HTM, NULL},
.t = {uf},
.ready_msg = check_centers_msg,
};
-Step
+ChoiceStep
eorl_HTM = {
.shortname = "eorl",
.name = "EO on R/L",
- .alt = {&sa_eofb_HTM, NULL},
+ .step = {&step_eofb_HTM, NULL},
.t = {ur},
.ready_msg = check_centers_msg,
};
-Step
+ChoiceStep
eoud_HTM = {
.shortname = "eoud",
.name = "EO on U/D",
- .alt = {&sa_eofb_HTM, NULL},
+ .step = {&step_eofb_HTM, NULL},
.t = {fd},
.ready_msg = check_centers_msg,
};
@@ -150,93 +116,90 @@ eoud_HTM = {
/* TODO: dr_eofb (generic), dr_eorl (generic), dr_eoud (generic) */
/* TODO: drud_eofb, drrl_eofb, drud_eorl, drfb_eorl, drrl_eoud, drfb_eoud */
-StepAlt
-sa_drud_HTM = {
+Step
+step_drud_HTM = {
.ready = check_centers,
.final = false,
.moveset = &moveset_HTM,
.n_coord = 1,
.coord = {&coord_drud_sym16},
.coord_trans = {uf},
- .compact_pd = {false}, /* TODO: maybe compactify */
- .n_dbtrick = 0,
.is_valid = validate_singlecw_ending,
};
-Step
+ChoiceStep
drany_HTM = {
.shortname = "dr",
.name = "DR on any axis",
- .alt = {&sa_drud_HTM, &sa_drud_HTM, &sa_drud_HTM, NULL},
+ .step = {&step_drud_HTM, &step_drud_HTM, &step_drud_HTM, NULL},
.t = {uf, rf, fd},
.ready_msg = check_centers_msg,
};
-Step
+ChoiceStep
drud_HTM = {
.shortname = "drud",
.name = "DR on U/D",
- .alt = {&sa_drud_HTM, NULL},
+ .step = {&step_drud_HTM, NULL},
.t = {uf},
.ready_msg = check_centers_msg,
};
-Step
+ChoiceStep
drrl_HTM = {
.shortname = "drrl",
.name = "DR on R/L",
- .alt = {&sa_drud_HTM, NULL},
+ .step = {&step_drud_HTM, NULL},
.t = {rf},
.ready_msg = check_centers_msg,
};
-Step
+ChoiceStep
drfb_HTM = {
.shortname = "drfb",
.name = "DR on F/B",
- .alt = {&sa_drud_HTM, NULL},
+ .step = {&step_drud_HTM, NULL},
.t = {fd},
.ready_msg = check_centers_msg,
};
/* DR finish steps */
-StepAlt
-sa_drfin_drud = {
+Step
+step_drfin_drud = {
.ready = check_drud,
.final = true,
.moveset = &moveset_drud,
.n_coord = 1,
.coord = {&coord_drudfin_noE_sym16}, /* TODO: maybe no noE */
.coord_trans = {uf},
- .compact_pd = {false}, /* TODO: maybe compactify */
- .n_dbtrick = 0,
.is_valid = NULL,
};
-Step
+ChoiceStep
dranyfin_DR = {
.shortname = "drfin",
.name = "DR finish on any axis without breaking DR",
- .alt = {&sa_drfin_drud, &sa_drfin_drud, &sa_drfin_drud, NULL},
+ .step = {&step_drfin_drud, &step_drfin_drud,
+ &step_drfin_drud, NULL},
.t = {uf, rf, fd},
.ready_msg = check_dr_msg,
};
-Step
+ChoiceStep
drudfin_drud = {
.shortname = "drudfin",
.name = "DR finis on U/D without breaking DR",
- .alt = {&sa_drfin_drud, NULL},
+ .step = {&step_drfin_drud, NULL},
.t = {uf},
.ready_msg = check_dr_msg,
};
-Step
+ChoiceStep
drrlfin_drrl = {
.shortname = "drrlfin",
.name = "DR finish on R/L without breaking DR",
- .alt = {&sa_drfin_drud, NULL},
+ .step = {&step_drfin_drud, NULL},
.t = {rf},
.ready_msg = check_dr_msg,
};
-Step
+ChoiceStep
drfbfin_drfb = {
.shortname = "drfbfin",
.name = "DR finish on F/B without breaking DR",
- .alt = {&sa_drfin_drud, NULL},
+ .step = {&step_drfin_drud, NULL},
.t = {fd},
.ready_msg = check_dr_msg,
};
@@ -247,13 +210,16 @@ drfbfin_drfb = {
/* HTR finish */
/* TODO: htrfin_htr */
-Step *steps[] = {
- &optimal_HTM, /* first is default */
+ChoiceStep *csteps[] = {
+/* TODO: re-implement optimal
+ &optimal_HTM,
+*/
&eoany_HTM, &eofb_HTM, &eorl_HTM, &eoud_HTM,
&drany_HTM, &drud_HTM, &drrl_HTM, &drfb_HTM,
&dranyfin_DR, &drudfin_drud, &drrlfin_drrl, &drfbfin_drfb,
+NULL
/* TODO:
&optimal_light_HTM,