CoCalc Public Filestmp / 2017-02-25-152742-rubiks.sagews.html
Authors: Harald Schilly, ℏal Snyder, William A. Stein
tmp/2017-02-25-152742-rubiks.sagews

# tmp/2017-02-25-152742-rubiks.sagews

 Author William Stein Date 2017-02-25T23:35:07 Project 4a5f0542-5873-4eed-a85c-a18c706e8bcd Location tmp/2017-02-25-152742-rubiks.sagews Original file 2017-02-25-152742-rubiks.sagews
C = RubiksCube()C
+--------------+ | 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 | +--------------+
RubiksCube??
   File: /projects/sage/sage-7.5/local/lib/python2.7/site-packages/sage/groups/perm_gps/cubegroup.py
Source:
class RubiksCube(SageObject):
r"""
The Rubik's cube (in a given state).

EXAMPLES::

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
"""
def __init__(self, state=None, history=[], colors=[lpurple,yellow,red,green,orange,blue]):
"""
Initialize self.

EXAMPLES::

sage: C = RubiksCube().move("R*U")
sage: TestSuite(C).run()
"""
self.colors = colors
self._history = history
self._group = CubeGroup()
if state is None:
self._state = self._group.identity()
else:
if isinstance(state, str):
state = self._group.faces(state)
if not isinstance(state, PermutationGroupElement):
legal, state = self._group.legal(state, mode="gimme_group_element")
if not legal:
raise ValueError("Not a legal cube.")
self._state = state

def move(self, g):
r"""
Move the Rubik's cube by g.

EXAMPLES::

sage: RubiksCube().move("R*U") == RubiksCube("R*U")
True
"""
if not isinstance(g, self._group._element_class()):
g = self._group.move(g)[0]
return RubiksCube(self._state * g, self._history + [g], self.colors)

def undo(self):
r"""
Undo the last move of the Rubik's cube.

EXAMPLES::

sage: C = RubiksCube()
sage: D = C.move("R*U")
sage: D.undo() == C
True
"""
if len(self._history) == 0:
raise ValueError("no moves to undo")
g = self._history[-1]
return RubiksCube(self._state * ~g, self._history[:-1], self.colors)

def _repr_(self):
r"""
Return a string representation of self.

EXAMPLES::

sage: RubiksCube().move("R*U")
+--------------+
|  3    5   38 |
|  2   top  36 |
|  1    4   25 |
+------------+--------------+-------------+------------+
| 33  34  35 |  9   10    8 | 19   29  32 | 48  26  27 |
| 12 left 13 | 20  front  7 | 18 right 31 | 45 rear 37 |
| 14  15  16 | 22   23    6 | 17   28  30 | 43  39  40 |
+------------+--------------+-------------+------------+
| 41   42   11 |
| 44 bottom 21 |
| 46   47   24 |
+--------------+

"""
return self._group.repr2d(self._state)

def facets(self):
r"""
Return the facets of self.

EXAMPLES::

sage: C = RubiksCube("R*U")
sage: C.facets()
[3, 5, 38, 2, 36, 1, 4, 25, 33, 34, 35, 12, 13, 14, 15, 16, 9, 10,
8, 20, 7, 22, 23, 6, 19, 29, 32, 18, 31, 17, 28, 30, 48, 26, 27,
45, 37, 43, 39, 40, 41, 42, 11, 44, 21, 46, 47, 24]
"""
return self._group.facets(self._state)

def plot(self):
r"""
Return a plot of self.

EXAMPLES::

sage: C = RubiksCube("R*U")
sage: C.plot()
Graphics object consisting of 55 graphics primitives
"""
return self._group.plot_cube(self._state)

def show(self):
r"""
Show a plot of self.

EXAMPLES::

sage: C = RubiksCube("R*U")
sage: C.show()
"""
self.plot().show()

def cubie(self, size, gap, x,y,z, colors, stickers=True):
"""
Return the cubie at (x,y,z).

INPUT:

- size -- The size of the cubie
- gap -- The gap between cubies
- x,y,z -- The position of the cubie
- colors -- The list of colors
- stickers -- (Default True) Boolean to display stickers

EXAMPLES::

sage: C = RubiksCube("R*U")
sage: C.cubie(0.15, 0.025, 0,0,0, C.colors*3)
Graphics3d Object
"""
sides = cubie_face_list[x,y,z]
t = 2*size+gap
my_colors = [colors[sides[i]+6] for i in range(6)]
if stickers:
B = Box(size, size, size, color=(.1, .1, .1))
S = B + B.stickers(my_colors, size*.1, size*.01)
return S.translate(-t*x, -t*z, -t*y)
else:
return ColorCube(size, [colors[sides[i]+6] for i in range(6)]).translate(-t*x, -t*z, -t*y)

def plot3d(self, stickers=True):
r"""
Return a 3D plot of self.

EXAMPLES::

sage: C = RubiksCube("R*U")
sage: C.plot3d()
Graphics3d Object
"""
while len(self.colors) < 7:
self.colors.append((.1, .1, .1))
side_colors = [Texture(color=c, ambient=.75) for c in self.colors]
start_colors = sum([[c]*8 for c in side_colors], [])
facets = self._group.facets(self._state)
facet_colors = [0]*48
for i in range(48):
facet_colors[facets[i]-1] = start_colors[i]
all_colors = side_colors + facet_colors
pm = [-1,0,1]
C = sum([self.cubie(.15, .025, x, y, z, all_colors, stickers) for x in pm for y in pm for z in pm], Box(.35, .35, .35, color=self.colors[-1]))
return C.rotateZ(1.5) #.scale([1,-1,1]).rotateZ(1.5)

def show3d(self):
r"""
Show a 3D plot of self.

EXAMPLES::

sage: C = RubiksCube("R*U")
sage: C.show3d()
"""
return self.plot3d().show()

def __cmp__(self, other):
"""
Comparison.

EXAMPLES::

sage: C = RubiksCube()
sage: D = RubiksCube("R*U")
sage: C < D
True
sage: C > D
False
sage: C == C
True
sage: C != D
True
"""
c = cmp(type(self), type(other))
if c == 0:
return cmp(self._state, other._state)
else:
return c

def solve(self, algorithm="hybrid", timeout=15):
r"""
Solve the Rubik's cube.

INPUT:

- algorithm -- must be one of the following:

- 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)

EXAMPLES::

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
"""
import sage.interfaces.rubik # here to avoid circular referencing
if algorithm == "default":
algorithm = "hybrid"

if algorithm == "hybrid":
try:
solver = sage.interfaces.rubik.DikSolver()
return solver.solve(self.facets(), timeout=timeout)
except RuntimeError:
solver = sage.interfaces.rubik.CubexSolver()
return solver.solve(self.facets())

elif algorithm == "kociemba":
solver = sage.interfaces.rubik.DikSolver()
return solver.solve(self.facets(), timeout=timeout)

elif algorithm == "dietz":
solver = sage.interfaces.rubik.CubexSolver()
return solver.solve(self.facets())

elif algorithm == "optimal":
# TODO: cache this, startup is expensive
solver = sage.interfaces.rubik.OptimalSolver()
return solver.solve(self.facets())

elif algorithm == "gap":
solver = CubeGroup()
return solver.solve(self._state)

else:
raise ValueError("Unrecognized algorithm: %s" % algorithm)

def scramble(self, moves=30):
"""
Scramble the Rubik's cube.

EXAMPLES::

sage: C = RubiksCube()
sage: C.scramble() # random
+--------------+
| 38   29   35 |
| 20   top  42 |
| 11   44   30 |
+------------+--------------+-------------+------------+
| 48  13  17 |  6   15   24 | 43   23   9 |  1  36  32 |
|  4 left 18 |  7  front 37 | 12 right 26 |  5 rear 10 |
| 33  31  40 | 14   28    8 | 25   47  16 | 22   2   3 |
+------------+--------------+-------------+------------+
| 46   21   19 |
| 45 bottom 39 |
| 27   34   41 |
+--------------+

"""
last_move = move = "  "
all = []
for i in range(moves):
while move[0] == last_move[0]:
move = "RLUDBF"[random.randint(0,5)] + " '2"[random.randint(0,2)]
last_move = move
all.append(move)
return self.move(' '.join(all))

C = RubiksCube("R*U*R")show(C.plot3d(), spin=1)
C._state
(1,38,19,33,24,6)(2,36,21,7,4)(3,43,11,35,32,25)(5,45)(8,27,30,17,9,48)(10,34,29,28,18)(26,31)
C.solve()
'R U R'
C = RubiksCube??()
C = C.scramble()
C.show()
C.plot3d()
C.solve()
"R2 B' L2 F D2 B2 R2 U2 D' R' B F U L D' L R2 B2 F2"