/// <summary>
        /// Obtém o vector dual.
        /// </summary>
        /// <param name="nonBasicCostsIndices">Os índices dos valores com custos relativos às variáveis básicas.</param>
        /// <param name="inverseMatrix">A matriz da base inversa.</param>
        /// <param name="objectiveFunction">O vector que representa a função objectivo.</param>
        /// <param name="basicVariables">As variáveis básicas.</param>
        /// <returns>O vector dual utilizado para determinar os valores dos custos.</returns>
        private SimplexMaximumNumberField <CoeffType>[] ComputeDualVector(
            SortedSet <int> nonBasicCostsIndices,
            ISquareMathMatrix <CoeffType> inverseMatrix,
            IMathVector <SimplexMaximumNumberField <CoeffType> > objectiveFunction,
            int[] basicVariables)
        {
            var result    = new SimplexMaximumNumberField <CoeffType> [basicVariables.Length];
            var dimension = basicVariables.Length;

            Parallel.For(0, dimension, i =>
            {
                var sum = new SimplexMaximumNumberField <CoeffType>(this.coeffsField.AdditiveUnity, this.coeffsField.AdditiveUnity);
                foreach (var index in nonBasicCostsIndices)
                {
                    var objectiveValue     = objectiveFunction[basicVariables[index]];
                    var finitePart         = objectiveValue.FinitePart;
                    var bigPart            = objectiveValue.BigPart;
                    var inverseMatrixEntry = inverseMatrix[index, i];
                    finitePart             = this.coeffsField.Multiply(
                        inverseMatrixEntry,
                        this.coeffsField.AdditiveInverse(objectiveValue.FinitePart));
                    bigPart = this.coeffsField.Multiply(
                        inverseMatrixEntry,
                        this.coeffsField.AdditiveInverse(objectiveValue.BigPart));
                    sum.Add(finitePart, bigPart, this.coeffsField);
                }

                result[i] = sum;
            });

            return(result);
        }
Example #2
0
 /// <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>
        /// Obtém o vector dual.
        /// </summary>
        /// <param name="nonBasicCostsIndices">Os índices dos valores com custos relativos às variáveis básicas.</param>
        /// <param name="inverseMatrix">A matriz da base inversa.</param>
        /// <param name="objectiveFunction">O vector que representa a função objectivo.</param>
        /// <param name="basicVariables">As variáveis básicas.</param>
        /// <returns>O vector dual utilizado para determinar os valores dos custos.</returns>
        private CoeffType[] ComputeDualVector(
            SortedSet <int> nonBasicCostsIndices,
            ISquareMathMatrix <CoeffType> inverseMatrix,
            IMathVector <CoeffType> objectiveFunction,
            int[] basicVariables)
        {
            var result    = new CoeffType[basicVariables.Length];
            var dimension = basicVariables.Length;

            Parallel.For(0, dimension, i =>
            {
                var sum = this.coeffsField.AdditiveUnity;
                foreach (var index in nonBasicCostsIndices)
                {
                    var objectiveValue = objectiveFunction[basicVariables[index]];
                    var valueToAdd     = inverseMatrix[index, i];
                    valueToAdd         = this.coeffsField.Multiply(
                        valueToAdd,
                        this.coeffsField.AdditiveInverse(objectiveValue));
                    sum = this.coeffsField.Add(sum, valueToAdd);
                }

                result[i] = sum;
            });

            return(result);
        }
Example #4
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>
        /// Determina a próxima variável de saída.
        /// </summary>
        /// <remarks>
        /// Esta função permite fazer um pré-cálculo do vector eta, sendo o respectivo contentor de dados
        /// passado como argumento.
        /// </remarks>
        /// <param name="enteringVariable">A variável de entrada.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="constraintsVector">O vector das restrições.</param>
        /// <param name="inverseBasisMatrix">A matriz das bases inversa.</param>
        /// <param name="etaVector">O contentor do vector eta.</param>
        /// <returns>A próxima variável de saída.</returns>
        private int GetNextLeavingVariable(
            int enteringVariable,
            IMathMatrix <CoeffType> constraintsMatrix,
            CoeffType[] constraintsVector,
            ISquareMathMatrix <CoeffType> inverseBasisMatrix,
            CoeffType[] etaVector)
        {
            // Calcula os coeficientes e coloca-os no vector eta.
            this.ComputeVariableCoefficients(
                enteringVariable,
                constraintsMatrix,
                inverseBasisMatrix,
                etaVector);

            var result = -1;
            var value  = this.coeffsField.AdditiveUnity;

            // Estabelece o primeiro valor para futura comparação.
            var constraintsLength = constraintsMatrix.GetLength(0);
            var index             = 0;

            while (index < constraintsLength && result == -1)
            {
                var currentValue = etaVector[index];
                if (this.coeffsComparer.Compare(currentValue, this.coeffsField.AdditiveUnity) > 0)
                {
                    value = this.coeffsField.Multiply(
                        constraintsVector[index],
                        this.coeffsField.MultiplicativeInverse(currentValue));
                    result = index;
                }

                ++index;
            }

            if (result != -1)
            {
                for (; index < constraintsLength; ++index)
                {
                    var currentValue = etaVector[index];
                    if (this.coeffsComparer.Compare(currentValue, this.coeffsField.AdditiveUnity) > 0)
                    {
                        currentValue = this.coeffsField.Multiply(
                            constraintsVector[index],
                            this.coeffsField.MultiplicativeInverse(currentValue));
                        if (this.coeffsComparer.Compare(currentValue, value) < 0)
                        {
                            result = index;
                            value  = currentValue;
                        }
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// Actualiza as entradas da matriz inversa.
        /// </summary>
        /// <param name="leavingVariableIndex">O índice da variável de saída.</param>
        /// <param name="inverseMatrix">A matriz inversa.</param>
        /// <param name="etaVector">O vector eta.</param>
        private void UpdateInverseMatrix(
            int leavingVariableIndex,
            ISquareMathMatrix <CoeffType> inverseMatrix,
            CoeffType[] etaVector)
        {
            // Actualiza o valor de eta
            var multiplicativeInverse = this.coeffsField.MultiplicativeInverse(etaVector[leavingVariableIndex]);

            Parallel.For(0, leavingVariableIndex, i =>
            {
                var value    = this.coeffsField.Multiply(etaVector[i], multiplicativeInverse);
                etaVector[i] = this.coeffsField.AdditiveInverse(value);
            });

            etaVector[leavingVariableIndex] = multiplicativeInverse;

            var length = etaVector.Length;

            Parallel.For(leavingVariableIndex + 1, length, i =>
            {
                var value    = this.coeffsField.Multiply(etaVector[i], multiplicativeInverse);
                etaVector[i] = this.coeffsField.AdditiveInverse(value);
            });

            // Actualiza a matriz inversa
            Parallel.For(0, leavingVariableIndex, i =>
            {
                inverseMatrix.CombineLines(
                    i,
                    leavingVariableIndex,
                    this.coeffsField.MultiplicativeUnity,
                    etaVector[i],
                    this.coeffsField);
            });

            Parallel.For(leavingVariableIndex + 1, length, i =>
            {
                inverseMatrix.CombineLines(
                    i,
                    leavingVariableIndex,
                    this.coeffsField.MultiplicativeUnity,
                    etaVector[i],
                    this.coeffsField);
            });

            inverseMatrix.ScalarLineMultiplication(leavingVariableIndex, etaVector[leavingVariableIndex], this.coeffsField);
        }
        /// <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);
                }
            }
        }
Example #9
0
 /// <summary>
 /// Cria uma instância de objectos do tipo <see cref="LinearDecompositionInput{ConstraintsType, ObjectiveCoeffType}"/>
 /// </summary>
 /// <param name="initialDecompositionPoints">As estimativas iniciais relativas ao problema da decomposição.</param>
 /// <param name="objectiveFunction">A função objectivo.</param>
 /// <param name="cost">O custo inicial.</param>
 /// <param name="masterConstraints">As restrições do problema principal.</param>
 /// <param name="decomposedConstraints">As restrições dos vários problemas decompostos.</param>
 /// <param name="inverseBasisMatrix">A matriz de base inversa.</param>
 public LinearDecompositionInput(
     IMathVector <ObjectiveCoeffType>[] initialDecompositionPoints,
     IMathVector <ObjectiveCoeffType> objectiveFunction,
     ObjectiveCoeffType cost,
     LinearConstraintsInput <ConstraintsType> masterConstraints,
     LinearConstraintsInput <ConstraintsType>[] decomposedConstraints,
     ISquareMathMatrix <ConstraintsType> inverseBasisMatrix)
 {
     this.ValidateArguments(
         initialDecompositionPoints,
         objectiveFunction,
         cost,
         masterConstraints,
         decomposedConstraints,
         inverseBasisMatrix);
     this.initialDecompositionPoints = initialDecompositionPoints;
     this.objectiveFunction          = objectiveFunction;
     this.cost = cost;
     this.masterConstraints     = masterConstraints;
     this.decomposedConstraints = decomposedConstraints;
     this.inverseBasisMatrix    = inverseBasisMatrix;
 }
        /// <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;
                        });
                    }
                }
            }
        }
Example #11
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));
            }
        }
 /// <summary>
 /// Obtém a decomposição de uma matriz M=LDL^* onde L é uma matriz triangular e D é uma matriz diagonal.
 /// </summary>
 /// <remarks>
 /// Caso a matriz não seja simétrica, é considerada a matriz simétrica cujas entradas acima da diagonal
 /// conicidam com as entradas respectivas da matriz original.
 /// </remarks>
 /// <param name="data">A matriz.</param>
 /// <returns>As matrizes triangular e diagonal.</returns>
 public abstract TriangDiagSymmMatrixDecompResult <CoeffType> Run(
     ISquareMathMatrix <CoeffType> data);
Example #14
0
 /// <summary>
 /// Valida a integridade dos dados nos argumentos.
 /// </summary>
 /// <param name="initialDecompositionPoints">As estimativas iniciais relativas ao problema da decomposição.</param>
 /// <param name="objectiveFunction">A função objectivo.</param>
 /// <param name="cost">O custo inicial.</param>
 /// <param name="masterConstraints">As restrições do problema principal.</param>
 /// <param name="decomposedConstraints">As restrições dos vários problemas decompostos.</param>
 /// <param name="inverseBasisMatrix">A matriz de base inversa.</param>
 private void ValidateArguments(
     IMathVector <ObjectiveCoeffType>[] initialDecompositionPoints,
     IMathVector <ObjectiveCoeffType> objectiveFunction,
     ObjectiveCoeffType cost,
     LinearConstraintsInput <ConstraintsType> masterConstraints,
     LinearConstraintsInput <ConstraintsType>[] decomposedConstraints,
     ISquareMathMatrix <ConstraintsType> inverseBasisMatrix)
 {
     if (initialDecompositionPoints == null)
     {
         throw new ArgumentNullException("initialDecompositionPoints");
     }
     else if (objectiveFunction == null)
     {
         throw new ArgumentNullException("objectiveFunction");
     }
     else if (cost == null)
     {
         throw new ArgumentNullException("cost");
     }
     else if (masterConstraints == null)
     {
         throw new ArgumentNullException("masterConstraints");
     }
     else if (decomposedConstraints == null)
     {
         throw new ArgumentNullException("decomposedConstraints");
     }
     else if (inverseBasisMatrix == null)
     {
         throw new ArgumentNullException("inverseBasisMatrix");
     }
     else if (initialDecompositionPoints.Length != decomposedConstraints.Length)
     {
         throw new ArgumentException(
                   "The number of initial problem points must match the number of decomposition problem constraints.");
     }
     else
     {
         var length = decomposedConstraints.Length;
         for (int i = 0; i < length; ++i)
         {
             var currentDecomposedConstraint = decomposedConstraints[i];
             var currentPoint = initialDecompositionPoints[i];
             if (currentDecomposedConstraint == null)
             {
                 throw new ArgumentException("Null decomposition constraints aren't allowed.");
             }
             else if (currentPoint == null)
             {
                 throw new ArgumentException("Null initial points aren't allowed.");
             }
             else
             {
                 var constraintColumnsLength = currentDecomposedConstraint.ConstraintsMatrix.GetLength(1);
                 if (initialDecompositionPoints.Length != constraintColumnsLength)
                 {
                     throw new ArgumentException(
                               "The number of initial points coordinates must match the number of columns of the decomposition problem constraints matrix.");
                 }
             }
         }
     }
 }