Esempio n. 1
0
        public void CombineUAndDEdgeCoordsTest()
        {
            Random random      = new Random(7777777);
            int    length      = 50;
            int    repetitions = 50;

            double[] phase2probabilities =
            {
                0d, 1d, 0d, 1d, 1d, 1d, 0d, 1d, 0d,
                0d, 1d, 0d, 1d, 1d, 1d, 0d, 1d, 0d
            };

            for (int repetition = 0; repetition < repetitions; repetition++)
            {
                Alg       alg  = Alg.FromRandomMoves(length, random, phase2probabilities);
                CubieCube cube = CubieCube.FromAlg(alg);

                int uEdgeCoord = Coordinates.GetUEdgePermutation(cube);
                int dEdgeCoord = Coordinates.GetDEdgePermutation(cube);
                int result     = Coordinates.CombineUEdgePermutationAndDEdgeOrder(uEdgeCoord, dEdgeCoord % Coordinates.NumDEdgeOrders);
                int expected   = Coordinates.GetUdEdgeOrder(cube);

                Assert.AreEqual(expected, result);
            }
        }
Esempio n. 2
0
        private void SearchPhase1(int eo, int co, int equator, int depth, int remainingMoves, int previousPruningValue)
        {
            if (IsTerminated.Value)
            {
                return;
            }

            if (remainingMoves == 0) //check if solved
            {
                lock (_lockObject)   //manage timeout
                    if (_timePassed.Elapsed > _timeout && (_requiredLength < 0 || (_solutions.Count > 0 && _shortestSolutionLength.Value <= _requiredLength)))
                    {
                        IsTerminated.Value = true;
                    }

                int cp                 = _cp;
                int uEdges             = _uEdges;
                int dEdges             = _dEdges;
                int equatorPermutation = equator;

                //TEST improvement
                for (int moveIndex = 0; moveIndex < depth; moveIndex++)
                {
                    int move = _currentPhase1Solution[moveIndex];

                    cp = TableController.CornerPermutationMoveTable[cp, move];
                }

                int cornerEquatorPruningIndex = Coordinates.NumEquatorOrders * cp + equator;
                int cornerEquatorPruningValue = TableController.Phase2CornerEquatorPruningTable[cornerEquatorPruningIndex];
                if (cornerEquatorPruningValue > MaxPhase2Length)
                {
                    return;
                }

                for (int moveIndex = 0; moveIndex < depth; moveIndex++)
                {
                    int move = _currentPhase1Solution[moveIndex];

                    uEdges = TableController.UEdgePermutationMoveTable[uEdges, move];
                    dEdges = TableController.DEdgePermutationMoveTable[dEdges, move];
                }

                int udEdgeOrder = Coordinates.CombineUEdgePermutationAndDEdgeOrder(uEdges, dEdges % Coordinates.NumDEdgeOrders);

                //prune
                int cornerUdPruningIndex = PruningTables.GetPhase2CornerUdPruningIndex(udEdgeOrder, cp);
                int minMoves             = TableController.Phase2CornerUdPruningTable[cornerUdPruningIndex];
                int maxMoves             = Math.Min(_shortestSolutionLength.Value - depth - 1, MaxPhase2Length);

                for (int length = minMoves; length <= maxMoves; length++)
                {
                    SearchPhase2(cp, equatorPermutation, udEdgeOrder, depth: 0, remainingMoves: length, phase1Length: depth);
                }

                return;
            }

            //increase depth
            for (int move = 0; move < NumMoves; move++)
            {
                //If the cube is already in the subgroup H and there are less
                //than 5 moves left it is only possible to stay in the subgroup
                //if exclusivly phase 2 moves are used, which means that this
                //solution can also be generated in phase 2.
                if (previousPruningValue == 0 && remainingMoves < 5 && !TwoPhaseConstants.Phase2Moves.Contains((Move)move))
                {
                    continue;
                }

                //prevent two consecutive moves on the same face or two
                //consecutive moves on the same axis in the wrong order
                if (depth > 0)
                {
                    int relation = move / 3 - _currentPhase1Solution[depth - 1] / 3;
                    if (relation == SameFace || relation == SameAxisInWrongOrder)
                    {
                        continue;
                    }
                }

                int newEo      = TableController.EdgeOrientationMoveTable[eo, move];
                int newCo      = TableController.CornerOrientationMoveTable[co, move];
                int newEquator = TableController.EquatorPermutationMoveTable[equator, move];

                //prune
                int pruningCoord = PruningTables.GetPhase1PruningIndex(newCo, newEo, newEquator / Coordinates.NumEquatorOrders);
                int pruningValue = TableController.Phase1PruningTable[pruningCoord];
                if (pruningValue > remainingMoves - 1)
                {
                    continue;
                }

                _currentPhase1Solution[depth] = move;
                SearchPhase1(newEo, newCo, newEquator, depth + 1, remainingMoves - 1, pruningValue);
            }
        }