internal static void init() { CubieCube.initPermSym2Raw(); initCPermMove(); initEPermMove(); initMPermMoveConj(); initCombMoveConj(); initMEPermPrun(); initMCPermPrun(); initPermCombPrun(); CubieCube.initFlipSym2Raw(); CubieCube.initTwistSym2Raw(); initFlipMove(); initTwistMove(); initUDSliceMoveConj(); if (Search.USE_TWIST_FLIP_PRUN) { initTwistFlipPrun(); } initSliceTwistPrun(); initSliceFlipPrun(); }
internal static void initTwistSym2Raw() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); int count = 0; TwistR2S = new char[2187]; for (int i = 0; i < 2187; i++) { if (TwistR2S[i] != 0) { continue; } c.setTwist(i); for (int s = 0; s < 16; s += 2) { CornConjugate(c, s, d); int idx = d.getTwist(); if (idx == i) { SymStateTwist[count] |= (char)(1 << (s >> 1)); } TwistR2S[idx] = (char)(count << 3 | s >> 1); if (Search.EXTRA_PRUN_LEVEL > 0) { TwistS2RF[count << 3 | s >> 1] = (char)idx; } } TwistS2R[count++] = (char)i; } if (count != 324) { throw new Exception("Unexpected count value"); } }
/** * prod = a * b, Edge Only. */ internal static void EdgeMult(CubieCube a, CubieCube b, CubieCube prod) { for (int ed = 0; ed < 12; ed++) { prod.ea[ed] = (byte)(a.ea[b.ea[ed] >> 1] ^ (b.ea[ed] & 1)); } }
protected static void initUDSliceMoveConj() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_SLICE; i++) { c.setUDSlice(i); for (int j = 0; j < N_MOVES; j += 3) { CubieCube.EdgeMult(c, CubieCube.moveCube[j], d); UDSliceMove[i, j] = (char)d.getUDSlice(); } for (int j = 0; j < 16; j += 2) { CubieCube.EdgeConjugate(c, CubieCube.SymInv[j], d); UDSliceConj[i, j >> 1] = (char)(d.getUDSlice() & 0x1ff); } } for (int i = 0; i < N_SLICE; i++) { for (int j = 0; j < N_MOVES; j += 3) { int udslice = UDSliceMove[i, j]; for (int k = 1; k < 3; k++) { int cx = UDSliceMove[udslice & 0x1ff, j]; udslice = Util.permMult[udslice >> 9, cx >> 9] << 9 | cx & 0x1ff; UDSliceMove[i, j + k] = (char)udslice; } } } }
static void initTwistMoveConj() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_TWIST; i++) { c.setTwist(i); for (int j = 0; j < N_MOVES; j += 3) { CubieCube.CornMult(c, CubieCube.moveCube[j], d); TwistMoveF[i, j] = (char)d.getTwist(); } for (int j = 0; j < 16; j++) { CubieCube.CornConjugate(c, CubieCube.SymInv[j], d); TwistConj[i, j] = (char)d.getTwist(); } } for (int i = 0; i < N_TWIST; i++) { for (int j = 0; j < N_MOVES; j += 3) { int twist = TwistMoveF[i, j]; for (int k = 1; k < 3; k++) { twist = TwistMoveF[twist, j]; TwistMoveF[i, j + k] = (char)twist; } } } }
internal static void initFlipSym2Raw() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); int count = 0; FlipR2S = new char[2048]; for (int i = 0; i < 2048; i++) { if (FlipR2S[i] != 0) { continue; } c.setFlip(i); for (int s = 0; s < 16; s += 2) { EdgeConjugate(c, s, d); int idx = d.getFlip(); if (idx == i) { SymStateFlip[count] |= (char)(1 << (s >> 1)); } FlipR2S[idx] = (char)(count << 3 | s >> 1); if (Search.USE_TWIST_FLIP_PRUN) { FlipS2RF[count << 3 | s >> 1] = (char)idx; } } FlipS2R[count++] = (char)i; } if (count != 336) { throw new Exception("Unexpected count value"); } }
internal static void init() { CubieCube.initPermSym2Raw(); initCPermMove(); initEPermMove(); initMPermMoveConj(); initCombMoveConj(); initMEPermPrun(); initMCPermPrun(); initPermCombPrun(); CubieCube.initFlipSym2Raw(); initFlipMove(); initUDSliceMoveConj(); CubieCube.initUDSliceFlipSym2Raw(); initUDSliceFlipMove(); initTwistMoveConj(); initUDSliceFlipTwistPrun(); if (Search.EXTRA_PRUN_LEVEL > 1) { initHugePrun(); } }
/** * b = S_idx^-1 * a * S_idx, Edge Only. */ internal static void EdgeConjugate(CubieCube a, int idx, CubieCube b) { CubieCube sinv = CubeSym[SymInv[idx]]; CubieCube s = CubeSym[idx]; for (int ed = 0; ed < 12; ed++) { b.ea[ed] = (byte)(sinv.ea[a.ea[s.ea[ed] >> 1] >> 1] ^ (a.ea[s.ea[ed] >> 1] & 1) ^ (s.ea[ed] & 1)); } }
internal virtual void set(CubieCube cc) { twist = cc.getTwistSym(); flip = cc.getFlipSym(); slice = cc.getUDSlice(); tsym = twist & 7; twist = twist >> 3; fsym = flip & 7; flip = flip >> 3; }
/** * this = S_urf^-1 * this * S_urf. */ internal void URFConjugate() { if (temps == null) { temps = new CubieCube(); } CornMult(urf2, this, temps); CornMult(temps, urf1, this); EdgeMult(urf2, this, temps); EdgeMult(temps, urf1, this); }
void copy(CubieCube c) { for (int i = 0; i < 8; i++) { this.ca[i] = c.ca[i]; } for (int i = 0; i < 12; i++) { this.ea[i] = c.ea[i]; } }
public bool equalsCorn(CubieCube c) { for (int i = 0; i < 8; i++) { if (ca[i] != c.ca[i]) { return(false); } } return(true); }
public bool equalsEdge(CubieCube c) { for (int i = 0; i < 12; i++) { if (ea[i] != c.ea[i]) { return(false); } } return(true); }
internal override void set(CubieCube cc) { twist = cc.getTwist(); flip = cc.getUDSliceFlipSym(); slice = cc.getUDSlice(); fsym = flip & 0xf; flip >>= 4; if (Search.EXTRA_PRUN_LEVEL > 1) { tsym = cc.getCComb(); //tsym -> CComb } }
/** * b = S_idx^-1 * a * S_idx, Corner Only. */ internal static void CornConjugate(CubieCube a, int idx, CubieCube b) { CubieCube sinv = CubeSym[SymInv[idx]]; CubieCube s = CubeSym[idx]; for (int corn = 0; corn < 8; corn++) { int oriA = sinv.ca[a.ca[s.ca[corn] & 7] & 7] >> 3; int oriB = a.ca[s.ca[corn] & 7] >> 3; int ori = (oriA < 3) ? oriB : (3 - oriB) % 3; b.ca[corn] = (byte)(sinv.ca[a.ca[s.ca[corn] & 7] & 7] & 7 | ori << 3); } }
public static String fromScramble(int[] scramble) { CubieCube c1 = new CubieCube(); CubieCube c2 = new CubieCube(); CubieCube tmp; for (int i = 0; i < scramble.Length; i++) { CubieCube.CornMult(c1, CubieCube.moveCube[scramble[i]], c2); CubieCube.EdgeMult(c1, CubieCube.moveCube[scramble[i]], c2); tmp = c1; c1 = c2; c2 = tmp; } return(Util.toFaceCube(c1)); }
protected static void initEPermMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_PERM_SYM; i++) { c.setEPerm(CubieCube.EPermS2R[i]); for (int j = 0; j < N_MOVES2; j++) { CubieCube.EdgeMult(c, CubieCube.moveCube[Util.ud2std[j]], d); EPermMove[i, j] = (char)d.getEPermSym(); } } }
protected static void initCPermMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_PERM_SYM; i++) { c.setCPerm(CubieCube.EPermS2R[i]); for (int j = 0; j < N_MOVES; j++) { CubieCube.CornMult(c, CubieCube.moveCube[j], d); CPermMove[i, j] = (char)d.getCPermSym(); } } }
static void initTwistMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_TWIST_SYM; i++) { c.setTwist(CubieCube.TwistS2R[i]); for (int j = 0; j < N_MOVES; j++) { CubieCube.CornMult(c, CubieCube.moveCube[j], d); TwistMove[i, j] = (char)d.getTwistSym(); } } }
protected static void initFlipMove() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_FLIP_SYM; i++) { c.setFlip(CubieCube.FlipS2R[i]); for (int j = 0; j < N_MOVES; j++) { CubieCube.EdgeMult(c, CubieCube.moveCube[j], d); FlipMove[i, j] = (char)d.getFlipSym(); } } }
/** * initializing from cached tables(move table, pruning table, etc.) * * @param in * Where to read tables. * * @see cs.min2phase.Tools#saveTo(java.io.DataOutput) */ public static void initFrom(System.IO.BinaryReader input) { if (Search.inited) { return; } CubieCube.initMove(); CubieCube.initSym(); read(CubieCube.FlipS2R, input); read(CubieCube.TwistS2R, input); read(CubieCube.EPermS2R, input); read(CubieCube.MtoEPerm, input); read(CubieCube.Perm2Comb, input); read(CoordCube.TwistMove, input); read(CoordCube.FlipMove, input); read(CoordCube.UDSliceMove, input); read(CoordCube.UDSliceConj, input); read(CoordCube.CPermMove, input); read(CoordCube.EPermMove, input); read(CoordCube.MPermMove, input); read(CoordCube.MPermConj, input); read(CoordCube.CCombMove, input); read(CoordCube.CCombConj, input); read(CoordCube.MCPermPrun, input); read(CoordCube.MEPermPrun, input); read(CoordCube.EPermCCombPrun, input); if (Search.EXTRA_PRUN_LEVEL > 0) { read(CubieCube.UDSliceFlipS2R, input); read(CubieCube.TwistS2RF, input); read(CoordCubeHuge.TwistMoveF, input); read(CoordCubeHuge.TwistConj, input); read(CoordCubeHuge.UDSliceFlipMove, input); read(CubieCube.FlipSlice2UDSliceFlip, input); CoordCubeHuge.initUDSliceFlipTwistPrun(); } else { read(CoordCube.UDSliceTwistPrun, input); read(CoordCube.UDSliceFlipPrun, input); if (Search.USE_TWIST_FLIP_PRUN) { read(CubieCube.FlipS2RF, input); read(CoordCube.TwistFlipPrun, input); } } Search.inited = true; }
/** * prod = a * b, Corner Only. */ internal static void CornMult(CubieCube a, CubieCube b, CubieCube prod) { for (int corn = 0; corn < 8; corn++) { int oriA = a.ca[b.ca[corn] & 7] >> 3; int oriB = b.ca[corn] >> 3; int ori = oriA; ori += (oriA < 3) ? oriB : 6 - oriB; ori %= 3; if ((oriA >= 3) ^ (oriB >= 3)) { ori += 3; } prod.ca[corn] = (byte)(a.ca[b.ca[corn] & 7] & 7 | ori << 3); } }
// ********************************************* Initialization functions ********************************************* internal static void initMove() { moveCube[0] = new CubieCube(15120, 0, 119750400, 0); moveCube[3] = new CubieCube(21021, 1494, 323403417, 0); moveCube[6] = new CubieCube(8064, 1236, 29441808, 550); moveCube[9] = new CubieCube(9, 0, 5880, 0); moveCube[12] = new CubieCube(1230, 412, 2949660, 0); moveCube[15] = new CubieCube(224, 137, 328552, 137); for (int a = 0; a < 18; a += 3) { for (int p = 0; p < 2; p++) { moveCube[a + p + 1] = new CubieCube(); EdgeMult(moveCube[a + p], moveCube[a], moveCube[a + p + 1]); CornMult(moveCube[a + p], moveCube[a], moveCube[a + p + 1]); } } }
internal void invCubieCube() { if (temps == null) { temps = new CubieCube(); } for (byte edge = 0; edge < 12; edge++) { temps.ea[ea[edge] >> 1] = (byte)(edge << 1 | ea[edge] & 1); } for (byte corn = 0; corn < 8; corn++) { int ori = ca[corn] >> 3; ori = 4 >> ori & 3; //0->0, 1->2, 2->1 temps.ca[ca[corn] & 0x7] = (byte)(corn | ori << 3); } copy(temps); }
private void initSearch() { conjMask = (TRY_INVERSE ? 0 : 0x38) | (TRY_THREE_AXES ? 0 : 0x36); CubieCube pc = new CubieCube(); selfSym = cc.selfSymmetry(); if (selfSym >> 48 != 0) { conjMask |= 0x38; } if ((selfSym >> 16 & 0xffff) != 0) { conjMask |= 0x12; } if ((selfSym >> 32 & 0xffff) != 0) { conjMask |= 0x24; } preIdxMax = conjMask > 7 ? 1 : PRE_IDX_MAX; for (int i = 0; i < 6; i++) { node0[i, 0].set(cc); corn0[i, 0] = cc.getCPermSym(); ud8e0[i, 0] = cc.getU4Comb() << 16 | cc.getD4Comb(); if ((conjMask & 1 << i) == 0) { for (int j = 1; j < preIdxMax; j++) { CubieCube.CornMult(CubieCube.moveCube[CubieCube.preMove[j]], cc, pc); CubieCube.EdgeMult(CubieCube.moveCube[CubieCube.preMove[j]], cc, pc); node0[i, j].set(pc); corn0[i, j] = pc.getCPermSym(); ud8e0[i, j] = pc.getU4Comb() << 16 | pc.getD4Comb(); } } cc.URFConjugate(); if (i % 3 == 2) { cc.invCubieCube(); } } selfSym = selfSym & 0xffffffffffffL; }
internal long selfSymmetry() { CubieCube c = new CubieCube(this); CubieCube d = new CubieCube(); long sym = 0L; for (int i = 0; i < 48; i++) { CornConjugate(c, SymInv[i % 16], d); if (d.equalsCorn(this)) { EdgeConjugate(c, SymInv[i % 16], d); if (d.equalsEdge(this)) { sym |= 1L << i; } } if (i % 16 == 15) { c.URFConjugate(); } } c.invCubieCube(); for (int i = 0; i < 48; i++) { CornConjugate(c, SymInv[i % 16], d); if (d.equalsCorn(this)) { EdgeConjugate(c, SymInv[i % 16], d); if (d.equalsEdge(this)) { sym |= 1L << 48; break; } } if (i % 16 == 15) { c.URFConjugate(); } } return(sym); }
protected static void initCombMoveConj() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_COMB; i++) { c.setCComb(i); for (int j = 0; j < N_MOVES; j++) { CubieCube.CornMult(c, CubieCube.moveCube[j], d); CCombMove[i, j] = (char)d.getCComb(); } for (int j = 0; j < 16; j++) { CubieCube.CornConjugate(c, CubieCube.SymInv[j], d); CCombConj[i, j] = (char)d.getCComb(); } } }
protected static void initMPermMoveConj() { CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); for (int i = 0; i < N_MPERM; i++) { c.setMPerm(i); for (int j = 0; j < N_MOVES2; j++) { CubieCube.EdgeMult(c, CubieCube.moveCube[Util.ud2std[j]], d); MPermMove[i, j] = (char)d.getMPerm(); } for (int j = 0; j < 16; j++) { CubieCube.EdgeConjugate(c, CubieCube.SymInv[j], d); MPermConj[i, j] = (char)d.getMPerm(); } } }
public static void init() { if (inited) { return; } CubieCube.initMove(); CubieCube.initSym(); if (EXTRA_PRUN_LEVEL > 0) { CoordCubeHuge.init(); } else { CoordCube.init(); } inited = true; }
internal int getEPermSym() { if (EPermR2S != null) { return(EPermR2S[getEPerm()]); } if (temps == null) { temps = new CubieCube(); } for (int k = 0; k < 16; k++) { EdgeConjugate(this, SymInv[k], temps); int idx = Array.BinarySearch(EPermS2R, (char)temps.getEPerm()); if (idx >= 0) { return(idx << 4 | k); } } return(0); }