-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathsymmetries.py
184 lines (162 loc) · 8.42 KB
/
symmetries.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# #################### Symmetry related functions. Symmetry considerations increase the performance of the solver.######
from os import path
import array as ar
import cubie as cb
from defs import N_TWIST, N_SYM, N_SYM_D4h, N_FLIP, N_SLICE_SORTED, N_MOVE, N_FLIPSLICESORTED_CLASS
from enums import Corner as Co, Edge as Ed, Move as Mv, BS
uint32 = 'I' if ar.array('I').itemsize >= 4 else 'L' # type codes differ between architectures
INVALID32 = 4294967295
# #################### Permutations and orientation changes of the basic symmetries ###################################
# 120° clockwise rotation around the long diagonal URF-DBL
cpROT_URF3 = [Co.URF, Co.DFR, Co.DLF, Co.UFL, Co.UBR, Co.DRB, Co.DBL, Co.ULB] # corner permutation
coROT_URF3 = [1, 2, 1, 2, 2, 1, 2, 1] # corner orientation
epROT_URF3 = [Ed.UF, Ed.FR, Ed.DF, Ed.FL, Ed.UB, Ed.BR, Ed.DB, Ed.BL, Ed.UR, Ed.DR, Ed.DL, Ed.UL] # edge permutation
eoROT_URF3 = [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1] # edge orientation
# 180° rotation around the axis through the F and B centers
cpROT_F2 = [Co.DLF, Co.DFR, Co.DRB, Co.DBL, Co.UFL, Co.URF, Co.UBR, Co.ULB]
coROT_F2 = [0, 0, 0, 0, 0, 0, 0, 0]
epROT_F2 = [Ed.DL, Ed.DF, Ed.DR, Ed.DB, Ed.UL, Ed.UF, Ed.UR, Ed.UB, Ed.FL, Ed.FR, Ed.BR, Ed.BL]
eoROT_F2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# 90° clockwise rotation around the axis through the U and D centers
cpROT_U4 = [Co.UBR, Co.URF, Co.UFL, Co.ULB, Co.DRB, Co.DFR, Co.DLF, Co.DBL]
coROT_U4 = [0, 0, 0, 0, 0, 0, 0, 0]
epROT_U4 = [Ed.UB, Ed.UR, Ed.UF, Ed.UL, Ed.DB, Ed.DR, Ed.DF, Ed.DL, Ed.BR, Ed.FR, Ed.FL, Ed.BL]
eoROT_U4 = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
# reflection at the plane through the U, D, F, B centers
cpMIRR_LR2 = [Co.UFL, Co.URF, Co.UBR, Co.ULB, Co.DLF, Co.DFR, Co.DRB, Co.DBL]
coMIRR_LR2 = [3, 3, 3, 3, 3, 3, 3, 3]
epMIRR_LR2 = [Ed.UL, Ed.UF, Ed.UR, Ed.UB, Ed.DL, Ed.DF, Ed.DR, Ed.DB, Ed.FL, Ed.FR, Ed.BR, Ed.BL]
eoMIRR_LR2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
basicSymCube = [cb.CubieCube()] * 4
basicSymCube[BS.ROT_URF3] = cb.CubieCube(cpROT_URF3, coROT_URF3, epROT_URF3, eoROT_URF3)
basicSymCube[BS.ROT_F2] = cb.CubieCube(cpROT_F2, coROT_F2, epROT_F2, eoROT_F2)
basicSymCube[BS.ROT_U4] = cb.CubieCube(cpROT_U4, coROT_U4, epROT_U4, eoROT_U4)
basicSymCube[BS.MIRR_LR2] = cb.CubieCube(cpMIRR_LR2, coMIRR_LR2, epMIRR_LR2, eoMIRR_LR2)
# ######################################################################################################################
# ######################################## Fill SymCube list ###########################################################
# 48 CubieCubes will represent the 48 cube symmetries
symCube = []
cc = cb.CubieCube() # Identity cube
idx = 0
for urf3 in range(3):
for f2 in range(2):
for u4 in range(4):
for lr2 in range(2):
symCube.append(cb.CubieCube(cc.cp, cc.co, cc.ep, cc.eo))
idx += 1
cc.multiply(basicSymCube[BS.MIRR_LR2])
cc.multiply(basicSymCube[BS.ROT_U4])
cc.multiply(basicSymCube[BS.ROT_F2])
cc.multiply(basicSymCube[BS.ROT_URF3])
########################################################################################################################
# ########################################## Fill the inv_idx array ####################################################
# Indices for the inverse symmetries: SymCube[inv_idx[idx]] == SymCube[idx]^(-1)
inv_idx = [0] * N_SYM
for j in range(N_SYM):
for i in range(N_SYM):
cc = cb.CubieCube(symCube[j].cp, symCube[j].co, symCube[j].ep, symCube[j].eo)
cc.corner_multiply(symCube[i])
if cc.cp[Co.URF] == Co.URF and cc.cp[Co.UFL] == Co.UFL and cc.cp[Co.ULB] == Co.ULB:
inv_idx[j] = i
break
########################################################################################################################
# #### Generate the table for the conjugation of a move m by a symmetry s. conj_move[N_MOVE*s + m] = s*m*s^-1 ##########
conj_move = ar.array('H', [0] * (N_MOVE * N_SYM))
for s in range(N_SYM):
for m in Mv:
ss = cb.CubieCube(symCube[s].cp, symCube[s].co, symCube[s].ep, symCube[s].eo) # copy cube
ss.multiply(cb.moveCube[m]) # s*m
ss.multiply(symCube[inv_idx[s]]) # s*m*s^-1
for m2 in Mv:
if ss == cb.moveCube[m2]:
conj_move[N_MOVE * s + m] = m2
########################################################################################################################
# ###### Generate table for the conjugation of the twist t by a symmetry s. twist_conj[t, s] = s*t*s^-1 ####
fname = "conj_twist"
if not path.isfile(fname):
print('On the first run, several tables will be created. This may take 8 hours using CPython '
'(depending on the hardware). ')
print('Using PyPy reduces the time to about 15 minutes.')
print('All tables are stored in ' + path.dirname(path.abspath(fname)))
print()
print("creating " + fname + " table...")
twist_conj = ar.array('H', [0] * (N_TWIST * N_SYM_D4h))
for t in range(N_TWIST):
cc = cb.CubieCube()
cc.set_twist(t)
for s in range(N_SYM_D4h):
ss = cb.CubieCube(symCube[s].cp, symCube[s].co, symCube[s].ep, symCube[s].eo) # copy cube
ss.corner_multiply(cc) # s*t
ss.corner_multiply(symCube[inv_idx[s]]) # s*t*s^-1
twist_conj[N_SYM_D4h * t + s] = ss.get_twist()
fh = open(fname, "wb")
twist_conj.tofile(fh)
else:
print("loading " + fname + " table...")
fh = open(fname, 'rb')
twist_conj = ar.array('H')
twist_conj.fromfile(fh, N_TWIST * N_SYM_D4h)
fh.close()
# ######################################################################################################################
# ############## Generate the tables to handle the symmetry reduced flip-slicesorted coordinate ########################
fname1 = "fs24_classidx"
fname2 = "fs24_sym"
fname3 = "fs24_rep"
if not (path.isfile(fname1) and path.isfile(fname2) and path.isfile(fname3)):
print("creating " + "flipslicesorted sym-tables...")
print("This may take about 15 minutes.")
flipslicesorted_classidx = ar.array(uint32, [INVALID32] * (N_FLIP * N_SLICE_SORTED)) # idx -> classidx
flipslicesorted_sym = ar.array('B', [0] * (N_FLIP * N_SLICE_SORTED)) # idx -> symmetry
flipslicesorted_rep = ar.array(uint32, [0] * N_FLIPSLICESORTED_CLASS) # classidx -> idx of representant ANPASSEN
classidx = 0
cc = cb.CubieCube()
for slc in range(N_SLICE_SORTED):
cc.set_slice_sorted(slc)
for flip in range(N_FLIP):
cc.set_flip(flip)
idx = N_FLIP * slc + flip
if (idx + 1) % 40000 == 0:
print('.', end='', flush=True)
if (idx + 1) % 3200000 == 0:
print('')
if flipslicesorted_classidx[idx] == INVALID32:
flipslicesorted_classidx[idx] = classidx
flipslicesorted_sym[idx] = 0
flipslicesorted_rep[classidx] = idx
else:
continue
for s in range(N_SYM_D4h): # conjugate representant by all 16 symmetries
ss = cb.CubieCube(symCube[inv_idx[s]].cp, symCube[inv_idx[s]].co, symCube[inv_idx[s]].ep,
symCube[inv_idx[s]].eo) # copy cube
ss.edge_multiply(cc)
ss.edge_multiply(symCube[s]) # s^-1*cc*s
idx_new = N_FLIP * ss.get_slice_sorted() + ss.get_flip()
if flipslicesorted_classidx[idx_new] == INVALID32:
flipslicesorted_classidx[idx_new] = classidx
flipslicesorted_sym[idx_new] = s
classidx += 1
print('')
fh = open(fname1, 'wb')
flipslicesorted_classidx.tofile(fh)
fh.close()
fh = open(fname2, 'wb')
flipslicesorted_sym.tofile(fh)
fh.close()
fh = open(fname3, 'wb')
flipslicesorted_rep.tofile(fh)
fh.close()
else:
print("loading " + "flipslicesorted sym-tables...")
fh = open(fname1, 'rb')
flipslicesorted_classidx = ar.array(uint32)
flipslicesorted_classidx.fromfile(fh, N_FLIP * N_SLICE_SORTED)
fh.close()
fh = open(fname2, 'rb')
flipslicesorted_sym = ar.array('B')
flipslicesorted_sym.fromfile(fh, N_FLIP * N_SLICE_SORTED)
fh.close()
fh = open(fname3, 'rb')
flipslicesorted_rep = ar.array(uint32)
flipslicesorted_rep.fromfile(fh, N_FLIPSLICESORTED_CLASS)
fh.close()
########################################################################################################################