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 (16403B)


      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    result - The return parameter for the resulting cube.
    153 
    154 Return values:
    155    NISSY_OK                  - The cube was inverted succesfully.
    156    NISSY_WARNING_UNSOLVABLE  - The resulting cube is not solvable. This is
    157                                either because the given cube was not solvable,
    158                                or due to an unknown internal error.
    159    NISSY_ERROR_INVALID_CUBE  - The given cube is invalid.
    160    NISSY_ERROR_UNKNOWN       - An unknown error occurred.
    161 */
    162 long long
    163 nissy_inverse(
    164 	const char cube[static NISSY_SIZE_CUBE],
    165 	char result[static NISSY_SIZE_CUBE]
    166 );
    167 
    168 /*
    169 Apply the given sequence of moves on the given cube.
    170 
    171 Parameters:
    172    cube   - The cube to move.
    173    moves  - The moves to apply to the cube. Must be a NULL-terminated string.
    174    result - The return parameter for the resulting cube.
    175 
    176 Return values:
    177    NISSY_OK                  - The moves were applied succesfully.
    178    NISSY_WARNING_UNSOLVABLE  - The resulting cube is not solvable. This is
    179                                either because the given cube was not solvable,
    180                                or due to an unknown internal error.
    181    NISSY_ERROR_INVALID_CUBE  - The given cube is invalid.
    182    NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
    183    NISSY_ERROR_NULL_POINTER  - The 'moves' argument is NULL.
    184 */
    185 long long
    186 nissy_applymoves(
    187 	const char cube[static NISSY_SIZE_CUBE],
    188 	const char *moves,
    189 	char result[static NISSY_SIZE_CUBE]
    190 );
    191 
    192 /*
    193 Apply the single given transformation to the given cube.
    194 
    195 Parameters:
    196    cube           - The cube to be transformed.
    197    transformation - The transformation in "(rotation|mirrored) __" format.
    198    result         - The return parameter for the resulting cube.
    199 
    200 Return values:
    201    NISSY_OK                  - The transformation was performed succesfully.
    202    NISSY_WARNING_UNSOLVABLE  - The resulting cube is not solvable. This is
    203                                probably due to an unknown internal error.
    204    NISSY_ERROR_INVALID_CUBE  - The given cube is invalid.
    205    NISSY_ERROR_INVALID_TRANS - The given transformation is invalid.
    206 */
    207 long long
    208 nissy_applytrans(
    209 	const char cube[static NISSY_SIZE_CUBE],
    210 	const char transformation[static NISSY_SIZE_TRANSFORMATION],
    211 	char result[static NISSY_SIZE_CUBE]
    212 );
    213 
    214 /*
    215 Find variations of a given move sequence, for example by changing
    216 the direction of the last quarter turn(s), or linearizing a NISS move
    217 sequence. The result consists of one or more move sequences, one per line,
    218 and it always ends in a newline character.
    219 
    220 Parameters:
    221    moves       - The moves of which to find the variation. Must be at most
    222                  NISSY_SIZE_MOVES long.
    223    variations  - Specify which kind of variations to find, for example
    224                  "lastqt" or "unniss".
    225    result_size - The size of the result buffer.
    226    result      - The result buffer.
    227 
    228 Return values:
    229    NISSY_ERROR_NULL_POINTER      - One of the provided pointers is NULL.
    230    NISSY_ERROR_INVALID_MOVES     - The given moves are invalid.
    231    NISSY_ERROR_INVALID_VARIATION - The given transformer is not known.
    232    NISSY_ERROR_BUFFER_SIZE       - Either the result buffer is too small or the
    233                                    given move sequence is longer than
    234                                    NISSY_SIZE_MOVES.
    235    Any value >= 0                - The number of variations found.
    236 */
    237 long long
    238 nissy_variations(
    239 	const char *moves,
    240 	const char *variation,
    241 	unsigned long long result_size,
    242 	char *result
    243 );
    244 
    245 /*
    246 Get the cube with the given ep, eo, cp and co values. The values must be in the
    247 ranges specified below, but if the option "fix" is given any values outside its
    248 range will be adjusted before using it. The option "fix" also fixes parity and
    249 orientation issues, resulting always in a solvable cube.
    250 
    251 Parameters:
    252    ep      - The edge permutation, 0 <= ep < 479001600 (12!)
    253    eo      - The edge orientation, 0 <= eo < 2047 (2^11)
    254    cp      - The corner permutation, 0 <= cp < 40320 (8!)
    255    co      - The corner orientation, 0 <= co < 2187 (3^7)
    256    orient  - The orientation of the cube, 0 <= orient < 24
    257    options - Other options.
    258    result  - The return parameter for the resulting cube.
    259 
    260 Return values:
    261    NISSY_OK                 - The cube was generated succesfully.
    262    NISSY_WARNING_UNSOLVABLE - The resulting cube is unsolvable.
    263    NISSY_ERROR_OPTIONS      - One or more of the given parameters is invalid.
    264 */
    265 long long
    266 nissy_getcube(
    267 	long long ep,
    268 	long long eo,
    269 	long long cp,
    270 	long long co,
    271 	long long orient,
    272 	const char *options,
    273 	char result[static NISSY_SIZE_CUBE]
    274 );
    275 
    276 /*
    277 Compute the size of the data generated by nissy_gendata when called for
    278 the given solver, and other useful information.
    279 
    280 Parameters:
    281    solver - The name of the solver.
    282    dataid - An identifier for the data computed for the solver. Different
    283             solvers may use equivalent data. This identifier can be used
    284             e.g. as a filename or database key to save and retrieve the
    285             correct data for each solver, without duplication.
    286 
    287 Return values:
    288    NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
    289    NISSY_ERROR_NULL_POINTER   - The 'solver' argument is null.
    290    NISSY_ERROR_UNKNOWN        - An unknown error occurred.
    291    Any value >= 0             - The size of the data, in bytes.
    292 */
    293 long long
    294 nissy_solverinfo(
    295 	const char *solver,
    296 	char dataid[static NISSY_SIZE_DATAID]
    297 );
    298 
    299 /*
    300 Compute the data for the given solver and store it in generated_data.
    301 
    302 Parameters:
    303    solver    - The name of the solver.
    304    data_size - The size of the data buffer. It is advised to use
    305                nissy_solverinfo to check how much memory is needed.
    306    data      - The return parameter for the generated data.
    307                This buffer must have 8-byte alignment. Some solvers (such as
    308                h48) will perform better if the buffer is 64-byte aligned.
    309 
    310 Return values:
    311    NISSY_ERROR_INVALID_SOLVER - The given solver is not known.
    312    NISSY_ERROR_NULL_POINTER   - The 'solver' argument is null.
    313    NISSY_ERROR_UNKNOWN        - An error occurred while generating the data.
    314    NISSY_ERROR_DATA           - The data buffer is invalid, for example because
    315                                 it is not 8-byte aligned.
    316    Any value >= 0             - The size of the data, in bytes.
    317 */
    318 long long
    319 nissy_gendata(
    320 	const char *solver,
    321 	unsigned long long data_size,
    322 	unsigned char *data
    323 );
    324 
    325 /*
    326 Check that the data is a valid data table for a solver.
    327 
    328 Parameters:
    329    solver    - The name of the solver.
    330    data_size - The size of the data buffer.
    331    data      - The data for the solver. Can be computed with gendata.
    332                This buffer must have 8-byte alignment. Some solvers (such as
    333                h48) will perform better if the buffer is 64-byte aligned, but
    334                this is not relevant for the purpose of checking the integrity
    335                of the data.
    336 
    337 Return values:
    338    NISSY_OK         - The data is valid.
    339    NISSY_ERROR_DATA - The data is invalid.
    340 */
    341 long long
    342 nissy_checkdata(
    343 	const char *solver,
    344 	unsigned long long data_size,
    345 	const unsigned char *data
    346 );
    347 
    348 /*
    349 Solve the given cube using the given solver and options.
    350 
    351 Parameters:
    352    cube             - The cube to solver.
    353    solver           - The name of the solver. See doc/solvers.md for a list.
    354    nissflag         - The flags for NISS (linear, inverse, mixed, or
    355                       combinations; see the constants at the top of this file).
    356    minmoves         - The minimum number of moves for a solution.
    357    maxmoves         - The maximum number of moves for a solution.
    358    maxsols          - The maximum number of solutions.
    359    optimal          - The maximum number of moves above the optimal solution.
    360    threads          - The number of threads to use. Must be less than or equal
    361                       to the value of the compile-time constant THREADS. If set
    362                       to 0, the default value THREADS will be used.
    363    data_size        - The size of the data buffer.
    364    data             - The data for the solver. Can be computed with gendata.
    365                       This buffer must have 8-byte alignment. Some solvers
    366                       (such as h48) will perform better if the buffer is
    367                       64-byte aligned.
    368    sols_size        - The size of the solutions buffer.
    369    sols             - The return parameter for the solutions. The solutions are
    370                       separated by a '\n' (newline) and a '\0' (NULL character)
    371                       terminates the list.
    372    stats            - An array to store some statistics about the solve.
    373    poll_status      - A callback function that should return the current
    374                       requested status for the solver (e.g. run, stop, pause,
    375                       resume; see the constants at the top of this file). The
    376                       way this status is polled and honored is solver-specific.
    377                       If this parameter is NULL, the status will always assumed
    378                       to be "run".
    379    poll_status_data - Auxiliary data for the poll_status callback function.
    380 
    381 Return values:
    382    NISSY_OK                    - Cube solved succesfully.
    383    NISSY_ERROR_INVALID_CUBE    - The given cube is invalid.
    384    NISSY_ERROR_UNSOLVABLE_CUBE - The given cube is valid, but not solvable with
    385                                  the given solver.
    386    NISSY_ERROR_OPTIONS         - One or more of the given options are invalid.
    387    NISSY_ERROR_INVALID_SOLVER  - The given solver is not known.
    388    NISSY_ERROR_NULL_POINTER    - The 'solver' argument is null.
    389    NISSY_ERROR_DATA            - The data buffer is invalid.
    390    Any value >= 0              - The number of solutions found.
    391 */
    392 long long
    393 nissy_solve(
    394 	const char cube[static NISSY_SIZE_CUBE],
    395 	const char *solver, 
    396 	unsigned nissflag,
    397 	unsigned minmoves,
    398 	unsigned maxmoves,
    399 	unsigned maxsolutions,
    400 	unsigned optimal,
    401 	unsigned threads,
    402 	unsigned long long data_size,
    403 	const unsigned char *data,
    404 	unsigned sols_size,
    405 	char *sols,
    406 	long long stats[static NISSY_SIZE_SOLVE_STATS],
    407 	int (*poll_status)(void *),
    408 	void *poll_status_data
    409 );
    410 
    411 /*
    412 Count the given moves.
    413 
    414 Parameters:
    415    moves  - The moves to be counted.
    416 
    417 Return values:
    418    NISSY_ERROR_INVALID_MOVES - The given moves are invalid.
    419    NISSY_ERROR_NULL_POINTER  - The 'moves' argument is NULL.
    420    Any value >= 0            - The number of moves.
    421 */
    422 long long
    423 nissy_countmoves(
    424 	const char *moves
    425 );
    426 
    427 /*
    428 Compare the two moves sequences. Both must be at most NISSY_SIZE_MOVES long.
    429 
    430 Parameters:
    431    moves1 - The first sequence of moves to compare.
    432    moves2 - The second sequence of moves to compare.
    433 
    434 Return values:
    435    NISSY_ERROR_INVALID_MOVES     - One of the given moves sequences is invalid.
    436    NISSY_ERROR_NULL_POINTER      - One of the arguments is NULL.
    437    NISSY_COMPARE_MOVES_EQUAL     - The two moves sequences are indentical, up
    438                                    to swapping parallel moves.
    439    NISSY_COMPARE_MOVES_DIFFERENT - The two moves sequences are different.
    440 */
    441 long long
    442 nissy_comparemoves(
    443 	const char *moves1,
    444 	const char *moves2
    445 );
    446 
    447 /*
    448 Set a global logger function used by this library. Setting the logger to NULL
    449 disables logging.
    450 
    451 Parameters:
    452    logger_function - A pointer to a function that takes two parameters:
    453                      * A C string, the string to be printed.
    454                      * Any other data via a void pointer.
    455    user_data       - Any data that will be provided by the logger when
    456                      calling logger_function.
    457 
    458 Return values:
    459    NISSY_OK - Logger set succesfully. No warning or error is going to be given
    460               if the logger is invalid.
    461 */
    462 long long
    463 nissy_setlogger(
    464 	void (*logger_function)(const char *, void *),
    465 	void *user_data
    466 );