protected string Searchopt() { int maxprun1 = 0; int maxprun2 = 0; for (int i = 0; i < 6; i++) { urfCoordCube[i].CalcPruning(false); if (i < 3) { maxprun1 = Math.Max(maxprun1, urfCoordCube[i].prun); } else { maxprun2 = Math.Max(maxprun2, urfCoordCube[i].prun); } } urfIdx = maxprun2 > maxprun1 ? 3 : 0; phase1Cubie[0] = urfCubieCube[urfIdx]; for (length1 = isRec ? length1 : 0; length1 < sol; length1++) { CoordCube ud = urfCoordCube[0 + urfIdx]; CoordCube rl = urfCoordCube[1 + urfIdx]; CoordCube fb = urfCoordCube[2 + urfIdx]; if (ud.prun <= length1 && rl.prun <= length1 && fb.prun <= length1 && Phase1opt(ud, rl, fb, selfSym, length1, -1) == 0) { return(solution ?? "Error 8"); } } return(solution ?? "Error 7"); }
public int DoMovePrunConj(CoordCube cc, int m) { m = CubieCube.SymMove[3, m]; flipc = FlipMove[cc.flipc >> 3, CubieCube.Sym8Move[m << 3 | cc.flipc & 7]] ^ (cc.flipc & 7); twistc = TwistMove[cc.twistc >> 3, CubieCube.Sym8Move[m << 3 | cc.twistc & 7]] ^ (cc.twistc & 7); return(GetPruning(TwistFlipPrun, (twistc >> 3) << 11 | CubieCube.FlipS2RF[flipc ^ (twistc & 7)])); }
///<returns> ///<para>-1: no solution found</para> ///<para>X: solution with X moves shorter than expectation. ///Hence, the length of the solution is depth - X</para> ///</returns> protected int Phase2(int edge, int esym, int corn, int csym, int mid, int maxl, int depth, int lm) { if (edge == 0 && corn == 0 && mid == 0) { return(maxl); } int moveMask = Util.ckmv2bit[lm]; for (int m = 0; m < 10; m++) { if ((moveMask >> m & 1) != 0) { m += 0x42 >> m & 3; continue; } int midx = CoordCube.MPermMove[mid, m]; int cornx = CoordCube.CPermMove[corn, CubieCube.SymMoveUD[csym, m]]; int csymx = CubieCube.SymMult[cornx & 0xf, csym]; cornx >>= 4; int edgex = CoordCube.EPermMove[edge, CubieCube.SymMoveUD[esym, m]]; int esymx = CubieCube.SymMult[edgex & 0xf, esym]; edgex >>= 4; int edgei = CubieCube.GetPermSymInv(edgex, esymx, false); int corni = CubieCube.GetPermSymInv(cornx, csymx, true); int prun = CoordCube.GetPruning(CoordCube.EPermCCombPPrun, (edgei >> 4) * CoordCube.N_COMB + CoordCube.CCombPConj[CubieCube.Perm2CombP[corni >> 4] & 0xff, CubieCube.SymMultInv[edgei & 0xf, corni & 0xf]]); if (prun > maxl + 1) { break; } else if (prun >= maxl) { m += 0x42 >> m & 3 & (maxl - prun); continue; } prun = Math.Max( CoordCube.GetPruning(CoordCube.MCPermPrun, cornx * CoordCube.N_MPERM + CoordCube.MPermConj[midx, csymx]), CoordCube.GetPruning(CoordCube.EPermCCombPPrun, edgex * CoordCube.N_COMB + CoordCube.CCombPConj[CubieCube.Perm2CombP[cornx] & 0xff, CubieCube.SymMultInv[esymx, csymx]])); if (prun >= maxl) { m += 0x42 >> m & 3 & (maxl - prun); continue; } int ret = Phase2(edgex, esymx, cornx, csymx, midx, maxl - 1, depth + 1, m); if (ret >= 0) { move[depth] = Util.ud2std[m]; return(ret); } } return(-1); }
protected int InitPhase2() { int p2corn = phase2Cubie.GetCPermSym(); int p2csym = p2corn & 0xf; p2corn >>= 4; int p2edge = phase2Cubie.GetEPermSym(); int p2esym = p2edge & 0xf; p2edge >>= 4; int p2mid = phase2Cubie.GetMPerm(); int prun = Math.Max( CoordCube.GetPruning(CoordCube.EPermCCombPPrun, p2edge * CoordCube.N_COMB + CoordCube.CCombPConj[CubieCube.Perm2CombP[p2corn] & 0xff, CubieCube.SymMultInv[p2esym, p2csym]]), CoordCube.GetPruning(CoordCube.MCPermPrun, p2corn * CoordCube.N_MPERM + CoordCube.MPermConj[p2mid, p2csym])); if (prun >= maxDep2) { return(prun > maxDep2 ? 2 : 1); } int depth2; for (depth2 = maxDep2 - 1; depth2 >= prun; depth2--) { int ret = Phase2(p2edge, p2esym, p2corn, p2csym, p2mid, depth2, depth1, 10); if (ret < 0) { break; } depth2 -= ret; sol = 0; for (int i = 0; i < depth1 + depth2; i++) { AppendSolMove(move[i]); } for (int i = preMoveLen - 1; i >= 0; i--) { AppendSolMove(preMoves[i]); } solution = SolutionTostring(); } if (depth2 != maxDep2 - 1) { //At least one solution has been found. maxDep2 = Math.Min(MAX_DEPTH2, sol - length1); return(probe >= probeMin ? 0 : 1); } else { return(1); } }
public int GetCPermSym() { int k = ESym2CSym(CoordCube.GetPruning(EPermR2S, GetCPerm())) & 0xf; temps = temps ?? new CubieCube(); CornConjugate(this, SymMultInv[0, k], temps); int idx = Array.BinarySearch(EPermS2R, (char)temps.GetCPerm()); //assert idx >= 0; return(idx << 4 | k); }
public int GetEPermSym() { int raw = GetEPerm(); int k = CoordCube.GetPruning(EPermR2S, raw); temps = temps ?? new CubieCube(); EdgeConjugate(this, SymMultInv[0, k], temps); int idx = Array.BinarySearch(EPermS2R, (char)temps.GetEPerm()); //assert idx >= 0; return(idx << 4 | k); }
public void Set(CoordCube node) { this.twist = node.twist; this.tsym = node.tsym; this.flip = node.flip; this.fsym = node.fsym; this.slice = node.slice; this.prun = node.prun; if (Search.USE_CONJ_PRUN) { this.twistc = node.twistc; this.flipc = node.flipc; } }
public Search() { for (int i = 0; i < 21; i++) { nodeUD[i] = new CoordCube(); nodeRL[i] = new CoordCube(); nodeFB[i] = new CoordCube(); phase1Cubie[i] = new CubieCube(); } for (int i = 0; i < 6; i++) { urfCubieCube[i] = new CubieCube(); urfCoordCube[i] = new CoordCube(); } for (int i = 0; i < MAX_PRE_MOVES; i++) { preMoveCubes[i + 1] = new CubieCube(); } }
public string Solution(string facelets, int maxDepth, long probeMax, long probeMin, int verbose) { int check = Verify(facelets); if (check != 0) { return("Error " + Math.Abs(check)); } this.sol = maxDepth + 1; this.probe = 0; this.probeMax = probeMax; this.probeMin = Math.Min(probeMin, probeMax); this.verbose = verbose; this.solution = null; this.isRec = false; CoordCube.Init(); InitSearch(); return((verbose & OPTIMAL_SOLUTION) == 0 ? SSearch() : Searchopt()); }
/** * @return pruning value */ public int DoMovePrun(CoordCube cc, int m, bool isPhase1) { slice = UDSliceMove[cc.slice, m]; flip = FlipMove[cc.flip, CubieCube.Sym8Move[m << 3 | cc.fsym]]; fsym = (flip & 7) ^ cc.fsym; flip >>= 3; twist = TwistMove[cc.twist, CubieCube.Sym8Move[m << 3 | cc.tsym]]; tsym = (twist & 7) ^ cc.tsym; twist >>= 3; prun = Math.Max( Math.Max( GetPruning(UDSliceTwistPrun, twist * N_SLICE + UDSliceConj[slice, tsym]), GetPruning(UDSliceFlipPrun, flip * N_SLICE + UDSliceConj[slice, fsym])), Search.USE_TWIST_FLIP_PRUN ? GetPruning(TwistFlipPrun, twist << 11 | CubieCube.FlipS2RF[flip << 3 | (fsym ^ tsym)]) : 0); return(prun); }
/** <returns> * <para>0: Found or Probe limit exceeded</para> * <para>1: Try Next Power</para> * <para>2: Try Next Axis</para> * </returns> */ protected int Phase1opt(CoordCube ud, CoordCube rl, CoordCube fb, long ssym, int maxl, int lm) { if (ud.prun == 0 && rl.prun == 0 && fb.prun == 0 && maxl < 5) { maxDep2 = maxl + 1; depth1 = length1 - maxl; return(InitPhase2Pre() == 0 ? 0 : 1); } int skipMoves = CubieCube.GetSkipMoves(ssym); for (int axis = 0; axis < 18; axis += 3) { if (axis == lm || axis == lm - 9) { continue; } for (int power = 0; power < 3; power++) { int m = axis + power; if (isRec && m != move[length1 - maxl] || skipMoves != 0 && (skipMoves & 1 << m) != 0) { continue; } // UD Axis int prun_ud = Math.Max(nodeUD[maxl].DoMovePrun(ud, m, false), USE_CONJ_PRUN ? nodeUD[maxl].DoMovePrunConj(ud, m) : 0); if (prun_ud > maxl) { break; } else if (prun_ud == maxl) { continue; } // RL Axis m = CubieCube.urfMove[2, m]; int prun_rl = Math.Max(nodeRL[maxl].DoMovePrun(rl, m, false), USE_CONJ_PRUN ? nodeRL[maxl].DoMovePrunConj(rl, m) : 0); if (prun_rl > maxl) { break; } else if (prun_rl == maxl) { continue; } // FB Axis m = CubieCube.urfMove[2, m]; int prun_fb = Math.Max(nodeFB[maxl].DoMovePrun(fb, m, false), USE_CONJ_PRUN ? nodeFB[maxl].DoMovePrunConj(fb, m) : 0); if (prun_ud == prun_rl && prun_rl == prun_fb && prun_fb != 0) { prun_fb++; } if (prun_fb > maxl) { break; } else if (prun_fb == maxl) { continue; } m = CubieCube.urfMove[2, m]; move[length1 - maxl] = m; valid1 = Math.Min(valid1, length1 - maxl); int ret = Phase1opt(nodeUD[maxl], nodeRL[maxl], nodeFB[maxl], ssym & CubieCube.moveCubeSym[m], maxl - 1, axis); if (ret == 0) { return(0); } } } return(1); }
/** * <returns> * <para>0: Found or Probe limit exceeded</para> * <para>1: Try Next Power</para> * <para>2: Try Next Axis</para> * </returns> */ protected int Phase1(CoordCube node, int ssym, int maxl, int lm) { if (node.prun == 0 && maxl < 5) { if (allowShorter || maxl == 0) { depth1 -= maxl; int ret = InitPhase2Pre(); depth1 += maxl; return(ret); } else { return(1); } } int skipMoves = CubieCube.GetSkipMoves(ssym); for (int axis = 0; axis < 18; axis += 3) { if (axis == lm || axis == lm - 9) { continue; } for (int power = 0; power < 3; power++) { int m = axis + power; if (isRec && m != move[depth1 - maxl] || skipMoves != 0 && (skipMoves & 1 << m) != 0) { continue; } int prun = nodeUD[maxl].DoMovePrun(node, m, true); if (prun > maxl) { break; } else if (prun == maxl) { continue; } if (USE_CONJ_PRUN) { prun = nodeUD[maxl].DoMovePrunConj(node, m); if (prun > maxl) { break; } else if (prun == maxl) { continue; } } move[depth1 - maxl] = m; valid1 = Math.Min(valid1, depth1 - maxl); int ret = Phase1(nodeUD[maxl], ssym & (int)CubieCube.moveCubeSym[m], maxl - 1, axis); if (ret == 0) { return(0); } else if (ret == 2) { break; } } } return(1); }
public static int InitSym2Raw(int N_RAW, char[] Sym2Raw, sbyte[] Raw2Sym, char[] SymState, int coord) { int N_RAW_HALF = (N_RAW + 1) / 2; CubieCube c = new CubieCube(); CubieCube d = new CubieCube(); int count = 0, idx = 0; int sym_inc = coord >= 2 ? 1 : 2; bool isEdge = coord != 1; for (int i = 0; i < N_RAW; i++) { if (CoordCube.GetPruning(Raw2Sym, i) != 0) { continue; } switch (coord) { case 0: c.SetFlip(i); break; case 1: c.SetTwist(i); break; case 2: c.SetEPerm(i); break; } for (int s = 0; s < 16; s += sym_inc) { if (isEdge) { EdgeConjugate(c, s, d); } else { CornConjugate(c, s, d); } switch (coord) { case 0: idx = d.GetFlip(); break; case 1: idx = d.GetTwist(); break; case 2: idx = d.GetEPerm(); break; } if (coord == 0 && Search.USE_TWIST_FLIP_PRUN) { FlipS2RF[count << 3 | s >> 1] = (char)idx; } if (idx == i) { SymState[count] |= (char)(1 << (s / sym_inc)); } int symIdx = (count << 4 | s) / sym_inc; if (CoordCube.GetPruning(Raw2Sym, idx) == 0) { CoordCube.SetPruning(Raw2Sym, idx, symIdx & 0xf); if (coord != 2) { Raw2Sym[idx + N_RAW_HALF] = (sbyte)(symIdx >> 4); } } } Sym2Raw[count++] = (char)i; } return(count); }
public int GetTwistSym() { int raw = GetTwist(); return(0xfff & TwistR2S[raw + CoordCube.N_TWIST_HALF] << 4 | CoordCube.GetPruning(TwistR2S, raw)); }
public static int FlipRaw2Sym(int raw) { return(0xfff & FlipR2S[raw + CoordCube.N_FLIP_HALF] << 4 | CoordCube.GetPruning(FlipR2S, raw)); }