Module: sage.groups.perm_gps.cubegroup
NOTE: ``Rubik's cube'' is trademarked. We shall omit the trademark symbol below for simplcity.
NOTATION: B denotes a clockwise quarter turn of the back face D denotes a clockwise quarter turn of the down face and similarly for F (front), L (left), R (right), U (up) Products of moves are read right to left, so for example, R*U means move U first and then R.
See CubeGroup.parse()
for all possible input notations.
The "Singmaster notation": * moves: U, D, R, L, F, B as in the diagram below, * corners: xyz means the facet is on face x (in R,F,L,U,D,B) and the clockwise rotation of the corner sends x->y->z * edges: xy means the facet is on face x and a flip of the edge sends x->y.
sage: rubik = CubeGroup() sage: rubik.display2d("") +--------------+ | 1 2 3 | | 4 top 5 | | 6 7 8 | +------------+--------------+-------------+------------+ | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | +------------+--------------+-------------+------------+ | 41 42 43 | | 44 bottom 45 | | 46 47 48 | +--------------+
Author: - David Joyner (2006-10-21): first version - " (2007-05): changed faces, added legal and solve - " (2007-06): added plotting functions - " (2007-08): colors corrected, "solve" rewritten (again),typos fixed. - Robert Miller (2007-08): editing, cleaned up display2d - Robert Bradshaw (2007-08): RubiksCube object, 3d plotting. - DJ (2007-09): rewrote docstring for CubeGroup's "solve". - Robert Bradshaw (2007-09): Versatile parse function for all input types. - Robert Bradshaw (2007-11): Cleanup.
REFERENCES: Cameron, P., Permutation Groups. New York: Cambridge University Press, 1999. Wielandt, H., Finite Permutation Groups. New York: Academic Press, 1964. Dixon, J. and Mortimer, B., Permutation Groups, Springer-Verlag, Berlin/New York, 1996. Joyner, D, Adventures in Group Theory, Johns Hopkins Univ Press, 2002.
Module-level Functions
facet, [colors=['lpurple', 'yellow', 'red', 'green', 'orange', 'blue']]) |
Returns the color the facet has in the solved state.
sage: from sage.groups.perm_gps.cubegroup import * sage: color_of_square(41) 'blue'
face, color) |
label) |
label, state0) |
) |
This provides a map from the 6 faces of the 27 cubies to the 48 facets of the larger cube.
-1,-1,-1 is left, top, front
facet) |
Translates index used (eg, 43) to Singmaster facet notation (eg, fdr).
sage: from sage.groups.perm_gps.cubegroup import * sage: index2singmaster(41) 'dlf'
lst) |
Input a list of ints 1, ..., m (in any order), outputs inverse perm.
sage: from sage.groups.perm_gps.cubegroup import * sage: L = [2,3,1] sage: inv_list(L) [3, 1, 2]
cnt, clrs) |
Plots the front, up and right face of a cubie centered at cnt and rgbcolors given by clrs (in the order FUR).
Type P.show() to view.
sage: from sage.groups.perm_gps.cubegroup import * sage: clrF = blue; clrU = red; clrR = green sage: P = plot3d_cubie([1/2,1/2,1/2],[clrF,clrU,clrR])
points, [tilt=30], [turn=30]) |
Plots a polygon viewed from an angle determined by tilt, turn, and vertices points.
WARNING: The ordering of the points is important to get "correct" and if you add several of these plots together, the one added first is also drawn first (ie, addition of Graphics objects is not commutative).
The following example produced a green-colored square with vertices at the points indicated.
sage: from sage.groups.perm_gps.cubegroup import * sage: P = polygon_plot3d([[1,3,1],[2,3,1],[2,3,2],[1,3,2],[1,3,1]],rgbcolor=green)
tilt, turn) |
x, y, z, r) |
x, y, z, r) |
Class: CubeGroup
If G denotes the cube group then it may be regarded as a subgroup of SymmetricGroup(48), where the 48 facets are labeled as follows.
sage: rubik = CubeGroup() sage: rubik.display2d("") +--------------+ | 1 2 3 | | 4 top 5 | | 6 7 8 | +------------+--------------+-------------+------------+ | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | +------------+--------------+-------------+------------+ | 41 42 43 | | 44 bottom 45 | | 46 47 48 | +--------------+
sage: rubik The PermutationGroup of all legal moves of the Rubik's cube. sage: print rubik The Rubik's cube group with genrators R,L,F,B,U,D in SymmetricGroup(48).
self) |
Functions: B,
D,
display2d,
F,
faces,
facets,
gen_names,
gens,
group,
L,
legal,
move,
parse,
plot3d_cube,
plot_cube,
R,
repr2d,
solve,
U
self, mv) |
Returns the dictionary of faces created by the effect of the
move mv, which is a string of the form
, where
,
, ... are in
and
are
integers. We call this ordering of the faces the
"BDFLRU, L2R, T2B ordering".
sage: rubik = CubeGroup()
Now type rubik.faces("")
for the dictionary of the solved state
and rubik.faces("R*L")
for the dictionary of the state obtained
after making the move R followed by L.
self, [g=None]) |
Returns the set of facets on which the group acts. This function is a "constant".
sage: rubik = CubeGroup() sage: rubik.facets()==range(1,49) True
self, state, [mode=quiet]) |
Returns 1 (true) if the dictionary state
(in the same format as
returned by the faces method) represents a legal position (or state) of
the Rubik's cube. Returns 0 (false) otherwise.
sage: rubik = CubeGroup() sage: G = rubik.group() sage: r0 = rubik.faces("") sage: r1 = {'back': [[33, 34, 35], [36, 0, 37], [38, 39, 40]], 'down': [[41, 42, 43], [44, 0, 45], [46, 47, 48]],'front': [[17, 18, 19], [20, 0, 21], [22, 23, 24]],'left': [[9, 10, 11], [12, 0, 13], [14, 15, 16]],'right': [[25, 26, 27], [28, 0, 29], [30, 31, 32]],'up': [[1, 2, 3], [4, 0, 5], [6, 8, 7]]} sage: rubik.legal(r0) 1 sage: rubik.legal(r0,"verbose") (1, ()) sage: rubik.legal(r1) 0
self, mv) |
Returns the group element and the reordered list of facets, as moved by the list mv (read left-to-right)
Input: mv is a string of the form "xâ*yb*...", where X, Y, ... are in R,L,F,B,U,D and a,b, ... are integers.
sage: rubik = CubeGroup() sage: rubik.move("")[0] () sage: rubik.move("R")[0] (3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28) sage: rubik.R() (3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)
self, mv) |
This function allows one to create the permutation group element from a variety of formats.
Input: one of the following
sage: C = CubeGroup() sage: C.parse(range(1,49)) () sage: g = C.parse("L"); g (1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12) sage: C.parse(str(g)) == g True sage: facets = C.facets(g); facets [17, 2, 3, 20, 5, 22, 7, 8, 11, 13, 16, 10, 15, 9, 12, 14, 41, 18, 19, 44, 21, 46, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 6, 36, 4, 38, 39, 1, 40, 42, 43, 37, 45, 35, 47, 48] sage: C.parse(facets) (1,17,41,40)(4,20,44,37)(6,22,46,35)(9,11,16,14)(10,13,15,12) sage: C.parse(facets) == g True sage: faces = C.faces("L"); faces {'right': [[25, 26, 27], [28, 0, 29], [30, 31, 32]], 'up': [[17, 2, 3], [20, 0, 5], [22, 7, 8]], 'back': [[33, 34, 6], [36, 0, 4], [38, 39, 1]], 'down': [[40, 42, 43], [37, 0, 45], [35, 47, 48]], 'front': [[41, 18, 19], [44, 0, 21], [46, 23, 24]], 'left': [[11, 13, 16], [10, 0, 15], [9, 12, 14]]} sage: C.parse(faces) == C.parse("L") True sage: C.parse("L' R2") == C.parse("L^(-1)*R^2") True sage: C.parse("L' R2") (1,40,41,17)(3,43)(4,37,44,20)(5,45)(6,35,46,22)(8,48)(9,14,16,11)(10,12,15 ,13)(19,38)(21,36)(24,33)(25,32)(26,31)(27,30)(28,29) sage: C.parse("L^4") () sage: C.parse("L^(-1)*R") (1,40,41,17)(3,38,43,19)(4,37,44,20)(5,36,45,21)(6,35,46,22)(8,33,48,24)(9, 14,16,11)(10,12,15,13)(25,27,32,30)(26,29,31,28)
self, mv, [title=True]) |
Displays F,U,R faces of the cube after the given move mv, where mv is a string in the Singmaster notation. Mostly included for the purpose of drawing pictures and checking moves.
The first one below is "superflip+4 spot" (in 26q* moves) and the second one is the superflip (in 20f* moves). Type show(P) to view them.
sage: rubik = CubeGroup() sage: P = rubik.plot3d_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") sage: P = rubik.plot3d_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3")
self, mv, [title=True], [colors=[(1, 0.63, 1), (1, 1, 0), (1, 0, 0), (0, 1, 0), (1, 0.59999999999999998, 0.29999999999999999), (0, 0, 1)]]) |
Input the move mv, as a string in the Singmaster notation, and output the 2-d plot of the cube in that state.
Type P.show() to display any of the plots below.
sage: rubik = CubeGroup() sage: P = rubik.plot_cube("R^2*U^2*R^2*U^2*R^2*U^2", title = False) sage: # (R^2U^2)^3 permutes 2 pairs of edges (uf,ub)(fr,br) sage: P = rubik.plot_cube("R*L*D^2*B^3*L^2*F^2*R^2*U^3*D*R^3*D^2*F^3*B^3*D^3*F^2*D^3*R^2*U^3*F^2*D^3") sage: # the superflip (in 20f* moves) sage: P = rubik.plot_cube("U^2*F*U^2*L*R^(-1)*F^2*U*F^3*B^3*R*L*U^2*R*D^3*U*L^3*R*D*R^3*L^3*D^2") sage: # "superflip+4 spot" (in 26q* moves)
self, mv) |
Displays a 2d map of the Rubik's cube after the move mv has been made. Nothing is returned.
sage: rubik = CubeGroup() sage: rubik.display2d("") +--------------+ | 1 2 3 | | 4 top 5 | | 6 7 8 | +------------+--------------+-------------+------------+ | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | +------------+--------------+-------------+------------+ | 41 42 43 | | 44 bottom 45 | | 46 47 48 | +--------------+
sage: rubik.display2d("R") +--------------+ | 1 2 38 | | 4 top 36 | | 6 7 33 | +------------+--------------+-------------+------------+ | 9 10 11 | 17 18 3 | 27 29 32 | 48 34 35 | | 12 left 13 | 20 front 5 | 26 right 31 | 45 rear 37 | | 14 15 16 | 22 23 8 | 25 28 30 | 43 39 40 | +------------+--------------+-------------+------------+ | 41 42 19 | | 44 bottom 21 | | 46 47 24 | +--------------+
You can see the right face has been rotated but not the left face.
self, state, [algorithm=default]) |
Solves the cube in the state
, given as a dictionary as
in legal
. See the solve
method of the RubiksCube
class for more details.
This may use GAP's EpimorphismFromFreeGroup
and PreImagesRepresentative
as explained below,
if 'gap' is passed in as the algorithm.
This algorithm
The Rubik's cube group has about
elements, so this
process is time-consuming.
See http://www.gap-system.org/Doc/Examples/rubik.html
for an interesting discussion of some GAP code analyzing the
Rubik's cube.
sage: rubik = CubeGroup() sage: state = rubik.faces("R") sage: rubik.solve(state) 'R' sage: state = rubik.faces("R*U") sage: rubik.solve(state, algorithm='gap') # long time 'R*U'
You can also check this another (but similar) way using the
word_problem
method (eg, G = rubik.group();
g = G("(3,38,43,19)(5,36,45,21)(8,33,48,24)(25,27,32,30)(26,29,31,28)");
g.word_problem([b,d,f,l,r,u]), though the output will be less intuitive).
Special Functions: __call__,
__init__,
__repr__,
__str__
self, mv) |
sage: rubik = CubeGroup() sage: rubik(1) ()
Class: RubiksCube
sage: C = RubiksCube().move("R U R'") sage: C.show3d()
sage: C = RubiksCube("R*L"); C +--------------+ | 17 2 38 | | 20 top 36 | | 22 7 33 | +------------+--------------+-------------+------------+ | 11 13 16 | 41 18 3 | 27 29 32 | 48 34 6 | | 10 left 15 | 44 front 5 | 26 right 31 | 45 rear 4 | | 9 12 14 | 46 23 8 | 25 28 30 | 43 39 1 | +------------+--------------+-------------+------------+ | 40 42 19 | | 37 bottom 21 | | 35 47 24 | +--------------+ sage: C.show() sage: C.solve(algorithm='gap') # long time 'L R' sage: C == RubiksCube("L*R") True
self, [state=None], [history=[]], [colors=[(1, 0.63, 1), (1, 1, 0), (1, 0, 0), (0, 1, 0), (1, 0.59999999999999998, 0.29999999999999999), (0, 0, 1)]]) |
Functions: cubie,
facets,
move,
plot,
plot3d,
scramble,
show,
show3d,
solve,
undo
self, [stickers=True]) |
sage: C = RubiksCube().move("R*U") sage: C.plot3d() sage: C.plot()
self, [algorithm=hybrid], [timeout=15]) |
Algorithm must be one of : hybrid - try kociemba for timeout seconds, then dietz kociemba - Use Dik T. Winter's program (reasonable speed, few moves) dietz - Use Eric Dietz's cubex program (fast but lots of moves) optimal - Use Michael Reid's optimal program (may take a long time) gap - Use GAP word solution (can be slow)
sage: C = RubiksCube("R U F L B D") sage: C.solve() 'R U F L B D'
Dietz's program is much faster, but may give highly non-optimal solutions.
sage: s = C.solve('dietz'); s "U' L' L' U L U' L U D L L D' L' D L' D' L D L' U' L D' L' U L' B' U' L' U B L D L D' U' L' U L B L B' L' U L U' L' F' L' F L' F L F' L' D' L' D D L D' B L B' L B' L B F' L F F B' L F' B D' D' L D B' B' L' D' B U' U' L' B' D' F' F' L D F'" sage: C2 = RubiksCube(s) sage: C == C2 True
Special Functions: __cmp__,
__init__,
__repr__
See About this document... for information on suggesting changes.