Exemplo n.º 1
0
        private void StartSearch()
        {
            #region rotate cube
            CubieCube rotatedCube = CubieCube.CreateSolved();

            for (int i = 0; i < _rotation; i++)
            {
                rotatedCube.Rotate(Rotation.y3);
                rotatedCube.Rotate(Rotation.x3);
            }

            rotatedCube.Multiply(_notRotatedCube);

            for (int i = 0; i < _rotation; i++)
            {
                rotatedCube.Rotate(Rotation.x1);
                rotatedCube.Rotate(Rotation.y1);
            }

            if (_inversed)
            {
                rotatedCube.Inverse();
            }
            #endregion rotate cube

            //calculate coordinates
            int co      = Coordinates.GetCornerOrientation(rotatedCube);
            int cp      = Coordinates.GetCornerPermutation(rotatedCube);
            int eo      = Coordinates.GetEdgeOrientation(rotatedCube);
            int equator = Coordinates.GetEquatorPermutation(rotatedCube);
            int uEdges  = Coordinates.GetUEdgePermutation(rotatedCube);
            int dEdges  = Coordinates.GetDEdgePermutation(rotatedCube);

            //store coordinates used in phase 2
            _cp     = cp;
            _uEdges = uEdges;
            _dEdges = dEdges;

            int pruningIndex    = PruningTables.GetPhase1PruningIndex(co, eo, equator / Coordinates.NumEquatorOrders);
            int minPhase1Length = TableController.Phase1PruningTable[pruningIndex];
            int maxPhase1Length = (_requiredLength > 0 && _requiredLength < GodsNumber) ? _requiredLength : GodsNumber;

            _currentPhase1Solution = new int[maxPhase1Length];
            _currentPhase2Solution = new int[MaxPhase2Length];

            for (int phase1Length = minPhase1Length; phase1Length < maxPhase1Length; phase1Length++)
            {
                SearchPhase1(eo, co, equator, depth: 0, remainingMoves: phase1Length, minPhase1Length);
            }
        }
Exemplo n.º 2
0
 //TODO handle exceptions
 /// <summary>
 /// Initialize the corner permutation and equator permutation pruning
 /// table for phase 2.
 /// </summary>
 public static void InitializePhase2CornerUdPruningTable()
 {
     if (Phase2CornerUdPruningTable is null)
     {
         string file = Directory + @"\phase2CornerUd.pruningtable";
         if (File.Exists(file))
         {
             Console.WriteLine("Loading phase 2 corner permutation and U- and D-edge permutation pruning table");
             Phase2CornerUdPruningTable = File.ReadAllBytes(file);
         }
         else
         {
             Console.WriteLine("Initializing phase 2 corner permutation and U- and D-edge permutation pruning table");
             Phase2CornerUdPruningTable = PruningTables.CreatePhase2CornerUdTable();
             File.WriteAllBytes(file, Phase2CornerUdPruningTable);
         }
     }
 }
Exemplo n.º 3
0
 //TODO add exception handling
 /// <summary>
 /// Initialize the pruning table for phase 1.
 /// </summary>
 public static void InitializePhase1PruningTable()
 {
     if (Phase1PruningTable is null)
     {
         string file = Directory + @"\phase1.pruningtable";
         if (File.Exists(file))
         {
             Console.WriteLine("Loading phase 1 pruning table");
             Phase1PruningTable = File.ReadAllBytes(file);
         }
         else
         {
             Console.WriteLine("Initializing phase 1 pruning table");
             Phase1PruningTable = PruningTables.CreatePhase1Table();
             File.WriteAllBytes(file, Phase1PruningTable);
         }
     }
 }
Exemplo n.º 4
0
        private void SearchPhase2(int cp, int equatorPermutation, int udEdgeOrder, int depth, int remainingMoves, int phase1Length)
        {
            if (IsTerminated.Value)
            {
                return;
            }

            if (remainingMoves == 0 && equatorPermutation == 0) //check if solved
            {
                Alg solution = Alg.FromEnumerable(_currentPhase1Solution.Take(phase1Length).Concat(_currentPhase2Solution.Take(depth)).Cast <Move>());

                for (int i = 0; i < _rotation; i++)
                {
                    solution = solution.Rotate(Rotation.y3).Rotate(Rotation.x3);
                }

                if (_inversed)
                {
                    solution = solution.Inverse();
                }

                lock (_lockObject)
                {
                    if (solution.Length < _shortestSolutionLength.Value)
                    {
                        _shortestSolutionIndex.Value  = _solutions.Count;
                        _shortestSolutionLength.Value = solution.Length;
                    }

                    _solutions.Add(solution);
                }

                if (solution.Length <= _returnLength)
                {
                    IsTerminated.Value = true;
                }

                return;
            }

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

                int newCp = TableController.CornerPermutationMoveTable[cp, move];
                int newEquatorPermutation = TableController.EquatorPermutationMoveTable[equatorPermutation, move];
                int newUdEdgePermutation  = TableController.UdEdgeOrderMoveTable[udEdgeOrder, MoveTables.Phase1IndexToPhase2Index[move]];

                //prune
                int cornerUdPruningIndex      = PruningTables.GetPhase2CornerUdPruningIndex(newUdEdgePermutation, newCp);
                int cornerUdPruningValue      = TableController.Phase2CornerUdPruningTable[cornerUdPruningIndex];
                int cornerEquatorPruningIndex = Coordinates.NumEquatorOrders * newCp + newEquatorPermutation;
                int cornerEquatorPruningValue = TableController.Phase2CornerEquatorPruningTable[cornerEquatorPruningIndex];
                if (Math.Max(cornerUdPruningValue, cornerEquatorPruningValue) > remainingMoves - 1)
                {
                    continue;
                }

                _currentPhase2Solution[depth] = move;
                SearchPhase2(newCp, newEquatorPermutation, newUdEdgePermutation, depth + 1, remainingMoves - 1, phase1Length);
            }
        }
Exemplo n.º 5
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);
            }
        }
        private void StartSearch()
        {
            #region rotate cube
            CubieCube rotatedCube = CubieCube.CreateSolved();

            for (int i = 0; i < _rotation; i++)
            {
                rotatedCube.Rotate(Rotation.y3);
                rotatedCube.Rotate(Rotation.x3);
            }

            rotatedCube.Multiply(_notRotatedCube);

            for (int i = 0; i < _rotation; i++)
            {
                rotatedCube.Rotate(Rotation.x1);
                rotatedCube.Rotate(Rotation.y1);
            }

            if (_inversed)
            {
                rotatedCube.Inverse();
            }
            #endregion rotate cube

            #region rotate weights
            _rotatedWeights = new float[NumMoves];

            for (int oldIndex = 0; oldIndex < NumMoves; oldIndex++)
            {
                int newIndex = oldIndex;
                for (int i = 0; i < _rotation; i++)
                {
                    newIndex = (int)((Move)newIndex).Rotate(Rotation.x1).Rotate(Rotation.y1);
                }
                _rotatedWeights[newIndex] = _nonRotatedWeights[oldIndex];
            }

            if (_inversed)
            {
                for (int face = 0; face < NumFaces; face++)
                {
                    //face * 3 = 90° cw, face * 3 + 2 = 90° ccw
                    float temp = _rotatedWeights[face * 3];
                    _rotatedWeights[face * 3]     = _rotatedWeights[face * 3 + 2];
                    _rotatedWeights[face * 3 + 2] = temp;
                }
            }
            #endregion rotate weights

            _phase1MoveOrder = MoveWeightsUtils.OrderedMoves((Move[])Enum.GetValues(typeof(Move)), _rotatedWeights);
            _phase2MoveOrder = MoveWeightsUtils.OrderedMoves(TwoPhaseConstants.Phase2Moves, _rotatedWeights);

            //calculate coordinates
            int co      = Coordinates.GetCornerOrientation(rotatedCube);
            int cp      = Coordinates.GetCornerPermutation(rotatedCube);
            int eo      = Coordinates.GetEdgeOrientation(rotatedCube);
            int equator = Coordinates.GetEquatorPermutation(rotatedCube);
            int uEdges  = Coordinates.GetUEdgePermutation(rotatedCube);
            int dEdges  = Coordinates.GetDEdgePermutation(rotatedCube);

            //store coordinates used in phase 2
            _cp     = cp;
            _uEdges = uEdges;
            _dEdges = dEdges;

            int pruningIndex    = PruningTables.GetPhase1PruningIndex(co, eo, equator / Coordinates.NumEquatorOrders);
            int minPhase1Length = TableController.Phase1PruningTable[pruningIndex];

            _currentPhase1Solution = new int[MaxPhase1Length];
            _currentPhase2Solution = new int[MaxPhase2Length];

            for (int phase1Length = minPhase1Length; phase1Length < MaxPhase1Length; phase1Length++)
            {
                SearchPhase1(eo, co, equator, depth: 0, remainingMoves: phase1Length, minPhase1Length);
            }
        }