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

                    return(result);
                }
            }
        }
        /// <summary>
        /// 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;
        }
        /// <summary>
        /// Obtém os valores da solução.
        /// </summary>
        /// <param name="solution">A solução do sistema modular.</param>
        /// <param name="matrixList">A matriz.</param>
        /// <param name="primesList">A lista dos números primos da base.</param>
        /// <param name="innerData">O número que está a ser factorizado.</param>
        /// <returns>Os factores.</returns>
        private Tuple <NumberType, NumberType> GetSolution(
            LinearSystemSolution <int> solution,
            List <int[]> matrixList,
            List <int> primesList,
            NumberType innerData)
        {
            var innerDataModularField = this.modularFieldFactory.CreateInstance(innerData);
            var countFactors          = primesList.Count - 1;

            foreach (var solutionBase in solution.VectorSpaceBasis)
            {
                var firstValue   = this.integerNumber.MultiplicativeUnity;
                var factorsCount = new Dictionary <int, int>();
                for (int i = 0; i < matrixList.Count; ++i)
                {
                    var currentMatrixLine = matrixList[i];
                    if (solutionBase[i] == 1)
                    {
                        firstValue = innerDataModularField.Multiply(
                            firstValue,
                            this.integerNumber.GetNorm(this.integerNumber.MapFrom(currentMatrixLine[currentMatrixLine.Length - 1])));

                        for (int j = 0; j < countFactors; ++j)
                        {
                            if (currentMatrixLine[j] != 0)
                            {
                                var countValue = 0;
                                if (factorsCount.TryGetValue(primesList[j], out countValue))
                                {
                                    countValue += currentMatrixLine[j];
                                    factorsCount[primesList[j]] = countValue;
                                }
                                else
                                {
                                    factorsCount.Add(primesList[j], currentMatrixLine[j]);
                                }
                            }
                        }
                    }
                }

                var secondValue = this.integerNumber.MultiplicativeUnity;
                foreach (var factorCountKvp in factorsCount)
                {
                    var primePower = MathFunctions.Power(
                        this.integerNumber.MapFrom(factorCountKvp.Key),
                        factorCountKvp.Value / 2,
                        innerDataModularField);

                    secondValue = innerDataModularField.Multiply(
                        secondValue,
                        primePower);
                }

                if (!this.integerNumber.Equals(firstValue, secondValue))
                {
                    var firstFactor = MathFunctions.GreatCommonDivisor(
                        innerData,
                        this.integerNumber.GetNorm(this.integerNumber.Add(firstValue, this.integerNumber.AdditiveInverse(secondValue))),
                        this.integerNumber);
                    if (!this.integerNumber.IsMultiplicativeUnity(firstFactor))
                    {
                        var secondFactor = this.integerNumber.Quo(innerData, firstFactor);
                        return(Tuple.Create(firstFactor, secondFactor));
                    }
                }
            }

            return(Tuple.Create(this.integerNumber.MultiplicativeUnity, innerData));
        }