API Documentation

Top-level package for Cube Solver.

class cube_solver.Cube(scramble=None, repr=None, random_state=False)[source]

Bases: object

Create Cube object.

Parameters:
  • scramble (str or None, optional) – Initial scramble. If None, no scramble is applied. Default is None.

  • repr (str or None, optional) – Cube string representation. If not None, the scramble parameter is ignored and creates a cube with the given string representation. Default is None. See Notes for the string representation format.

  • random_state (bool, optional) – If True, the scramble and repr parameters are ignored and creates a cube with a uniform random state. Default is False.

Notes

The repr parameter must contain characters from {‘W’, ‘G’, ‘R’, ‘Y’, ‘B’, ‘O’}, representing the colors Color.WHITE, Color.GREEN, Color.RED, Color.YELLOW, Color.BLUE, and Color.ORANGE, respectively. The order of the string representation is:

           ------------
           | 01 02 03 |
           | 04 05 06 |
           | 07 08 09 |
---------------------------------------------
| 10 11 12 | 19 20 21 | 28 29 30 | 37 38 39 |
| 13 14 15 | 22 23 24 | 31 32 33 | 40 41 42 |
| 16 17 18 | 25 26 27 | 34 35 36 | 43 44 45 |
---------------------------------------------
           | 46 47 48 |
           | 49 50 51 |
           | 52 53 54 |
           ------------

If the orientation, permutation, or permutation_parity values cannot be determined correctly from the string representation, the orientation and permutation arrays will contain -1 at those positions, and permutation_parity will be set to None.

The default color scheme used for the cube is as follows (note: this may differ when using the repr parameter):

Examples

>>> from cube_solver import Cube

Initial scramble.

>>> cube = Cube("U F2 R'")
>>> cube  # string representation of the cube state
WWBWWBYYOGGROOROOBGGWGGWRRYBRRBRROOGYOOYBBWBBWWGYYGYYR

Initial string representation.

>>> cube = Cube(repr="WWBWWBYYOGGROOROOBGGWGGWRRYBRRBRROOGYOOYBBWBBWWGYYGYYR")
>>> print(cube)  # print a visual layout of the cube state
        ---------
        | W W B |
        | W W B |
        | Y Y O |
---------------------------------
| G G R | G G W | B R R | Y O O |
| O O R | G G W | B R R | Y B B |
| O O B | R R Y | O O G | W B B |
---------------------------------
        | W W G |
        | Y Y G |
        | Y Y R |
        ---------

Initial random state.

>>> cube = Cube(random_state=True)
>>> cube.coords  # coordinates of the cube state (result might differ) 
(167, 48, 22530, 203841327)
orientation: ndarray

Orientation array.

The orientation array contains the orientation values of the 8 corners and 12 edges of the cube. The first 8 elements represent the corner orientation values, and the remaining 12 elements represent the edge orientation values.

A corner is correctly oriented when the top or bottom facelet of the corner piece matches either the top or bottom color of the cube. Corner orientation values are:

  • 0 if the corner is correctly oriented.

  • 1 if the corner is twisted clockwise relative to the correct orientation.

  • 2 if the corner is twisted counter-clockwise relative to the correct orientation.

An edge is correctly oriented if, when placed in its correct position using only Face.UP, Face.DOWN, Face.RIGHT and Face.LEFT face turns, it does not appear flipped. Edge orientation values are:

  • 0 if the edge is correctly oriented.

  • 1 if the edge is incorrectly oriented (i.e. flipped).

permutation: ndarray

Permutation array.

The permutation array contains the permutation values of the 8 corners and 12 edges of the cube. The first 8 elements represent the corner permutation values, and the remaining 12 elements represent the edge permutation values.

The solved state permutation goes from 0 to 7 for the corners, and from 8 to 19 for the edges. The piece ordering in the solved state is:

  • Corners: [UBL, UFR, DBR, DFL, UBR, UFL, DBL, DFR]

  • Edges: [UB, UF, DB, DF, UL, UR, DL, DR, BL, BR, FL, FR]

permutation_parity: bool | None

Permutation parity.

The permutation_parity indicates the parity of both corner and edge permutations (i.e. both parities are always the same), True for odd parity, False for even parity, and None if the parity cannot be determined.

The solved state permutation parity starts with even corner and endge parity.

property coords: Tuple[int, ...]

Cube coordinates.

Corner orientation, edge orientation, corner permutation, and edge permutation coordinates.

Examples

>>> from cube_solver import Cube
>>> cube = Cube("U F2 R'")

Get cube coordinates.

>>> cube.coords
(657, 0, 25253, 85684063)

Set cube coordinates.

>>> cube.coords = (0, 0, 0, 0)  # solved state
>>> cube
WWWWWWWWWOOOOOOOOOGGGGGGGGGRRRRRRRRRBBBBBBBBBYYYYYYYYY
property is_solved: bool

Whether the cube is solved.

Examples

>>> from cube_solver import Cube
>>> cube = Cube()
>>> cube.is_solved
True
>>> cube.apply_maneuver("U F2 R'")
>>> cube.is_solved
False
reset()[source]

Reset the cube to the solved state using the default color scheme.

Examples

>>> from cube_solver import Cube
>>> cube = Cube(random_state=True)
>>> cube.reset()
>>> cube
WWWWWWWWWOOOOOOOOOGGGGGGGGGRRRRRRRRRBBBBBBBBBYYYYYYYYY
set_random_state()[source]

Set a uniform random state.

Sets random coords (corner orientation, edge orientation, corner permutation, and edge permutation coordinates).

Examples

>>> from cube_solver import Cube
>>> cube = Cube()
>>> cube.set_random_state()
>>> cube.coords  # result might differ 
(167, 48, 22530, 203841327)
apply_move(move)[source]

Apply a move to the cube.

Parameters:

move (Move) – Move to apply.

Examples

>>> from cube_solver import Cube, Move
>>> cube = Cube()
>>> cube.apply_move(Move.U1)   # U face move
>>> cube.apply_move(Move.M2)   # M2 slice move
>>> cube.apply_move(Move.FW3)  # Fw' wide move
>>> cube.apply_move(Move.X1)   # x rotation
>>> cube
RGGBBORGGWYWWYWGOOGOOGOOYWYYWYYWYRRBRRBRRBWYWBRBBGBOGO
apply_maneuver(maneuver)[source]

Apply a sequence of moves to the cube.

Accepts the following move types:

  • Face moves (e.g. U, F2, R’).

  • Slice moves (e.g. M, E2, S’).

  • Wide moves (e.g. Uw, Fw2, Rw’ or u, f2, r’).

  • Rotations (e.g. x, y2, z’).

Parameters:

maneuver (str) – The sequence of moves to apply.

Examples

>>> from cube_solver import Cube
>>> cube = Cube()
>>> cube.apply_maneuver("U M2 Fw' x")
>>> cube
RGGBBORGGWYWWYWGOOGOOGOOYWYYWYYWYRRBRRBRRBWYWBRBBGBOGO
get_coord(coord_name)[source]

Get cube coordinate value.

Parameters:

coord_name ({'co', 'eo', 'cp', 'ep', 'pcp', 'pep'}) –

Get the specified cube coordinate.

  • ’co’ means corner orientation.

  • ’eo’ means edge orientation.

  • ’cp’ means corner permutation.

  • ’ep’ means edge permutation.

  • ’pcp’ means partial corner permutation (a value for each corner orbit).

  • ’pep’ means partial edge permutation (a value for each edge orbit).

Returns:

coord – Cube coordinate value. For partial coordinate values, a value of -1 indicates an orbit with no permutation values (e.g., (-1, -1, 0)), meaning the permutation (and orientation) values for that orbit are set to -1. If only the value of the first orbit is available (i.e., (coord, -1, -1)), returns an int representing that partial coordinate value.

The orbit order for partial coordinate values is:

Return type:

int or tuple of int

Examples

>>> from cube_solver import Cube
>>> cube = Cube("U F2 R'")

Get corner coordinates.

>>> cube.get_coord('co')   # corner orientation
657
>>> cube.get_coord('cp')   # corner permutation
25253
>>> cube.get_coord('pcp')  # partial corner permutation
(984, 679)

Get edge coordinates.

>>> cube.get_coord('eo')   # edge orientation
0
>>> cube.get_coord('ep')   # edge permutation
85684063
>>> cube.get_coord('pep')  # partial edge permutation
(8087, 7016, 3576)
set_coord(coord_name, coord)[source]

Set cube coordinate value.

Parameters:
  • coord_name ({'co', 'eo', 'cp', 'ep', 'pcp', 'pep'}) –

    Set the specified cube coordinate.

    • ’co’ means corner orientation.

    • ’eo’ means edge orientation.

    • ’cp’ means corner permutation.

    • ’ep’ means edge permutation.

    • ’pcp’ means partial corner permutation (a value for each corner orbit).

    • ’pep’ means partial edge permutation (a value for each edge orbit).

  • coord (int or tuple of int) –

    Cube coordinate value. For partial coordinate values, a value of -1 indicates an orbit with no permutation values (e.g., (-1, -1, 0)), meaning the permutation (and orientation) values for that orbit are set to -1. If an int is passed as a partial coordinate value, the value will be applied only to the first orbit (i.e., (coord, -1, -1)).

    The orbit order for partial coordinate values is:

Notes

Corner and edge permutation parities are always either both even or both odd. This constraint is enforced when setting the (partial) corner permutation and the normal edge permutation coordinates by adjusting the permutation of the edges in the permutation array while preserving the same normal edge permutation coordinate (i.e. the number of valid edge permutations is effectively halved). When setting the partial edge permutation coordinate, if the edge permutation parity does not match the corner permutation parity, permutation_parity will be set to None.

Examples

>>> from cube_solver import Cube
>>> cube = Cube()

Set corner coordinates.

>>> cube.set_coord('co', 456)           # corner orientation
>>> cube.orientation[:8]
array([0, 1, 2, 1, 2, 2, 0, 1])
>>> cube.set_coord('cp', 28179)         # corner permutation
>>> cube.permutation[:8]
array([5, 4, 0, 7, 1, 3, 6, 2])
>>> cube.set_coord('pcp', (1273, 391))  # partial corner permutation
>>> cube.permutation[:8]
array([5, 4, 0, 7, 1, 3, 6, 2])

Set edge coordinates.

>>> cube.set_coord('eo', 673)                  # edge orientation
>>> cube.orientation[8:]
array([0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0])
>>> cube.set_coord('ep', 96690777)             # edge permutation
>>> cube.permutation[8:]
array([12, 18, 10, 19,  9, 13, 14, 17, 16,  8, 11, 15])
>>> cube.set_coord('pep', (7262, 2633, 8640))  # partial edge permutation
>>> cube.permutation[8:]
array([12, 18, 10, 19,  9, 13, 14, 17, 16,  8, 11, 15])

Set some partial coordinates with -1.

>>> cube.set_coord('pcp', (1273, -1))      # same as cube.set_coord('pcp', 1273)
>>> cube.permutation[:8]
array([-1, -1,  0, -1,  1,  3, -1,  2])
>>> cube.set_coord('pep', (7262, -1, -1))  # same as cube.set_coord('pep', 7262)
>>> cube.permutation[8:]
array([-1, -1, 10, -1,  9, -1, -1, -1, -1,  8, 11, -1])
get_coords(partial_corner_perm=False, partial_edge_perm=False)[source]

Get cube coordinates.

Get the corner orientation, edge orientation, (partial) corner permutation and (partial) edge permutation coordinates.

Parameters:
  • partial_corner_perm (bool, optional) – If True, returns the partial corner permutation coordinate, otherwise returns the normal corner permutation coordinate. Default is False.

  • partial_edge_perm (bool, optional) – If True, returns the partial edge permutation coordinate, otherwise returns the normal edge permutation coordinate. Default is False.

Returns:

coords – Cube coordinates in the following order: corner orientation, edge orientation, (partial) corner permutation, (partial) edge permutation.

Return type:

tuple of (int or tuple of int)

See also

get_coord

Examples

>>> from cube_solver import Cube
>>> cube = Cube("U F2 R'")

Get cube coordinates.

>>> cube.get_coords()
(657, 0, 25253, 85684063)

Get cube coordinates with partial corner permutation and partial edge permutation.

>>> cube.get_coords(partial_corner_perm=True, partial_edge_perm=True)
(657, 0, (984, 679), (8087, 7016, 3576))
set_coords(coords, partial_corner_perm=False, partial_edge_perm=False)[source]

Set cube coordinates.

Set the corner orientation, edge orientation, (partial) corner permutation and (partial) edge permutation coordinates.

Parameters:
  • coords (tuple of (int or tuple of int)) – Cube coordinates in the following order: corner orientation, edge orientation, (partial) corner permutation, (partial) edge permutation.

  • partial_corner_perm (bool, optional) – If True, sets the partial corner permutation coordinate, otherwise sets the normal corner permutation coordinate. Default is False.

  • partial_edge_perm (bool, optional) – If True, sets the partial edge permutation coordinate, otherwise sets the normal edge permutation coordinate. Default is False.

See also

set_coord

Examples

>>> from cube_solver import Cube
>>> cube = Cube()

Set cube coordinates.

>>> coords = (657, 0, 25253, 85684063)
>>> cube.set_coords(coords)
>>> cube
WWBWWBYYOGGROOROOBGGWGGWRRYBRRBRROOGYOOYBBWBBWWGYYGYYR

Set cube coordinates with partial corner permutation and partial edge permutation.

>>> coords = (657, 0, (984, 679), (8087, 7016, 3576))
>>> cube.set_coords(coords, partial_corner_perm=True, partial_edge_perm=True)
>>> cube
WWBWWBYYOGGROOROOBGGWGGWRRYBRRBRROOGYOOYBBWBBWWGYYGYYR
copy()[source]

Return a copy of the cube.

Returns:

cube – Copy of cube object.

Return type:

Cube

Examples

>>> from cube_solver import Cube
>>> cube = Cube("U F2 R'")
>>> cube_copy = cube.copy()
>>> cube_copy
WWBWWBYYOGGROOROOBGGWGGWRRYBRRBRROOGYOOYBBWBBWWGYYGYYR
>>> cube_copy == cube
True
class cube_solver.Maneuver(moves, reduce=True)[source]

Bases: str

Create Maneuver object.

A Maneuver is a subclass of str that represents the sequence of moves that can be applied to a cube_solver.Cube object.

Parameters:
  • moves (str or list of Move) – Sequence of moves.

  • reduce (bool, optional) – Whether to reduce the sequence of moves. Default is True.

Examples

>>> from cube_solver import Cube, Move, Maneuver

Apply a maneuver to a cube.

>>> Maneuver("U F2 R'")
"U F2 R'"
>>> Maneuver([Move.U1, Move.F2, Move.R3])
"U F2 R'"
>>> Cube(Maneuver("U F2 R'")) == Cube("U F2 R'")
True

Compare equvalent maneuvers.

>>> Maneuver("R L") == "L R"
True
>>> Maneuver("F S B'") == "z"
True
>>> Maneuver("R L F2 B2 R' L' D R L F2 B2 R' L'") == "U"
True

Reduce consecutive moves along the same axis.

>>> Maneuver("U U")
'U2'
>>> Maneuver("R L R")
'R2 L'
>>> Maneuver("F S' B2 F")
'S z2'
>>> Maneuver("F S' B2 F", reduce=False)  # do not reduce
"F S' B2 F"

Inverse maneuver.

>>> Maneuver("R U R' U'").inverse
"U R U' R'"

Container operations.

>>> maneuver = Maneuver("U F2 R'")
>>> maneuver[0]
Move.U1
>>> maneuver[:2]
'U F2'
>>> [move for move in maneuver]
[Move.U1, Move.F2, Move.R3]
>>> list(maneuver)
[Move.U1, Move.F2, Move.R3]
>>> Move.U1 in maneuver
True

Numeric operations.

>>> A = Maneuver("U R'")
>>> B = Maneuver("F'")
>>> -A     # '-' negation, same as A'
"R U'"
>>> A + B  # '+' addition, same as A B
"U R' F'"
>>> A - B  # '-' subtraction, same as A B'
"U R' F"
>>> 2 * A  # '*' scalar multiplication, same as A A
"U R' U R'"
>>> A * B  # '*' conjugation, same as A B A'
"U R' F' R U'"
>>> A @ B  # '@' commutator, same as A B A' B'
"U R' F' R U' F"
property inverse: Maneuver

Inverse maneuver.

Examples

>>> from cube_solver import Maneuver
>>> Maneuver("R U R' U'").inverse
"U R U' R'"
classmethod random(length=25)[source]

Generate a random maneuver.

Parameters:

length (int, optional) – Maneuver length. Default is 25.

Returns:

maneuver – Random maneuver of the specified length.

Return type:

Maneuver

Examples

>>> from cube_solver import Maneuver
>>> Maneuver.random(10)  # result might differ 
"D2 R2 L' B2 D L D F L D2"
class cube_solver.BaseSolver(use_transition_tables=True, use_pruning_tables=True)[source]

Bases: ABC

Create BaseSolver object.

Parameters:
  • use_transition_tables (bool, optional) – Whether to use transition tables for cube state transitions. If True, creates or loads the tables from the tables/ directory. Default is True.

  • use_pruning_tables (bool, optional) – Whether to use pruning tables to reduce the tree search space. If True, creates or loads the tables from the tables/ directory. Default is True.

See also

solve

Solve a cube position.

num_phases: int = 1

Number of phases of the solving algorithm.

partial_corner_perm: bool

Whether the solving algorithm uses the normal or the partial corner permutation.

partial_edge_perm: bool

Whether the solving algorithm uses the normal or the partial edge permutation.

phase_moves: List[List[Move]]

Available moves for each phase.

transition_defs: List[TransitionDef]

Transition table definitions for each phase.

pruning_defs: List[List[PruningDef]]

Pruning table definitions for each phase.

solved_coords: List[Tuple[int, ...]]

Solved flatten coordinates for each phase.

next_moves: List[Dict[Move, List[Move]]]

Allowed next moves based on the previous move, for each phase.

final_moves: List[Set[Move]]

Final allowed moves for each phase, except the last.

use_transition_tables: bool

Whether to use transition tables for cube state transitions.

use_pruning_tables: bool

Whether to use pruning tables to reduce the tree search space.

transition_tables: Dict[str, ndarray]

Transition tables used to compute cube state transitions.

pruning_tables: Dict[str, ndarray]

Pruning tables used to reduce the tree search space.

nodes: List[int]

Number of visited nodes during a solve for each phase.

checks: List[int]

Number of solve checks during a solve for each phase.

prunes: List[int]

Number of pruned nodes during a solve for each phase.

terminated: bool

Whether the solve search was terminated due to a timeout.

abstract static phase_coords(coords, phase)[source]

Get the coordinates for the specified phase.

Parameters:
  • coords (tuple of int) – Flatten cube coordinates.

  • phase (int) – Solver phase (0-indexed).

Returns:

phase_coords – Phase coordinates.

Return type:

tuple of int

Notes

Depending on the class attributes partial_corner_perm and partial_edge_perm, the coords parameter is the flattened version of the output from the get_coords() method.

get_coords(cube)[source]

Get cube coordinates.

Get the corner orientation, edge orientation, (partial) corner permutation and (partial) edge permutation coordinates, according to partial_corner_perm and partial_edge_perm.

Parameters:

cube (Cube) – Cube object.

Returns:

coords – Cube coordinates in the following order: corner orientation, edge orientation, (partial) corner permutation, (partial) edge permutation, according to partial_corner_perm and partial_edge_perm.

Return type:

tuple of (int or tuple of int)

Examples

>>> from cube_solver import Cube, Kociemba
>>> solver = Kociemba()
>>> cube = Cube("U F2 R2")
>>> solver.get_coords(cube)
(0, 0, 26939, (1007, 11859, 673))
set_coords(cube, coords)[source]

Set cube coordinates.

Set the corner orientation, edge orientation, (partial) corner permutation and (partial) edge permutation coordinates, according to partial_corner_perm and partial_edge_perm.

Parameters:
  • cube (Cube) – Cube object.

  • coords (tuple of (int or tuple of int)) – Cube coordinates in the following order: corner orientation, edge orientation, (partial) corner permutation, (partial) edge permutation, according to partial_corner_perm and partial_edge_perm.

Examples

>>> from cube_solver import Cube, Kociemba
>>> solver = Kociemba()
>>> cube = Cube(random_state=True)
>>> coords = (0, 0, 26939, (1007, 11859, 673))
>>> solver.set_coords(cube, coords)
>>> solver.get_coords(cube)
(0, 0, 26939, (1007, 11859, 673))
is_solved(position, phase)[source]

Whether the cube position is solved at the specified phase.

Parameters:
  • position (Cube or tuple of (int or tuple of int)) – Cube object or cube coordinates to check.

  • phase (int) – Solver phase (0-indexed).

Returns:

True if the cube position is solved, False otherwise.

Return type:

bool

Examples

>>> from cube_solver import Cube, Kociemba
>>> solver = Kociemba()
>>> cube = Cube("U F2 R2")
>>> solver.is_solved(cube, phase=0)
True
>>> solver.is_solved(cube, phase=1)
False
prune(position, phase, depth)[source]

Whether to prune the search tree.

Checks whether the current depth meets the lower bound specified by the pruning_tables.

Parameters:
  • position (Cube or tuple of (int or tuple of int)) – Cube object or cube coordinates to check.

  • depth (int) – Current search depth.

  • phase (int) – Solver phase (0-indexed).

Returns:

True if the search tree should be pruned, False otherwise.

Return type:

bool

Examples

>>> from cube_solver import Cube, Kociemba
>>> solver = Kociemba()
>>> cube = Cube("U F2 R2")
>>> solver.prune(cube, phase=1, depth=2)
True
>>> solver.prune(cube, phase=1, depth=3)
False
next_position(position: Cube, move: Move) Cube[source]
next_position(position: CoordsType, move: Move) CoordsType

Get the next cube position.

Parameters:
  • position (Cube or tuple of (int or tuple of int)) – Cube object or cube coordinates.

  • move (Move) – Move to apply.

Returns:

next_position – Cube object or cube coordinates with the move applied.

Return type:

Cube or tuple of (int or tuple of int)

Examples

>>> from cube_solver import Cube, Move, Kociemba
>>> solver = Kociemba()
>>> cube = Cube("R2")
>>> coords = solver.get_coords(cube)
>>> solver.next_position(cube, Move.R2)
WWWWWWWWWOOOOOOOOOGGGGGGGGGRRRRRRRRRBBBBBBBBBYYYYYYYYY
>>> solver.next_position(coords, Move.R2)
(0, 0, 0, (0, 11856, 1656))
solve(cube, max_length=None, optimal=False, timeout=None, verbose=0)[source]

Solve the cube position.

Parameters:
  • cube (Cube) – Cube object to be solved.

  • max_length (int or None, optional) – Maximum number of moves to search. If None, search indefinitely. Default is None.

  • optimal (bool, optimal) – If True, finds the optimal solution. Default is False.

  • timeout (int or None, optional) – Stop the search after the specified number of seconds. If None, no time limit is applied. Default is None.

  • verbose ({0, 1, 2}, optional) –

    Verbosity level. Default is 0.

    • 0 returns only the solution.

    • 1 logs all solutions found if optimal is True.

    • 2 returns the solution for each phase.

Returns:

solution – Solution for the cube position, or list of solutions for each phase if verbose is 2, or None if no solution is found.

Return type:

Maneuver or list of Maneuver or None

Examples

>>> from cube_solver import Cube, Kociemba
>>> solver = Kociemba()
>>> cube = Cube("L2 U R D' B2 D2 F B D")
>>> solver.solve(cube)
"D' F' B' U2 F2 D L' F2 D2 L2 F2 U D L2 B2 D L2"
>>> solver.solve(cube, optimal=True, verbose=2)
["D' F' B' D2 B2 D R'", "U' L2"]

Subpackages

Submodules