Пример #1
0
        private string searchopt()
        {
            int maxprun1 = 0;
            int maxprun2 = 0;

            for (int i = 0; i < 6; i++)
            {
                node0[i, 0].calcPruning(false);
                if (i < 3)
                {
                    maxprun1 = Math.Max(maxprun1, node0[i, 0].prun);
                }
                else
                {
                    maxprun2 = Math.Max(maxprun2, node0[i, 0].prun);
                }
            }
            urfIdx = maxprun2 > maxprun1 ? 3 : 0;
            preIdx = 0;
            for (length1 = isRec ? length1 : 0; length1 < sol; length1++)
            {
                CoordCube ud = node0[0 + urfIdx, 0];
                CoordCube rl = node0[1 + urfIdx, 0];
                CoordCube fb = node0[2 + urfIdx, 0];

                if (ud.prun <= length1 && rl.prun <= length1 && fb.prun <= length1 &&
                    phase1opt(ud, rl, fb, selfSym, length1, -1) == 0)
                {
                    return(this.solution_ == null ? "Error 8" : this.solution_);
                }
            }
            return(this.solution_ == null ? "Error 7" : this.solution_);
        }
Пример #2
0
 protected 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;
 }
Пример #3
0
 //-1: no solution found
 // X: solution with X moves shorter than expectation. Hence, the length of the solution is  depth - X
 private int phase2(int eidx, int esym, int cidx, int csym, int mid, int maxl, int depth, int lm)
 {
     if (eidx == 0 && cidx == 0 && mid == 0)
     {
         return(maxl);
     }
     for (int m = 0; m < 10; m++)
     {
         if (lm < 0 ? (m == -lm) : Util.ckmv2[lm, m])
         {
             continue;
         }
         int midx  = CoordCube.MPermMove[mid, m];
         int cidxx = CoordCube.CPermMove[cidx, CubieCube.SymMove[csym, Util.ud2std[m]]];
         int csymx = CubieCube.SymMult[cidxx & 0xf, csym];
         cidxx >>= 4;
         if (CoordCube.getPruning(CoordCube.MCPermPrun,
                                  cidxx * 24 + CoordCube.MPermConj[midx, csymx]) >= maxl)
         {
             continue;
         }
         int eidxx = CoordCube.EPermMove[eidx, CubieCube.SymMoveUD[esym, m]];
         int esymx = CubieCube.SymMult[eidxx & 0xf, esym];
         eidxx >>= 4;
         if (CoordCube.getPruning(CoordCube.EPermCCombPrun,
                                  eidxx * 70 + CoordCube.CCombConj[CubieCube.Perm2Comb[cidxx], CubieCube.SymMultInv[esymx, csymx]]) >= maxl)
         {
             continue;
         }
         if (CoordCube.getPruning(CoordCube.MEPermPrun,
                                  eidxx * 24 + CoordCube.MPermConj[midx, esymx]) >= maxl)
         {
             continue;
         }
         int ret = phase2(eidxx, esymx, cidxx, csymx, midx, maxl - 1, depth + 1, (lm < 0 && m + lm == -5) ? -lm : m);
         if (ret >= 0)
         {
             move[depth] = Util.ud2std[m];
             return(ret);
         }
     }
     return(-1);
 }
Пример #4
0
        public static void init()
        {
            if (inited)
            {
                return;
            }
            CubieCube.initMove();
            CubieCube.initSym();

            if (EXTRA_PRUN_LEVEL > 0)
            {
                CoordCubeHuge.init();
            }
            else
            {
                CoordCube.init();
            }

            inited = true;
        }
Пример #5
0
        /**
         * @return
         *      0: Success
         *      1: Try Next Power
         *      2: Try Next Axis
         */
        internal virtual int doMovePrun(CoordCube cc, int m, bool isPhase1)
        {
            slice = UDSliceMove[cc.slice & 0x1ff, m] & 0x1ff;

            flip   = FlipMove[cc.flip, CubieCube.Sym8Move[m << 3 | cc.fsym]];
            fsym   = CubieCube.Sym8Mult[flip & 7 | cc.fsym << 3];
            flip >>= 3;

            twist   = TwistMove[cc.twist, CubieCube.Sym8Move[m << 3 | cc.tsym]];
            tsym    = CubieCube.Sym8Mult[twist & 7 | cc.tsym << 3];
            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 | CubieCube.Sym8MultInv[fsym << 3 | tsym]]) : 0);
            return(prun);
        }
Пример #6
0
        /**
         * @return
         *      0: Success
         *      1: Try Next Power
         *      2: Try Next Axis
         */
        internal override int doMovePrun(CoordCube cc, int m, bool isPhase1)
        {
            twist  = TwistMoveF[cc.twist, m];
            flip   = UDSliceFlipMove[cc.flip, CubieCube.SymMove[cc.fsym, m]];
            fsym   = CubieCube.SymMult[flip & 0xf, cc.fsym];
            flip >>= 4;

            int prunm3;

            if (Search.EXTRA_PRUN_LEVEL > 1 && !isPhase1)
            {
                tsym   = CCombMove[cc.tsym, m];
                prunm3 = getPruningP(HugePrunP,
                                     flip * ((long)N_TWIST) * N_COMB + TwistConj[twist, fsym] * N_COMB + CCombConj[tsym, fsym], N_HUGE_5 * 4L);
            }
            else
            {
                prunm3 = getPruningP(UDSliceFlipTwistPrunP,
                                     flip * N_TWIST + TwistConj[twist, fsym], N_FULL_5 * 4);
            }
            prun = ((0x49249249 << prunm3 >> cc.prun) & 3) + cc.prun - 1;

            return(prun);
        }
Пример #7
0
        /**
         * @return
         *      0: Found or Probe limit exceeded
         *      1: Try Next Power
         *      2: Try Next Axis
         */
        private int initPhase2()
        {
            isRec = false;
            if (probe >= (this.solution_ == null ? probeMax : probeMin))
            {
                return(0);
            }
            ++probe;
            int cidx = corn0[urfIdx, preIdx] >> 4;
            int csym = corn0[urfIdx, preIdx] & 0xf;
            int mid  = node0[urfIdx, preIdx].slice;

            for (int i = 0; i < depth1; i++)
            {
                int m = move[i];
                cidx   = CoordCube.CPermMove[cidx, CubieCube.SymMove[csym, m]];
                csym   = CubieCube.SymMult[cidx & 0xf, csym];
                cidx >>= 4;

                int cx = CoordCube.UDSliceMove[mid & 0x1ff, m];
                mid = Util.permMult[mid >> 9, cx >> 9] << 9 | cx & 0x1ff;
            }
            mid >>= 9;
            int prun = CoordCube.getPruning(CoordCube.MCPermPrun, cidx * 24 + CoordCube.MPermConj[mid, csym]);

            if (prun >= maxDep2)
            {
                return(prun > maxDep2 ? 2 : 1);
            }

            int u4e = ud8e0[urfIdx, preIdx] >> 16;
            int d4e = ud8e0[urfIdx, preIdx] & 0xffff;

            for (int i = 0; i < depth1; i++)
            {
                int m = move[i];

                int cx = CoordCube.UDSliceMove[u4e & 0x1ff, m];
                u4e = Util.permMult[u4e >> 9, cx >> 9] << 9 | cx & 0x1ff;

                cx  = CoordCube.UDSliceMove[d4e & 0x1ff, m];
                d4e = Util.permMult[d4e >> 9, cx >> 9] << 9 | cx & 0x1ff;
            }

            int edge = CubieCube.MtoEPerm[494 - (u4e & 0x1ff) + (u4e >> 9) * 70 + (d4e >> 9) * 1680];
            int esym = edge & 0xf;

            edge >>= 4;

            prun = Math.Max(prun, Math.Max(
                                CoordCube.getPruning(CoordCube.MEPermPrun,
                                                     edge * 24 + CoordCube.MPermConj[mid, esym]),
                                CoordCube.getPruning(CoordCube.EPermCCombPrun,
                                                     edge * 70 + CoordCube.CCombConj[CubieCube.Perm2Comb[cidx], CubieCube.SymMultInv[esym, csym]])));

            if (prun >= maxDep2)
            {
                return(prun > maxDep2 ? 2 : 1);
            }

            int lm = 10;

            if (depth1 >= 2 && move[depth1 - 1] / 3 % 3 == move[depth1 - 2] / 3 % 3)
            {
                lm = Util.std2ud[Math.Max(move[depth1 - 1], move[depth1 - 2]) / 3 * 3 + 1];
            }
            else if (depth1 >= 1)
            {
                lm = Util.std2ud[move[depth1 - 1] / 3 * 3 + 1];
                if (move[depth1 - 1] > Util.Fx3)
                {
                    lm = -lm;
                }
            }

            int depth2;

            for (depth2 = maxDep2 - 1; depth2 >= prun; depth2--)
            {
                int ret = phase2(edge, esym, cidx, csym, mid, depth2, depth1, lm);
                if (ret < 0)
                {
                    break;
                }
                depth2 = depth2 - ret;
                sol    = depth1 + depth2;
                if (preIdx != 0)
                {
                    // assert depth2 > 0; //If depth2 == 0, the solution is optimal. In this case, we won't try preScramble to find shorter solutions.
                    int axisPre  = Util.preMove[preIdx] / 3;
                    int axisLast = move[sol - 1] / 3;
                    if (axisPre == axisLast)
                    {
                        int pow = (Util.preMove[preIdx] % 3 + move[sol - 1] % 3 + 1) % 4;
                        move[sol - 1] = axisPre * 3 + pow;
                    }
                    else if (depth2 > 1 &&
                             axisPre % 3 == axisLast % 3 &&
                             move[sol - 2] / 3 == axisPre)
                    {
                        int pow = (Util.preMove[preIdx] % 3 + move[sol - 2] % 3 + 1) % 4;
                        move[sol - 2] = axisPre * 3 + pow;
                    }
                    else
                    {
                        move[sol++] = Util.preMove[preIdx];
                    }
                }
                this.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);
            }
        }
Пример #8
0
        /**
         * @return
         *      0: Found or Probe limit exceeded
         *      1: Try Next Power
         *      2: Try Next Axis
         */
        private 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(initPhase2() == 0 ? 0 : 1);
            }

            int skipMoves = 0;
            int i         = 1;

            for (long s = ssym; (s >>= 1) != 0; i++)
            {
                if ((s & 1) == 1)
                {
                    skipMoves |= CubieCube.firstMoveSym[i];
                }
            }

            for (int axis = 0; axis < 18; axis += 3)
            {
                if (axis == lm || axis == lm - 9 || (isRec && axis < move[length1 - maxl] - 2))
                {
                    continue;
                }
                for (int power = 0; power < 3; power++)
                {
                    int m = axis + power;

                    if (isRec && m != move[length1 - maxl] ||
                        ssym != 1 && (skipMoves & 1 << m) != 0)
                    {
                        continue;
                    }

                    // UD Axis
                    int prun_ud = nodeUD[maxl].doMovePrun(ud, m, false);
                    if (prun_ud > maxl)
                    {
                        break;
                    }
                    else if (prun_ud == maxl)
                    {
                        continue;
                    }

                    // RL Axis
                    m = CubieCube.urfMove[2, m];

                    int prun_rl = nodeRL[maxl].doMovePrun(rl, m, false);
                    if (prun_rl > maxl)
                    {
                        break;
                    }
                    else if (prun_rl == maxl)
                    {
                        continue;
                    }

                    // FB Axis
                    m = CubieCube.urfMove[2, m];

                    int prun_fb = nodeFB[maxl].doMovePrun(fb, m, false);
                    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;
                    int ret = phase1opt(nodeUD[maxl], nodeRL[maxl], nodeFB[maxl], ssym & CubieCube.moveCubeSym[m], maxl - 1, axis);
                    if (ret == 0)
                    {
                        return(0);
                    }
                    else if (ret == 2)
                    {
                        break;
                    }
                }
            }
            return(1);
        }
Пример #9
0
        /**
         * @return
         *      0: Found or Probe limit exceeded
         *      1: Try Next Power
         *      2: Try Next Axis
         */
        private int phase1(CoordCube node, long ssym, int maxl, int lm)
        {
            if (node.prun == 0 && maxl < 5)
            {
                if (maxl == 0)
                {
                    int ret = initPhase2();
                    if (ret == 0 || preIdx == 0)
                    {
                        return(ret);
                    }
                    preIdx++;
                    ret = Math.Min(initPhase2(), ret);
                    preIdx--;
                    return(ret);
                }
                else
                {
                    return(1);
                }
            }

            int skipMoves = 0;
            int i         = 1;

            for (long s = ssym; (s >>= 1) != 0; i++)
            {
                if ((s & 1) == 1)
                {
                    skipMoves |= CubieCube.firstMoveSym[i];
                }
            }

            for (int axis = 0; axis < 18; axis += 3)
            {
                if (axis == lm || axis == lm - 9 ||
                    (isRec && axis < move[depth1 - maxl] - 2))
                {
                    continue;
                }
                for (int power = 0; power < 3; power++)
                {
                    int m = axis + power;

                    if (isRec && m != move[depth1 - maxl] ||
                        ssym != 1 && (skipMoves & 1 << m) != 0)
                    {
                        continue;
                    }

                    int prun = nodeUD[maxl].doMovePrun(node, m, true);
                    if (prun > maxl)
                    {
                        break;
                    }
                    else if (prun == maxl)
                    {
                        continue;
                    }

                    move[depth1 - maxl] = m;
                    int ret = phase1(nodeUD[maxl], ssym & CubieCube.moveCubeSym[m], maxl - 1, axis);
                    if (ret == 0)
                    {
                        return(0);
                    }
                    else if (ret == 2)
                    {
                        break;
                    }
                }
            }
            return(1);
        }