Esempio n. 1
0
        /// <summary>
        /// Verifies a matrix product is equal to a given matrix
        /// </summary>
        public static bool IsEqual(string matrixProduct, ImmutableMatrix2x2 compareMatrix)
        {
            var matrix = MatrixProductIdentifiersToMatrix(matrixProduct);

            if (!matrix.Equals(compareMatrix))
            {
                return(false);
            }
            return(true);
        }
        public void Inverse_Throws_IfDeterminantZero()
        {
            var values = new BigRational[2, 2]
            {
                { 2, 8 },
                { 1, 4 }
            };
            var matrix = new ImmutableMatrix2x2(values);

            Assert.Throws <InvalidOperationException>(() => matrix.Inverse());
        }
        /// <summary>
        /// Converts a matrix in SL(2,Z) to a form using only generator matrices.
        /// Returns a list of matrices made up of only S and R that when mutliplied in order
        /// are equivelent to the original matrix.
        /// Based on the algorithm described here:
        /// https://kconrad.math.uconn.edu/blurbs/grouptheory/SL(2,Z).pdf
        /// </summary>
        public static string ConvertMatrixToCanonicalString(ImmutableMatrix2x2 matrix)
        {
            // The process is 3 steps. First convert the matrix to use the T and S matrices.
            // Then T, T^-1 and S^-1 need to be replaced to use S,R,X
            // Finally, simplify the expression to canonical form
            var matrixProduct = ConvertMatrixToUseTAndSGeneratorMatrices(matrix)
                                .ReplaceTAndInverseWithStandardGenerators()
                                .SimplifyToCanonicalForm();

            return(String.Join("", matrixProduct.Select(m => m.ToString())));
        }
        public void Determinant_FindsDeterminant()
        {
            var values = new BigRational[2, 2]
            {
                { 2, 5 },
                { 1, 4 }
            };
            var matrix = new ImmutableMatrix2x2(values);

            var determinant = matrix.Determinant();

            Assert.Equal(3, determinant);
        }
Esempio n. 5
0
        public void ConvertMatrixToUseTAndSGeneratorMatrices_ConvertsCorrectly()
        {
            var matrixValues = new BigRational[2, 2] {
                { 437, 202 }, { 543, 251 }
            };
            var matrix = new ImmutableMatrix2x2(matrixValues);
            var expectedIdentifierList = new[]
            {
                GeneratorMatrixIdentifier.X,
                GeneratorMatrixIdentifier.SInverse,
                // -1
                GeneratorMatrixIdentifier.TInverse,
                // S Switch
                GeneratorMatrixIdentifier.SInverse,
                // 4
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                // S Switch
                GeneratorMatrixIdentifier.SInverse,
                // -8
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                // S Switch
                GeneratorMatrixIdentifier.SInverse,
                // 6
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                GeneratorMatrixIdentifier.T,
                // S Switch
                GeneratorMatrixIdentifier.SInverse,
                // -2
                GeneratorMatrixIdentifier.TInverse,
                GeneratorMatrixIdentifier.TInverse,
                // S Switch
                GeneratorMatrixIdentifier.SInverse
            };
            var matrixIdentifierList = MathematicalHelper.ConvertMatrixToUseTAndSGeneratorMatrices(matrix);

            Assert.Equal(expectedIdentifierList, matrixIdentifierList);
        }
        public void Inverse_InvertsMatrix()
        {
            var values = new BigRational[2, 2]
            {
                { 2, 5 },
                { 1, 4 }
            };
            var matrix  = new ImmutableMatrix2x2(values);
            var inverse = matrix.Inverse();

            Assert.Equal(new BigRational(4, 3), inverse.UnderlyingValues[0, 0]);
            Assert.Equal(new BigRational(-5, 3), inverse.UnderlyingValues[0, 1]);
            Assert.Equal(new BigRational(-1, 3), inverse.UnderlyingValues[1, 0]);
            Assert.Equal(new BigRational(2, 3), inverse.UnderlyingValues[1, 1]);

            Assert.Equal(Constants.Matrices.I, matrix * inverse);
        }
        public void Constructor_Initialises_IfValidValues(int value1, int value2, int value3, int value4)
        {
            var values = new BigRational[2, 2]
            {
                { value1, value2 },
                { value3, value4 }
            };

            // No exception thrown is a pass.
            var matrix = new ImmutableMatrix2x2(values);

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    Assert.Equal(values[i, j], matrix.UnderlyingValues[i, j]);
                }
            }
        }
        public void Multiply_MultipliesAMatrixAndVector()
        {
            var matrixValues = new BigRational[2, 2]
            {
                { 3, 4 },
                { 5, 6 }
            };
            var vectorValues = new BigRational[2]
            {
                1,
                5
            };

            var matrix = new ImmutableMatrix2x2(matrixValues);
            var vector = new ImmutableVector2D(vectorValues);

            var resultingVector = matrix * vector;

            Assert.Equal(23, resultingVector.UnderlyingVector[0]);
            Assert.Equal(35, resultingVector.UnderlyingVector[1]);
        }
Esempio n. 9
0
        public void ConvertMatrixToUseTAndSGeneratorMatrices_ConvertsCorrectly_WithTFinish(int bValue, int cornerSign, GeneratorMatrixIdentifier expectedIdentifier, bool expectedX)
        {
            var matrixValues = new BigRational[2, 2] {
                { cornerSign, bValue }, { 0, cornerSign }
            };
            var matrix = new ImmutableMatrix2x2(matrixValues);
            var count  = Math.Abs(bValue);
            var expectedIdentifierList = new List <GeneratorMatrixIdentifier>();

            if (expectedX)
            {
                expectedIdentifierList.Add(GeneratorMatrixIdentifier.X);
            }

            for (int i = 0; i < count; i++)
            {
                expectedIdentifierList.Add(expectedIdentifier);
            }
            var matrixIdentifierList = MathematicalHelper.ConvertMatrixToUseTAndSGeneratorMatrices(matrix);

            Assert.Equal(expectedIdentifierList, matrixIdentifierList);
        }
        internal static LinkedList <GeneratorMatrixIdentifier> ConvertMatrixToUseTAndSGeneratorMatrices(ImmutableMatrix2x2 toConvertMatrix)
        {
            var matrix = Matrix2x2.Copy(toConvertMatrix);
            LinkedList <GeneratorMatrixIdentifier> matrixProduct = new LinkedList <GeneratorMatrixIdentifier>();
            // Setup aliases for a and c
            Func <BigInteger> a = () => matrix.UnderlyingValues[0, 0].Numerator;
            Func <BigInteger> c = () => matrix.UnderlyingValues[1, 0].Numerator;
            Action            PerformSSwitchIfNeeded = () =>
            {
                if (BigInteger.Abs(a()) < BigInteger.Abs(c()))
                {
                    matrix.MultiplyLeft(Constants.Matrices.S);
                    matrixProduct.AddLast(GeneratorMatrixIdentifier.SInverse);
                }
            };

            PerformSSwitchIfNeeded();

            // Continue until the lower left entry is 0
            while (c() != 0)
            {
                var quotient = a() / c();

                var targetMatrix = TToPower(-quotient);
                matrix.MultiplyLeft(targetMatrix);

                var targetMatrixIdentifier = GeneratorMatrixIdentifier.TInverse;
                // Choose either T or T^-1 depending on the matrix used
                if (quotient > 0)
                {
                    targetMatrixIdentifier = GeneratorMatrixIdentifier.T;
                }

                for (int i = 0; i < BigInteger.Abs(quotient); i++)
                {
                    matrixProduct.AddLast(targetMatrixIdentifier);
                }

                PerformSSwitchIfNeeded();
            }
            // The matrix should now be in the form [[+-1, m], [0, +-1]]. This is ensured by the SL(2,Z) Group Property
            // Therefore it is either T^m or -T^-m = X*T^-m.
            var sign = a();

            if (sign == -1)
            {
                // We need to add a minus to the front (I.e. X)
                matrixProduct.AddFirst(GeneratorMatrixIdentifier.X);
            }

            var power       = matrix.UnderlyingValues[0, 1].Numerator * sign;
            var TOrTInverse = GeneratorMatrixIdentifier.T;

            // If the resulting matrix has a negative power of T, use the inverse matrix instead.
            if (power < 0)
            {
                TOrTInverse = GeneratorMatrixIdentifier.TInverse;
            }
            for (int i = 0; i < BigInteger.Abs(power); i++)
            {
                matrixProduct.AddLast(TOrTInverse);
            }
            return(matrixProduct);
        }
Esempio n. 11
0
            static Matrices()
            {
                var tMatrix = new BigRational[2, 2];

                tMatrix[0, 0] = 1;
                tMatrix[0, 1] = 1;
                tMatrix[1, 0] = 0;
                tMatrix[1, 1] = 1;
                T             = new ImmutableMatrix2x2(tMatrix);

                var sMatrix = new BigRational[2, 2];

                sMatrix[0, 0] = 0;
                sMatrix[0, 1] = -1;
                sMatrix[1, 0] = 1;
                sMatrix[1, 1] = 0;
                S             = new ImmutableMatrix2x2(sMatrix);

                var rMatrix = new BigRational[2, 2];

                rMatrix[0, 0] = 0;
                rMatrix[0, 1] = -1;
                rMatrix[1, 0] = 1;
                rMatrix[1, 1] = 1;
                R             = new ImmutableMatrix2x2(rMatrix);

                var xMatrix = new BigRational[2, 2];

                xMatrix[0, 0] = -1;
                xMatrix[0, 1] = 0;
                xMatrix[1, 0] = 0;
                xMatrix[1, 1] = -1;
                X             = new ImmutableMatrix2x2(xMatrix);

                var iMatrix = new BigRational[2, 2];

                iMatrix[0, 0] = 1;
                iMatrix[0, 1] = 0;
                iMatrix[1, 0] = 0;
                iMatrix[1, 1] = 1;
                I             = new ImmutableMatrix2x2(iMatrix);

                MatrixIdentifierDictionary = new Dictionary <GeneratorMatrixIdentifier, ImmutableMatrix2x2>
                {
                    [GeneratorMatrixIdentifier.T]        = Constants.Matrices.T,
                    [GeneratorMatrixIdentifier.S]        = Constants.Matrices.S,
                    [GeneratorMatrixIdentifier.R]        = Constants.Matrices.R,
                    [GeneratorMatrixIdentifier.X]        = Constants.Matrices.X,
                    [GeneratorMatrixIdentifier.SInverse] = Constants.Matrices.S.Inverse(), // Or -S
                    [GeneratorMatrixIdentifier.TInverse] = Constants.Matrices.T.Inverse()
                };

                GeneratorMatrixIdentifierLookup = new Dictionary <GeneratorMatrixIdentifier, GeneratorMatrixIdentifier[]>
                {
                    [GeneratorMatrixIdentifier.T] = new GeneratorMatrixIdentifier[]
                    {
                        GeneratorMatrixIdentifier.X,
                        GeneratorMatrixIdentifier.S,
                        GeneratorMatrixIdentifier.R
                    },
                    [GeneratorMatrixIdentifier.TInverse] = new GeneratorMatrixIdentifier[]
                    {
                        GeneratorMatrixIdentifier.X,
                        GeneratorMatrixIdentifier.R,
                        GeneratorMatrixIdentifier.R,
                        GeneratorMatrixIdentifier.S
                    },
                    [GeneratorMatrixIdentifier.SInverse] = new GeneratorMatrixIdentifier[]
                    {
                        GeneratorMatrixIdentifier.X,
                        GeneratorMatrixIdentifier.S
                    }
                };
            }