aboutsummaryrefslogtreecommitdiff
path: root/src/solve.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/solve.c')
-rw-r--r--src/solve.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/solve.c b/src/solve.c
new file mode 100644
index 0000000..1f4a155
--- /dev/null
+++ b/src/solve.c
@@ -0,0 +1,173 @@
1#include "solve.h"
2
3/* Local functions ***********************************************************/
4
5static bool allowed_next(Move move, DfsData *dd);
6static void dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd);
7static void dfs_branch(Cube c, Step *s, SolveOptions *os, DfsData *dd);
8static bool dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd);
9static void dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd);
10static bool dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd);
11
12/* Local functions ***********************************************************/
13
14static bool
15allowed_next(Move move, DfsData *dd)
16{
17 if (!possible_next(dd->last2, dd->last1, move))
18 return false;
19
20 if (commute(dd->last1, move))
21 return dd->move_position[dd->last1] < dd->move_position[move];
22
23 return true;
24}
25
26static void
27dfs(Cube c, Step *s, SolveOptions *opts, DfsData *dd)
28{
29 if (dfs_stop(c, s, opts, dd))
30 return;
31
32 if (dfs_check_solved(s, opts, dd))
33 return;
34
35 dfs_branch(c, s, opts, dd);
36
37 if (opts->can_niss && !dd->niss)
38 dfs_niss(c, s, opts, dd);
39}
40
41static void
42dfs_branch(Cube c, Step *s, SolveOptions *opts, DfsData *dd)
43{
44 Move m, l1 = dd->last1, l2 = dd->last2, *moves = dd->sorted_moves;
45
46 int i, maxnsol = opts->max_solutions;
47
48 for (i = 0; moves[i] != NULLMOVE && dd->sols->len < maxnsol; i++) {
49 m = moves[i];
50 if (allowed_next(m, dd)) {
51 dd->last2 = dd->last1;
52 dd->last1 = m;
53 append_move(dd->current_alg, m, dd->niss);
54
55 dfs(apply_move(m, c), s, opts, dd);
56
57 dd->current_alg->len--;
58 dd->last2 = l2;
59 dd->last1 = l1;
60 }
61 }
62}
63
64static bool
65dfs_check_solved(Step *s, SolveOptions *opts, DfsData *dd)
66{
67 if (dd->lb != 0)
68 return false;
69
70 if (dd->current_alg->len == dd->d) {
71 if (s->is_valid(dd->current_alg) || opts->all)
72 append_alg(dd->sols, dd->current_alg);
73
74 if (opts->verbose)
75 print_alg(dd->current_alg, false);
76 }
77
78 return true;
79}
80
81static void
82dfs_niss(Cube c, Step *s, SolveOptions *opts, DfsData *dd)
83{
84 Move l1 = dd->last1, l2 = dd->last2;
85 CubeTarget ct;
86
87 ct.cube = apply_move(inverse_move(l1), (Cube){0});
88 ct.target = 1;
89
90 if (dd->current_alg->len == 0 || s->estimate(ct)) {
91 dd->niss = true;
92 dd->last1 = NULLMOVE;
93 dd->last2 = NULLMOVE;
94
95 dfs(inverse_cube(c), s, opts, dd);
96
97 dd->last1 = l1;
98 dd->last2 = l2;
99 dd->niss = false;
100 }
101}
102
103static bool
104dfs_stop(Cube c, Step *s, SolveOptions *opts, DfsData *dd)
105{
106 CubeTarget ct = {
107 .cube = c,
108 .target = dd->d - dd->current_alg->len
109 };
110
111 if (dd->sols->len >= opts->max_solutions)
112 return true;
113
114 dd->lb = s->estimate(ct);
115 if (opts->can_niss && !dd->niss)
116 dd->lb = MIN(1, dd->lb);
117
118 if (dd->current_alg->len + dd->lb > dd->d)
119 return true;
120
121 return false;
122}
123
124/* Public functions **********************************************************/
125
126AlgList *
127solve(Cube cube, Step *step, SolveOptions *opts)
128{
129 AlgListNode *node;
130 AlgList *sols = new_alglist();
131 Cube c;
132
133 if (step->detect != NULL)
134 step->pre_trans = step->detect(cube);
135 c = apply_trans(step->pre_trans, cube);
136
137 DfsData dd = {
138 .m = 0,
139 .niss = false,
140 .lb = -1,
141 .last1 = NULLMOVE,
142 .last2 = NULLMOVE,
143 .sols = sols,
144 .current_alg = new_alg("")
145 };
146
147 if (step->ready != NULL && !step->ready(c)) {
148 fprintf(stderr, "Cube not ready for solving step: ");
149 fprintf(stderr, "%s\n", step->ready_msg);
150 return sols;
151 }
152
153 moveset_to_list(step->moveset, dd.sorted_moves);
154 movelist_to_position(dd.sorted_moves, dd.move_position);
155
156 for (dd.d = opts->min_moves;
157 dd.d <= opts->max_moves &&
158 !(sols->len && opts->optimal_only) &&
159 sols->len < opts->max_solutions;
160 dd.d++) {
161 if (opts->verbose)
162 fprintf(stderr,
163 "Found %d solutions, searching depth %d...\n",
164 sols->len, dd.d);
165 dfs(c, step, opts, &dd);
166 }
167
168 for (node = sols->first; node != NULL; node = node->next)
169 transform_alg(inverse_trans(step->pre_trans), node->alg);
170
171 free_alg(dd.current_alg);
172 return sols;
173}

Generated with cgit - Back to sebastiano.tronto.net