private ElementType GetMinimumCover(
            IntegerSequence chosenReferences,
            IEnumerable <KeyValuePair <int, ILongSparseMatrixLine <ElementType> > > lines,
            int solutionValue)
        {
            var minimumCover   = default(ElementType);
            var lineEnumerator = lines.GetEnumerator();
            var status         = lineEnumerator.MoveNext();

            if (status)
            {
                var line = lineEnumerator.Current;
                if (line.Key != solutionValue &&
                    chosenReferences.Contains(line.Key) &&
                    line.Value.ContainsColumn(solutionValue))
                {
                    minimumCover = line.Value[solutionValue];
                }
                else
                {
                    status = lineEnumerator.MoveNext();
                    while (status &&
                           (line.Key == solutionValue ||
                            !chosenReferences.Contains(line.Key) ||
                            !line.Value.ContainsColumn(solutionValue)))
                    {
                        status = lineEnumerator.MoveNext();
                    }
                }

                while (status)
                {
                    line = lineEnumerator.Current;
                    if (line.Key != solutionValue &&
                        chosenReferences.Contains(line.Key) &&
                        line.Value.ContainsColumn(solutionValue))
                    {
                        var compareValue = line.Value[solutionValue];
                        if (this.comparer.Compare(compareValue, minimumCover) < 0)
                        {
                            minimumCover = compareValue;
                        }
                    }
                }
            }

            return(minimumCover);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Escolhe a referência que maximiza o ganho.
        /// </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 corresponde à próxima referência bem como o ganho respectivo.</returns>
        public Tuple <int, ElementType> Run(
            IntegerSequence chosenReferences,
            ILongSparseMathMatrix <ElementType> currentMatrix,
            ElementType[] currentLineBoard)
        {
            var result         = default(KeyValuePair <int, ILongSparseMatrixLine <ElementType> >);
            var lines          = currentMatrix.GetLines();
            var currentMaxGain = this.ring.AdditiveInverse(this.ring.MultiplicativeUnity);
            var foundRef       = false;

            Parallel.ForEach(lines,
                             line =>
            {
                if (!chosenReferences.Contains(line.Key))
                {
                    var sum = this.ring.AdditiveUnity;

                    foreach (var column in line.Value)
                    {
                        if (column.Key != line.Key)
                        {
                            var currentValue = column.Value;
                            if (this.comparer.Compare(currentValue, currentLineBoard[column.Key]) < 0)
                            {
                                var difference = this.ring.Add(
                                    currentLineBoard[column.Key],
                                    this.ring.AdditiveInverse(currentValue));
                                sum = this.ring.Add(sum, difference);
                            }
                        }
                        else
                        {
                            sum = this.ring.Add(sum, currentLineBoard[column.Key]);
                        }
                    }

                    lock (this.lockObject)
                    {
                        if (this.comparer.Compare(currentMaxGain, sum) < 0)
                        {
                            currentMaxGain = sum;
                            result         = line;
                            foundRef       = true;
                        }
                    }
                }
            });

            if (foundRef)
            {
                foreach (var column in result.Value.GetColumns())
                {
                    if (column.Key != result.Key)
                    {
                        if (this.comparer.Compare(column.Value, currentLineBoard[column.Key]) < 0)
                        {
                            currentLineBoard[column.Key] = column.Value;
                        }
                    }
                    else
                    {
                        currentLineBoard[column.Key] = this.ring.AdditiveUnity;
                    }
                }

                return(Tuple.Create(result.Key, currentMaxGain));
            }
            else
            {
                return(Tuple.Create(-1, currentMaxGain));
            }
        }
        /// <summary>
        /// Permite calcular o custo associado à escolha de um conjunto de medianas escolhidas.
        /// </summary>
        /// <param name="chosen">O conjunto de medianas escolhidas.</param>
        /// <param name="costs">A matriz dos custos.</param>
        /// <param name="solutionBoard">A linha que mantém os mínimos por mediana.</param>
        /// <returns>O valor do custo associado à escolha.</returns>
        private CoeffType ComputeCost(
            IntegerSequence chosen,
            ILongSparseMathMatrix <CoeffType> costs,
            CoeffType[] solutionBoard,
            BitArray marked)
        {
            var resultCost = this.coeffsField.AdditiveUnity;

            foreach (var item in chosen)
            {
                var currentCostLine = default(ILongSparseMatrixLine <CoeffType>);
                if (costs.TryGetLine(item, out currentCostLine))
                {
                    foreach (var column in currentCostLine.GetColumns())
                    {
                        if (column.Key == item)
                        {
                            if (marked[item])
                            {
                                resultCost = this.coeffsField.Add(
                                    resultCost,
                                    this.coeffsField.AdditiveInverse(solutionBoard[item]));
                            }
                            else
                            {
                                marked[item] = true;
                            }

                            solutionBoard[item] = this.coeffsField.AdditiveUnity;
                        }
                        else
                        {
                            if (marked[column.Key])
                            {
                                var boardCost = solutionBoard[column.Key];
                                if (this.comparer.Compare(column.Value, boardCost) < 0)
                                {
                                    solutionBoard[column.Key] = column.Value;
                                    var difference = this.coeffsField.Add(
                                        column.Value,
                                        this.coeffsField.AdditiveInverse(boardCost));
                                    resultCost = this.coeffsField.Add(
                                        resultCost,
                                        difference);
                                }
                            }
                            else
                            {
                                resultCost = this.coeffsField.Add(
                                    resultCost,
                                    column.Value);
                                solutionBoard[column.Key] = column.Value;
                                marked[column.Key]        = true;
                            }
                        }
                    }
                }
                else
                {
                    marked[item]        = true;
                    solutionBoard[item] = this.coeffsField.AdditiveUnity;
                }
            }

            for (int i = 0; i < marked.Length; ++i)
            {
                if (!marked[i] && !chosen.Contains(i))
                {
                    throw new OdmpProblemException("Not all nodes are covered by some median.");
                }
            }

            return(resultCost);
        }