aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/nissy.c24
-rw-r--r--src/nissy.h53
-rw-r--r--src/solvers/coord/solve.h14
-rw-r--r--src/solvers/h48/solve.h69
-rw-r--r--src/utils/sleep.h48
-rw-r--r--src/utils/utils.h1
6 files changed, 174 insertions, 35 deletions
diff --git a/src/nissy.c b/src/nissy.c
index 2dd5a41..acf6ebe 100644
--- a/src/nissy.c
+++ b/src/nissy.c
@@ -460,7 +460,9 @@ nissy_solve(
460 const unsigned char data[data_size], 460 const unsigned char data[data_size],
461 unsigned sols_size, 461 unsigned sols_size,
462 char sols[sols_size], 462 char sols[sols_size],
463 long long stats[static NISSY_SIZE_SOLVE_STATS] 463 long long stats[static NISSY_SIZE_SOLVE_STATS],
464 int (*poll_status)(void *),
465 void *poll_status_data
464) 466)
465{ 467{
466 oriented_cube_t oc; 468 oriented_cube_t oc;
@@ -475,14 +477,23 @@ nissy_solve(
475 477
476 oc = readcube(cube); 478 oc = readcube(cube);
477 479
478/* TODO: solve should handle oriented cubes */
479
480 if (!isconsistent(oc)) { 480 if (!isconsistent(oc)) {
481 LOG("[solve] Error: cube is invalid\n"); 481 LOG("[solve] Error: cube is invalid\n");
482 return NISSY_ERROR_INVALID_CUBE; 482 return NISSY_ERROR_INVALID_CUBE;
483 } 483 }
484 484
485/* TODO: checks for minmoves, maxmoves, nissflag */ 485 if (maxmoves > 20) {
486 LOG("[solve] 'maxmoves' larger than 20 not supported yet, "
487 "setting it to 20\n");
488 maxmoves = 20;
489 }
490
491 if (minmoves > maxmoves) {
492 LOG("[solve] value provided for 'minmoves' (%u) is larger "
493 "than that provided for 'maxmoves' (%u), setting "
494 "'minmoves' to %u\n", minmoves, maxmoves, maxmoves);
495 minmoves = maxmoves;
496 }
486 497
487 if (maxsols == 0) { 498 if (maxsols == 0) {
488 LOG("[solve] 'maxsols' is 0, returning no solution\n"); 499 LOG("[solve] 'maxsols' is 0, returning no solution\n");
@@ -505,11 +516,12 @@ nissy_solve(
505 if (parse_ret != NISSY_OK) 516 if (parse_ret != NISSY_OK)
506 return parse_ret; 517 return parse_ret;
507 return solve_h48(oc, minmoves, maxmoves, maxsols, 518 return solve_h48(oc, minmoves, maxmoves, maxsols,
508 optimal, t, data_size, data, sols_size, sols, stats); 519 optimal, t, data_size, data, sols_size, sols, stats,
520 poll_status, poll_status_data);
509 } else if (!strncmp(solver, "coord_", 6)) { 521 } else if (!strncmp(solver, "coord_", 6)) {
510 return solve_coord_dispatch(oc, solver + 6, nissflag, 522 return solve_coord_dispatch(oc, solver + 6, nissflag,
511 minmoves, maxmoves, maxsols, optimal, t, data_size, data, 523 minmoves, maxmoves, maxsols, optimal, t, data_size, data,
512 sols_size, sols); 524 sols_size, sols, poll_status, poll_status_data);
513 } else { 525 } else {
514 LOG("[solve] Error: unknown solver '%s'\n", solver); 526 LOG("[solve] Error: unknown solver '%s'\n", solver);
515 return NISSY_ERROR_INVALID_SOLVER; 527 return NISSY_ERROR_INVALID_SOLVER;
diff --git a/src/nissy.h b/src/nissy.h
index 5800490..2fa4a75 100644
--- a/src/nissy.h
+++ b/src/nissy.h
@@ -37,6 +37,11 @@ for example 'rotation UF' or 'mirrored BL'.
37#define NISSY_NISSFLAG_ALL \ 37#define NISSY_NISSFLAG_ALL \
38 (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED) 38 (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED)
39 39
40/* Status for stopping / pausing / resuming a solver */
41#define NISSY_STATUS_RUN 0
42#define NISSY_STATUS_STOP 1
43#define NISSY_STATUS_PAUSE 2
44
40/* The solved cube */ 45/* The solved cube */
41#define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A" 46#define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A"
42 47
@@ -296,24 +301,32 @@ nissy_checkdata(
296Solve the given cube using the given solver and options. 301Solve the given cube using the given solver and options.
297 302
298Parameters: 303Parameters:
299 cube - The cube to solver. 304 cube - The cube to solver.
300 solver - The name of the solver. 305 solver - The name of the solver.
301 nissflag - The flags for NISS (linear, inverse, mixed, or combinations). 306 nissflag - The flags for NISS (linear, inverse, mixed, or
302 minmoves - The minimum number of moves for a solution. 307 combinations; see the constants at the top of this file).
303 maxmoves - The maximum number of moves for a solution. 308 minmoves - The minimum number of moves for a solution.
304 maxsols - The maximum number of solutions. 309 maxmoves - The maximum number of moves for a solution.
305 optimal - The maximum number of moves above the optimal solution length. 310 maxsols - The maximum number of solutions.
306 threads - The number of threads to use. Must be less than or equalt to 311 optimal - The maximum number of moves above the optimal solution.
307 the value of the compile-time constant THREADS. If set to 0, 312 threads - The number of threads to use. Must be less than or equal
308 the default value THREADS will be used. 313 to the value of the compile-time constant THREADS. If set
309 data_size - The size of the data buffer. 314 to 0, the default value THREADS will be used.
310 data - The data for the solver. Can be computed with gendata. 315 data_size - The size of the data buffer.
311 This buffer must have 8-byte alignment. 316 data - The data for the solver. Can be computed with gendata.
312 sols_size - The size of the solutions buffer. 317 This buffer must have 8-byte alignment.
313 sols - The return parameter for the solutions. The solutions are 318 sols_size - The size of the solutions buffer.
314 separated by a '\n' (newline) and a '\0' (NULL character) 319 sols - The return parameter for the solutions. The solutions are
315 terminates the list. 320 separated by a '\n' (newline) and a '\0' (NULL character)
316 stats - An array to store some statistics about the solve. 321 terminates the list.
322 stats - An array to store some statistics about the solve.
323 poll_status - A callback function that should return the current
324 requested status for the solver (e.g. run, stop, pause,
325 resume; see the constants at the top of this file). The
326 way this status is polled and honored is solver-specific.
327 If this parameter is NULL, the status will always assumed
328 to be "run".
329 poll_status_data - Auxiliary data for the poll_status callback function.
317 330
318Return values: 331Return values:
319 NISSY_OK - Cube solved succesfully. 332 NISSY_OK - Cube solved succesfully.
@@ -340,7 +353,9 @@ nissy_solve(
340 const unsigned char data[data_size], 353 const unsigned char data[data_size],
341 unsigned sols_size, 354 unsigned sols_size,
342 char sols[sols_size], 355 char sols[sols_size],
343 long long stats[static NISSY_SIZE_SOLVE_STATS] 356 long long stats[static NISSY_SIZE_SOLVE_STATS],
357 int (*poll_status)(void *),
358 void *poll_status_data
344); 359);
345 360
346/* 361/*
diff --git a/src/solvers/coord/solve.h b/src/solvers/coord/solve.h
index 48cc704..8eb3e9d 100644
--- a/src/solvers/coord/solve.h
+++ b/src/solvers/coord/solve.h
@@ -14,10 +14,10 @@ typedef struct {
14 14
15STATIC int64_t solve_coord(oriented_cube_t, coord_t [static 1], uint8_t, 15STATIC int64_t solve_coord(oriented_cube_t, coord_t [static 1], uint8_t,
16 uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, 16 uint8_t, uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t,
17 const unsigned char *, size_t n, char [n]); 17 const unsigned char *, size_t n, char [n], int (*)(void *), void *);
18STATIC int64_t solve_coord_dispatch(oriented_cube_t, const char *, uint8_t, 18STATIC int64_t solve_coord_dispatch(oriented_cube_t, const char *, uint8_t,
19 uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t, 19 uint8_t, uint8_t, uint64_t, uint8_t, uint8_t, uint64_t,
20 const unsigned char *, size_t n, char [n]); 20 const unsigned char *, size_t n, char [n], int (*)(void *), void *);
21STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]); 21STATIC bool coord_solution_admissible(const dfsarg_solve_coord_t [static 1]);
22STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]); 22STATIC bool solve_coord_dfs_stop(const dfsarg_solve_coord_t [static 1]);
23STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]); 23STATIC bool coord_continue_onnormal(const dfsarg_solve_coord_t [static 1]);
@@ -211,7 +211,9 @@ solve_coord_dispatch(
211 uint64_t data_size, 211 uint64_t data_size,
212 const unsigned char *data, 212 const unsigned char *data,
213 size_t solutions_size, 213 size_t solutions_size,
214 char sols[solutions_size] 214 char sols[solutions_size],
215 int (*poll_status)(void *),
216 void *poll_status_data
215) 217)
216{ 218{
217 coord_t *coord; 219 coord_t *coord;
@@ -233,7 +235,7 @@ solve_coord_dispatch(
233 235
234 return solve_coord(oc, coord, axis, nissflag, minmoves, maxmoves, 236 return solve_coord(oc, coord, axis, nissflag, minmoves, maxmoves,
235 maxsolutions, optimal, threads, data_size, data, 237 maxsolutions, optimal, threads, data_size, data,
236 solutions_size, sols); 238 solutions_size, sols, poll_status, poll_status_data);
237} 239}
238 240
239STATIC int64_t 241STATIC int64_t
@@ -250,7 +252,9 @@ solve_coord(
250 uint64_t data_size, 252 uint64_t data_size,
251 const unsigned char *data, 253 const unsigned char *data,
252 size_t solutions_size, 254 size_t solutions_size,
253 char sols[solutions_size] 255 char sols[solutions_size],
256 int (*poll_status)(void *),
257 void *poll_status_data
254) 258)
255{ 259{
256 int8_t d; 260 int8_t d;
diff --git a/src/solvers/h48/solve.h b/src/solvers/h48/solve.h
index e3ef9b9..f2967ed 100644
--- a/src/solvers/h48/solve.h
+++ b/src/solvers/h48/solve.h
@@ -35,6 +35,10 @@ typedef struct {
35 solve_h48_task_t *tasks; 35 solve_h48_task_t *tasks;
36 int thread_id; 36 int thread_id;
37 pthread_mutex_t *solutions_mutex; 37 pthread_mutex_t *solutions_mutex;
38 int (*poll_status)(void *);
39 void *poll_status_data;
40 _Atomic bool cancelled;
41 _Atomic bool cantsleep;
38} dfsarg_solve_h48_t; 42} dfsarg_solve_h48_t;
39 43
40typedef struct { 44typedef struct {
@@ -50,11 +54,12 @@ STATIC_INLINE bool solve_h48_stop(dfsarg_solve_h48_t [static 1]);
50STATIC int64_t solve_h48_maketasks( 54STATIC int64_t solve_h48_maketasks(
51 dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1], 55 dfsarg_solve_h48_t [static 1], dfsarg_solve_h48_maketasks_t [static 1],
52 solve_h48_task_t [static STARTING_CUBES], int [static 1]); 56 solve_h48_task_t [static STARTING_CUBES], int [static 1]);
57STATIC bool solve_h48_runthread_continue(dfsarg_solve_h48_t *);
53STATIC void *solve_h48_runthread(void *); 58STATIC void *solve_h48_runthread(void *);
54STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]); 59STATIC int64_t solve_h48_dfs(dfsarg_solve_h48_t [static 1]);
55STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t, 60STATIC int64_t solve_h48(oriented_cube_t, uint8_t, uint8_t, uint8_t, uint8_t,
56 uint8_t, uint64_t, const unsigned char *, size_t n, char [n], 61 uint8_t, uint64_t, const unsigned char *, size_t n, char [n],
57 long long [static NISSY_SIZE_SOLVE_STATS]); 62 long long [static NISSY_SIZE_SOLVE_STATS], int (*)(void *), void *);
58 63
59STATIC_INLINE bool 64STATIC_INLINE bool
60solve_h48_stop(dfsarg_solve_h48_t arg[static 1]) 65solve_h48_stop(dfsarg_solve_h48_t arg[static 1])
@@ -232,16 +237,42 @@ solve_h48_dfs(dfsarg_solve_h48_t arg[static 1])
232 return ret; 237 return ret;
233} 238}
234 239
240STATIC bool
241solve_h48_runthread_continue(dfsarg_solve_h48_t *arg)
242{
243 int status;
244
245 for (status = NISSY_STATUS_PAUSE; status == NISSY_STATUS_PAUSE; ) {
246 status = arg->poll_status == NULL ? NISSY_STATUS_RUN :
247 arg->poll_status(arg->poll_status_data);
248 msleep(500);
249 }
250
251 return status == NISSY_STATUS_RUN;
252}
253
235STATIC void * 254STATIC void *
236solve_h48_runthread(void *arg) 255solve_h48_runthread(void *arg)
237{ 256{
238 int i, j; 257 int i, j, status;
239 solve_h48_task_t task; 258 solve_h48_task_t task;
240 dfsarg_solve_h48_t *dfsarg; 259 dfsarg_solve_h48_t *dfsarg;
241 260
242 dfsarg = (dfsarg_solve_h48_t *)arg; 261 dfsarg = (dfsarg_solve_h48_t *)arg;
243 262
244 for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += dfsarg->threads) { 263 for (i = dfsarg->thread_id; i < dfsarg->ntasks; i += dfsarg->threads) {
264 status = dfsarg->poll_status == NULL ? NISSY_STATUS_RUN :
265 dfsarg->poll_status(dfsarg->poll_status_data);
266 switch (status) {
267 case NISSY_STATUS_STOP:
268 goto solve_h48_runthread_cancel;
269 case NISSY_STATUS_PAUSE:
270 if (!NISSY_CANSLEEP)
271 goto solve_h48_runthread_cantsleep;
272 if (!solve_h48_runthread_continue(dfsarg))
273 goto solve_h48_runthread_cancel;
274 }
275
245 task = dfsarg->tasks[i]; 276 task = dfsarg->tasks[i];
246 277
247 solution_moves_reset(dfsarg->solution_moves); 278 solution_moves_reset(dfsarg->solution_moves);
@@ -265,6 +296,12 @@ solve_h48_runthread(void *arg)
265 } 296 }
266 297
267 return NULL; 298 return NULL;
299
300solve_h48_runthread_cantsleep:
301 dfsarg->cantsleep = true;
302solve_h48_runthread_cancel:
303 dfsarg->cancelled = true;
304 return NULL;
268} 305}
269 306
270STATIC int64_t 307STATIC int64_t
@@ -351,9 +388,12 @@ solve_h48(
351 const unsigned char *data, 388 const unsigned char *data,
352 size_t solutions_size, 389 size_t solutions_size,
353 char solutions[solutions_size], 390 char solutions[solutions_size],
354 long long stats[static NISSY_SIZE_SOLVE_STATS] 391 long long stats[static NISSY_SIZE_SOLVE_STATS],
392 int (*poll_status)(void *),
393 void *poll_status_data
355) 394)
356{ 395{
396 bool anycancelled, anycantsleep;
357 int i, ntasks, eoesep_table_index; 397 int i, ntasks, eoesep_table_index;
358 int8_t d; 398 int8_t d;
359 dfsarg_solve_h48_t arg[THREADS]; 399 dfsarg_solve_h48_t arg[THREADS];
@@ -434,6 +474,10 @@ solve_h48(
434 .threads = threads, 474 .threads = threads,
435 .thread_id = i, 475 .thread_id = i,
436 .solutions_mutex = &solutions_mutex, 476 .solutions_mutex = &solutions_mutex,
477 .poll_status = poll_status,
478 .poll_status_data = poll_status_data,
479 .cancelled = false,
480 .cantsleep = false,
437 }; 481 };
438 482
439 } 483 }
@@ -460,9 +504,10 @@ solve_h48(
460 504
461 LOG("[H48 solve] Prepared %d tasks\n", ntasks); 505 LOG("[H48 solve] Prepared %d tasks\n", ntasks);
462 506
507 anycancelled = anycantsleep = false;
463 for ( 508 for (
464 d = MAX(minmoves, STARTING_MOVES + 1); 509 d = MAX(minmoves, STARTING_MOVES + 1);
465 !solutions_done(&sollist, &settings, d); 510 !(solutions_done(&sollist, &settings, d) || anycancelled);
466 d++ 511 d++
467 ) { 512 ) {
468 if (d >= 15) 513 if (d >= 15)
@@ -474,8 +519,22 @@ solve_h48(
474 pthread_create( 519 pthread_create(
475 &thread[i], NULL, solve_h48_runthread, &arg[i]); 520 &thread[i], NULL, solve_h48_runthread, &arg[i]);
476 } 521 }
477 for (i = 0; i < threads; i++) 522 for (i = 0; i < threads; i++) {
478 pthread_join(thread[i], NULL); 523 pthread_join(thread[i], NULL);
524 anycancelled = anycancelled || arg[i].cancelled;
525 anycantsleep = anycantsleep || arg[i].cantsleep;
526 }
527 }
528
529 if (anycantsleep) {
530 LOG("[H48 solve] Received pause request, but this feature is "
531 "not available on this system. "
532 "Taking it as a stop request.\n");
533 }
534
535 if (anycancelled) {
536 LOG("[H48 solve] Received stop request, ending solution "
537 "search early.\n");
479 } 538 }
480 539
481solve_h48_done: 540solve_h48_done:
diff --git a/src/utils/sleep.h b/src/utils/sleep.h
new file mode 100644
index 0000000..d618e9b
--- /dev/null
+++ b/src/utils/sleep.h
@@ -0,0 +1,48 @@
1STATIC void msleep(int);
2
3#if defined(WIN32)
4
5#define NISSY_CANSLEEP true
6
7STATIC void
8msleep(int milliseconds)
9{
10 Sleep(milliseconds);
11}
12
13#elif defined(__wasm__)
14
15#include <emscripten.h>
16
17#define NISSY_CANSLEEP true
18
19STATIC void
20msleep(int milliseconds)
21{
22 emscripten_sleep(milliseconds);
23}
24
25#elif defined(__unix__)
26
27#include <time.h>
28
29#define NISSY_CANSLEEP true
30
31STATIC void
32msleep(int milliseconds)
33{
34 struct timespec t;
35 t.tv_sec = milliseconds / 1000;
36 t.tv_nsec = (milliseconds % 1000) * 1000000;
37 nanosleep(&t, NULL);
38}
39
40#else
41
42#define NISSY_CANSLEEP false
43STATIC void
44msleep(int milliseconds)
45{
46}
47
48#endif
diff --git a/src/utils/utils.h b/src/utils/utils.h
index ce4355e..d14b285 100644
--- a/src/utils/utils.h
+++ b/src/utils/utils.h
@@ -1,3 +1,4 @@
1#include "dbg_log.h" 1#include "dbg_log.h"
2#include "constants.h" 2#include "constants.h"
3#include "math.h" 3#include "math.h"
4#include "sleep.h"

Generated with cgit - Back to sebastiano.tronto.net