예제 #1
0
        /// <summary>
        /// Obtém um vector com todos os elementos de uma linha, incluindo os valores por defeito.
        /// </summary>
        /// <typeparam name="T">O tipo de objectos que constituem as entradas da matriz.</typeparam>
        /// <param name="line">A linha.</param>
        /// <param name="matrix">A matriz.</param>
        /// <returns>O vector com as entradas correspondentes à linha da matriz especificada.</returns>
        private T[] GetLineAsArray <T>(int line, SparseDictionaryMathMatrix <T> matrix)
        {
            var matrixColumnsNumber = matrix.GetLength(1);
            var currentMatrixLine   = default(ILongSparseMatrixLine <T>);
            var result = new T[matrixColumnsNumber];

            if (matrix.TryGetLine(line, out currentMatrixLine))
            {
                for (int i = 0; i < matrixColumnsNumber; ++i)
                {
                    var currentValue = default(T);
                    if (currentMatrixLine.TryGetColumnValue(i, out currentValue))
                    {
                        result[i] = currentMatrixLine[i];
                    }
                    else
                    {
                        result[i] = matrix.DefaultValue;
                    }
                }
            }
            else
            {
                for (int i = 0; i < result.Length; ++i)
                {
                    result[i] = matrix.DefaultValue;
                }
            }

            return(result);
        }
예제 #2
0
        /// <summary>
        /// Verifica a validade da combinação de uma linha com a próxima tendo em conta os factores proporcionados.
        /// </summary>
        /// <typeparam name="T">O tipo de objectos que constituem as entradas das matrizes.</typeparam>
        /// <param name="target">A matriz.</param>
        /// <param name="firstFactor">O factor afecto à linha a ser substituída.</param>
        /// <param name="secondFactor">O factor afecto à linha a ser combinada.</param>
        /// <param name="ring">O anel responsável pelas operações sobre os coeficientes.</param>
        private void AssertTarget <T>(
            SparseDictionaryMathMatrix <T> target,
            T firstFactor,
            T secondFactor,
            IRing <T> ring)
        {
            var numberOfLines   = target.GetLength(0);
            var numberOfColumns = target.GetLength(1);

            var firstLine  = 0;
            var secondLine = 1;

            while (secondLine < numberOfLines)
            {
                var firstArray  = this.GetLineAsArray(firstLine, target);
                var secondArray = this.GetLineAsArray(secondLine, target);
                this.CombineArrays(firstArray, secondArray, firstFactor, secondFactor, ring);

                target.CombineLines(firstLine, secondLine, firstFactor, secondFactor, ring);

                var targetLine = default(ILongSparseMatrixLine <T>);
                if (target.TryGetLine(firstLine, out targetLine))
                {
                    for (int i = 0; i < numberOfColumns; ++i)
                    {
                        var targetValue = default(T);
                        if (!targetLine.TryGetColumnValue(i, out targetValue))
                        {
                            targetValue = target.DefaultValue;
                        }

                        Assert.AreEqual(firstArray[i], targetValue);
                    }
                }
                else
                {
                    for (int i = 0; i < numberOfColumns; ++i)
                    {
                        Assert.AreEqual(firstArray[i], target.DefaultValue);
                    }
                }

                ++firstLine;
                ++secondLine;
            }
        }
예제 #3
0
        /// <summary>
        /// Verifica a validade de todas as linhas com excepção da linha especificada.
        /// </summary>
        /// <param name="line">A linha a ser ignorada.</param>
        /// <param name="matrix">A matriz a ser verificada.</param>
        private void AssertLinesExcept(int line, SparseDictionaryMathMatrix <Fraction <int> > matrix)
        {
            var lineDimension   = matrix.GetLength(0);
            var columnDimension = matrix.GetLength(1);
            var assertMatrix    = this.GetDefaultMatrix(matrix.DefaultValue);

            for (int i = 0; i < line; ++i)
            {
                for (int j = 0; j < columnDimension; ++j)
                {
                    Assert.AreEqual(assertMatrix[i, j], matrix[i, j]);
                }
            }

            for (int i = line + 1; i < lineDimension; ++i)
            {
                for (int j = 0; j < columnDimension; ++j)
                {
                    Assert.AreEqual(assertMatrix[i, j], matrix[i, j]);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Obtém o custo inicial da matriz especificada.
        /// </summary>
        /// <param name="matrix">A matriz.</param>
        /// <returns>O custo.</returns>
        private ElementType GetMatrixInitialCost(SparseDictionaryMathMatrix <ElementType> matrix)
        {
            var result = this.ring.AdditiveUnity;

            if (matrix.GetLength(0) > 0)
            {
                var firstLine    = matrix[0];
                var coverColumns = firstLine.GetColumns();
                foreach (var column in coverColumns)
                {
                    result = this.ring.Add(result, column.Value);
                }
            }

            return(result);
        }
        /// <summary>
        /// Aplica o algoritmo sobre a matriz dos custos.
        /// </summary>
        /// <param name="costs">A matriz dos custos.</param>
        /// <param name="numberOfMedians">O número de medianas a serem escolhidas.</param>
        /// <returns>O resultado da relaxação.</returns>
        public CoeffType[] Run(SparseDictionaryMathMatrix <CoeffType> costs, int numberOfMedians)
        {
            if (costs == null)
            {
                throw new ArgumentNullException("costs");
            }
            else
            {
                var numberOfVertices  = costs.GetLength(1);
                var objectiveFunction = new List <SimplexMaximumNumberField <CoeffType> >();

                // A mediana que cobre todas as outras é ligeiramente diferente
                objectiveFunction.Add(new SimplexMaximumNumberField <CoeffType>(
                                          this.coeffsField.AdditiveUnity,
                                          this.coeffsField.AdditiveInverse(this.coeffsField.MultiplicativeUnity)));

                for (int i = 1; i < numberOfVertices; ++i)
                {
                    objectiveFunction.Add(new SimplexMaximumNumberField <CoeffType>(
                                              this.coeffsField.AdditiveUnity,
                                              this.coeffsField.AddRepeated(
                                                  this.coeffsField.AdditiveInverse(this.coeffsField.MultiplicativeUnity),
                                                  2)));
                }

                // Adiciona as variáveis x à função objectivo.
                var numberXVars = 0;
                foreach (var line in costs.GetLines())
                {
                    foreach (var column in line.Value.GetColumns())
                    {
                        if (line.Key != column.Key)
                        {
                            ++numberXVars;
                            var valueToAdd = new SimplexMaximumNumberField <CoeffType>(
                                column.Value,
                                this.coeffsField.AdditiveInverse(this.coeffsField.MultiplicativeUnity));
                            objectiveFunction.Add(valueToAdd);
                        }
                    }
                }

                // Cria a matriz das restrições e preenche-a com os valores correctos
                var constraintsNumber = numberXVars + numberOfVertices;
                var nonBasicVariables = new int[objectiveFunction.Count];
                var basicVariables    = new int[constraintsNumber];
                var linesLength       = nonBasicVariables.Length + basicVariables.Length;

                // Preence os vectores que permitem seleccionar as variáveis.
                this.FillVariablesSelectors(nonBasicVariables, basicVariables, linesLength);

                // Preencimento da matriz das restrições
                var constraintsMatrix = new ArrayMathMatrix <CoeffType>(
                    constraintsNumber,
                    constraintsNumber,
                    this.coeffsField.AdditiveUnity);

                var constraintLineNumber   = 0;
                var constraintXYLineNumber = 0;
                var unity           = this.coeffsField.MultiplicativeUnity;
                var inverseAdditive = this.coeffsField.AdditiveInverse(unity);
                foreach (var line in costs.GetLines())
                {
                    foreach (var column in line.Value.GetColumns())
                    {
                        if (line.Key != column.Key)
                        {
                            constraintsMatrix[constraintXYLineNumber, constraintLineNumber] = inverseAdditive;
                            constraintsMatrix[constraintXYLineNumber, constraintXYLineNumber + numberOfVertices] = unity;
                            ++constraintXYLineNumber;
                        }
                    }

                    ++constraintLineNumber;
                }

                var lastLine = constraintsNumber - 1;
                constraintsMatrix[lastLine, 0] = unity;
                constraintLineNumber           = numberXVars;
                for (int i = 1; i < numberOfVertices; ++i)
                {
                    constraintsMatrix[constraintLineNumber, i] = unity;
                    constraintsMatrix[lastLine, i]             = unity;
                    constraintXYLineNumber = numberOfVertices;
                    foreach (var lines in costs.GetLines())
                    {
                        foreach (var column in lines.Value.GetColumns())
                        {
                            if (lines.Key != column.Key)
                            {
                                if (column.Key == i)
                                {
                                    constraintsMatrix[constraintLineNumber, constraintXYLineNumber] = unity;
                                }

                                ++constraintXYLineNumber;
                            }
                        }
                    }

                    ++constraintLineNumber;
                }

                // Preenchimento do vector independente das restrições
                var vector = new ArrayMathVector <CoeffType>(constraintsNumber, this.coeffsField.AdditiveUnity);
                lastLine = constraintsNumber - 1;
                for (int i = numberXVars; i < lastLine; ++i)
                {
                    vector[i] = unity;
                }

                vector[lastLine] = this.conversion.InverseConversion(numberOfMedians);
                var sumVector = this.coeffsField.AdditiveUnity;
                for (int i = 0; i < vector.Length; ++i)
                {
                    sumVector = this.coeffsField.Add(sumVector, vector[i]);
                }

                sumVector = this.coeffsField.AdditiveInverse(sumVector);
                var simplexInput = new SimplexInput <CoeffType, SimplexMaximumNumberField <CoeffType> >(
                    basicVariables,
                    nonBasicVariables,
                    new ArrayMathVector <SimplexMaximumNumberField <CoeffType> >(objectiveFunction.ToArray()),
                    new SimplexMaximumNumberField <CoeffType>(this.coeffsField.AdditiveUnity, sumVector),
                    constraintsMatrix,
                    vector);

                var resultSimplexSol = this.simplexAlg.Run(simplexInput);
                var result           = new CoeffType[numberOfVertices];
                Array.Copy(resultSimplexSol.Solution, result, numberOfVertices);
                return(result);
            }
        }