/// <summary>
        /// Obtém a simetrização da matriz.
        /// </summary>
        /// <param name="matrix">A matriz original.</param>
        /// <returns>A matriz simétrica.</returns>
        private ISquareMathMatrix <CoeffType> GetSymmetricMatrix(
            IMathMatrix <CoeffType> matrix)
        {
            var lines   = matrix.GetLength(0);
            var columns = matrix.GetLength(1);
            var result  = this.squareMatrixFactory.Invoke(columns);

            for (var i = 0; i < columns; ++i)
            {
                for (var j = 0; j < columns; ++j)
                {
                    var sum = this.ring.AdditiveUnity;
                    for (var k = 0; k < lines; ++k)
                    {
                        var value = this.ring.Multiply(
                            matrix[k, i],
                            matrix[k, j]);
                        sum = this.ring.Add(
                            sum,
                            value);
                    }

                    result[i, j] = sum;
                }
            }

            return(result);
        }
        /// <summary>
        /// Averigua se o sistema possui alguma solução.
        /// </summary>
        /// <param name="diagonalMatrix">A matriz diagonal.</param>
        /// <param name="indSolVector">O vector independente da solução.</param>
        /// <param name="size">A dimensão das matrizes.</param>
        /// <returns>
        /// Verdadeiro caso o sistema tenha solução e falso caso contrário.
        /// </returns>
        private bool ProcessDiagonal(
            IMathMatrix <CoeffType> diagonalMatrix,
            IMathVector <CoeffType> indSolVector,
            int size)
        {
            var field = this.decompositionAlgorithm.Field;

            for (var i = 0; i < size; ++i)
            {
                var diagValue = diagonalMatrix[i, i];
                if (field.IsAdditiveUnity(diagValue))
                {
                    var indValue = indSolVector[i];
                    if (!field.IsAdditiveUnity(indValue))
                    {
                        return(false);
                    }
                }
                else
                {
                    indSolVector[i] = field.Multiply(
                        indSolVector[i],
                        field.MultiplicativeInverse(diagValue));
                }
            }

            return(true);
        }
 /// <summary>
 /// Cria uma nova instância de um objecto do tipo <see cref="TriangDiagSymmMatrixDecompResult{CoeffType}"/>.
 /// </summary>
 /// <param name="upperTriangularMatrix">A matriz triangular inferior.</param>
 /// <param name="diagonalMatrix">A matriz diagonal.</param>
 internal TriangDiagSymmMatrixDecompResult(
     IMathMatrix <CoeffType> upperTriangularMatrix,
     IMathMatrix <CoeffType> diagonalMatrix)
 {
     this.upperTriangularMatrix = upperTriangularMatrix;
     this.diagonalMatrix        = diagonalMatrix;
 }
Ejemplo n.º 4
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 dos coeficientes independentes após a transformação.
        /// </summary>
        /// <param name="matrix">A matriz dos coeficientes das variáveis.</param>
        /// <param name="independent">O vector dos coeficientes independentes.</param>
        /// <returns>O vector transformado.</returns>
        private IMathMatrix <CoeffType> GetTransformedVector(
            IMathMatrix <CoeffType> matrix,
            IMathMatrix <CoeffType> independent)
        {
            var lines   = matrix.GetLength(0);
            var columns = matrix.GetLength(1);
            var result  = this.independentVectorFactory.Invoke(columns);

            for (var i = 0; i < columns; ++i)
            {
                var sum = this.ring.AdditiveUnity;
                for (var j = 0; j < lines; ++j)
                {
                    var value = this.ring.Multiply(
                        matrix[j, i],
                        independent[j, 0]);
                    sum = this.ring.Add(
                        sum,
                        value);
                }

                result[i, 0] = sum;
            }

            return(result);
        }
        /// <summary>
        /// Testa a solução do sistema de equações.
        /// </summary>
        /// <param name="matrix">A matriz dos coeficientes das variáveis.</param>
        /// <param name="independent">O vector dos coeficientes independentes.</param>
        /// <param name="solution">A solução do sistema simétrico.</param>
        private void TestSolution(
            IMathMatrix <CoeffType> matrix,
            IMathMatrix <CoeffType> independent,
            LinearSystemSolution <CoeffType> solution)
        {
            if (solution.Vector != null)
            {
                var vec     = solution.Vector;
                var lines   = matrix.GetLength(0);
                var columns = matrix.GetLength(1);
                for (var i = 0; i < lines; ++i)
                {
                    var sum = this.ring.AdditiveUnity;
                    for (var j = 0; j < columns; ++j)
                    {
                        var value = this.ring.Multiply(
                            matrix[i, j],
                            vec[j]);
                        sum = this.ring.Add(
                            sum,
                            value);
                    }

                    if (!this.ring.Equals(sum, independent[i, 0]))
                    {
                        solution.Vector = null;
                        solution.VectorSpaceBasis.Clear();
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Cria instâncias de objectos do tipo <see cref="MetricMatrixVectorScalarProduct{CoeffType}"/>.
        /// </summary>
        /// <param name="metricMatrix">A matriz dos coeficientes métricos.</param>
        /// <param name="comparer">O comparador de coeficientes.</param>
        /// <param name="ring">O anel responsável pelas operações sobre os coeficientes.</param>
        /// <exception cref="ArgumentNullException">
        /// Caso a matriz dos coeficientes métricos ou o anel responsável pelas operações sobre os coeficientes
        /// sejam nulos.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// Se a matriz dos coeficientes métricos não for quadrada.
        /// </exception>
        public MetricMatrixVectorScalarProduct(
            IMathMatrix <CoeffType> metricMatrix,
            IComparer <CoeffType> comparer,
            IRing <CoeffType> ring)
        {
            if (ring == null)
            {
                throw new ArgumentNullException("ring");
            }
            else if (metricMatrix == null)
            {
                throw new ArgumentNullException("metricMatrix");
            }
            else if (metricMatrix.GetLength(0) == metricMatrix.GetLength(1))
            {
                if (comparer == null)
                {
                    this.comparer = Comparer <CoeffType> .Default;
                }
                else
                {
                    this.comparer = comparer;
                }

                this.metricMatrix = metricMatrix;
                this.ring         = ring;
            }
            else
            {
                throw new ArgumentException("The metric coefficients matrix must be square.");
            }
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Determina a solução de um sistema linear de equações.
        /// </summary>
        /// <remarks>
        /// A matriz e o vector independente são alterados durante o processo.
        /// </remarks>
        /// <param name="coefficientsMatrix">A matriz dos coeficientes.</param>
        /// <param name="independentVector">O vector independente.</param>
        /// <returns>A solução do sistema.</returns>
        public LinearSystemSolution <ElementType> Run(
            IMathMatrix <ElementType> coefficientsMatrix,
            IMathMatrix <ElementType> independentVector)
        {
            this.condensationAlgorithm.Run(coefficientsMatrix, independentVector);
            var result                    = new LinearSystemSolution <ElementType>();
            var matrixLines               = coefficientsMatrix.GetLength(0);
            var matrixColumns             = coefficientsMatrix.GetLength(1);
            var currentPivotLine          = 0;
            var currentPivotColumn        = 0;
            var lastNonZeroColumn         = -1;
            var independentSolutionVector = new ArrayMathVector <ElementType>(matrixColumns, this.field.AdditiveUnity);

            while (currentPivotLine < matrixLines && currentPivotColumn < matrixColumns)
            {
                var pivotValue = coefficientsMatrix[currentPivotLine, currentPivotColumn];
                if (this.field.IsAdditiveUnity(pivotValue))
                {
                    if (this.field.IsAdditiveUnity(independentSolutionVector[currentPivotLine]))
                    {
                        var basisVector = new ArrayMathVector <ElementType>(matrixColumns, this.field.AdditiveUnity);
                        basisVector[currentPivotColumn] = this.field.AdditiveInverse(
                            this.field.MultiplicativeUnity);
                        var i = currentPivotLine - 1;
                        var j = lastNonZeroColumn;
                        while (i >= 0 && j >= 0)
                        {
                            var linePivotValue = coefficientsMatrix[i, j];
                            if (this.field.IsMultiplicativeUnity(linePivotValue))
                            {
                                basisVector[j] = coefficientsMatrix[i, currentPivotColumn];
                                --i;
                            }

                            --j;
                        }

                        result.VectorSpaceBasis.Add(basisVector);
                    }
                    else
                    {
                        result.Vector = null;
                        result.VectorSpaceBasis.Clear();
                        return(result);
                    }
                }
                else
                {
                    lastNonZeroColumn = currentPivotColumn;
                    independentSolutionVector[currentPivotColumn] = independentVector[currentPivotLine, 0];
                    ++currentPivotLine;
                }

                ++currentPivotColumn;
            }

            result.Vector = independentSolutionVector;
            return(result);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Processa a função objectivo.
        /// </summary>
        /// <param name="enteringVariable">A variável de entrada.</param>
        /// <param name="leavingVariable">a variável de saída.</param>
        /// <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="currentCost">O custo actual.</param>
        /// <param name="objective">A função objectivo.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="constraintsVector">O vector das restrições.</param>
        /// <returns>O resultado.</returns>
        private SimplexMaximumNumberField <CoeffType> ProcessObjectiveFunction(
            int enteringVariable,
            int leavingVariable,
            int[] basicVariables,
            int[] nonBasicVariables,
            SimplexMaximumNumberField <CoeffType> currentCost,
            IMathVector <SimplexMaximumNumberField <CoeffType> > objective,
            IMathMatrix <CoeffType> constraintsMatrix,
            IMathVector <CoeffType> constraintsVector)
        {
            var result = currentCost;
            var multiplicativeProduct = this.GetAdditiveInverse(objective[enteringVariable]);

            if (!this.IsAdditiveUnity(multiplicativeProduct))
            {
                Parallel.For(0, enteringVariable, column =>
                {
                    objective[column] = this.Add(
                        objective[column],
                        this.Multiply(constraintsMatrix[leavingVariable, column],
                                      multiplicativeProduct));
                });

                var constraintsEntry = constraintsMatrix[leavingVariable, enteringVariable];
                if (this.coeffsField.IsAdditiveUnity(constraintsEntry))
                {
                    objective[enteringVariable] = multiplicativeProduct;
                }
                else
                {
                    objective[enteringVariable] = this.Multiply(
                        constraintsEntry,
                        multiplicativeProduct);
                }

                Parallel.For(enteringVariable + 1, objective.Length, column =>
                {
                    objective[column] = this.Add(
                        objective[column],
                        this.Multiply(constraintsMatrix[leavingVariable, column],
                                      multiplicativeProduct));
                });

                result = this.Add(
                    result,
                    this.Multiply(constraintsVector[leavingVariable],
                                  multiplicativeProduct));
            }

            // Troca as variáveis
            var swap = nonBasicVariables[enteringVariable];

            nonBasicVariables[enteringVariable] = basicVariables[leavingVariable];
            basicVariables[leavingVariable]     = swap;

            return(result);
        }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Obtém a variável de entrada.
        /// </summary>
        /// <param name="dualVector">O vector dual que irá permitir calcular os coeficientes do custo.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="objectiveFunction">A função objectivo.</param>
        /// <param name="nonBasicVariables">As variáveis não básicas.</param>
        /// <returns>O índice da variável a entrar.</returns>
        private int GetNextEnteringVariable(
            CoeffType[] dualVector,
            IMathMatrix <CoeffType> constraintsMatrix,
            IMathVector <CoeffType> objectiveFunction,
            int[] nonBasicVariables)
        {
            var result                 = -1;
            var value                  = this.coeffsField.AdditiveUnity;
            var nonBasicLength         = nonBasicVariables.Length;
            var constraintsLinesLength = dualVector.Length;

            var syncObject = new object(); // Utilizado para sincronizar as comparações.

            Parallel.For(0, nonBasicLength, i =>
            {
                var innerValue       = this.coeffsField.AdditiveUnity;
                var nonBasicVariable = nonBasicVariables[i];
                if (nonBasicVariable < nonBasicLength)
                {
                    for (int j = 0; j < constraintsLinesLength; ++j)
                    {
                        var valueToAdd = this.coeffsField.Multiply(dualVector[j], constraintsMatrix[j, nonBasicVariable]);
                        valueToAdd     = this.coeffsField.Add(
                            valueToAdd,
                            objectiveFunction[nonBasicVariable]);
                        innerValue = this.coeffsField.Add(innerValue, valueToAdd);
                    }

                    lock (syncObject)
                    {
                        if (this.coeffsComparer.Compare(innerValue, value) < 0)
                        {
                            result = i;
                            value  = innerValue;
                        }
                    }
                }
                else
                {
                    var index  = nonBasicVariable - nonBasicLength;
                    innerValue = dualVector[index];

                    lock (syncObject)
                    {
                        if (this.coeffsComparer.Compare(innerValue, value) < 0)
                        {
                            result = i;
                            value  = innerValue;
                        }
                    }
                }
            });

            return(result);
        }
        /// <summary>
        /// Estabelece os valores na parte trangular inferior da matriz.
        /// </summary>
        /// <param name="matrix">A matriz.</param>
        private void SetLowerTerms(IMathMatrix <CoeffType> matrix)
        {
            var dimension = matrix.GetLength(0);

            for (int i = 0; i < dimension; ++i)
            {
                for (int j = i + 1; j < dimension; ++j)
                {
                    matrix[j, i] = matrix[i, j];
                }
            }
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Cria instâncias de objectos do tipo <see cref="MatrixRowVector{CoeffType}"/>.
 /// </summary>
 /// <param name="lineNumber">O número da linha.</param>
 /// <param name="matrix">A matriz da qual é extraída a linha como sendo um vector.</param>
 /// <exception cref="ArgumentOutOfRangeException">Se a matriz for nula.</exception>
 public MatrixRowVector(int lineNumber, IMathMatrix <CoeffType> matrix)
 {
     if (lineNumber < 0)
     {
         throw new ArgumentOutOfRangeException("matrix");
     }
     else
     {
         this.lineNumber = lineNumber;
         this.matrix     = matrix;
     }
 }
Ejemplo n.º 14
0
 /// <summary>
 /// Cria instâncias de objectos do tipo <see cref="MatrixColumnVector{CoeffType}"/>.
 /// </summary>
 /// <param name="columnNumber">O número da coluna.</param>
 /// <param name="matrix">A matriz da qual se considera a coluna como sendo vector.</param>
 /// <exception cref="ArgumentOutOfRangeException">Se a matriz for nula.</exception>
 public MatrixColumnVector(int columnNumber, IMathMatrix <CoeffType> matrix)
 {
     if (columnNumber < 0)
     {
         throw new ArgumentOutOfRangeException("matrix");
     }
     else
     {
         this.columnNumber = columnNumber;
         this.matrix       = matrix;
     }
 }
Ejemplo n.º 15
0
        /// <summary>
        /// Calcula as entradas da matriz de multiplicação.
        /// </summary>
        /// <param name="data">A matriz.</param>
        /// <param name="diagonalElement">O elemento na diagonal.</param>
        /// <param name="subMatrixSequence">A sequência que define a sub-matriz.</param>
        /// <param name="singleValueSequence">A sequência que define o valor.</param>
        /// <param name="multiplicator">O objecto responsável pela multiplicação de matrizes.</param>
        /// <param name="multiplicationMatrix">A matriz que comporta o resultado da multiplicação.</param>
        private void FillMultiplicationMatrix(
            IMathMatrix <ElementType> data,
            ElementType diagonalElement,
            IntegerSequence subMatrixSequence,
            IntegerSequence singleValueSequence,
            MatrixMultiplicationOperation <ElementType> multiplicator,
            IMatrix <ElementType> multiplicationMatrix)
        {
            var dimension       = multiplicationMatrix.GetLength(1);
            var rowSubMatrix    = data.GetSubMatrix(singleValueSequence, subMatrixSequence);
            var columnSubMatrix = data.GetSubMatrix(subMatrixSequence, singleValueSequence);
            var mainSubMatrix   = data.GetSubMatrix(subMatrixSequence, subMatrixSequence);

            for (int i = 0; i < dimension; ++i)
            {
                multiplicationMatrix[i, i] = this.ring.MultiplicativeUnity;
            }

            for (int i = 0; i < dimension; ++i)
            {
                multiplicationMatrix[i + 1, i] = this.ring.AdditiveInverse(diagonalElement);
            }

            var vectorsMultiply = multiplicator.Multiply(rowSubMatrix, columnSubMatrix);

            for (int i = 0; i < dimension - 1; ++i)
            {
                multiplicationMatrix[i + 2, i] = this.ring.AdditiveInverse(vectorsMultiply[0, 0]);
            }

            vectorsMultiply = multiplicator.Multiply(rowSubMatrix, mainSubMatrix);
            vectorsMultiply = multiplicator.Multiply(vectorsMultiply, columnSubMatrix);
            for (int i = 0; i < dimension - 2; ++i)
            {
                multiplicationMatrix[i + 3, i] = this.ring.AdditiveInverse(vectorsMultiply[0, 0]);
            }

            var subMatrix = mainSubMatrix;

            for (int i = 3; i < dimension; ++i)
            {
                subMatrix       = multiplicator.Multiply(mainSubMatrix, subMatrix);
                vectorsMultiply = multiplicator.Multiply(rowSubMatrix, subMatrix);
                vectorsMultiply = multiplicator.Multiply(vectorsMultiply, columnSubMatrix);
                for (int j = 0; j < dimension - i; ++j)
                {
                    multiplicationMatrix[j + i + 1, j] = this.ring.AdditiveInverse(vectorsMultiply[0, 0]);
                }
            }
        }
        /// <summary>
        /// Obtém o próximo pivô não nulo da matriz.
        /// </summary>
        /// <param name="startLine">A linha onde é iniciada a pesquisa.</param>
        /// <param name="data">A matriz.</param>
        /// <returns>A linha cujo pivô seja não nulo e -1 caso não exista.</returns>
        private int GetNextNonEmptyPivotLineNumber(int startLine, IMathMatrix <ObjectType> data)
        {
            var result          = -1;
            var matrixDimension = data.GetLength(0);

            for (int i = startLine + 1; i < matrixDimension; ++i)
            {
                if (!this.ring.IsAdditiveUnity(data[i, startLine]))
                {
                    result = i;
                    i      = matrixDimension;
                }
            }

            return(result);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Obtém o próximo pivô não nulo da matriz.
        /// </summary>
        /// <param name="startLine">A linha onde é iniciada a pesquisa.</param>
        /// <param name="pivotColumn">O coluna pivô.</param>
        /// <param name="data">A matriz.</param>
        /// <returns>A linha cujo pivô seja não nulo e -1 caso não exista.</returns>
        private int GetNextNonEmptyPivotLineNumber(int startLine, int pivotColumn, IMathMatrix <ElementType> data)
        {
            var result          = -1;
            var matrixDimension = data.GetLength(0);

            for (int i = startLine + 1; i < matrixDimension; ++i)
            {
                if (!this.field.IsAdditiveUnity(data[i, pivotColumn]))
                {
                    result = i;
                    i      = matrixDimension;
                }
            }

            return(result);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Obtém a próxima variável de saída.
        /// </summary>
        /// <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>
        /// <returns>A variável caso exista e -1 caso contrário.</returns>
        private int GetNextLeavingVariable(
            int enteringVariable,
            IMathMatrix <CoeffType> constraintsMatrix,
            IMathVector <CoeffType> constraintsVector)
        {
            var result = -1;
            var value  = this.coeffsField.AdditiveUnity;

            // Estabelece o primeiro valor para futura comparação.
            var index = 0;

            while (index < constraintsMatrix.GetLength(0) && result == -1)
            {
                var currentValue = constraintsMatrix[index, enteringVariable];
                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)
            {
                var constraintsLength = constraintsMatrix.GetLength(0);
                for (int i = index; i < constraintsLength; ++i)
                {
                    var currentValue = constraintsMatrix[i, enteringVariable];
                    if (this.coeffsComparer.Compare(currentValue, this.coeffsField.AdditiveUnity) > 0)
                    {
                        currentValue = this.coeffsField.Multiply(
                            constraintsVector[i],
                            this.coeffsField.MultiplicativeInverse(currentValue));
                        if (this.coeffsComparer.Compare(currentValue, value) < 0)
                        {
                            result = i;
                            value  = currentValue;
                        }
                    }
                }
            }

            return(result);
        }
        /// <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);
                }
            }
        }
Ejemplo n.º 20
0
 /// <summary>
 /// Executa o algoritmo sobre a matriz.
 /// </summary>
 /// <param name="data">A matriz.</param>
 /// <returns>O determinante da matriz.</returns>
 /// <exception cref="MathematicsException">Se a matriz não for quadrada.</exception>
 public ElementsType Run(IMathMatrix <ElementsType> data)
 {
     if (data == null)
     {
         return(this.ring.AdditiveUnity);
     }
     else
     {
         var lines   = data.GetLength(0);
         var columns = data.GetLength(1);
         if (lines != columns)
         {
             throw new MathematicsException("Determinants can only be applied to square matrices.");
         }
         else
         {
             return(this.ComputeDeterminant(data));
         }
     }
 }
 /// <summary>
 /// Resolve o sistema de equações com o auxílio da decomposição LDL.
 /// </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(
     IMathMatrix <CoeffType> first,
     IMathMatrix <CoeffType> second)
 {
     if (first == null)
     {
         throw new ArgumentNullException("first");
     }
     else if (second == null)
     {
         throw new ArgumentNullException("second");
     }
     else
     {
         var squareMatrix = this.GetSymmetricMatrix(first);
         var vec          = this.GetTransformedVector(first, second);
         var solution     = this.symmSolvAlg.Run(squareMatrix, vec);
         this.TestSolution(first, second, solution);
         return(solution);
     }
 }
        /// <summary>
        /// Processa a primeira matriz.
        /// </summary>
        /// <param name="upperTriangularMatrix">A matriz triangular superior.</param>
        /// <param name="independent">O vector independente.</param>
        /// <param name="size">O tamanho das matrizes.</param>
        private IMathVector <CoeffType> ProcessFirstMatrix(
            IMathMatrix <CoeffType> upperTriangularMatrix,
            IMathMatrix <CoeffType> independent,
            int size)
        {
            var result = this.independentVectorFactory.Invoke(size);
            var field  = this.decompositionAlgorithm.Field;

            for (var j = 0; j < size; ++j)
            {
                var sumValue = field.AdditiveUnity;
                for (var i = 0; i < j; ++i)
                {
                    var value = upperTriangularMatrix[i, j];
                    if (field.IsMultiplicativeUnity(value))
                    {
                        sumValue = field.Add(
                            sumValue,
                            result[i]);
                    }
                    else
                    {
                        value = field.Multiply(
                            value,
                            result[i]);
                        sumValue = field.Add(
                            sumValue,
                            value);
                    }
                }

                sumValue  = field.AdditiveInverse(sumValue);
                result[j] = field.Add(
                    independent[j, 0],
                    sumValue);
            }

            return(result);
        }
Ejemplo n.º 23
0
 /// <summary>
 /// Cria uma nova instância de um objecto do tipo <see cref="LinearConstraintsInput{ConstraintsType}"/>.
 /// </summary>
 /// <param name="constraintsMatrix">A matriz das restrições.</param>
 /// <param name="constraintsVector">O vector dos coeficientes independentes das restrições.</param>
 public LinearConstraintsInput(
     IMathMatrix <ConstraintsType> constraintsMatrix,
     IMathVector <ConstraintsType> constraintsVector)
 {
     if (constraintsMatrix == null)
     {
         throw new ArgumentNullException("constraintsMatrix");
     }
     else if (constraintsVector == null)
     {
         throw new ArgumentNullException("constraintsVector");
     }
     else if (constraintsMatrix.GetLength(1) != constraintsVector.Length)
     {
         throw new ArgumentException("The vector length must match the constraints matrix second dimension.");
     }
     else
     {
         this.constraintsMatrix = constraintsMatrix;
         this.constraintsVector = constraintsVector;
     }
 }
        /// <summary>
        /// Vefica se o produto da matriz pelo vector actual resulta no esperado.
        /// </summary>
        /// <typeparam name="CoeffType">
        /// O tipo de objectos que constituem as entradas das estruturas.
        /// </typeparam>
        /// <param name="expected">O vector esperado.</param>
        /// <param name="matrix">a matriz.</param>
        /// <param name="field">
        /// O objecto responsável pelas operações sobre os coeficientes.
        /// </param>
        /// <param name="actual">O vector actual.</param>
        private void AssertVector <CoeffType>(
            IMathVector <CoeffType> expected,
            IMathMatrix <CoeffType> matrix,
            IMathVector <CoeffType> actual,
            IField <CoeffType> field)
        {
            var lines   = matrix.GetLength(0);
            var columns = matrix.GetLength(1);

            for (var i = 0; i < lines; ++i)
            {
                var sum = field.AdditiveUnity;
                for (var j = 0; j < columns; ++j)
                {
                    var value = field.Multiply(
                        matrix[i, j],
                        actual[j]);
                    sum = field.Add(sum, value);
                }

                Assert.AreEqual(expected[i], sum);
            }
        }
Ejemplo n.º 25
0
        /// <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;
                        });
                    }
                }
            }
        }
Ejemplo n.º 26
0
 /// <summary>
 /// Permite criar uma instância de entrada para o algoritmo do simplex na forma normal de minimização.
 /// Esta instância poderá corresponder a um estado intermédio deste 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>
 /// <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 SimplexInput(
     int[] basicVariables,
     int[] nonBasicVariables,
     IMathVector <ObjectiveCoeffType> objectiveFunction,
     ObjectiveCoeffType cost,
     IMathMatrix <ConstraintsType> constraintsMatrix,
     IMathVector <ConstraintsType> constraintsVector)
 {
     if (basicVariables == null)
     {
         throw new ArgumentNullException("basicVariables");
     }
     else if (nonBasicVariables == null)
     {
         throw new ArgumentNullException("nonBasicVariables");
     }
     else if (objectiveFunction == null)
     {
         throw new ArgumentNullException("objectiveFunction");
     }
     else if (cost == null)
     {
         throw new ArgumentNullException("cost");
     }
     else if (constraintsMatrix == null)
     {
         throw new ArgumentNullException("constraintsMatrix");
     }
     else if (constraintsVector == null)
     {
         throw new ArgumentNullException("constraintsVector");
     }
     else
     {
         if (constraintsMatrix.GetLength(0) != constraintsVector.Length)
         {
             throw new ArgumentException(
                       "Constraints matrix must have the same number of lines as constraints vector.");
         }
         else if (nonBasicVariables.Length != constraintsMatrix.GetLength(1))
         {
             throw new ArgumentException(
                       "The number of variables must be equal to the number of columns in constraints matrix.");
         }
         else if (nonBasicVariables.Length != objectiveFunction.Length)
         {
             throw new ArgumentException(
                       "The number of non basic variables must be equal to the number of coefficients in objective funcion.");
         }
         else
         {
             // Verifica a validade dos índices contidos nas variáveis básicas e não básicas.
             this.CheckVariablesIndices(basicVariables, nonBasicVariables);
             this.basicVariables    = basicVariables;
             this.nonBasicVariables = nonBasicVariables;
             this.objectiveFunction = objectiveFunction;
             this.cost = cost;
             this.constraintsMatrix = constraintsMatrix;
             this.constraintsVector = constraintsVector;
         }
     }
 }
Ejemplo n.º 27
0
        /// <summary>
        /// Obtém a variável de entrada.
        /// </summary>
        /// <param name="dualVector">O vector dual que irá permitir calcular os coeficientes do custo.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="objectiveFunction">A função objectivo.</param>
        /// <param name="nonBasicVariables">As variáveis não básicas.</param>
        /// <returns>O índice da variável a entrar.</returns>
        private int GetNextEnteringVariable(
            SimplexMaximumNumberField <CoeffType>[] dualVector,
            IMathMatrix <CoeffType> constraintsMatrix,
            IMathVector <SimplexMaximumNumberField <CoeffType> > objectiveFunction,
            int[] nonBasicVariables)
        {
            var result = -1;
            var value  = new SimplexMaximumNumberField <CoeffType>(
                this.coeffsField.AdditiveUnity,
                this.coeffsField.AdditiveUnity);
            var nonBasicLength         = nonBasicVariables.Length;
            var constraintsLinesLength = dualVector.Length;

            var syncObject = new object(); // Utilizado para sincronizar as comparações.

            Parallel.For(0, nonBasicLength, i =>
            {
                var finitePart       = this.coeffsField.AdditiveUnity;
                var bigPart          = this.coeffsField.AdditiveUnity;
                var nonBasicVariable = nonBasicVariables[i];
                if (nonBasicVariable < nonBasicLength)
                {
                    for (int j = 0; j < constraintsLinesLength; ++j)
                    {
                        var dualVectorEntry        = dualVector[j];
                        var constraintsMatrixEntry = constraintsMatrix[j, nonBasicVariable];
                        var finiteValueToAdd       = this.coeffsField.Multiply(dualVectorEntry.FinitePart, constraintsMatrixEntry);
                        var bigValueToAdd          = this.coeffsField.Multiply(dualVectorEntry.BigPart, constraintsMatrixEntry);

                        var objectiveValue = objectiveFunction[nonBasicVariable];
                        finiteValueToAdd   = this.coeffsField.Add(finiteValueToAdd, objectiveValue.FinitePart);
                        bigValueToAdd      = this.coeffsField.Add(bigValueToAdd, objectiveValue.BigPart);

                        finitePart = this.coeffsField.Add(finitePart, finiteValueToAdd);
                        bigPart    = this.coeffsField.Add(bigPart, bigValueToAdd);
                    }

                    lock (syncObject)
                    {
                        var comparisionValue = this.coeffsComparer.Compare(bigPart, value.BigPart);
                        if (comparisionValue < 0)
                        {
                            result           = i;
                            value.FinitePart = finitePart;
                            value.BigPart    = bigPart;
                        }
                        else if (comparisionValue == 0)
                        {
                            if (this.coeffsComparer.Compare(finitePart, value.FinitePart) < 0)
                            {
                                result           = i;
                                value.FinitePart = finitePart;
                                value.BigPart    = bigPart;
                            }
                        }
                    }
                }
                else
                {
                    var index     = nonBasicVariable - nonBasicLength;
                    var dualValue = dualVector[index];
                    finitePart    = dualValue.FinitePart;
                    bigPart       = dualValue.BigPart;

                    lock (syncObject)
                    {
                        var comparisionValue = this.coeffsComparer.Compare(bigPart, value.BigPart);
                        if (comparisionValue < 0)
                        {
                            result           = i;
                            value.FinitePart = finitePart;
                            value.BigPart    = bigPart;
                        }
                        else if (comparisionValue == 0)
                        {
                            if (this.coeffsComparer.Compare(finitePart, value.FinitePart) < 0)
                            {
                                result           = i;
                                value.FinitePart = finitePart;
                                value.BigPart    = bigPart;
                            }
                        }
                    }
                }
            });

            return(result);
        }
        /// <summary>
        /// Processa as restantes matrizes.
        /// </summary>
        /// <param name="upperTriangMatrix">A matriz triangular superior.</param>
        /// <param name="diagMatrix">A matriz diagonal.</param>
        /// <param name="independent">O vector independente.</param>
        /// <param name="size">O tamanho das matrizes.</param>
        /// <param name="solution">A solução do sistema.</param>
        private void ProcessRemainingMatrices(
            IMathMatrix <CoeffType> upperTriangMatrix,
            IMathMatrix <CoeffType> diagMatrix,
            IMathVector <CoeffType> independent,
            int size,
            LinearSystemSolution <CoeffType> solution)
        {
            var field     = this.decompositionAlgorithm.Field;
            var innerSize = size - 1;

            for (var i = innerSize; i >= 0; --i)
            {
                var diagValue = diagMatrix[i, i];
                if (field.IsAdditiveUnity(diagValue))
                {
                    var basisVector = this.basisVectorFactory.Invoke(
                        size,
                        field.AdditiveUnity);
                    var basisVal = field.MultiplicativeUnity;
                    basisVector[i] = basisVal;

                    for (var j = i - 1; j >= 0; --j)
                    {
                        if (!field.IsAdditiveUnity(diagMatrix[j, j]))
                        {
                            var curr = upperTriangMatrix[j, i];
                            curr = field.Multiply(
                                curr,
                                basisVal);
                            curr           = field.AdditiveInverse(curr);
                            basisVector[j] = field.Add(
                                basisVector[j],
                                curr);
                        }
                    }

                    solution.VectorSpaceBasis.Add(basisVector);
                }
                else
                {
                    var value = independent[i];
                    if (!field.IsAdditiveUnity(value))
                    {
                        for (var j = i - 1; j >= 0; --j)
                        {
                            if (!field.IsAdditiveUnity(diagMatrix[j, j]))
                            {
                                var curr = upperTriangMatrix[j, i];
                                curr = field.Multiply(
                                    curr,
                                    value);
                                curr           = field.AdditiveInverse(curr);
                                independent[j] = field.Add(
                                    independent[j],
                                    curr);
                            }
                        }
                    }

                    var basis      = solution.VectorSpaceBasis;
                    var basisCount = basis.Count;
                    for (var k = 0; k < basisCount; ++k)
                    {
                        var vec      = basis[k];
                        var basisVal = vec[i];
                        if (!field.IsAdditiveUnity(basisVal))
                        {
                            for (var j = i - 1; j >= 0; --j)
                            {
                                if (!field.IsAdditiveUnity(diagMatrix[j, j]))
                                {
                                    var curr = upperTriangMatrix[j, i];
                                    curr = field.Multiply(
                                        curr,
                                        basisVal);
                                    curr   = field.AdditiveInverse(curr);
                                    vec[j] = field.Add(
                                        vec[j],
                                        curr);
                                }
                            }
                        }
                    }
                }
            }

            solution.Vector = independent;
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Aplica a condensação a todas as linhas da matriz das restrições.
        /// </summary>
        /// <param name="enteringVariable">A variável de entrada.</param>
        /// <param name="leavingVariable">A variável de saída.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="constraintsVector">O vector das restrições.</param>
        private void ProcessReduction(
            int enteringVariable,
            int leavingVariable,
            IMathMatrix <CoeffType> constraintsMatrix,
            IMathVector <CoeffType> constraintsVector)
        {
            // Actualiza a linha pivô
            var multiplicativeProduct   = constraintsMatrix[leavingVariable, enteringVariable];
            var constraintsColumnLength = constraintsMatrix.GetLength(1);

            if (!this.coeffsField.IsMultiplicativeUnity(multiplicativeProduct))
            {
                multiplicativeProduct = this.coeffsField.MultiplicativeInverse(multiplicativeProduct);
                Parallel.For(0, enteringVariable, i =>
                {
                    constraintsMatrix[leavingVariable, i] = this.coeffsField.Multiply(
                        constraintsMatrix[leavingVariable, i],
                        multiplicativeProduct);
                });

                Parallel.For(enteringVariable + 1, constraintsColumnLength, i =>
                {
                    constraintsMatrix[leavingVariable, i] = this.coeffsField.Multiply(
                        constraintsMatrix[leavingVariable, i],
                        multiplicativeProduct);
                });

                constraintsVector[leavingVariable] = this.coeffsField.Multiply(
                    constraintsVector[leavingVariable],
                    multiplicativeProduct);

                constraintsMatrix[leavingVariable, enteringVariable] = multiplicativeProduct;
            }

            Parallel.For(0, leavingVariable, line =>
            {
                var innerMultiplicativeProduct = constraintsMatrix[line, enteringVariable];
                if (!this.coeffsField.IsAdditiveUnity(innerMultiplicativeProduct))
                {
                    innerMultiplicativeProduct = this.coeffsField.AdditiveInverse(
                        innerMultiplicativeProduct);
                    for (int column = 0; column < enteringVariable; ++column)
                    {
                        constraintsMatrix[line, column] = this.coeffsField.Add(
                            constraintsMatrix[line, column],
                            this.coeffsField.Multiply(constraintsMatrix[leavingVariable, column],
                                                      innerMultiplicativeProduct));
                    }

                    var pivotColumnValue = innerMultiplicativeProduct;
                    if (!this.coeffsField.IsMultiplicativeUnity(multiplicativeProduct))
                    {
                        pivotColumnValue = this.coeffsField.Multiply(innerMultiplicativeProduct, multiplicativeProduct);
                    }

                    constraintsMatrix[line, enteringVariable] = pivotColumnValue;

                    for (int column = enteringVariable + 1; column < constraintsColumnLength; ++column)
                    {
                        constraintsMatrix[line, column] = this.coeffsField.Add(
                            constraintsMatrix[line, column],
                            this.coeffsField.Multiply(constraintsMatrix[leavingVariable, column],
                                                      innerMultiplicativeProduct));
                    }

                    constraintsVector[line] = this.coeffsField.Add(
                        constraintsVector[line],
                        this.coeffsField.Multiply(constraintsVector[leavingVariable],
                                                  innerMultiplicativeProduct));
                }
            });

            var constraintsLineLength = constraintsMatrix.GetLength(0);

            Parallel.For(leavingVariable + 1, constraintsLineLength, line =>
            {
                var innerMultiplicativeProduct = constraintsMatrix[line, enteringVariable];
                if (!this.coeffsField.IsAdditiveUnity(innerMultiplicativeProduct))
                {
                    innerMultiplicativeProduct = this.coeffsField.AdditiveInverse(
                        constraintsMatrix[line, enteringVariable]);
                    for (int column = 0; column < enteringVariable; ++column)
                    {
                        constraintsMatrix[line, column] = this.coeffsField.Add(
                            constraintsMatrix[line, column],
                            this.coeffsField.Multiply(constraintsMatrix[leavingVariable, column],
                                                      innerMultiplicativeProduct));
                    }

                    var pivotColumnValue = innerMultiplicativeProduct;
                    if (!this.coeffsField.IsMultiplicativeUnity(multiplicativeProduct))
                    {
                        pivotColumnValue = this.coeffsField.Multiply(innerMultiplicativeProduct, multiplicativeProduct);
                    }

                    constraintsMatrix[line, enteringVariable] = pivotColumnValue;

                    for (int column = enteringVariable + 1; column < constraintsColumnLength; ++column)
                    {
                        constraintsMatrix[line, column] = this.coeffsField.Add(
                            constraintsMatrix[line, column],
                            this.coeffsField.Multiply(constraintsMatrix[leavingVariable, column],
                                                      innerMultiplicativeProduct));
                    }

                    constraintsVector[line] = this.coeffsField.Add(
                        constraintsVector[line],
                        this.coeffsField.Multiply(constraintsVector[leavingVariable],
                                                  innerMultiplicativeProduct));
                }
            });
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Aplica o método de condensação a uma matriz dependente baseando-se na matriz inicial.
        /// </summary>
        /// <remarks>
        /// As matrizes de entrada serão alteradas. No final, a matriz inicial é condensada e as mesmas operações
        /// são efectuadas sobre todas as linhas da segunda matriz.
        /// </remarks>
        /// <param name="initialMatrix">A matriz de coeficientes.</param>
        /// <param name="finalMatrix">A matriz dependente.</param>
        /// <returns>Verdadeiro caso tenha sido realizada alguma operação e falso caso contrário.</returns>
        /// <exception cref="ArgumentNullException">Se pelo menos um dos argumentos for nulo.</exception>
        /// <exception cref="MathematicsException">
        /// Se o número de linhas da matriz não conicidir com o tamanho do vector.
        /// </exception>
        public bool Run(
            IMathMatrix <ElementType> initialMatrix,
            IMathMatrix <ElementType> finalMatrix)
        {
            if (initialMatrix == null)
            {
                throw new ArgumentNullException("initialMatrix");
            }
            else if (finalMatrix == null)
            {
                throw new ArgumentNullException("finalMatrix");
            }
            else if (initialMatrix.GetLength(0) != finalMatrix.GetLength(0))
            {
                throw new MathematicsException(
                          "Linear system matrix must have the same number of lines as independent vector.");
            }
            else if (initialMatrix.GetLength(0) == 0)
            {
                return(false);
            }
            else
            {
                var result               = false;
                var initialMatrixLines   = initialMatrix.GetLength(0);
                var initialMatrixColumns = initialMatrix.GetLength(1);
                var matrixDimension      = Math.Min(initialMatrixLines, initialMatrixColumns);
                var finalMatrixColumns   = finalMatrix.GetLength(1);

                var i = 0;
                var currentPivotColumn = 0;
                while (i < initialMatrixLines - 1 && currentPivotColumn < initialMatrixColumns)
                {
                    var pivotValue = initialMatrix[i, currentPivotColumn];
                    if (this.field.IsAdditiveUnity(pivotValue))
                    {
                        var nextPivotCandidate = this.GetNextNonEmptyPivotLineNumber(
                            i,
                            currentPivotColumn,
                            initialMatrix);
                        if (nextPivotCandidate != -1)
                        {
                            initialMatrix.SwapLines(i, nextPivotCandidate);
                            finalMatrix.SwapLines(i, nextPivotCandidate);
                            pivotValue = initialMatrix[i, currentPivotColumn];
                            result     = true;
                        }
                    }

                    if (!this.field.IsAdditiveUnity(pivotValue))
                    {
                        if (!this.field.IsMultiplicativeUnity(pivotValue))
                        {
                            result = true;
                            initialMatrix[i, currentPivotColumn] = this.field.MultiplicativeUnity;
                            for (int j = currentPivotColumn + 1; j < initialMatrix.GetLength(1); ++j)
                            {
                                var value = initialMatrix[i, j];
                                if (!this.field.IsAdditiveUnity(value))
                                {
                                    value = this.field.Multiply(
                                        value,
                                        this.field.MultiplicativeInverse(pivotValue));
                                    initialMatrix[i, j] = value;
                                }
                            }

                            for (int j = 0; j < finalMatrixColumns; ++j)
                            {
                                var value = finalMatrix[i, j];
                                if (!this.field.IsAdditiveUnity(value))
                                {
                                    value = this.field.Multiply(
                                        value,
                                        this.field.MultiplicativeInverse(pivotValue));
                                    finalMatrix[i, j] = value;
                                }
                            }
                        }

                        for (int j = i + 1; j < initialMatrixLines; ++j)
                        {
                            var value = initialMatrix[j, currentPivotColumn];
                            if (!this.field.IsAdditiveUnity(value))
                            {
                                result = true;
                                initialMatrix[j, i] = this.field.AdditiveUnity;
                                for (int k = i + 1; k < matrixDimension; ++k)
                                {
                                    var temp = this.field.Multiply(value, initialMatrix[i, k]);
                                    initialMatrix[j, k] = this.field.Add(
                                        initialMatrix[j, k],
                                        this.field.AdditiveInverse(temp));
                                }

                                for (int k = 0; k < finalMatrixColumns; ++k)
                                {
                                    var temp = this.field.Multiply(value, finalMatrix[i, k]);
                                    finalMatrix[j, k] = this.field.Add(
                                        finalMatrix[j, k],
                                        this.field.AdditiveInverse(temp));
                                }
                            }
                        }

                        ++i;
                    }

                    ++currentPivotColumn;
                }

                i = Math.Min(initialMatrixLines - 1, initialMatrixColumns - 1);
                currentPivotColumn = i;
                var state = true;
                while (state)
                {
                    var currenPivotValue = initialMatrix[i, currentPivotColumn];
                    if (this.field.IsMultiplicativeUnity(currenPivotValue))
                    {
                        state = false;
                    }
                    else if (this.field.IsAdditiveUnity(currenPivotValue))
                    {
                        ++currentPivotColumn;
                        if (currentPivotColumn >= initialMatrixColumns)
                        {
                            --i;
                            if (i < 0)
                            {
                                state = false;
                            }
                            else
                            {
                                currentPivotColumn = i;
                            }
                        }
                    }
                }

                while (i > 0 && currentPivotColumn > 0)
                {
                    var pivotValue = initialMatrix[i, currentPivotColumn];
                    if (this.field.IsMultiplicativeUnity(pivotValue))
                    {
                        for (int j = i - 1; j >= 0; --j)
                        {
                            var value = initialMatrix[j, currentPivotColumn];
                            if (!this.field.IsAdditiveUnity(value))
                            {
                                result = true;
                                initialMatrix[j, currentPivotColumn] = this.field.AdditiveUnity;
                                for (int k = currentPivotColumn + 1; k < matrixDimension; ++k)
                                {
                                    var temp = this.field.Multiply(value, initialMatrix[i, k]);
                                    initialMatrix[j, k] = this.field.Add(
                                        initialMatrix[j, k],
                                        this.field.AdditiveInverse(temp));
                                }

                                for (int k = 0; k < finalMatrixColumns; ++k)
                                {
                                    var temp = this.field.Multiply(value, finalMatrix[i, k]);
                                    finalMatrix[j, k] = this.field.Add(
                                        finalMatrix[j, k],
                                        this.field.AdditiveInverse(temp));
                                }
                            }
                        }
                    }

                    --i;
                    --currentPivotColumn;
                }

                return(result);
            }
        }