/// <summary>
        /// Calcula o custo da substituição de uma mediana por outra.
        /// </summary>
        /// <param name="replacementMedian">A mediana que substitui.</param>
        /// <param name="medianToBeReplaced">A mediana que é substituída.</param>
        /// <param name="existingMedians">As medianas que forma escolhidas.</param>
        /// <param name="costs">A matriz dos custos.</param>
        /// <param name="currentSolutionBoard">O quadro de solução actual.</param>
        /// <param name="replacementSolutionBoard">O quadro da solução substituída.</param>
        /// <returns>O valor do mínimo.</returns>
        private CoeffType ComputeReplacementCost(
            int replacementMedian,
            int medianToBeReplaced,
            IntegerSequence existingMedians,
            ILongSparseMathMatrix <CoeffType> costs,
            CoeffType[] currentSolutionBoard,
            CoeffType[] replacementSolutionBoard)
        {
            Array.Copy(currentSolutionBoard, replacementSolutionBoard, currentSolutionBoard.Length);
            var result = this.coeffsField.AdditiveUnity;

            var minimum = this.GetMinimumFromColumn(
                existingMedians,
                medianToBeReplaced,
                medianToBeReplaced,
                costs);

            replacementSolutionBoard[medianToBeReplaced] = minimum;
            result = this.coeffsField.Add(result, minimum);

            var boardValue = currentSolutionBoard[replacementMedian];

            replacementSolutionBoard[replacementMedian] = this.coeffsField.AdditiveUnity;
            result = this.coeffsField.Add(
                result,
                this.coeffsField.AdditiveInverse(boardValue));

            // Remove a linha a ser substituída.
            var currentRow = default(ILongSparseMatrixLine <CoeffType>);

            if (costs.TryGetLine(medianToBeReplaced, out currentRow))
            {
                foreach (var column in currentRow.GetColumns())
                {
                    if (column.Key != medianToBeReplaced && column.Key != replacementMedian)
                    {
                        if (this.coeffsField.Equals(column.Value, replacementSolutionBoard[column.Key]))
                        {
                            var current = replacementSolutionBoard[column.Key];
                            minimum = this.GetMinimumFromColumn(
                                existingMedians,
                                medianToBeReplaced,
                                column.Key,
                                costs);
                            replacementSolutionBoard[column.Key] = minimum;
                            var temp = this.coeffsField.Add(
                                minimum,
                                this.coeffsField.AdditiveInverse(current));
                            result = this.coeffsField.Add(result, temp);
                        }
                    }
                }
            }

            // Insere a linha a substituir.
            if (costs.TryGetLine(replacementMedian, out currentRow))
            {
                foreach (var column in currentRow.GetColumns())
                {
                    if (column.Key != replacementMedian)
                    {
                        var current = replacementSolutionBoard[column.Key];
                        if (this.comparer.Compare(column.Value, current) < 0)
                        {
                            replacementSolutionBoard[column.Key] = column.Value;
                            var temp = this.coeffsField.Add(
                                column.Value,
                                this.coeffsField.AdditiveInverse(current));
                            result = this.coeffsField.Add(result, temp);
                        }
                    }
                }
            }

            return(result);
        }
        /// <summary>
        /// Permite obter o valor mínimo entre as colunas da matriz para as linhas escolhidas com excepção
        /// de uma delas.
        /// </summary>
        /// <param name="chosen">As linhas escolhidas.</param>
        /// <param name="exceptLine">
        /// A linha que não vai ser considerada.</param>
        /// <param name="column">A coluna sobre a qual é calculado o mínimo.</param>
        /// <param name="costs">A matriz dos custos.</param>
        /// <returns>O valor do custo mínimo.</returns>
        private CoeffType GetMinimumFromColumn(
            IntegerSequence chosen,
            int exceptLine,
            int column,
            ILongSparseMathMatrix <CoeffType> costs)
        {
            var result           = default(CoeffType);
            var chosenEnumerator = chosen.GetEnumerator();
            var state            = chosenEnumerator.MoveNext();
            var keep             = true;

            while (state && keep)
            {
                // Pesquisa pelo primeiro elemento.
                var currentChosen = chosenEnumerator.Current;
                if (currentChosen != exceptLine)
                {
                    var currentLine = default(ILongSparseMatrixLine <CoeffType>);
                    if (costs.TryGetLine(currentChosen, out currentLine))
                    {
                        var columnValue = default(CoeffType);
                        if (currentLine.TryGetColumnValue(column, out columnValue))
                        {
                            if (this.coeffsField.IsAdditiveUnity(columnValue))
                            {
                                return(columnValue);
                            }
                            else
                            {
                                result = columnValue;
                                keep   = false;
                            }
                        }
                    }
                }

                state = chosenEnumerator.MoveNext();
            }

            if (keep)
            {
                throw new OdmpProblemException("Something went very wrong. Check if costs matrix is valid.");
            }
            else
            {
                while (state)
                {
                    var currentChosen = chosenEnumerator.Current;
                    if (currentChosen != exceptLine)
                    {
                        var currentLine = default(ILongSparseMatrixLine <CoeffType>);
                        if (costs.TryGetLine(currentChosen, out currentLine))
                        {
                            var columnValue = default(CoeffType);
                            if (currentLine.TryGetColumnValue(column, out columnValue))
                            {
                                if (this.coeffsField.IsAdditiveUnity(columnValue))
                                {
                                    return(columnValue);
                                }
                                else
                                {
                                    if (this.comparer.Compare(columnValue, result) < 0)
                                    {
                                        result = columnValue;
                                    }
                                }
                            }
                        }
                    }

                    state = chosenEnumerator.MoveNext();
                }
            }

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