Exemplo n.º 1
0
        /// <summary>
        /// Obtém uma matriz identidade.
        /// </summary>
        /// <typeparam name="RingType">O tipo do anel responsável pelas operações sobre os coeficientes.</typeparam>
        /// <param name="order">A dimensão da matriz.</param>
        /// <param name="ring">O anel responsável pelas operações sobre os coeficientes.</param>
        /// <returns>A matriz identidade.</returns>
        /// <exception cref="ArgumentNullException">Se o anel proporcionado for nulo.</exception>
        /// <exception cref="ArgumentOutOfRangeException">See a dimensão da matriz for inferior a um.</exception>
        public static ArrayMathMatrix <ObjectType> GetIdentity <RingType>(int order, RingType ring)
            where RingType : IRing <ObjectType>
        {
            if (ring == null)
            {
                throw new ArgumentNullException("ring");
            }
            else if (order <= 0)
            {
                throw new ArgumentOutOfRangeException("Order of identity matrix must be greater than one.");
            }
            else
            {
                var result = new ArrayMathMatrix <ObjectType>(order, order);
                for (int i = 0; i < order; ++i)
                {
                    for (int j = 0; j < order; ++j)
                    {
                        if (i == j)
                        {
                            result.elements[i][j] = ring.MultiplicativeUnity;
                        }
                        else
                        {
                            result.elements[i][j] = ring.AdditiveUnity;
                        }
                    }
                }

                return(result);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Obtém o produto da matriz corrente com outra matriz.
        /// </summary>
        /// <param name="right">A outra matriz.</param>
        /// <param name="ring">O anel.</param>
        /// <returns>O resultado do produto.</returns>
        public ArrayMathMatrix <ObjectType> ParallelMultiply(
            ArrayMathMatrix <ObjectType> right,
            IRing <ObjectType> ring)
        {
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }
            else if (ring == null)
            {
                throw new ArgumentNullException("ring");
            }
            else
            {
                var columnNumber = this.numberOfColumns;
                var lineNumber   = right.numberOfColumns;
                if (columnNumber != lineNumber)
                {
                    throw new MathematicsException("To multiply two matrices, the number of columns of the first must match the number of lines of second.");
                }
                else
                {
                    var firstDimension  = this.numberOfLines;
                    var secondDimension = right.numberOfColumns;
                    var result          = new ArrayMathMatrix <ObjectType>(
                        firstDimension,
                        secondDimension);
                    Parallel.For(0, firstDimension, i =>
                    {
                        for (int j = 0; j < secondDimension; ++j)
                        {
                            var addResult = ring.AdditiveUnity;
                            for (int k = 0; k < columnNumber; ++k)
                            {
                                var multResult = ring.Multiply(
                                    this.elements[i][k],
                                    right.elements[k][j]);
                                addResult = ring.Add(addResult, multResult);
                            }

                            result.elements[i][j] = addResult;
                        }
                    });

                    return(result);
                }
            }
        }
        /// <summary>
        /// Obtém o valor final do determinante.
        /// </summary>
        /// <param name="triangularMatrix">A matriz triangular resultante.</param>
        /// <param name="divisors">A lista de factores.</param>
        /// <param name="sign">O sinal.</param>
        /// <returns>O resultado do cálculo.</returns>
        private ObjectType GetDeterminantValue(ArrayMathMatrix <ObjectType> triangularMatrix, List <ObjectType> divisors, bool sign)
        {
            var dimensions = triangularMatrix.GetLength(0);
            var result     = triangularMatrix[0, 0];

            for (int i = 1; i < dimensions; ++i)
            {
                result = this.ring.Multiply(result, triangularMatrix[i, i]);
            }

            for (int i = 0; i < divisors.Count; ++i)
            {
                result = this.domain.Quo(result, divisors[i]);
            }

            if (!sign)
            {
                result = this.ring.AdditiveInverse(result);
            }

            return(result);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Obtém a soma da matriz corrente com outra matriz.
        /// </summary>
        /// <param name="right">A outra matriz.</param>
        /// <param name="semigroup">O semigrupo.</param>
        /// <returns>O resultado da soma.</returns>
        public ArrayMathMatrix <ObjectType> Add(ArrayMathMatrix <ObjectType> right, ISemigroup <ObjectType> semigroup)
        {
            if (right == null)
            {
                throw new ArgumentNullException("right");
            }
            else if (semigroup == null)
            {
                throw new ArgumentNullException("semigroup");
            }
            else
            {
                if (this.numberOfLines == right.numberOfLines &&
                    this.numberOfColumns == right.numberOfColumns)
                {
                    var result = new ArrayMathMatrix <ObjectType>(
                        this.numberOfLines,
                        this.numberOfColumns);
                    for (int i = 0; i < this.numberOfLines; ++i)
                    {
                        for (int j = 0; j < this.numberOfColumns; ++j)
                        {
                            result.elements[i][j] = semigroup.Add(
                                this.elements[i][j],
                                right.elements[i][j]);
                        }
                    }

                    return(result);
                }
                else
                {
                    throw new ArgumentException("Matrices don't have the same dimensions.");
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Determina o polinómio característico de uma matriz.
        /// </summary>
        /// <param name="data">A matriz.</param>
        /// <returns>O polinómio característico.</returns>
        public UnivariatePolynomialNormalForm <ElementType> Run(ISquareMathMatrix <ElementType> data)
        {
            if (data == null)
            {
                return(new UnivariatePolynomialNormalForm <ElementType>(this.variableName));
            }
            else
            {
                var lines = data.GetLength(0);
                if (lines == 0)
                {
                    return(new UnivariatePolynomialNormalForm <ElementType>(this.variableName));
                }
                else if (lines == 1)
                {
                    var entry  = data[0, 0];
                    var result = new UnivariatePolynomialNormalForm <ElementType>(
                        this.ring.MultiplicativeUnity,
                        1,
                        this.variableName,
                        this.ring);
                    result = result.Add(this.ring.AdditiveInverse(entry), 0, this.ring);
                    return(result);
                }
                else if (lines == 2)
                {
                    var variablePol = new UnivariatePolynomialNormalForm <ElementType>(
                        this.ring.MultiplicativeUnity,
                        1,
                        this.variableName,
                        this.ring);
                    var firstDiagonalElement = variablePol.Add(
                        this.ring.AdditiveInverse(data[0, 0]),
                        this.ring);
                    var secondDiagonalElement = variablePol.Add(
                        this.ring.AdditiveInverse(data[1, 1]),
                        this.ring);
                    var result = firstDiagonalElement.Multiply(secondDiagonalElement, this.ring);
                    result = result.Add(
                        this.ring.AdditiveInverse(this.ring.Multiply(data[0, 1], data[1, 0])),
                        this.ring);
                    return(result);
                }
                else
                {
                    var matrixFactory       = new ArrayMathMatrixFactory <ElementType>();
                    var matrixMultiplicator = new MatrixMultiplicationOperation <ElementType>(
                        matrixFactory, this.ring, this.ring);
                    var subMatrixSequence   = new IntegerSequence();
                    var singleValueSequence = new IntegerSequence();

                    IMatrix <ElementType> multiplicationMatrix = new ArrayMathMatrix <ElementType>(
                        lines + 1,
                        lines,
                        this.ring.AdditiveUnity);
                    subMatrixSequence.Add(1, lines - 1);
                    singleValueSequence.Add(0);
                    this.FillMultiplicationMatrix(
                        data,
                        data[0, 0],
                        subMatrixSequence,
                        singleValueSequence,
                        matrixMultiplicator,
                        multiplicationMatrix);

                    var currentDimension = 1;
                    while (currentDimension < lines - 1)
                    {
                        subMatrixSequence.Clear();
                        singleValueSequence.Clear();
                        subMatrixSequence.Add(currentDimension + 1, lines - 1);
                        singleValueSequence.Add(currentDimension);
                        var otherLines = lines - currentDimension;
                        var otherMultiplicationMatrix = new ArrayMathMatrix <ElementType>(
                            otherLines + 1,
                            otherLines,
                            this.ring.AdditiveUnity);

                        this.FillMultiplicationMatrix(
                            data,
                            data[currentDimension, currentDimension],
                            subMatrixSequence,
                            singleValueSequence,
                            matrixMultiplicator,
                            otherMultiplicationMatrix);

                        multiplicationMatrix = matrixMultiplicator.Multiply(
                            multiplicationMatrix,
                            otherMultiplicationMatrix);
                        ++currentDimension;
                    }

                    var lastOtherMultiplicationMatrix = new ArrayMathMatrix <ElementType>(
                        2,
                        1,
                        this.ring.AdditiveUnity);
                    lastOtherMultiplicationMatrix[0, 0] = this.ring.MultiplicativeUnity;
                    lastOtherMultiplicationMatrix[1, 0] = this.ring.AdditiveInverse(data[currentDimension, currentDimension]);
                    multiplicationMatrix = matrixMultiplicator.Multiply(
                        multiplicationMatrix,
                        lastOtherMultiplicationMatrix);

                    var result = new UnivariatePolynomialNormalForm <ElementType>(
                        multiplicationMatrix[0, 0],
                        lines,
                        this.variableName,
                        this.ring);
                    for (int i = 1; i <= lines; ++i)
                    {
                        result = result.Add(multiplicationMatrix[i, 0], lines - i, this.ring);
                    }

                    return(result);
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Processa o polinómio determinando os respectivos factores.
        /// </summary>
        /// <remarks>
        /// Os factores constantes são ignorados, os factores lineares são anexados ao resultado e os factores
        /// cujos graus são superiores são retornados para futuro processamento. Se o polinómio a ser processado
        /// for irredutível, é adicionado ao resultado.
        /// </remarks>
        /// <param name="polynom">O polinómio a ser processado.</param>
        /// <param name="result">O contentor dos factores sucessivamente processados.</param>
        /// <param name="integerModule">O objecto responsável pelas operações sobre inteiros.</param>
        /// <param name="polynomField">O objecto responsável pelas operações sobre os polinómios.</param>
        /// <param name="inverseAlgorithm">O algoritmo inverso.</param>
        /// <returns></returns>
        List <UnivariatePolynomialNormalForm <CoeffType> > Process(
            UnivariatePolynomialNormalForm <CoeffType> polynom,
            List <UnivariatePolynomialNormalForm <CoeffType> > result,
            IModularField <CoeffType> integerModule,
            UnivarPolynomEuclideanDomain <CoeffType> polynomField,
            LagrangeAlgorithm <UnivariatePolynomialNormalForm <CoeffType> > inverseAlgorithm)
        {
            var resultPol = new List <UnivariatePolynomialNormalForm <CoeffType> >();

            if (polynom.Degree < 2)
            {
                result.Add(polynom);
            }
            else
            {
                var module = new ModularBachetBezoutField <UnivariatePolynomialNormalForm <CoeffType> >(
                    polynom,
                    inverseAlgorithm);

                var degree      = polynom.Degree;
                var arrayMatrix = new ArrayMathMatrix <CoeffType>(degree, degree, integerModule.AdditiveUnity);
                arrayMatrix[0, 0] = integerModule.AdditiveUnity;
                var pol = new UnivariatePolynomialNormalForm <CoeffType>(
                    integerModule.MultiplicativeUnity,
                    1,
                    polynom.VariableName,
                    integerModule);

                var integerModuleValue = this.integerNumber.ConvertToInt(integerModule.Module);

                pol = MathFunctions.Power(pol, integerModuleValue, module);
                foreach (var term in pol)
                {
                    arrayMatrix[term.Key, 1] = term.Value;
                }

                var auxPol = pol;
                for (int i = 2; i < degree; ++i)
                {
                    auxPol = module.Multiply(auxPol, pol);
                    foreach (var term in auxPol)
                    {
                        arrayMatrix[term.Key, i] = term.Value;
                    }
                }

                for (int i = 1; i < degree; ++i)
                {
                    var value = arrayMatrix[i, i];
                    value = integerModule.Add(
                        value,
                        integerModule.AdditiveInverse(integerModule.MultiplicativeUnity));
                    arrayMatrix[i, i] = value;
                }

                var emtpyMatrix          = new ZeroMatrix <CoeffType>(degree, 1, integerModule);
                var linearSystemSolution = this.linearSystemSolver.Run(arrayMatrix, emtpyMatrix);

                var numberOfFactors = linearSystemSolution.VectorSpaceBasis.Count;
                if (numberOfFactors < 2)
                {
                    result.Add(polynom);
                }
                else
                {
                    var hPol = default(UnivariatePolynomialNormalForm <CoeffType>);
                    var linearSystemCount = linearSystemSolution.VectorSpaceBasis.Count;
                    for (int i = 0; i < linearSystemCount; ++i)
                    {
                        var currentBaseSolution = linearSystemSolution.VectorSpaceBasis[i];
                        var rowsLength          = currentBaseSolution.Length;
                        for (int j = 1; j < rowsLength; ++j)
                        {
                            if (!integerModule.IsAdditiveUnity(currentBaseSolution[j]))
                            {
                                hPol = this.GetPolynomial(currentBaseSolution, integerModule, polynom.VariableName);
                                j    = rowsLength;
                            }

                            if (hPol != null)
                            {
                                j = rowsLength;
                            }
                        }

                        if (hPol != null)
                        {
                            i = linearSystemCount;
                        }
                    }

                    for (int i = 0, k = 0; k < numberOfFactors && i < integerModuleValue; ++i)
                    {
                        var converted  = this.integerNumber.MapFrom(i);
                        var currentPol = MathFunctions.GreatCommonDivisor(
                            polynom,
                            hPol.Subtract(converted, integerModule),
                            polynomField);
                        var currentDegree = currentPol.Degree;
                        if (currentDegree == 1)
                        {
                            result.Add(currentPol);
                            ++k;
                        }
                        else if (currentDegree > 1)
                        {
                            resultPol.Add(currentPol);
                            ++k;
                        }
                    }
                }
            }

            return(resultPol);
        }
        /// <summary>
        /// Calcula o determinante.
        /// </summary>
        /// <param name="data">A matriz.</param>
        /// <returns>O valor do determinante.</returns>
        protected override ObjectType ComputeDeterminant(IMatrix <ObjectType> data)
        {
            var positiveResult     = true;
            var determinantFactors = new List <ObjectType>();
            var matrixDimension    = data.GetLength(0);

            if (matrixDimension == 0)
            {
                return(this.ring.AdditiveUnity);
            }
            else
            {
                // Copia a matriz uma vez que o algoritmo a vai alterar
                var temporaryArray = new ArrayMathMatrix <ObjectType>(matrixDimension, matrixDimension);
                for (int i = 0; i < matrixDimension; ++i)
                {
                    for (int j = 0; j < matrixDimension; ++j)
                    {
                        temporaryArray[i, j] = data[i, j];
                    }
                }

                for (int i = 0; i < matrixDimension - 1; ++i)
                {
                    var pivotValue = temporaryArray[i, i];
                    if (this.ring.IsAdditiveUnity(pivotValue))
                    {
                        var nextPivotCandidate = this.GetNextNonEmptyPivotLineNumber(i, temporaryArray);
                        if (nextPivotCandidate == -1)
                        {
                            return(this.ring.AdditiveUnity);
                        }
                        else
                        {
                            positiveResult = !positiveResult;
                            temporaryArray.SwapLines(i, nextPivotCandidate);
                            pivotValue = temporaryArray[i, i];
                        }
                    }

                    if (this.ring.IsMultiplicativeUnity(pivotValue))
                    {
                        for (int j = i + 1; j < matrixDimension; ++j)
                        {
                            var value = temporaryArray[j, i];
                            if (!this.ring.IsAdditiveUnity(value))
                            {
                                temporaryArray[j, i] = this.ring.AdditiveUnity;
                                for (int k = i + 1; k < matrixDimension; ++k)
                                {
                                    var temp = this.ring.Multiply(value, temporaryArray[i, k]);
                                    temporaryArray[j, k] = this.ring.Add(temporaryArray[j, k], this.ring.AdditiveInverse(temp));
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int j = i + 1; j < matrixDimension; ++j)
                        {
                            var value = temporaryArray[j, i];
                            if (!this.ring.IsAdditiveUnity(value))
                            {
                                var gcd = MathFunctions.GreatCommonDivisor(pivotValue, value, this.domain);
                                var lcm = this.ring.Multiply(pivotValue, value);
                                lcm = this.domain.Quo(lcm, gcd);
                                var pivotCoffactor = this.domain.Quo(pivotValue, gcd);
                                var valueCoffactor = this.domain.Quo(value, gcd);
                                determinantFactors.Add(pivotCoffactor);
                                temporaryArray[j, i] = this.ring.AdditiveUnity;
                                for (int k = i + 1; k < matrixDimension; ++k)
                                {
                                    var positive = this.ring.Multiply(pivotCoffactor, temporaryArray[j, k]);
                                    var negative = this.ring.Multiply(valueCoffactor, temporaryArray[i, k]);
                                    temporaryArray[j, k] = this.ring.Add(positive, this.ring.AdditiveInverse(negative));
                                }
                            }
                        }
                    }
                }

                return(this.GetDeterminantValue(temporaryArray, determinantFactors, positiveResult));
            }
        }