예제 #1
0
        public void EoEquatorCoordinateTest()
        {
            bool found;

            for (int expanded = 0; expanded < NumEquatorDistributions * NumEdgeOrientations; expanded++)
            {
                found = false;

                int reduced     = SymmetryReduction.ReduceEoEquatorCoordinate[expanded];
                int expandedSym = SymmetryReduction.ExpandEoEquatorCoordinate[reduced];

                CubieCube expandedCube = CubieCube.CreateSolved();
                SetEdgeOrientation(expandedCube, expanded % 2048);
                SetEquatorDistribution(expandedCube, expanded / 2048);

                for (int sym = 0; sym < NumSymmetriesDh4; sym++)
                {
                    CubieCube symCube = Symmetries.SymmetryCubes[sym].Clone();
                    symCube.MultiplyEdges(expandedCube);
                    symCube.MultiplyEdges(Symmetries.SymmetryCubes[Symmetries.InverseIndex[sym]]);

                    if (expandedSym % 2048 == GetEdgeOrientation(symCube) &&
                        expandedSym / 2048 == GetEquatorDistribution(symCube))
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    Assert.Fail();
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Create a move table for U- and D-edge order. Only valid for cubes
        /// in the subgroup G1.
        /// </summary>
        /// <returns>
        /// A move table for U- and D-edge order.
        /// </returns>
        public static ushort[,] CreateUdEdgeOrderMoveTable()
        {
            ushort[,] udEdgeOrderMoveTable = new ushort[Coordinates.NumUdEdgeOrders, TwoPhaseConstants.NumMovesPhase2];

            //invalidate table
            for (int udEdgeOrder = 0; udEdgeOrder < Coordinates.NumUdEdgeOrders; udEdgeOrder++)
            {
                for (int move = 0; move < TwoPhaseConstants.NumMovesPhase2; move++)
                {
                    udEdgeOrderMoveTable[udEdgeOrder, move] = ushort.MaxValue;
                }
            }

            //populate table
            for (int udEdgeOrder = 0; udEdgeOrder < Coordinates.NumCornerPermutations; udEdgeOrder++)
            {
                for (int face = 0; face < NumFaces; face++)
                {
                    CubieCube cube = CubieCube.CreateSolved();
                    Coordinates.SetUdEdgeOrder(cube, udEdgeOrder);
                    for (int move = 0; move < 3; move++)
                    {
                        cube.MultiplyEdges(CubieCube.MovesArray[face * 3]);
                        if (TwoPhaseConstants.Phase2Moves.Contains((Move)(face * 3 + move)))
                        {
                            udEdgeOrderMoveTable[udEdgeOrder, Phase1IndexToPhase2Index[face * 3 + move]] = (ushort)Coordinates.GetUdEdgeOrder(cube);
                        }
                    }
                }
            }

            return(udEdgeOrderMoveTable);
        }
예제 #3
0
        /// <summary>
        /// Create a move table for edge orientation.
        /// </summary>
        /// <returns>
        /// A move table for edge orientation.
        /// </returns>
        public static short[,] CreateEdgeOrientationMoveTable()
        {
            CubieCube cube = CubieCube.CreateSolved();

            short[,] edgeOrientationMoveTable = new short[Coordinates.NumEdgeOrientations, NumMoves];

            //invalidate table
            for (int edgeOrientation = 0; edgeOrientation < Coordinates.NumEdgeOrientations; edgeOrientation++)
            {
                for (int move = 0; move < NumMoves; move++)
                {
                    edgeOrientationMoveTable[edgeOrientation, move] = -1;
                }
            }

            //populate table
            for (int edgeOrientation = 0; edgeOrientation < Coordinates.NumEdgeOrientations; edgeOrientation++)
            {
                for (int face = 0; face < NumFaces; face++)
                {
                    Coordinates.SetEdgeOrientation(cube, edgeOrientation);
                    for (int move = 0; move < 3; move++)
                    {
                        cube.MultiplyEdges(CubieCube.MovesArray[face * 3]);
                        edgeOrientationMoveTable[edgeOrientation, face * 3 + move] = (short)Coordinates.GetEdgeOrientation(cube);
                    }
                }
            }

            return(edgeOrientationMoveTable);
        }
예제 #4
0
        //TODO remove redundant indexes
        /// <summary>
        /// Create a move table for equator order. Only valid for cubes in the
        /// subgroup G1.
        /// </summary>
        /// <returns>
        /// A move table for equator order.
        /// </returns>
        public static sbyte[,] CreateEquatorOrderMoveTable()
        {
            sbyte[,] equatorOrderMoveTable = new sbyte[Coordinates.NumEquatorOrders, NumMoves];

            //invalidate table
            for (int equatorOrder = 0; equatorOrder < Coordinates.NumEquatorOrders; equatorOrder++)
            {
                for (int move = 0; move < NumMoves; move++)
                {
                    equatorOrderMoveTable[equatorOrder, move] = -1;
                }
            }

            //populate table
            for (int equatorOrder = 0; equatorOrder < Coordinates.NumEquatorOrders; equatorOrder++)
            {
                for (int face = 0; face < NumFaces; face++)
                {
                    CubieCube cube = CubieCube.CreateSolved();
                    Coordinates.SetEquatorOrder(cube, equatorOrder);
                    for (int move = 0; move < 3; move++)
                    {
                        cube.MultiplyEdges(CubieCube.MovesArray[face * 3]);
                        if (TwoPhaseConstants.Phase2Moves.Contains((Move)(face * 3 + move)))
                        {
                            equatorOrderMoveTable[equatorOrder, face * 3 + move] = (sbyte)Coordinates.GetEquatorOrder(cube);
                        }
                    }
                }
            }

            return(equatorOrderMoveTable);
        }
예제 #5
0
        static SymmetryReduction()
        {
            //avoid naming conflicts
            CubieCube cube;
            int       reducedEoEquator, reducedCornerPermutation;

            #region initialize ConjugateCoCoordinate
            ConjugateCornerOrientationCoordinate = new int[NumCornerOrientations, NumSymmetriesDh4];

            //invalidate
            for (int cornerOrientation = 0; cornerOrientation < NumCornerOrientations; cornerOrientation++)
            {
                for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                {
                    ConjugateCornerOrientationCoordinate[cornerOrientation, symmetryIndex] = -1;
                }
            }

            //populate
            cube = CubieCube.CreateSolved();
            for (int cornerOrientation = 0; cornerOrientation < NumCornerOrientations; cornerOrientation++)
            {
                cube.IsMirrored = false; //TEST if necessary
                SetCornerOrientation(cube, cornerOrientation);
                for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                {
                    //conjugate cube
                    CubieCube symmetryCube = SymmetryCubes[symmetryIndex].Clone();
                    symmetryCube.MultiplyCorners(cube);
                    symmetryCube.MultiplyCorners(SymmetryCubes[InverseIndex[symmetryIndex]]);

                    //store result
                    ConjugateCornerOrientationCoordinate[cornerOrientation, symmetryIndex] = GetCornerOrientation(symmetryCube);
                }
            }
            #endregion initialize ConjugateCoCoordinate

            //TODO simplify
            #region initialize ReduceEoEquatorCoordinate, ExpandEoEquatorCoordinate and EoEquatorReductionSymmetry
            //initialize and invalidate
            ReduceEoEquatorCoordinate = Enumerable.Repeat(-1, NumEquatorDistributions * NumEdgeOrientations)
                                        .ToArray();
            ExpandEoEquatorCoordinate = Enumerable.Repeat(-1, NumEoEquatorSymmetryClasses)
                                        .ToArray();
            EoEquatorReductionSymmetry = Enumerable.Repeat(-1, NumEquatorDistributions * NumEdgeOrientations)
                                         .ToArray();

            //populate
            cube             = CubieCube.CreateSolved();
            reducedEoEquator = 0;
            for (int equatorDistribution = 0; equatorDistribution < NumEquatorDistributions; equatorDistribution++)
            {
                SetEquatorDistribution(cube, equatorDistribution);
                for (int edgeOrientation = 0; edgeOrientation < NumEdgeOrientations; edgeOrientation++)
                {
                    int eoEquator = NumEdgeOrientations * equatorDistribution + edgeOrientation;
                    if (ReduceEoEquatorCoordinate[eoEquator] == -1)
                    {
                        SetEdgeOrientation(cube, edgeOrientation);

                        //store representative
                        ReduceEoEquatorCoordinate[eoEquator]        = reducedEoEquator;
                        EoEquatorReductionSymmetry[eoEquator]       = 0;
                        ExpandEoEquatorCoordinate[reducedEoEquator] = eoEquator;

                        //go through all symmetries of the current cube and set
                        //their reduced index to the same full index
                        for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                        {
                            //symmetry ^ -1 * cube * symmetry
                            CubieCube symCube = SymmetryCubes[InverseIndex[symmetryIndex]].Clone();
                            symCube.MultiplyEdges(cube);
                            symCube.MultiplyEdges(SymmetryCubes[symmetryIndex]);

                            //store
                            int newEdgeOrientation     = GetEdgeOrientation(symCube);
                            int newEquatorDistribution = GetEquatorDistribution(symCube);
                            int newEoEquator           = NumEdgeOrientations * newEquatorDistribution + newEdgeOrientation;
                            //TODO test if necessary
                            if (ReduceEoEquatorCoordinate[newEoEquator] == -1)
                            {
                                ReduceEoEquatorCoordinate[newEoEquator]  = reducedEoEquator;
                                EoEquatorReductionSymmetry[newEoEquator] = symmetryIndex;
                            }
                        }
                        reducedEoEquator++;
                    }
                }
            }
            #endregion initialize ReduceEoEquatorCoordinate, ExpandEoEquatorCoordinate and EoEquatorReductionSymmetry

            #region initialize EoEquatorSymmetries
            //initialize and invalidate
            EoEquatorSymmetries = Enumerable.Repeat(0, NumEoEquatorSymmetryClasses)
                                  .ToArray();

            //populate
            cube = CubieCube.CreateSolved();
            for (reducedEoEquator = 0; reducedEoEquator < NumEoEquatorSymmetryClasses; reducedEoEquator++)
            {
                //set cube to the representative of the reduced index
                int eoEquator = ExpandEoEquatorCoordinate[reducedEoEquator];
                SetEoEquatorCoord(cube, eoEquator);

                //find all symmetries of the cube
                for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                {
                    //symmetry * cube * symmetry ^ -1
                    CubieCube symmetryCube = SymmetryCubes[symmetryIndex].Clone();
                    symmetryCube.MultiplyEdges(cube);
                    symmetryCube.MultiplyEdges(SymmetryCubes[InverseIndex[symmetryIndex]]);
                    //set flag if symmetrical
                    int newEoEquator = GetEoEquatorCoord(symmetryCube);
                    if (eoEquator == newEoEquator)
                    {
                        EoEquatorSymmetries[reducedEoEquator] |= 1 << symmetryIndex;
                    }
                }
            }
            #endregion initialize EoEoquatorSymmetries

            #region initialize ConjugateUdEdgeOrderCoordinate
            ConjugateUdEdgeOrderCoordinate = new int[NumUdEdgeOrders, NumSymmetriesDh4];

            //invalidate
            for (int udEdgeOrders = 0; udEdgeOrders < NumUdEdgeOrders; udEdgeOrders++)
            {
                for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                {
                    ConjugateUdEdgeOrderCoordinate[udEdgeOrders, symmetryIndex] = -1;
                }
            }

            //populate
            cube = CubieCube.CreateSolved();
            for (int udEdgePermutation = 0; udEdgePermutation < NumUdEdgeOrders; udEdgePermutation++)
            {
                SetUdEdgeOrder(cube, udEdgePermutation);
                for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                {
                    //conjugate cube
                    CubieCube symmetryCube = SymmetryCubes[symmetryIndex].Clone();
                    symmetryCube.MultiplyEdges(cube);
                    symmetryCube.MultiplyEdges(SymmetryCubes[InverseIndex[symmetryIndex]]);

                    //store result
                    ConjugateUdEdgeOrderCoordinate[udEdgePermutation, symmetryIndex] = GetUdEdgeOrder(symmetryCube);
                }
            }
            #endregion initialize ConjugateUdEdgeOrderCoordinate

            #region initialize ReduceCpCoordinate, ExpandCpCoordinate and CpReductionSymmetry
            //initialize and invalidate
            ReduceCornerPermutationCoordinate = Enumerable.Repeat(-1, NumCornerPermutations)
                                                .ToArray();
            ExpandCornerPermutationCoordinate = Enumerable.Repeat(-1, NumCornerPermutationSymmetryClasses)
                                                .ToArray();
            CornerPermutationReductionSymmetry = Enumerable.Repeat(-1, NumCornerPermutations)
                                                 .ToArray();

            //populate
            cube = CubieCube.CreateSolved();
            reducedCornerPermutation = 0;
            for (int cornerPermutation = 0; cornerPermutation < NumCornerPermutations; cornerPermutation++)
            {
                if (ReduceCornerPermutationCoordinate[cornerPermutation] == -1)
                {
                    cube.IsMirrored = false; //TEST if necessary
                    SetCornerPermutation(cube, cornerPermutation);

                    //store representative
                    ReduceCornerPermutationCoordinate[cornerPermutation]        = reducedCornerPermutation;
                    CornerPermutationReductionSymmetry[cornerPermutation]       = 0;
                    ExpandCornerPermutationCoordinate[reducedCornerPermutation] = cornerPermutation;

                    //go through all symmetries of the current cube and set
                    //their reduced index to the same full index
                    for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                    {
                        //symmetry ^ -1 * cube * symmetry
                        CubieCube symmetryCube = SymmetryCubes[InverseIndex[symmetryIndex]].Clone();
                        symmetryCube.MultiplyCorners(cube);
                        symmetryCube.MultiplyCorners(SymmetryCubes[symmetryIndex]);

                        //store
                        int newCornerPermutation = GetCornerPermutation(symmetryCube);
                        //TODO test if necessary
                        if (ReduceCornerPermutationCoordinate[newCornerPermutation] == -1)
                        {
                            ReduceCornerPermutationCoordinate[newCornerPermutation]  = reducedCornerPermutation;
                            CornerPermutationReductionSymmetry[newCornerPermutation] = symmetryIndex;
                        }
                    }
                    reducedCornerPermutation++;
                }
            }
            #endregion initialize ReduceCpCoordinate, ExpandCpCoordinate and CpReductionSymmetry

            #region initialize CpSymmetries
            CornerPermutationSymmetries = Enumerable.Repeat(0, NumCornerPermutationSymmetryClasses)
                                          .ToArray();

            cube = CubieCube.CreateSolved();
            for (reducedCornerPermutation = 0; reducedCornerPermutation < NumCornerPermutationSymmetryClasses; reducedCornerPermutation++)
            {
                //set cube to the representative of the reduced index
                int cornerPermutation = ExpandCornerPermutationCoordinate[reducedCornerPermutation];
                SetCornerPermutation(cube, cornerPermutation);

                //find all symmetries of the cube
                for (int symmetryIndex = 0; symmetryIndex < NumSymmetriesDh4; symmetryIndex++)
                {
                    //symmetry * cube * symmetry ^ -1
                    CubieCube symmetryCube = SymmetryCubes[symmetryIndex].Clone();
                    symmetryCube.MultiplyCorners(cube);
                    symmetryCube.MultiplyCorners(SymmetryCubes[InverseIndex[symmetryIndex]]);
                    //set flag if symmetrical
                    int newCornerPermutation = GetCornerPermutation(symmetryCube);
                    if (cornerPermutation == newCornerPermutation)
                    {
                        CornerPermutationSymmetries[reducedCornerPermutation] |= 1 << symmetryIndex;
                    }
                }
            }
            #endregion initialize CpSymmetries
        }