diff options
Diffstat (limited to 'src/solvers/coord/solve.h')
| -rw-r--r-- | src/solvers/coord/solve.h | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h new file mode 100644 index 0000000..e954aac --- /dev/null +++ b/src/solvers/coord/solve.h | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | #define MAXLEN_COORDSOL 20 | ||
| 2 | |||
| 3 | typedef struct { | ||
| 4 | cube_t cube; | ||
| 5 | uint8_t depth; | ||
| 6 | uint8_t nmoves; | ||
| 7 | uint8_t moves[MAXLEN_COORDSOL]; | ||
| 8 | coord_t *coord; | ||
| 9 | const void *coord_data; | ||
| 10 | const uint8_t *ptable; | ||
| 11 | uint8_t trans; | ||
| 12 | int64_t *nsols; | ||
| 13 | int64_t maxsolutions; | ||
| 14 | int optimal; | ||
| 15 | uint8_t *shortest_sol; | ||
| 16 | uint64_t solutions_size; | ||
| 17 | uint64_t *solutions_used; | ||
| 18 | char **solutions; | ||
| 19 | } dfsarg_solve_coord_t; | ||
| 20 | |||
| 21 | STATIC int64_t solve_coord(cube_t, coord_t *, uint8_t, uint8_t, uint8_t, | ||
| 22 | uint8_t, uint64_t, int, int, uint64_t, const void *, uint64_t, char *); | ||
| 23 | STATIC int64_t solve_coord_dispatch(cube_t, const char *, uint8_t, uint8_t, | ||
| 24 | uint8_t, uint64_t, int, int, uint64_t, const void *, uint64_t, char *); | ||
| 25 | STATIC bool solve_coord_appendchar(char *, uint64_t, uint64_t *, char); | ||
| 26 | STATIC int64_t solve_coord_appendsolution(dfsarg_solve_coord_t *); | ||
| 27 | STATIC int64_t solve_coord_dfs(dfsarg_solve_coord_t *); | ||
| 28 | |||
| 29 | STATIC int64_t | ||
| 30 | solve_coord_appendsolution(dfsarg_solve_coord_t *arg) | ||
| 31 | { | ||
| 32 | uint8_t i, t, tmoves[MAXLEN_COORDSOL]; | ||
| 33 | |||
| 34 | if (*arg->nsols >= arg->maxsolutions || | ||
| 35 | arg->nmoves > *arg->shortest_sol + arg->optimal) | ||
| 36 | return 0; | ||
| 37 | |||
| 38 | sortparallel(arg->moves, arg->nmoves); | ||
| 39 | |||
| 40 | t = inverse_trans(arg->trans); | ||
| 41 | for (i = 0; i < arg->nmoves; i++) | ||
| 42 | tmoves[i] = transform_move(arg->moves[i], t); | ||
| 43 | |||
| 44 | /* TODO append tmoves[] */ | ||
| 45 | |||
| 46 | return 1; | ||
| 47 | } | ||
| 48 | |||
| 49 | STATIC bool | ||
| 50 | solve_coord_appendchar(char *s, uint64_t s_size, uint64_t *s_used, char c) | ||
| 51 | { | ||
| 52 | if (s_size == *s_used) | ||
| 53 | return false; | ||
| 54 | |||
| 55 | s[*s_used] = c; | ||
| 56 | (*s_used)++; | ||
| 57 | |||
| 58 | return true; | ||
| 59 | } | ||
| 60 | |||
| 61 | STATIC int64_t | ||
| 62 | solve_coord_dfs(dfsarg_solve_coord_t *arg) | ||
| 63 | { | ||
| 64 | uint64_t coord; | ||
| 65 | uint8_t pval; | ||
| 66 | |||
| 67 | coord = arg->coord->coord(arg->cube, arg->coord_data); | ||
| 68 | |||
| 69 | if (coord == 0) { | ||
| 70 | if (arg->nmoves != arg->depth) | ||
| 71 | return 0; | ||
| 72 | return solve_coord_appendsolution(arg); | ||
| 73 | } | ||
| 74 | |||
| 75 | pval = get_coord_pval(arg->coord, arg->ptable, coord); | ||
| 76 | if (arg->nmoves + pval > arg->depth) | ||
| 77 | return 0; | ||
| 78 | |||
| 79 | /* TODO recursive call */ | ||
| 80 | /* Is allowednextmove available here? */ | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | STATIC int64_t | ||
| 86 | solve_coord_dispatch( | ||
| 87 | cube_t cube, | ||
| 88 | const char *coord_axis, | ||
| 89 | uint8_t nissflag, | ||
| 90 | uint8_t minmoves, | ||
| 91 | uint8_t maxmoves, | ||
| 92 | uint64_t maxsolutions, | ||
| 93 | int optimal, | ||
| 94 | int threads, | ||
| 95 | uint64_t data_size, | ||
| 96 | const void *data, | ||
| 97 | uint64_t sols_size, | ||
| 98 | char *sols | ||
| 99 | ) | ||
| 100 | { | ||
| 101 | int i, n; | ||
| 102 | coord_t *coord; | ||
| 103 | uint8_t axis; | ||
| 104 | |||
| 105 | n = strlen(coord_axis); | ||
| 106 | for (i = 0; coord_axis[i] != ' ' && coord_axis[i] != '\0'; i++) ; | ||
| 107 | |||
| 108 | coord = parse_coord(coord_axis, i); | ||
| 109 | axis = parse_axis(coord_axis + i + 1, n - i - 1); | ||
| 110 | |||
| 111 | if (coord == NULL) { | ||
| 112 | LOG("Could not parse coordinate '%s'\n", coord_axis); | ||
| 113 | return NISSY_ERROR_INVALID_SOLVER; | ||
| 114 | } | ||
| 115 | |||
| 116 | if (axis == UINT8_ERROR) { | ||
| 117 | LOG("Could not parse axis from '%s'\n", coord_axis); | ||
| 118 | return NISSY_ERROR_INVALID_SOLVER; | ||
| 119 | } | ||
| 120 | |||
| 121 | return solve_coord(cube, coord, axis, nissflag, minmoves, maxmoves, | ||
| 122 | maxsolutions, optimal, threads, data_size, data, sols_size, sols); | ||
| 123 | } | ||
| 124 | |||
| 125 | STATIC int64_t | ||
| 126 | solve_coord( | ||
| 127 | cube_t cube, | ||
| 128 | coord_t *coord, | ||
| 129 | uint8_t axis, | ||
| 130 | uint8_t nissflag, | ||
| 131 | uint8_t minmoves, | ||
| 132 | uint8_t maxmoves, | ||
| 133 | uint64_t maxsolutions, | ||
| 134 | int optimal, | ||
| 135 | int threads, | ||
| 136 | uint64_t data_size, | ||
| 137 | const void *data, | ||
| 138 | uint64_t sols_size, | ||
| 139 | char *sols | ||
| 140 | ) | ||
| 141 | { | ||
| 142 | int8_t d; | ||
| 143 | uint8_t t, shortest_sol; | ||
| 144 | int64_t nsols; | ||
| 145 | uint64_t sols_used; | ||
| 146 | cube_t c; | ||
| 147 | const void *coord_data; | ||
| 148 | const uint8_t *ptable; | ||
| 149 | dfsarg_solve_coord_t arg; | ||
| 150 | tableinfo_t info; | ||
| 151 | |||
| 152 | if (readtableinfo(data_size, data, &info) != NISSY_OK) | ||
| 153 | goto solve_coord_error_data; | ||
| 154 | |||
| 155 | if (info.type == TABLETYPE_PRUNING) { | ||
| 156 | /* Only the pruning table */ | ||
| 157 | coord_data = NULL; | ||
| 158 | ptable = (uint8_t *)data + INFOSIZE; | ||
| 159 | } else { | ||
| 160 | /* Coordinate has extra data */ | ||
| 161 | coord_data = (uint8_t *)data + INFOSIZE; | ||
| 162 | ptable = (uint8_t *)data + info.next + INFOSIZE; | ||
| 163 | } | ||
| 164 | |||
| 165 | nsols = 0; | ||
| 166 | sols_used = 0; | ||
| 167 | shortest_sol = MAXLEN_COORDSOL + 1; | ||
| 168 | c = transform(cube, t); | ||
| 169 | t = coord->axistrans[axis]; | ||
| 170 | |||
| 171 | arg = (dfsarg_solve_coord_t) { | ||
| 172 | .cube = c, | ||
| 173 | .coord = coord, | ||
| 174 | .coord_data = coord_data, | ||
| 175 | .ptable = ptable, | ||
| 176 | .trans = t, | ||
| 177 | .nsols = &nsols, | ||
| 178 | .maxsolutions = (int64_t)maxsolutions, | ||
| 179 | .optimal = optimal, | ||
| 180 | .shortest_sol = &shortest_sol, | ||
| 181 | .solutions_size = sols_size, | ||
| 182 | .solutions_used = &sols_used, | ||
| 183 | .solutions = &sols, | ||
| 184 | }; | ||
| 185 | |||
| 186 | if (coord->coord(c, coord_data) == 0) { | ||
| 187 | if (minmoves == 0) { | ||
| 188 | nsols = 1; | ||
| 189 | if (!solve_coord_appendchar( | ||
| 190 | sols, sols_size, &sols_used, '\n')) | ||
| 191 | goto solve_coord_error_buffer; | ||
| 192 | } | ||
| 193 | goto solve_coord_done; | ||
| 194 | } | ||
| 195 | |||
| 196 | for ( | ||
| 197 | d = MAX(minmoves, 1); | ||
| 198 | d <= maxmoves && nsols < (int64_t)maxsolutions | ||
| 199 | && !(nsols != 0 && d > shortest_sol + optimal); | ||
| 200 | d++ | ||
| 201 | ) { | ||
| 202 | if (d >= 10) | ||
| 203 | LOG("Found %" PRId64 " solutions, searching at depth %" | ||
| 204 | PRId8 "\n", nsols, d); | ||
| 205 | |||
| 206 | arg.depth = d; | ||
| 207 | arg.nmoves = 0; | ||
| 208 | nsols += solve_coord_dfs(&arg); | ||
| 209 | } | ||
| 210 | |||
| 211 | solve_coord_done: | ||
| 212 | if (!solve_coord_appendchar(sols, sols_size, &sols_used, '\0')) | ||
| 213 | goto solve_coord_error_buffer; | ||
| 214 | |||
| 215 | return nsols; | ||
| 216 | |||
| 217 | solve_coord_error_data: | ||
| 218 | LOG("solve_coord: error reading table\n"); | ||
| 219 | return NISSY_ERROR_DATA; | ||
| 220 | |||
| 221 | solve_coord_error_buffer: | ||
| 222 | LOG("Could not append solution to buffer: size too small\n"); | ||
| 223 | return NISSY_ERROR_BUFFER_SIZE; | ||
| 224 | } | ||
