nissy-core

The "engine" of nissy, including the H48 optimal solver.
git clone https://git.tronto.net/nissy-core
Download | Log | Files | Refs | README | LICENSE

nissy.h (16986B)


      1 /*
      2 This is libnissy (temporarily also known as h48), a Rubik's cube library.
      3 
      4 All the functions return 0 or a positive integer in case of success and
      5 a negative integer in case of error, unless otherwise specified. See
      6 below for the list of error codes and their meaning.
      7 
      8 Cubes are passed as strings in the cccccccc=eeeeeeeeeeee=r format,
      9 see the README.md file for more information.
     10 
     11 Accepted moves are any of the following:
     12 U, D, R, L, F, B, Uw, Dw, Rw, Lw, Fw, Bw, M, S, E, x, y, z
     13 optionally followed by a 2, a ' or a 3.
     14 The standard NISS notation is also accepted: moves in parentheses () are
     15 inverted and used as premoves.
     16 
     17 A transformation must be given in the format
     18     (rotation|mirrored) (2 letters)
     19 for example 'rotation UF' or 'mirrored BL'.
     20 */
     21 
     22 
     23 /* Constants *****************************************************************/
     24 
     25 /* Some constants for size for I/O buffers */
     26 #define NISSY_SIZE_CUBE           24U
     27 #define NISSY_SIZE_TRANSFORMATION 12U
     28 #define NISSY_SIZE_SOLVE_STATS    10U
     29 #define NISSY_SIZE_DATAID         255U
     30 #define NISSY_SIZE_MOVES          1000U
     31 
     32 /* Flags for NISS options */
     33 #define NISSY_NISSFLAG_NORMAL  1U
     34 #define NISSY_NISSFLAG_INVERSE 2U
     35 #define NISSY_NISSFLAG_MIXED   4U
     36 #define NISSY_NISSFLAG_LINEAR \
     37     (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE)
     38 #define NISSY_NISSFLAG_ALL \
     39     (NISSY_NISSFLAG_NORMAL | NISSY_NISSFLAG_INVERSE | NISSY_NISSFLAG_MIXED)
     40 
     41 /* Status for stopping / pausing / resuming a solver */
     42 #define NISSY_STATUS_RUN    0
     43 #define NISSY_STATUS_STOP   1
     44 #define NISSY_STATUS_PAUSE  2
     45 
     46 /* Possible results of move sequence comparison */
     47 #define NISSY_COMPARE_MOVES_EQUAL     0
     48 #define NISSY_COMPARE_MOVES_DIFFERENT 99
     49 
     50 /* The solved cube */
     51 #define NISSY_SOLVED_CUBE "ABCDEFGH=ABCDEFGHIJKL=A"
     52 
     53 /* Error codes ***************************************************************/
     54 
     55 /*
     56 The value NISSY_OK denotes a success. If returned by solve, it means
     57 that no solution has been found.
     58 */
     59 #define NISSY_OK 0LL
     60 
     61 /*
     62 The value NISSY_WARNING_UNSOLVABLE is a warning. It means that the
     63 operation was completed succesfully, but the resulting cube is in an
     64 unsolvable state. This could be intended, for example if the user has
     65 provided an unsolvable cube as input.
     66 */
     67 #define NISSY_WARNING_UNSOLVABLE -1LL
     68 
     69 /*
     70 The value NISSY_ERROR_INVALID_CUBE means that the provided cube is
     71 invalid. It could be written in an unknown format, or be ill-formed.
     72 */
     73 #define NISSY_ERROR_INVALID_CUBE -10LL
     74 
     75 /*
     76 The value NISSY_ERROR_UNSOLVABLE_CUBE means that the provided cube is in
     77 an unsolvable state for the given solver. This could mean either that the
     78 cube is not solvable at all (for example in case it has a single twisted
     79 corner), or that it is not ready for the given step (for example if the
     80 caller wants to solve a DR finish without the cube being in DR state).
     81 */
     82 #define NISSY_ERROR_UNSOLVABLE_CUBE -11LL
     83 
     84 /*
     85 The value NISSY_ERROR_INVALID_MOVES means that the given moves are
     86 invalid.
     87 */
     88 #define NISSY_ERROR_INVALID_MOVES -20LL
     89 
     90 /*
     91 The value NISSY_ERROR_INVALID_TRANS means that the given transformation
     92 is invalid.
     93 */
     94 #define NISSY_ERROR_INVALID_TRANS -30LL
     95 
     96 /*
     97 The value NISSY_ERROR_INVALID_SOLVER means that the given solver is
     98 not known.
     99 */
    100 #define NISSY_ERROR_INVALID_SOLVER -50LL
    101 
    102 /*
    103 The value NISSY_ERROR_INVALID_VARIATION means that the given method of
    104 finding variations for a solution is not known.
    105 */
    106 #define NISSY_ERROR_INVALID_VARIATION -51LL
    107 
    108 /*
    109 The value NISSY_ERROR_NULL_POINTER means that one of the provided pointer
    110 arguments is NULL. For example, it may be returned by solve when called
    111 with a solver that requires some pre-computed data, but the provided
    112 data is NULL.
    113 */
    114 #define NISSY_ERROR_NULL_POINTER -60LL
    115 
    116 /*
    117 The value NISSY_ERROR_BUFFER_SIZE means that one of the buffers provided
    118 is too small. For example, it could be too small to hold the result or
    119 too small to hold the data generated by gendata.
    120 */
    121 #define NISSY_ERROR_BUFFER_SIZE -61LL
    122 
    123 /*
    124 The value NISSY_ERROR_DATA means that the provided data is invalid. For
    125 example, it may be returned by solve when called with incompatible solver
    126 and data arguments.
    127 */
    128 #define NISSY_ERROR_DATA -70LL
    129 
    130 /*
    131 The value NISSY_ERROR_OPTIONS means that one or more of the given options
    132 are invalid. For example, it may be returned by solve when called with
    133 a negative maximum number of solutions.
    134 */
    135 #define NISSY_ERROR_OPTIONS -80LL
    136 
    137 /*
    138 The value NISSY_ERROR_UNKNOWN denotes an unexpected error. It probably
    139 means that there some bug in this library.  If you can, report any error
    140 of this kind to sebastiano@tronto.net. Thanks!
    141 */
    142 #define NISSY_ERROR_UNKNOWN -999LL
    143 
    144 
    145 /* Library functions *********************************************************/
    146 
    147 /*
    148 Compute the inverse of the given cube.
    149 
    150 Parameters:
    151    cube   - The cube to be inverted.
    152             Required size: NISSY_SIZE_CUBE.
    153    result - The return parameter for the resulting cube.
    154             Required size: NISSY_SIZE_CUBE.
    155 
    156 Return values:
    157    NISSY_OK                  - The cube was inverted succesfully.
    158    NISSY_WARNING_UNSOLVABLE  - The resulting cube is not solvable. This is
    159                                either because the given cube was not solvable,
    160                                or due to an unknown internal error.
    161    NISSY_ERROR_INVALID_CUBE  - The given cube is invalid.
    162    NISSY_ERROR_UNKNOWN       - An unknown error occurred.
    163 */
    164 long long
    165 nissy_inverse(
    166 	const char cube[], /* NISSY_SIZE_CUBE */
    167 	char result[]      /* NISSY_SIZE_CUBE */
    168 );
    169 
    170 /*
    171 Apply the given sequence of moves on the given cube.
    172 
    173 Parameters:
    174    cube   - The cube to move.
    175             Required size: NISSY_SIZE_CUBE.
    176    moves  - The moves to apply to the cube. Must be a NULL-terminated string.
    177    result - The return parameter for the resulting cube.
    178             Required size: NISSY_SIZE_CUBE.
    179 
    180 Return values:
    181    NISSY_OK                  - The moves were applied succesfully.
    182    NISSY_WARNING_UNSOLVABLE  - The resulting cube is not solvable. This is
    183                                either because the given cube was not solvable,
    184                                or due to an unknown internal error.
    185    NISSY_ERROR_INVALID_CUBE  - The given cube is invalid.
    186    NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
    187    NISSY_ERROR_NULL_POINTER  - The 'moves' argument is NULL.
    188 */
    189 long long
    190 nissy_applymoves(
    191 	const char cube[], /* NISSY_SIZE_CUBE */
    192 	const char *moves,
    193 	char result[]      /* NISSY_SIZE_CUBE */
    194 );
    195 
    196 /*
    197 Apply the single given transformation to the given cube.
    198 
    199 Parameters:
    200    cube           - The cube to be transformed.
    201                     Required size: NISSY_SIZE_CUBE.
    202    transformation - The transformation in "(rotation|mirrored) __" format.
    203                     Required size: NISSY_SIZE_TRANSFORMATION.
    204    result         - The return parameter for the resulting cube.
    205                     Required size: NISSY_SIZE_CUBE.
    206 
    207 Return values:
    208    NISSY_OK                  - The transformation was performed succesfully.
    209    NISSY_WARNING_UNSOLVABLE  - The resulting cube is not solvable. This is
    210                                probably due to an unknown internal error.
    211    NISSY_ERROR_INVALID_CUBE  - The given cube is invalid.
    212    NISSY_ERROR_INVALID_TRANS - The given transformation is invalid.
    213 */
    214 long long
    215 nissy_applytrans(
    216 	const char cube[],           /* NISSY_SIZE_CUBE */
    217 	const char transformation[], /* NISSY_SIZE_TRANSFORMATION */
    218 	char result[]                /* NISSY_SIZE_CUBE */
    219 );
    220 
    221 /*
    222 Find variations of a given move sequence, for example by changing
    223 the direction of the last quarter turn(s), or linearizing a NISS move
    224 sequence. The result consists of one or more move sequences, one per line,
    225 and it always ends in a newline character.
    226 
    227 Parameters:
    228    moves       - The moves of which to find the variation. Must be at most
    229                  NISSY_SIZE_MOVES long.
    230    variations  - Specify which kind of variations to find, for example
    231                  "lastqt" or "unniss".
    232    result_size - The size of the result buffer.
    233    result      - The result buffer.
    234 
    235 Return values:
    236    NISSY_ERROR_NULL_POINTER      - One of the provided pointers is NULL.
    237    NISSY_ERROR_INVALID_MOVES     - The given moves are invalid.
    238    NISSY_ERROR_INVALID_VARIATION - The given transformer is not known.
    239    NISSY_ERROR_BUFFER_SIZE       - Either the result buffer is too small or the
    240                                    given move sequence is longer than
    241                                    NISSY_SIZE_MOVES.
    242    Any value >= 0                - The number of variations found.
    243 */
    244 long long
    245 nissy_variations(
    246 	const char *moves,
    247 	const char *variation,
    248 	unsigned long long result_size,
    249 	char *result
    250 );
    251 
    252 /*
    253 Get the cube with the given ep, eo, cp and co values. The values must be in the
    254 ranges specified below, but if the option "fix" is given any values outside its
    255 range will be adjusted before using it. The option "fix" also fixes parity and
    256 orientation issues, resulting always in a solvable cube.
    257 
    258 Parameters:
    259    ep      - The edge permutation, 0 <= ep < 479001600 (12!)
    260    eo      - The edge orientation, 0 <= eo < 2047 (2^11)
    261    cp      - The corner permutation, 0 <= cp < 40320 (8!)
    262    co      - The corner orientation, 0 <= co < 2187 (3^7)
    263    orient  - The orientation of the cube, 0 <= orient < 24
    264    options - Other options.
    265    result  - The return parameter for the resulting cube.
    266              Required size: NISSY_SIZE_CUBE.
    267 
    268 Return values:
    269    NISSY_OK                 - The cube was generated succesfully.
    270    NISSY_WARNING_UNSOLVABLE - The resulting cube is unsolvable.
    271    NISSY_ERROR_OPTIONS      - One or more of the given parameters is invalid.
    272 */
    273 long long
    274 nissy_getcube(
    275 	long long ep,
    276 	long long eo,
    277 	long long cp,
    278 	long long co,
    279 	long long orient,
    280 	const char *options,
    281 	char result[] /* NISSY_SIZE_CUBE */
    282 );
    283 
    284 /*
    285 Compute the size of the data generated by nissy_gendata when called for
    286 the given solver, and other useful information.
    287 
    288 Parameters:
    289    solver - The name of the solver.
    290    dataid - An identifier for the data computed for the solver. Different
    291             solvers may use equivalent data. This identifier can be used
    292             e.g. as a filename or database key to save and retrieve the
    293             correct data for each solver, without duplication.
    294             Required size: NISSY_SIZE_DATAID.
    295 
    296 Return values:
    297    NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
    298    NISSY_ERROR_NULL_POINTER   - The 'solver' argument is null.
    299    NISSY_ERROR_UNKNOWN        - An unknown error occurred.
    300    Any value >= 0             - The size of the data, in bytes.
    301 */
    302 long long
    303 nissy_solverinfo(
    304 	const char *solver,
    305 	char dataid[] /* NISSY_SIZE_DATAID */
    306 );
    307 
    308 /*
    309 Compute the data for the given solver and store it in generated_data.
    310 
    311 Parameters:
    312    solver    - The name of the solver.
    313    data_size - The size of the data buffer. It is advised to use
    314                nissy_solverinfo to check how much memory is needed.
    315    data      - The return parameter for the generated data.
    316                This buffer must have 8-byte alignment. Some solvers (such as
    317                h48) will perform better if the buffer is 64-byte aligned.
    318 
    319 Return values:
    320    NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
    321    NISSY_ERROR_NULL_POINTER   - The 'solver' argument is null.
    322    NISSY_ERROR_UNKNOWN        - An error occurred while generating the data.
    323    NISSY_ERROR_DATA           - The data buffer is invalid, for example because
    324                                 it is not 8-byte aligned.
    325    Any value >= 0             - The size of the data, in bytes.
    326 */
    327 long long
    328 nissy_gendata(
    329 	const char *solver,
    330 	unsigned long long data_size,
    331 	unsigned char *data
    332 );
    333 
    334 /*
    335 Check that the data is a valid data table for a solver.
    336 
    337 Parameters:
    338    solver    - The name of the solver.
    339    data_size - The size of the data buffer.
    340    data      - The data for the solver. Can be computed with gendata.
    341                This buffer must have 8-byte alignment. Some solvers (such as
    342                h48) will perform better if the buffer is 64-byte aligned, but
    343                this is not relevant for the purpose of checking the integrity
    344                of the data.
    345 
    346 Return values:
    347    NISSY_OK         - The data is valid.
    348    NISSY_ERROR_DATA - The data is invalid.
    349 */
    350 long long
    351 nissy_checkdata(
    352 	const char *solver,
    353 	unsigned long long data_size,
    354 	const unsigned char *data
    355 );
    356 
    357 /*
    358 Solve the given cube using the given solver and options.
    359 
    360 Parameters:
    361    cube             - The cube to solver.
    362                       Required size: NISSY_SIZE_CUBE.
    363    solver           - The name of the solver. See doc/solvers.md for a list.
    364    nissflag         - The flags for NISS (linear, inverse, mixed, or
    365                       combinations; see the constants at the top of this file).
    366    minmoves         - The minimum number of moves for a solution.
    367    maxmoves         - The maximum number of moves for a solution.
    368    maxsols          - The maximum number of solutions.
    369    optimal          - The maximum number of moves above the optimal solution.
    370    threads          - The number of threads to use. Must be less than or equal
    371                       to the value of the compile-time constant THREADS. If set
    372                       to 0, the default value THREADS will be used.
    373    data_size        - The size of the data buffer.
    374    data             - The data for the solver. Can be computed with gendata.
    375                       This buffer must have 8-byte alignment. Some solvers
    376                       (such as h48) will perform better if the buffer is
    377                       64-byte aligned.
    378    sols_size        - The size of the solutions buffer.
    379    sols             - The return parameter for the solutions. The solutions are
    380                       separated by a '\n' (newline) and a '\0' (NULL character)
    381                       terminates the list.
    382    stats            - An array to store some statistics about the solve.
    383                       Required size: NISSY_SIZE_SOLVE_STATS.
    384    poll_status      - A callback function that should return the current
    385                       requested status for the solver (e.g. run, stop, pause,
    386                       resume; see the constants at the top of this file). The
    387                       way this status is polled and honored is solver-specific.
    388                       If this parameter is NULL, the status will always assumed
    389                       to be "run".
    390    poll_status_data - Auxiliary data for the poll_status callback function.
    391 
    392 Return values:
    393    NISSY_OK                    - Cube solved succesfully.
    394    NISSY_ERROR_INVALID_CUBE    - The given cube is invalid.
    395    NISSY_ERROR_UNSOLVABLE_CUBE - The given cube is valid, but not solvable with
    396                                  the given solver.
    397    NISSY_ERROR_OPTIONS         - One or more of the given options are invalid.
    398    NISSY_ERROR_INVALID_SOLVER  - The given solver is not known.
    399    NISSY_ERROR_NULL_POINTER    - The 'solver' argument is null.
    400    NISSY_ERROR_DATA            - The data buffer is invalid.
    401    Any value >= 0              - The number of solutions found.
    402 */
    403 long long
    404 nissy_solve(
    405 	const char cube[], /* NISSY_SIZE_CUBE */
    406 	const char *solver, 
    407 	unsigned nissflag,
    408 	unsigned minmoves,
    409 	unsigned maxmoves,
    410 	unsigned maxsolutions,
    411 	unsigned optimal,
    412 	unsigned threads,
    413 	unsigned long long data_size,
    414 	const unsigned char *data,
    415 	unsigned sols_size,
    416 	char *sols,
    417 	long long stats[], /* NISSY_SIZE_SOLVE_STATS */
    418 	int (*poll_status)(void *),
    419 	void *poll_status_data
    420 );
    421 
    422 /*
    423 Count the given moves.
    424 
    425 Parameters:
    426    moves  - The moves to be counted.
    427 
    428 Return values:
    429    NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
    430    NISSY_ERROR_NULL_POINTER  - The 'moves' argument is NULL.
    431    Any value >= 0            - The number of moves.
    432 */
    433 long long
    434 nissy_countmoves(
    435 	const char *moves
    436 );
    437 
    438 /*
    439 Compare the two moves sequences. Both must be at most NISSY_SIZE_MOVES long.
    440 
    441 Parameters:
    442    moves1 - The first sequence of moves to compare.
    443    moves2 - The second sequence of moves to compare.
    444 
    445 Return values:
    446    NISSY_ERROR_INVALID_MOVES     - One of the given moves sequences is invalid.
    447    NISSY_ERROR_NULL_POINTER      - One of the arguments is NULL.
    448    NISSY_COMPARE_MOVES_EQUAL     - The two moves sequences are indentical, up
    449                                    to swapping parallel moves.
    450    NISSY_COMPARE_MOVES_DIFFERENT - The two moves sequences are different.
    451 */
    452 long long
    453 nissy_comparemoves(
    454 	const char *moves1,
    455 	const char *moves2
    456 );
    457 
    458 /*
    459 Set a global logger function used by this library. Setting the logger to NULL
    460 disables logging.
    461 
    462 Parameters:
    463    logger_function - A pointer to a function that takes two parameters:
    464                      * A C string, the string to be printed.
    465                      * Any other data via a void pointer.
    466    user_data       - Any data that will be provided by the logger when
    467                      calling logger_function.
    468 
    469 Return values:
    470    NISSY_OK - Logger set succesfully. No warning or error is going to be given
    471               if the logger is invalid.
    472 */
    473 long long
    474 nissy_setlogger(
    475 	void (*logger_function)(const char *, void *),
    476 	void *user_data
    477 );