コード例 #1
0
        /// <summary>
        /// Obtém o valor da estimativa a ser adicionada a cada um dos nós durante o algoritmo.
        /// </summary>
        /// <param name="input">Os dados de entrada.</param>
        /// <param name="line">A linha correspondente ao nó de cobertura.</param>
        /// <param name="component">A matriz dos custos.</param>
        /// <returns>O valor da estimativa.</returns>
        private ElementType GetBigDelta(
            DualHeuristicAlgInput <ElementType> input,
            KeyValuePair <int, ILongSparseMatrixLine <ElementType> > line,
            SparseDictionaryMathMatrix <ElementType> component)
        {
            var result = this.ring.Add(input.Gamma, this.ring.AdditiveInverse(input.Taus[line.Key]));

            foreach (var otherLine in component.GetLines())
            {
                if (otherLine.Key != line.Key)
                {
                    if (otherLine.Value.ContainsColumn(line.Key))
                    {
                        var currentCost   = otherLine.Value[line.Key];
                        var currentLambda = input.Lambdas[line.Key];
                        if (this.comparer.Compare(currentLambda, currentCost) >= 0)
                        {
                            var difference = this.ring.Add(
                                input.Gamma,
                                this.ring.AdditiveInverse(input.Taus[otherLine.Key]));
                            if (this.comparer.Compare(difference, result) < 0)
                            {
                                result = difference;
                            }
                        }
                    }
                }
            }

            return(result);
        }
コード例 #2
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);
        }
コード例 #3
0
        /// <summary>
        /// Constrói uma matriz de teste na qual o valor por defeito é nulo.
        /// </summary>
        /// <remarks>
        ///     - 1 - 2 -
        ///     - 3 - 4 -
        ///     1 2 - - 3
        ///     - - - - -
        ///     3 1 4 5 2
        /// </remarks>
        /// <param name="defaultValue">O valor por defeito.</param>
        /// <returns>A matriz de teste.</returns>
        private SparseDictionaryMathMatrix <Fraction <int> > GetDefaultMatrix(Fraction <int> defaultValue)
        {
            var result        = new SparseDictionaryMathMatrix <Fraction <int> >(5, 5, defaultValue);
            var integerDomain = new IntegerDomain();

            // Primeira linha.
            result[0, 1] = new Fraction <int>(1, 1, integerDomain);
            result[0, 3] = new Fraction <int>(1, 1, integerDomain);

            // Segunda linha.
            result[1, 1] = new Fraction <int>(3, 1, integerDomain);
            result[1, 3] = new Fraction <int>(4, 1, integerDomain);

            // Terceira linha.
            result[2, 0] = new Fraction <int>(1, 1, integerDomain);
            result[2, 1] = new Fraction <int>(2, 1, integerDomain);
            result[2, 4] = new Fraction <int>(3, 1, integerDomain);

            // Quinta linha.
            result[4, 0] = new Fraction <int>(3, 1, integerDomain);
            result[4, 1] = new Fraction <int>(1, 1, integerDomain);
            result[4, 2] = new Fraction <int>(4, 1, integerDomain);
            result[4, 3] = new Fraction <int>(5, 1, integerDomain);
            result[4, 4] = new Fraction <int>(2, 1, integerDomain);

            return(result);
        }
コード例 #4
0
        private ElementType GetMinimumSum(
            IntegerSequence chosenReferences,
            SparseDictionaryMathMatrix <ElementType> currentMatrix,
            ElementType[] currentLineBoard,
            IEnumerable <KeyValuePair <int, ILongSparseMatrixLine <ElementType> > > lines,
            int chosenSolution)
        {
            var sum           = this.ring.AdditiveUnity;
            var solutionValue = chosenReferences[chosenSolution];
            var minimumCover  = GetMinimumCover(chosenReferences, lines, solutionValue);

            sum = this.ring.Add(sum, minimumCover);

            var columns = currentMatrix.GetColumns(solutionValue);

            foreach (var column in columns)
            {
                if (column.Key != solutionValue)
                {
                    var currentValue = currentMatrix[solutionValue, column.Key];
                    if (this.ring.Equals(currentValue, currentLineBoard[column.Key]))
                    {
                        minimumCover = this.GetMinimumCover(
                            chosenReferences,
                            lines,
                            column.Key);

                        minimumCover = this.ring.Add(minimumCover, this.ring.AdditiveInverse(currentValue));
                        sum          = this.ring.Add(sum, minimumCover);
                    }
                }
            }

            return(sum);
        }
コード例 #5
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);
        }
コード例 #6
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;
            }
        }
コード例 #7
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]);
                }
            }
        }
コード例 #8
0
 /// <summary>
 /// Aplica o algoritmo dual aos dados de entrada para um determinado número de referências.
 /// </summary>
 /// <remarks>
 /// Os dados de entrada são alterados pelo algoritmo e podem ser reutilizados em fases posteriores.
 /// O valor de gama tem de ser previamente estimado.
 /// </remarks>
 /// <param name="refsNumber">O número de referências.</param>
 /// <param name="matrix">A matriz com os custos.</param>
 /// <param name="input">Os dados de entrada.</param>
 /// <returns>O custo aproximado pela heurística.</returns>
 public ElementType Run(
     int refsNumber,
     SparseDictionaryMathMatrix <ElementType> matrix,
     DualHeuristicAlgInput <ElementType> input)
 {
     if (refsNumber < 1)
     {
         throw new ArgumentException("The number of references must be at least one.");
     }
     else if (matrix == null)
     {
         throw new ArgumentNullException("matrix");
     }
     else if (input == null)
     {
         throw new ArgumentNullException("input");
     }
     else
     {
         this.dualGammaEstimAlgorithm.Run(matrix, input);
         return(this.Process(refsNumber, matrix, input));
     }
 }
コード例 #9
0
        /// <summary>
        /// Obtém uma solução corrigida a partir de uma inicial.
        /// </summary>
        /// <param name="refsNumber">O número de referências.</param>
        /// <param name="matrix">A matriz.</param>
        /// <param name="initialSolution">A solução inicial.</param>
        /// <param name="initialLineBoard">A linha condensada inicial.</param>
        /// <returns>
        /// A solução obtida.
        /// </returns>
        public GreedyAlgSolution <ElementType> Run(
            int refsNumber,
            SparseDictionaryMathMatrix <ElementType> matrix,
            GreedyAlgSolution <ElementType> initialSolution,
            ElementType[] initialLineBoard)
        {
            if (refsNumber < 1)
            {
                throw new ArgumentException("The number of references must be at least one.");
            }
            else if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }
            else if (initialSolution == null)
            {
                throw new ArgumentNullException("initialSolution");
            }
            else if (initialLineBoard == null)
            {
                throw new ArgumentNullException("initialLineBoard");
            }
            else
            {
                var greedyAlgResult   = initialSolution.Clone();
                var initialRefsNumber = greedyAlgResult.Chosen.Count;

                if (refsNumber < initialRefsNumber)
                {
                    var refGetAlg = this.inverseRefGetAlgorithm;
                    while (refsNumber < initialRefsNumber)
                    {
                        var nextRef = refGetAlg.Run(greedyAlgResult.Chosen, matrix, initialLineBoard);
                        if (nextRef.Item1 == -1)
                        {
                            return(null);
                        }
                        else
                        {
                            greedyAlgResult.Chosen.Remove(greedyAlgResult.Chosen[nextRef.Item1]);
                            greedyAlgResult.Cost = this.ring.Add(greedyAlgResult.Cost, nextRef.Item2);
                        }
                    }
                }
                else if (refsNumber > initialRefsNumber)
                {
                    var refGetAlg = this.directRefGetAlgorithm;
                    var nextRef   = refGetAlg.Run(greedyAlgResult.Chosen, matrix, initialLineBoard);
                    if (nextRef.Item1 == -1)
                    {
                        return(null);
                    }
                    else
                    {
                        greedyAlgResult.Chosen.Remove(greedyAlgResult.Chosen[nextRef.Item1]);
                        greedyAlgResult.Cost = this.ring.Add(
                            greedyAlgResult.Cost,
                            this.ring.AdditiveInverse(nextRef.Item2));
                    }
                }

                return(greedyAlgResult);
            }
        }
コード例 #10
0
        /// <summary>
        /// Obtém os valores iniciais das variáveis lambda.
        /// </summary>
        /// <param name="matrix">A matriz dos custos.</param>
        /// <param name="greedySolution">A solução do algoritmo guloso.</param>
        /// <param name="dualInput">A entrada para o algoritmo dual propriamente dito.</param>
        /// <returns>Verdadeiro caso o algoritmo seja bem sucedido e falso caso contrário.</returns>
        public bool Run(
            SparseDictionaryMathMatrix <ElementType> matrix,
            GreedyAlgSolution <ElementType> greedySolution,
            DualHeuristicAlgInput <ElementType> dualInput)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }
            else if (greedySolution == null)
            {
                throw new ArgumentNullException("greedySolution");
            }
            else if (dualInput == null)
            {
                throw new ArgumentNullException("dualInput");
            }
            else
            {
                dualInput.Lambdas.Clear();
                var componentEnum = matrix.GetLines().GetEnumerator();
                if (componentEnum.MoveNext())
                {
                    dualInput.Lambdas.Add(componentEnum.Current.Key, this.ring.AdditiveUnity);
                    foreach (var column in componentEnum.Current.Value.GetColumns())
                    {
                        if (column.Key != componentEnum.Current.Key)
                        {
                            if (greedySolution.Chosen.Contains(column.Key))
                            {
                                dualInput.Lambdas.Add(column.Key, this.ring.AdditiveUnity);
                            }
                            else
                            {
                                dualInput.Lambdas.Add(column.Key, column.Value);
                            }
                        }
                    }

                    while (componentEnum.MoveNext())
                    {
                        if (greedySolution.Chosen.Contains(componentEnum.Current.Key))
                        {
                            foreach (var column in componentEnum.Current.Value.GetColumns())
                            {
                                if (column.Key != componentEnum.Current.Key)
                                {
                                    var forComponentValue = this.ring.AdditiveUnity;
                                    if (dualInput.Lambdas.TryGetValue(column.Key, out forComponentValue))
                                    {
                                        if (this.comparer.Compare(column.Value, forComponentValue) < 0)
                                        {
                                            dualInput.Lambdas[column.Key] = column.Value;
                                        }
                                    }
                                    else
                                    {
                                        dualInput.Lambdas.Add(column.Key, this.ring.AdditiveUnity);
                                    }
                                }
                            }
                        }
                    }
                }

                return(true);
            }
        }
コード例 #11
0
        /// <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);
            }
        }
コード例 #12
0
        /// <summary>
        /// Realiza as iterações de melhoramento sobre os dados aproximados inicialmente.
        /// </summary>
        /// <param name="refsNumber">O número de referências.</param>
        /// <param name="matrix">A matriz dos custos.</param>
        /// <param name="input">Os dados de entrada.</param>
        /// <returns>O valor do custo dual.</returns>
        private ElementType Process(
            int refsNumber,
            SparseDictionaryMathMatrix <ElementType> matrix,
            DualHeuristicAlgInput <ElementType> input)
        {
            var multiplicativeSymmetric = this.ring.AdditiveInverse(this.ring.MultiplicativeUnity);
            var delta = this.ring.AdditiveUnity;

            while (!this.ring.IsMultiplicativeUnity(delta))
            {
                foreach (var line in matrix.GetLines())
                {
                    var bigDelta = this.GetBigDelta(
                        input,
                        line,
                        matrix);

                    var currentLambda = input.Lambdas[line.Key];
                    if (input.Cbar.ContainsKey(line.Key))
                    {
                        var value = this.ring.Add(
                            input.Cbar[line.Key],
                            this.ring.AdditiveInverse(currentLambda));
                        if (this.comparer.Compare(value, bigDelta) < 0)
                        {
                            bigDelta = value;
                            delta    = this.ring.MultiplicativeUnity;
                            input.Cbar.Remove(line.Key);

                            // TODO: cbar = min(u que cobre line tal que o custo é maior que lambda[line]
                            foreach (var coverLine in matrix.GetLines())
                            {
                                if (coverLine.Key != line.Key)
                                {
                                    if (coverLine.Value.ContainsColumn(line.Key))
                                    {
                                        var currentCost = coverLine.Value[line.Key];
                                        var compareCost = this.ring.Add(currentLambda, bigDelta);
                                        if (this.comparer.Compare(compareCost, currentCost) < 0)
                                        {
                                            var currentCbar = this.ring.AdditiveUnity;
                                            if (input.Cbar.TryGetValue(line.Key, out currentCbar))
                                            {
                                                if (this.comparer.Compare(currentCost, currentCbar) < 0)
                                                {
                                                    input.Cbar[line.Key] = currentCost;
                                                }
                                            }
                                            else
                                            {
                                                input.Cbar.Add(line.Key, currentCost);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    if (this.comparer.Compare(this.ring.AdditiveUnity, bigDelta) < 0)
                    {
                        foreach (var coveringLine in matrix.GetLines())
                        {
                            if (coveringLine.Key != line.Key)
                            {
                                if (coveringLine.Value.ContainsColumn(line.Key))
                                {
                                    if (this.comparer.Compare(coveringLine.Value[line.Key], currentLambda) <= 0)
                                    {
                                        input.Taus[coveringLine.Key] = this.ring.Add(
                                            input.Taus[coveringLine.Key],
                                            bigDelta);
                                    }
                                }
                            }
                        }

                        input.Lambdas[line.Key] = this.ring.Add(input.Lambdas[line.Key], bigDelta);
                        input.Taus[line.Key]    = this.ring.Add(input.Taus[line.Key], bigDelta);
                    }
                }
            }

            var result = this.ring.AdditiveUnity;
            var prod   = this.ring.AddRepeated(input.Gamma, refsNumber);

            foreach (var line in matrix.GetLines())
            {
                result = this.ring.Add(result, input.Lambdas[line.Key]);
            }

            result = this.ring.Add(result, this.ring.AdditiveInverse(prod));
            return(result);
        }
コード例 #13
0
        public ElementType Run(
            SparseDictionaryMathMatrix <ElementType> matrix,
            DualHeuristicAlgInput <ElementType> input)
        {
            if (matrix == null)
            {
                throw new ArgumentNullException("matrix");
            }
            else if (input == null)
            {
                throw new ArgumentNullException("input");
            }
            else
            {
                input.Taus.Clear();
                var result = new Dictionary <int, ElementType>();
                input.Gamma = this.ring.AdditiveUnity;
                var currentGamma = this.ring.AdditiveUnity;
                foreach (var line in matrix.GetLines())
                {
                    // Setup the tau and cbar values
                    var tempTau = input.Lambdas[line.Key];
                    foreach (var coveredLine in line.Value.GetColumns())
                    {
                        if (coveredLine.Key != line.Key)
                        {
                            var difference = this.ring.Add(
                                input.Lambdas[coveredLine.Key],
                                this.ring.AdditiveInverse(coveredLine.Value));
                            if (this.comparer.Compare(difference, this.ring.AdditiveUnity) < 0)
                            {
                                tempTau = this.ring.Add(tempTau, difference);
                            }
                        }
                    }

                    if (this.comparer.Compare(input.Gamma, tempTau) < 0)
                    {
                        input.Gamma = tempTau;
                    }

                    if (this.comparer.Compare(currentGamma, tempTau) < 0)
                    {
                        currentGamma = tempTau;
                    }

                    input.Taus.Add(line.Key, tempTau);
                }

                foreach (var line in matrix.GetLines())
                {
                    foreach (var coveredLine in line.Value.GetColumns())
                    {
                        if (coveredLine.Key != line.Key)
                        {
                            var tempCbarValue = this.ring.Add(
                                coveredLine.Value,
                                this.ring.AdditiveInverse(input.Lambdas[coveredLine.Key]));
                            if (this.comparer.Compare(this.ring.AdditiveUnity, tempCbarValue) < 0)
                            {
                                var currentCbarInCoveredVertice = this.ring.AdditiveUnity;
                                if (input.Cbar.TryGetValue(coveredLine.Key, out currentCbarInCoveredVertice))
                                {
                                    if (this.comparer.Compare(tempCbarValue, currentCbarInCoveredVertice) < 0)
                                    {
                                        input.Cbar[coveredLine.Key] = coveredLine.Value;
                                    }
                                }
                                else
                                {
                                    input.Cbar.Add(coveredLine.Key, coveredLine.Value);
                                }
                            }
                        }
                    }
                }

                return(currentGamma);
            }
        }
コード例 #14
0
        /// <summary>
        /// Escolhe a referência que minimiza a perda.
        /// </summary>
        /// <param name="chosenReferences">As referências escolhidas anteriormente.</param>
        /// <param name="currentMatrix">A matriz dos custos.</param>
        /// <param name="currentLineBoard">A linha que contém a condensação dos custos das linhas escolhidas.</param>
        /// <returns>O índice da linha correspondente à próxima referência bem como a perda respectiva.</returns>
        public Tuple <int, ElementType> Run(
            IntegerSequence chosenReferences,
            SparseDictionaryMathMatrix <ElementType> currentMatrix,
            ElementType[] currentLineBoard)
        {
            var result             = -1;
            var currentMinimumLost = default(ElementType);
            var lines = currentMatrix.GetLines();

            if (chosenReferences.Count > 2)
            {
                currentMinimumLost = this.GetMinimumSum(
                    chosenReferences,
                    currentMatrix,
                    currentLineBoard,
                    lines,
                    2);
                result = 2;
            }

            Parallel.For(2, chosenReferences.Count,
                         chosenSolution =>
            {
                var sum = this.GetMinimumSum(
                    chosenReferences,
                    currentMatrix,
                    currentLineBoard,
                    lines,
                    chosenSolution);

                lock (this.lockObject)
                {
                    if (this.comparer.Compare(sum, currentMinimumLost) < 0)
                    {
                        currentMinimumLost = sum;
                        result             = chosenSolution;
                    }
                }
            });

            if (result != -1)
            {
                var solutionValue = chosenReferences[result];
                var minimumCover  = this.GetMinimumCover(
                    chosenReferences,
                    lines,
                    solutionValue);

                currentLineBoard[solutionValue] = minimumCover;

                var columns = currentMatrix.GetColumns(solutionValue);
                foreach (var column in columns)
                {
                    if (column.Key != solutionValue)
                    {
                        var currentValue = currentMatrix[solutionValue, column.Key];
                        if (this.ring.Equals(currentValue, currentLineBoard[column.Key]))
                        {
                            minimumCover = this.GetMinimumCover(
                                chosenReferences,
                                lines,
                                solutionValue);

                            currentLineBoard[column.Key] = minimumCover;
                        }
                    }
                }
            }

            return(Tuple.Create(result, currentMinimumLost));
        }