Beispiel #1
0
        /// <summary>
        /// Testa a deomposição sequencial relativa à matriz.
        /// </summary>
        /// <param name="target">O algoritmo.</param>
        /// <param name="matrix">A matriz.</param>
        private void TestDecomposition(
            ATriangDiagSymmMatrixDecomp <Fraction <int> > target,
            ISquareMathMatrix <Fraction <int> > matrix)
        {
            // Execução do algoritmo.
            var decomposition = target.Run(
                matrix);

            // Calcula o valor esperado.
            var matrixFactory       = new ArrayMathMatrixFactory <Fraction <int> >();
            var matrixMultiplicaton = new MatrixMultiplicationOperation <Fraction <int> >(
                matrixFactory,
                target.Field,
                target.Field);
            var actual = new TransposeMatrix <Fraction <int> >(decomposition.UpperTriangularMatrix)
                         as IMatrix <Fraction <int> >;

            actual = matrixMultiplicaton.Multiply(actual, decomposition.DiagonalMatrix);
            actual = matrixMultiplicaton.Multiply(actual, decomposition.UpperTriangularMatrix);

            // Valida as asserções.
            Assert.AreEqual(matrix.GetLength(0), actual.GetLength(0));
            Assert.AreEqual(matrix.GetLength(1), actual.GetLength(1));
            for (int i = 0; i < actual.GetLength(0); ++i)
            {
                for (int j = 0; j < actual.GetLength(1); ++j)
                {
                    Assert.AreEqual(matrix[i, j], actual[i, j]);
                }
            }
        }
 /// <summary>
 /// Permite criar uma instância de entrada para o algoritmo do simplex na forma normal.
 /// A base pode corresponder a uma instância que resultou da aplicação do algoritmo.
 /// </summary>
 /// <param name="basicVariables">O conjunto de variáveis básicas.</param>
 /// <param name="nonBasicVariables">O conjunto de variáveis não-básicas.</param>
 /// <param name="objectiveFunction">Os coeficientes da função objectivo.</param>
 /// <param name="cost">O custo.</param>
 /// <param name="constraintsMatrix">A matriz das restrições.</param>
 /// <param name="constraintsVector">O vector das restrições.</param>
 /// <param name="inverseBasisMatrix">A matriz de base inversa que é utilizada durante o processo algorítmico.</param>
 /// /// <exception cref="ArgumentNullException">Se algum dos argumentos for nulo.</exception>
 /// <exception cref="ArgumentException">
 /// Se as dimensões dos argumentos não definirem correctamente um problema.
 /// </exception>
 public RevisedSimplexInput(
     int[] basicVariables,
     int[] nonBasicVariables,
     IMathVector <ObjectiveCoeffType> objectiveFunction,
     ObjectiveCoeffType cost,
     IMathMatrix <ConstraintsType> constraintsMatrix,
     IMathVector <ConstraintsType> constraintsVector,
     ISquareMathMatrix <ConstraintsType> inverseBasisMatrix)
     : base(
         basicVariables,
         nonBasicVariables,
         objectiveFunction,
         cost,
         constraintsMatrix,
         constraintsVector)
 {
     if (inverseBasisMatrix == null)
     {
         throw new ArgumentNullException("The basis matrix must not be null.");
     }
     else if (inverseBasisMatrix.GetLength(0) != ConstraintsMatrix.GetLength(0))
     {
         throw new ArgumentException("The dimension of basis matrix must match the number of lines in constraints matrix.");
     }
     else
     {
         this.inverseBasisMatrix = inverseBasisMatrix;
     }
 }
        /// <summary>
        /// Calcula o vector dos termos independentes actual.
        /// </summary>
        /// <param name="inverseMatrix">A matriz inversa.</param>
        /// <param name="constraintsVector">O vector dos termos independentes original.</param>
        /// <param name="result">O contentor para os resultados.</param>
        private void ComputeConstraintsVector(
            ISquareMathMatrix <CoeffType> inverseMatrix,
            IMathVector <CoeffType> constraintsVector,
            CoeffType[] result)
        {
            var basicLength         = inverseMatrix.GetLength(0);
            var inverseSparseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>;

            if (inverseSparseMatrix == null)
            {
                Parallel.For(0, basicLength, i =>
                {
                    var sum = this.coeffsField.AdditiveUnity;
                    for (int j = 0; j < basicLength; ++j)
                    {
                        var valueToAdd = constraintsVector[j];
                        valueToAdd     = this.coeffsField.Multiply(valueToAdd, inverseMatrix[i, j]);
                        sum            = this.coeffsField.Add(sum, valueToAdd);
                    }

                    result[i] = sum;
                });
            }
            else
            {
                Parallel.For(0, basicLength, i =>
                {
                    result[i] = this.coeffsField.AdditiveUnity;
                });

                Parallel.ForEach(inverseSparseMatrix.GetLines(), inverseLine =>
                {
                    var sum     = this.coeffsField.AdditiveUnity;
                    var columns = inverseLine.Value.GetColumns();
                    foreach (var columnKvp in columns)
                    {
                        var valueToAdd = constraintsVector[columnKvp.Key];
                        valueToAdd     = this.coeffsField.Multiply(valueToAdd, columnKvp.Value);
                        sum            = this.coeffsField.Add(sum, valueToAdd);
                    }

                    result[inverseLine.Key] = sum;
                });
            }
        }
        /// <summary>
        /// Executa o algorimtmo que permite determinar a solução do sistema simétrico
        /// com base na decomposição LDL^T.
        /// </summary>
        /// <param name="first">A matriz dos coeficientes das variáveis.</param>
        /// <param name="second">O vector dos coeficientes independentes.</param>
        /// <returns>A solução do sistema.</returns>
        public LinearSystemSolution <CoeffType> Run(
            ISquareMathMatrix <CoeffType> first,
            IMathMatrix <CoeffType> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            else if (second == null)
            {
                throw new ArgumentNullException("second");
            }
            else
            {
                var size = first.GetLength(0);
                if (second.GetLength(0) != size)
                {
                    throw new ArgumentException(
                              "The number of columns in coefficients matrix must equal the number of lines in independent vector.");
                }
                else
                {
                    var result    = new LinearSystemSolution <CoeffType>();
                    var decompRes = this.decompositionAlgorithm.Run(
                        first);
                    var indSol = this.ProcessFirstMatrix(
                        decompRes.UpperTriangularMatrix,
                        second,
                        size);
                    if (this.ProcessDiagonal(decompRes.DiagonalMatrix, indSol, size))
                    {
                        this.ProcessRemainingMatrices(
                            decompRes.UpperTriangularMatrix,
                            decompRes.DiagonalMatrix,
                            indSol,
                            size,
                            result);
                    }

                    return(result);
                }
            }
        }
        /// <summary>
        /// Calcula os coeficientes da variável de entrada e coloca-os no vector eta.
        /// </summary>
        /// <param name="enteringVariable">A variável de entrada.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="inverseMatrix">A matriz inversa.</param>
        /// <param name="etaVector">O vector eta.</param>
        private void ComputeVariableCoefficients(
            int enteringVariable,
            IMathMatrix <CoeffType> constraintsMatrix,
            ISquareMathMatrix <CoeffType> inverseMatrix,
            CoeffType[] etaVector)
        {
            var length = constraintsMatrix.GetLength(1);

            if (enteringVariable >= length) // A matriz das restrições contém a identidade como entrada.
            {
                var entryIndex = enteringVariable - length;

                // O vector conterá a entrada respectiva na matriz inversa.
                var sparseInverseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>;
                length = etaVector.Length;
                if (sparseInverseMatrix == null)
                {
                    Parallel.For(0, length, i =>
                    {
                        etaVector[i] = inverseMatrix[i, entryIndex];
                    });
                }
                else
                {
                    Parallel.For(0, length, i =>
                    {
                        etaVector[i] = this.coeffsField.AdditiveUnity;
                    });

                    foreach (var line in sparseInverseMatrix.GetLines())
                    {
                        etaVector[line.Key] = line.Value[entryIndex];
                    }
                }
            }
            else
            {
                length = inverseMatrix.GetLength(0);
                var sparseContraintsMatrix = constraintsMatrix as ISparseMathMatrix <CoeffType>;
                if (sparseContraintsMatrix == null)
                {
                    var sparseInverseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>;
                    if (sparseInverseMatrix == null)
                    {
                        Parallel.For(0, length, i =>
                        {
                            var sum = this.coeffsField.AdditiveUnity;
                            for (int j = 0; j < length; ++j)
                            {
                                var valueToAdd = inverseMatrix[i, j];
                                valueToAdd     = this.coeffsField.Multiply(
                                    valueToAdd,
                                    constraintsMatrix[j, enteringVariable]);
                                sum = this.coeffsField.Add(sum, valueToAdd);
                            }

                            etaVector[i] = sum;
                        });
                    }
                    else
                    {
                        Parallel.For(0, length, i =>
                        {
                            etaVector[i] = this.coeffsField.AdditiveUnity;
                        });

                        var inverseMatrixLines = sparseInverseMatrix.GetLines();
                        Parallel.ForEach(inverseMatrixLines, lineKvp =>
                        {
                            var sum = this.coeffsField.AdditiveUnity;
                            foreach (var columnKvp in lineKvp.Value.GetColumns())
                            {
                                var valueToAdd = constraintsMatrix[columnKvp.Key, enteringVariable];
                                valueToAdd     = this.coeffsField.Multiply(valueToAdd, columnKvp.Value);
                                sum            = this.coeffsField.Add(sum, valueToAdd);
                            }

                            etaVector[lineKvp.Key] = sum;
                        });
                    }
                }
                else
                {
                    var sparseInverseMatrix = inverseMatrix as ISparseMathMatrix <CoeffType>;
                    if (sparseInverseMatrix == null)
                    {
                        Parallel.For(0, length, i =>
                        {
                            var sum = this.coeffsField.AdditiveUnity;
                            var constraintsMatrixLines = sparseContraintsMatrix.GetLines();
                            foreach (var constraintsLine in constraintsMatrixLines)
                            {
                                var j          = constraintsLine.Key;
                                var valueToAdd = default(CoeffType);
                                if (constraintsLine.Value.TryGetColumnValue(enteringVariable, out valueToAdd))
                                {
                                    valueToAdd = this.coeffsField.Multiply(valueToAdd, inverseMatrix[i, j]);
                                    sum        = this.coeffsField.Add(sum, valueToAdd);
                                }
                            }

                            etaVector[i] = sum;
                        });
                    }
                    else
                    {
                        Parallel.For(0, length, i =>
                        {
                            etaVector[i] = this.coeffsField.AdditiveUnity;
                        });

                        Parallel.ForEach(sparseInverseMatrix.GetLines(), inverseMatrixLine =>
                        {
                            var sum = this.coeffsField.AdditiveUnity;
                            var constraintsMatrixLines = sparseContraintsMatrix.GetLines();
                            foreach (var constraintsLine in constraintsMatrixLines)
                            {
                                var j            = constraintsLine.Key;
                                var inverseValue = default(CoeffType);
                                if (inverseMatrixLine.Value.TryGetColumnValue(j, out inverseValue))
                                {
                                    var constraintsValue = default(CoeffType);
                                    if (constraintsLine.Value.TryGetColumnValue(enteringVariable, out constraintsValue))
                                    {
                                        var valueToAdd = this.coeffsField.Multiply(inverseValue, constraintsValue);
                                        sum            = this.coeffsField.Add(sum, valueToAdd);
                                    }
                                }
                            }

                            etaVector[inverseMatrixLine.Key] = sum;
                        });
                    }
                }
            }
        }
Beispiel #6
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);
                }
            }
        }
        /// <summary>
        /// Obtém a decomposição de uma matriz M=LDL^* onde L é uma matriz triangular e D é uma matriz diagonal.
        /// </summary>
        /// <param name="matrix">A matriz.</param>
        /// <returns>As matrizes triangular e diagonal.</returns>
        public override TriangDiagSymmMatrixDecompResult <CoeffType> Run(
            ISquareMathMatrix <CoeffType> matrix)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }
            else
            {
                var matrixDimension  = matrix.GetLength(0);
                var triangularMatrix = this.upperTriangularMatrixFactory.Invoke(
                    matrixDimension,
                    this.field.AdditiveUnity);
                var diagonalMatrix = this.diagonalMatrixFactory.Invoke(
                    matrixDimension,
                    this.field.AdditiveUnity);
                for (int i = 0; i < matrixDimension; ++i)
                {
                    var diagonalTask = new Task(() =>
                    {
                        var sumValue = this.field.AdditiveUnity;
                        for (int j = 0; j < i; ++j)
                        {
                            var diag = diagonalMatrix[j, j];
                            if (!this.field.IsAdditiveUnity(diag))
                            {
                                var value = triangularMatrix[j, i];
                                value     = this.field.Multiply(value, value);
                                value     = this.field.Multiply(value, diag);
                                sumValue  = this.field.Add(sumValue, value);
                            }
                        }

                        sumValue = this.field.Add(
                            matrix[i, i],
                            this.field.AdditiveInverse(sumValue));
                        diagonalMatrix[i, i] = sumValue;
                    });

                    var triangularTask = new Task(() =>
                    {
                        Parallel.For(i + 1, matrixDimension, (j, state) =>
                        {
                            var sumValue = this.field.AdditiveUnity;
                            for (int k = 0; k < i; ++k)
                            {
                                var value = triangularMatrix[k, i];
                                value     = this.field.Multiply(value, triangularMatrix[k, j]);
                                value     = this.field.Multiply(value, diagonalMatrix[k, k]);
                                sumValue  = this.field.Add(sumValue, value);
                            }

                            triangularMatrix[i, j] = this.field.Add(
                                matrix[i, j],
                                this.field.AdditiveInverse(sumValue));
                        });
                    });

                    diagonalTask.Start();
                    triangularTask.Start();
                    Task.WaitAll(new[] { diagonalTask, triangularTask });

                    var diagonalValue = diagonalMatrix[i, i];
                    if (!this.field.IsAdditiveUnity(diagonalValue))
                    {
                        triangularMatrix.ScalarLineMultiplication(
                            i,
                            this.field.MultiplicativeInverse(diagonalMatrix[i, i]),
                            this.field);
                    }

                    triangularMatrix[i, i] = this.field.MultiplicativeUnity;
                }

                return(new TriangDiagSymmMatrixDecompResult <CoeffType>(
                           triangularMatrix,
                           diagonalMatrix));
            }
        }