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); }
/// <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); }