aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2023-11-11 22:19:03 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2023-11-11 22:19:03 +0100
commit91afd406dca8dee4dfdb84ad025dd390f4e5a70c (patch)
tree712bdcbf9bf0d88218095b1da42199934ea91985
parent067ba55add258ab03db328234168af66c4ad87c3 (diff)
downloadnissy-core-91afd406dca8dee4dfdb84ad025dd390f4e5a70c.tar.gz
nissy-core-91afd406dca8dee4dfdb84ad025dd390f4e5a70c.zip
Implemented simple solver
Diffstat (limited to '')
-rw-r--r--TODO.txt2
-rw-r--r--cube.c237
-rw-r--r--cube.h2
3 files changed, 209 insertions, 32 deletions
diff --git a/TODO.txt b/TODO.txt
index 27ff198..f661363 100644
--- a/TODO.txt
+++ b/TODO.txt
@@ -2,7 +2,7 @@
2 2
3See the sections below for details 3See the sections below for details
4 4
5* Implement some simple solver 5* Tests for simple solver
6* Extend cube and moves to include centers 6* Extend cube and moves to include centers
7* More complex optimal solvers, pruning tables 7* More complex optimal solvers, pruning tables
8* Benchmarks 8* Benchmarks
diff --git a/cube.c b/cube.c
index 4806b95..3cd4381 100644
--- a/cube.c
+++ b/cube.c
@@ -9,6 +9,7 @@
9#ifdef DEBUG 9#ifdef DEBUG
10#include <stdio.h> 10#include <stdio.h>
11#define DBG_LOG(...) fprintf(stderr, __VA_ARGS__) 11#define DBG_LOG(...) fprintf(stderr, __VA_ARGS__)
12#define DBG_WARN(condition, ...) if (!(condition)) DBG_LOG(__VA_ARGS__);
12#define DBG_ASSERT(condition, retval, ...) \ 13#define DBG_ASSERT(condition, retval, ...) \
13 if (!(condition)) { \ 14 if (!(condition)) { \
14 DBG_LOG(__VA_ARGS__); \ 15 DBG_LOG(__VA_ARGS__); \
@@ -16,6 +17,7 @@
16 } 17 }
17#else 18#else
18#define DBG_LOG(...) 19#define DBG_LOG(...)
20#define DBG_WARN(condition, ...)
19#define DBG_ASSERT(condition, retval, ...) 21#define DBG_ASSERT(condition, retval, ...)
20#endif 22#endif
21 23
@@ -255,6 +257,10 @@ typedef __m256i cube_fast_t;
255#define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, 0x2020202020202020) 257#define _cocw_avx2 _mm256_set_epi64x(0, 0, 0, 0x2020202020202020)
256#define _eo_avx2 _mm256_set_epi64x(0x10101010, 0x1010101010101010, 0, 0) 258#define _eo_avx2 _mm256_set_epi64x(0x10101010, 0x1010101010101010, 0, 0)
257#define zero_fast _mm256_set_epi64x(0, 0, 0, 0); 259#define zero_fast _mm256_set_epi64x(0, 0, 0, 0);
260#define solved_fast _mm256_set_epi8( \
261 0, 0, 0, 0, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, \
262 0, 0, 0, 0, 0, 0, 0, 0, 7, 6, 5, 4, 3, 2, 1, 0 \
263)
258 264
259static cube_fast_t cubetofast(cube_t); 265static cube_fast_t cubetofast(cube_t);
260static cube_t fasttocube(cube_fast_t); 266static cube_t fasttocube(cube_fast_t);
@@ -1482,6 +1488,12 @@ equal_fast(cube_fast_t c1, cube_fast_t c2)
1482 return mask == 0xffffffffU; 1488 return mask == 0xffffffffU;
1483} 1489}
1484 1490
1491static inline bool
1492issolved_fast(cube_fast_t cube)
1493{
1494 return equal_fast(cube, solved_fast);
1495}
1496
1485static inline cube_fast_t 1497static inline cube_fast_t
1486invertco_fast(cube_fast_t c) 1498invertco_fast(cube_fast_t c)
1487{ 1499{
@@ -1614,7 +1626,11 @@ typedef cube_t cube_fast_t;
1614 r[k] ^= _eobit; \ 1626 r[k] ^= _eobit; \
1615 r[l] ^= _eobit; 1627 r[l] ^= _eobit;
1616 1628
1617static const cube_fast_t zero_fast = { .corner = {0}, .edge = {0} }; 1629static cube_fast_t zero_fast = { .corner = {0}, .edge = {0} };
1630static cube_t solved_fast = {
1631 .corner = {0, 1, 2, 3, 4, 5, 6, 7},
1632 .edge = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}
1633};
1618 1634
1619static cube_fast_t cubetofast(cube_t); 1635static cube_fast_t cubetofast(cube_t);
1620static cube_t fasttocube(cube_fast_t); 1636static cube_t fasttocube(cube_fast_t);
@@ -2842,6 +2858,12 @@ equal_fast(cube_fast_t c1, cube_fast_t c2)
2842 return ret; 2858 return ret;
2843} 2859}
2844 2860
2861static inline bool
2862issolved_fast(cube_fast_t cube)
2863{
2864 return equal_fast(cube, solved_fast);
2865}
2866
2845static inline cube_fast_t 2867static inline cube_fast_t
2846inverse_fast(cube_fast_t cube) 2868inverse_fast(cube_fast_t cube)
2847{ 2869{
@@ -2930,7 +2952,7 @@ static void writecube_SRC(cube_t, char *);
2930static uint8_t readmove(char); 2952static uint8_t readmove(char);
2931static uint8_t readmodifier(char); 2953static uint8_t readmodifier(char);
2932static uint8_t readtrans(char *); 2954static uint8_t readtrans(char *);
2933static void writemoves(uint8_t *, int, char *); 2955static int writemoves(uint8_t *, int, char *);
2934static void writetrans(uint8_t, char *); 2956static void writetrans(uint8_t, char *);
2935static cube_fast_t transform(cube_fast_t, uint8_t); 2957static cube_fast_t transform(cube_fast_t, uint8_t);
2936static cube_fast_t move(cube_fast_t, uint8_t); 2958static cube_fast_t move(cube_fast_t, uint8_t);
@@ -3256,7 +3278,7 @@ readtrans(char *buf)
3256 return _error; 3278 return _error;
3257} 3279}
3258 3280
3259static void 3281static int
3260writemoves(uint8_t *m, int n, char *buf) 3282writemoves(uint8_t *m, int n, char *buf)
3261{ 3283{
3262 int i; 3284 int i;
@@ -3271,6 +3293,8 @@ writemoves(uint8_t *m, int n, char *buf)
3271 *b = ' '; 3293 *b = ' ';
3272 } 3294 }
3273 *b = '\0'; 3295 *b = '\0';
3296
3297 return b - buf;
3274} 3298}
3275 3299
3276static void 3300static void
@@ -3628,16 +3652,16 @@ Here you can find the implementation of all the solving algorithms.
3628typedef struct { 3652typedef struct {
3629 cube_fast_t cube; 3653 cube_fast_t cube;
3630 uint8_t depth; 3654 uint8_t depth;
3631 int maxsols; 3655 int64_t maxsols;
3632 uint8_t *sols; 3656 char *sols;
3633 int nsols; 3657 int64_t nsols;
3634 int nmoves; 3658 uint8_t nmoves;
3635 uint8_t moves[20]; 3659 uint8_t moves[20];
3636 int (*estimate)(cube_fast_t); 3660 uint8_t (*estimate)(cube_fast_t);
3637} dfs_arg_t; 3661} dfsarg_generic_t;
3638 3662
3639static bool 3663static bool
3640allowednextmove(dfs_arg_t arg, uint8_t m) 3664allowednextmove(dfsarg_generic_t arg, uint8_t m)
3641{ 3665{
3642 int n; 3666 int n;
3643 uint8_t mbase, l1base, l2base, maxis, l1axis, l2axis; 3667 uint8_t mbase, l1base, l2base, maxis, l1axis, l2axis;
@@ -3665,11 +3689,11 @@ allowednextmove(dfs_arg_t arg, uint8_t m)
3665} 3689}
3666 3690
3667static int 3691static int
3668solve_generic_dfs(dfs_arg_t arg) 3692solve_generic_dfs(dfsarg_generic_t arg)
3669{ 3693{
3670 dfs_arg_t nextarg; 3694 dfsarg_generic_t nextarg;
3671 int bound, ret; 3695 uint8_t m, bound;
3672 uint8_t m; 3696 int64_t ret;
3673 3697
3674 bound = arg.estimate(arg.cube); 3698 bound = arg.estimate(arg.cube);
3675 3699
@@ -3679,11 +3703,13 @@ solve_generic_dfs(dfs_arg_t arg)
3679 if (bound == 0) { 3703 if (bound == 0) {
3680 if (arg.nmoves != arg.depth) 3704 if (arg.nmoves != arg.depth)
3681 return 0; 3705 return 0;
3682 memcpy(&arg.sols[arg.depth * arg.nsols], arg.moves, arg.depth); 3706 arg.sols += writemoves(arg.moves, arg.depth, arg.sols);
3707 *arg.sols = '\n';
3708 arg.sols++;
3683 return 1; 3709 return 1;
3684 } 3710 }
3685 3711
3686 memcpy(&nextarg, &arg, sizeof(dfs_arg_t)); 3712 memcpy(&nextarg, &arg, sizeof(dfsarg_generic_t));
3687 nextarg.nmoves = arg.nmoves + 1; 3713 nextarg.nmoves = arg.nmoves + 1;
3688 for (m = 0, ret = 0; m < 18; m++) { 3714 for (m = 0, ret = 0; m < 18; m++) {
3689 if (allowednextmove(arg, m)) { 3715 if (allowednextmove(arg, m)) {
@@ -3696,24 +3722,65 @@ solve_generic_dfs(dfs_arg_t arg)
3696 return ret; 3722 return ret;
3697} 3723}
3698 3724
3699/* TODO 3725static int64_t
3700int
3701solve_generic( 3726solve_generic(
3702 cube_fast_t cube, 3727 cube_t cube,
3703 uint8_t depth, 3728 char *nisstype,
3704 int maxsols, 3729 /* TODO: handle NISS */
3705 uint8_t *sols, 3730 int8_t minmoves,
3706 int (*estimate)(cube_fast_t) 3731 int8_t maxmoves,
3732 int64_t maxsols,
3733 int8_t optimal,
3734 char *sols,
3735 uint8_t (*estimate)(cube_fast_t)
3736 /* TODO: add validator */
3737 /* TODO: maybe add data for estimate */
3738 /* TODO: add moveset (and allowednext?) */
3707) 3739)
3708{ 3740{
3709 dfs_arg_t arg; 3741 dfsarg_generic_t arg;
3742 int64_t ret, tmp, first;
3710 3743
3711 if (!issolvable(cube) || depth > 20 || estimate == NULL) 3744 if (!issolvable(cube)) {
3745 DBG_LOG("solve: cube is not solvable\n");
3712 return -1; 3746 return -1;
3747 }
3713 3748
3714 arg = (dfs_arg_t) { 3749 DBG_WARN(!strcmp(nisstype, ""),
3715 .cube = cube, 3750 "solve: NISS not implemented yet, 'nisstype' ignored\n");
3716 .depth = depth, 3751
3752 if (minmoves < 0) {
3753 DBG_LOG("solve: 'minmoves' is negative, setting to 0\n");
3754 minmoves = 0;
3755 }
3756
3757 if (maxmoves < 0) {
3758 DBG_LOG("solve: invalid 'maxmoves', setting to 20\n");
3759 maxmoves = 20;
3760 }
3761
3762 if (maxsols < 0) {
3763 DBG_LOG("solve: 'maxsols' is negative\n");
3764 return -1;
3765 }
3766
3767 if (maxsols == 0) {
3768 DBG_LOG("solve: 'maxsols' is 0\n");
3769 return 0;
3770 }
3771
3772 if (sols == NULL) {
3773 DBG_LOG("solve: return parameter 'sols' is NULL\n");
3774 return -1;
3775 }
3776
3777 if (estimate == NULL) {
3778 DBG_LOG("solve: 'estimate' is NULL\n");
3779 return -1;
3780 }
3781
3782 arg = (dfsarg_generic_t) {
3783 .cube = cubetofast(cube),
3717 .maxsols = maxsols, 3784 .maxsols = maxsols,
3718 .sols = sols, 3785 .sols = sols,
3719 .nsols = 0, 3786 .nsols = 0,
@@ -3722,6 +3789,116 @@ solve_generic(
3722 .estimate = estimate, 3789 .estimate = estimate,
3723 }; 3790 };
3724 3791
3725 return solve_generic_dfs(arg); 3792 ret = 0;
3793 first = -1;
3794 for (arg.depth = minmoves; arg.depth <= maxmoves; arg.depth++) {
3795 tmp = solve_generic_dfs(arg);
3796 ret += tmp;
3797 if (tmp != 0)
3798 first = arg.depth;
3799
3800 DBG_LOG("Found %" PRId64 " solutions at depth %" PRIu8 "\n",
3801 tmp, arg.depth);
3802
3803 if (ret >= maxsols)
3804 break;
3805
3806 if (optimal >= 0 && first >= 0 && arg.depth - first == optimal)
3807 break;
3808 }
3809
3810 DBG_ASSERT(ret <= maxsols, ret,
3811 "solve: found more than 'maxsols' solutions\n");
3812
3813 return ret;
3814}
3815
3816static uint8_t
3817estimate_simple(cube_fast_t cube)
3818{
3819 return issolved_fast(cube) ? 0 : 1;
3820}
3821
3822static int64_t
3823solve_simple(
3824 cube_t cube,
3825 int8_t minmoves,
3826 int8_t maxmoves,
3827 int64_t maxsols,
3828 int8_t optimal,
3829 char *solutions
3830)
3831{
3832 return solve_generic(
3833 cube,
3834 "",
3835 minmoves,
3836 maxmoves,
3837 maxsols,
3838 optimal,
3839 solutions,
3840 &estimate_simple
3841 );
3842}
3843
3844int64_t
3845solve(
3846 cube_t cube,
3847 char *solver,
3848 char *options,
3849 char *nisstype,
3850 int8_t minmoves,
3851 int8_t maxmoves,
3852 int64_t maxsols,
3853 int8_t optimal,
3854 void *data,
3855 char *solutions
3856)
3857{
3858 DBG_WARN(!strcmp(options, ""),
3859 "solve: 'options' not implemented yet, ignoring\n");
3860
3861 DBG_WARN(!strcmp(nisstype, ""),
3862 "solve: NISS not implemented yet, ignoring 'nisstype'\n");
3863
3864 DBG_WARN(data == NULL,
3865 "solve: 'data' not implemented yet, ignoring\n");
3866
3867 if (!strcmp(solver, "simple")) {
3868 return solve_simple(
3869 cube,
3870 minmoves,
3871 maxmoves,
3872 maxsols,
3873 optimal,
3874 solutions
3875 );
3876 } else {
3877 DBG_LOG("solve: unknown solver\n");
3878 return -1;
3879 }
3880
3881 DBG_LOG("solve: error\n");
3882 return -1;
3883}
3884
3885void
3886multisolve(int n, cube_t *cube, char *solver, void *data, char *sols)
3887{
3888 char *s;
3889 int i;
3890
3891 s = sols;
3892 for (i = 0; i < n; i++) {
3893 solve(cube[i], solver, "", "normal", 0, -1, 1, 0, NULL, s);
3894 while (s++);
3895 }
3896}
3897
3898int64_t
3899gendata(char *solver, void *data)
3900{
3901 DBG_LOG("gendata: not implemented yet\n");
3902
3903 return -1;
3726} 3904}
3727*/
diff --git a/cube.h b/cube.h
index 791d167..0a39d12 100644
--- a/cube.h
+++ b/cube.h
@@ -130,7 +130,7 @@ int64_t solve(
130 * maximum length is unlimited. 130 * maximum length is unlimited.
131 */ 131 */
132 int64_t maxsols, /* The maximum number of solutions. */ 132 int64_t maxsols, /* The maximum number of solutions. */
133 int64_t optimal, /* All solutions at most "optimal" moves from the 133 int8_t optimal, /* All solutions at most "optimal" moves from the
134 * shortest solution (respecting minmoves) are found. 134 * shortest solution (respecting minmoves) are found.
135 * If negative, this parameter is ignored. 135 * If negative, this parameter is ignored.
136 */ 136 */

Generated with cgit - Back to sebastiano.tronto.net