예제 #1
0
        /// <summary>
        /// Constrói a solução a partir da iteração actual.
        /// </summary>
        /// <param name="basicVariables">As variáveis básicas.</param>
        /// <param name="nonBasicVariables">As variáveis não-básicas.</param>
        /// <param name="constraintsVector">O vector das restrições.</param>
        /// <param name="cost">O custo actual.</param>
        /// <returns>A solução.</returns>
        private SimplexOutput <CoeffType> BuildSolution(
            int[] basicVariables,
            int[] nonBasicVariables,
            IMathVector <CoeffType> constraintsVector,
            SimplexMaximumNumberField <CoeffType> cost
            )
        {
            var solution    = default(CoeffType[]);
            var hasSolution = false;

            if (this.coeffsField.IsAdditiveUnity(cost.BigPart))
            {
                hasSolution = true;
                solution    = new CoeffType[nonBasicVariables.Length];
                for (int i = 0; i < solution.Length; ++i)
                {
                    solution[i] = this.coeffsField.AdditiveUnity;
                }

                for (int i = 0; i < basicVariables.Length; ++i)
                {
                    var basicVariable = basicVariables[i];
                    if (basicVariable < solution.Length)
                    {
                        solution[basicVariable] = constraintsVector[i];
                    }
                }
            }

            return(new SimplexOutput <CoeffType>(solution, cost.FinitePart, hasSolution));
        }
예제 #2
0
        /// <summary>
        /// Obtém o vector dual.
        /// </summary>
        /// <param name="nonBasicCostsIndices">Os índices dos valores com custos relativos às variáveis básicas.</param>
        /// <param name="inverseMatrix">A matriz da base inversa.</param>
        /// <param name="objectiveFunction">O vector que representa a função objectivo.</param>
        /// <param name="basicVariables">As variáveis básicas.</param>
        /// <returns>O vector dual utilizado para determinar os valores dos custos.</returns>
        private SimplexMaximumNumberField <CoeffType>[] ComputeDualVector(
            SortedSet <int> nonBasicCostsIndices,
            ISquareMathMatrix <CoeffType> inverseMatrix,
            IMathVector <SimplexMaximumNumberField <CoeffType> > objectiveFunction,
            int[] basicVariables)
        {
            var result    = new SimplexMaximumNumberField <CoeffType> [basicVariables.Length];
            var dimension = basicVariables.Length;

            Parallel.For(0, dimension, i =>
            {
                var sum = new SimplexMaximumNumberField <CoeffType>(this.coeffsField.AdditiveUnity, this.coeffsField.AdditiveUnity);
                foreach (var index in nonBasicCostsIndices)
                {
                    var objectiveValue     = objectiveFunction[basicVariables[index]];
                    var finitePart         = objectiveValue.FinitePart;
                    var bigPart            = objectiveValue.BigPart;
                    var inverseMatrixEntry = inverseMatrix[index, i];
                    finitePart             = this.coeffsField.Multiply(
                        inverseMatrixEntry,
                        this.coeffsField.AdditiveInverse(objectiveValue.FinitePart));
                    bigPart = this.coeffsField.Multiply(
                        inverseMatrixEntry,
                        this.coeffsField.AdditiveInverse(objectiveValue.BigPart));
                    sum.Add(finitePart, bigPart, this.coeffsField);
                }

                result[i] = sum;
            });

            return(result);
        }
예제 #3
0
 /// <summary>
 /// Otbém o simétrico aditivo de um número enorme.
 /// </summary>
 /// <param name="maxNumberField">O número.</param>
 /// <returns>O simétrico aditivo.</returns>
 private SimplexMaximumNumberField <CoeffType> GetAdditiveInverse(
     SimplexMaximumNumberField <CoeffType> maxNumberField)
 {
     return(new SimplexMaximumNumberField <CoeffType>(
                this.coeffsField.AdditiveInverse(maxNumberField.FinitePart),
                this.coeffsField.AdditiveInverse(maxNumberField.BigPart)));
 }
예제 #4
0
 /// <summary>
 /// Adiciona dois números enormes.
 /// </summary>
 /// <param name="firstNumber">O primeiro número.</param>
 /// <param name="secondNumber">O segundo número.</param>
 /// <returns>O resultado da soma.</returns>
 private SimplexMaximumNumberField <CoeffType> Add(
     SimplexMaximumNumberField <CoeffType> firstNumber,
     SimplexMaximumNumberField <CoeffType> secondNumber)
 {
     return(new SimplexMaximumNumberField <CoeffType>(
                this.coeffsField.Add(firstNumber.FinitePart, secondNumber.FinitePart),
                this.coeffsField.Add(firstNumber.BigPart, secondNumber.BigPart)));
 }
예제 #5
0
        /// <summary>
        /// Processa a função objectivo.
        /// </summary>
        /// <param name="enteringVariable">A variável de entrada.</param>
        /// <param name="leavingVariable">a variável de saída.</param>
        /// <param name="basicVariables">O conjunto de variáveis básicas.</param>
        /// <param name="nonBasicVariables">O conjunto de variáveis não-básicas.</param>
        /// <param name="currentCost">O custo actual.</param>
        /// <param name="objective">A função objectivo.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="constraintsVector">O vector das restrições.</param>
        /// <returns>O resultado.</returns>
        private SimplexMaximumNumberField <CoeffType> ProcessObjectiveFunction(
            int enteringVariable,
            int leavingVariable,
            int[] basicVariables,
            int[] nonBasicVariables,
            SimplexMaximumNumberField <CoeffType> currentCost,
            IMathVector <SimplexMaximumNumberField <CoeffType> > objective,
            IMathMatrix <CoeffType> constraintsMatrix,
            IMathVector <CoeffType> constraintsVector)
        {
            var result = currentCost;
            var multiplicativeProduct = this.GetAdditiveInverse(objective[enteringVariable]);

            if (!this.IsAdditiveUnity(multiplicativeProduct))
            {
                Parallel.For(0, enteringVariable, column =>
                {
                    objective[column] = this.Add(
                        objective[column],
                        this.Multiply(constraintsMatrix[leavingVariable, column],
                                      multiplicativeProduct));
                });

                var constraintsEntry = constraintsMatrix[leavingVariable, enteringVariable];
                if (this.coeffsField.IsAdditiveUnity(constraintsEntry))
                {
                    objective[enteringVariable] = multiplicativeProduct;
                }
                else
                {
                    objective[enteringVariable] = this.Multiply(
                        constraintsEntry,
                        multiplicativeProduct);
                }

                Parallel.For(enteringVariable + 1, objective.Length, column =>
                {
                    objective[column] = this.Add(
                        objective[column],
                        this.Multiply(constraintsMatrix[leavingVariable, column],
                                      multiplicativeProduct));
                });

                result = this.Add(
                    result,
                    this.Multiply(constraintsVector[leavingVariable],
                                  multiplicativeProduct));
            }

            // Troca as variáveis
            var swap = nonBasicVariables[enteringVariable];

            nonBasicVariables[enteringVariable] = basicVariables[leavingVariable];
            basicVariables[leavingVariable]     = swap;

            return(result);
        }
예제 #6
0
 /// <summary>
 /// Compara dois números enormes.
 /// </summary>
 /// <param name="firstNumber">O primeiro número a ser comparado.</param>
 /// <param name="secondNumber">O segundo número a ser comparado.</param>
 /// <returns>
 /// Os valores -1, 0 e 1 caso o primeiro número seja respectivamente menor, igual ou maior
 /// do que o segundo número.
 /// </returns>
 private int ComapareBigNumbers(
     SimplexMaximumNumberField <CoeffType> firstNumber,
     SimplexMaximumNumberField <CoeffType> secondNumber)
 {
     return(SimplexMaximumNumberField <CoeffType> .UncheckedCompare(
                firstNumber,
                secondNumber,
                this.coeffsComparer));
 }
예제 #7
0
        /// <summary>
        /// Constrói a soução final a partir dos dados.
        /// </summary>
        /// <param name="nonBasicVariables">As variáveis não básicas.</param>
        /// <param name="basicVariables">As variáveis básicas.</param>
        /// <param name="dataCost">O custo inicial.</param>
        /// <param name="dualVector">O vector dual.</param>
        /// <param name="computedConstraintsVector">O vector das restrições calculado.</param>
        /// <param name="constraintsVector">O vector das restrições.</param>
        /// <returns>A solução.</returns>
        private SimplexOutput <CoeffType> BuildSolution(
            int[] nonBasicVariables,
            int[] basicVariables,
            SimplexMaximumNumberField <CoeffType> dataCost,
            SimplexMaximumNumberField <CoeffType>[] dualVector,
            CoeffType[] computedConstraintsVector,
            IMathVector <CoeffType> constraintsVector)
        {
            var nonBasicLength = nonBasicVariables.Length;
            var basicLength    = basicVariables.Length;

            // Constrói a solução.
            CoeffType[] solution = new CoeffType[nonBasicLength];

            Parallel.For(0, basicLength, i =>
            {
                var basicVariable = basicVariables[i];
                if (basicVariable < nonBasicLength)
                {
                    solution[basicVariable] = computedConstraintsVector[i];
                }
            });

            // Calcula o custo.
            var finiteCost = this.coeffsField.AdditiveUnity;
            var bigCost    = this.coeffsField.AdditiveUnity;
            var length     = dualVector.Length;

            for (int i = 0; i < length; ++i)
            {
                var constraintsVectorValue = constraintsVector[i];
                var dualValue        = dualVector[i];
                var finiteValueToAdd = dualValue.FinitePart;
                var bigValueToAdd    = dualValue.BigPart;
                finiteValueToAdd = this.coeffsField.Multiply(finiteValueToAdd, constraintsVectorValue);
                bigValueToAdd    = this.coeffsField.Multiply(bigValueToAdd, constraintsVectorValue);
                finiteCost       = this.coeffsField.Add(finiteCost, finiteValueToAdd);
                bigCost          = this.coeffsField.Add(bigCost, bigValueToAdd);
            }

            finiteCost = this.coeffsField.Add(finiteCost, dataCost.FinitePart);
            bigCost    = this.coeffsField.Add(bigCost, dataCost.BigPart);
            if (this.coeffsField.IsAdditiveUnity(bigCost))
            {
                return(new SimplexOutput <CoeffType>(solution, finiteCost, true));
            }
            else
            {
                // A solução corresponde a um valor inifinito para o custo.
                return(new SimplexOutput <CoeffType>(solution, default(CoeffType), false));
            }
        }
예제 #8
0
        /// <summary>
        /// Permite comparar dois números grandes sem efectuar qualquer verificação dos argumentos.
        /// </summary>
        /// <remarks>
        /// A utilização é destinada aos processo internos da livraria.
        /// </remarks>
        /// <param name="first">O primeiro número a ser comparado.</param>
        /// <param name="second">O segundo número a ser comparado.</param>
        /// <param name="comparer">O comparador de coeficientes.</param>
        /// <returns>
        /// O valor 1 caso o primeiro número seja superior ao segundo, 0 se ambos forem iguais e -1 se o
        /// primeiro número for inferior ao segundo.
        /// </returns>
        internal static int UncheckedCompare(
            SimplexMaximumNumberField <ObjectType> first,
            SimplexMaximumNumberField <ObjectType> second,
            IComparer <ObjectType> comparer)
        {
            var compareValue = comparer.Compare(first.bigPart, second.bigPart);

            if (compareValue == 0)
            {
                return(comparer.Compare(first.finitePart, second.finitePart));
            }
            else
            {
                return(compareValue);
            }
        }
예제 #9
0
 /// <summary>
 /// Obtém o produto de um coeficiente por um número enorme.
 /// </summary>
 /// <param name="coeff">O coeficiente.</param>
 /// <param name="number">O número enorme.</param>
 /// <returns>O número enorme que resulta do produto.</returns>
 private SimplexMaximumNumberField <CoeffType> Multiply(
     CoeffType coeff,
     SimplexMaximumNumberField <CoeffType> number)
 {
     if (this.coeffsField.IsAdditiveUnity(coeff))
     {
         return(new SimplexMaximumNumberField <CoeffType>(
                    this.coeffsField.AdditiveUnity,
                    this.coeffsField.AdditiveUnity));
     }
     else
     {
         return(new SimplexMaximumNumberField <CoeffType>(
                    this.coeffsField.Multiply(coeff, number.FinitePart),
                    this.coeffsField.Multiply(coeff, number.BigPart)));
     }
 }
예제 #10
0
 /// <summary>
 /// Permite comparar dois números grandes.
 /// </summary>
 /// <param name="first">O primeiro número a ser comparado.</param>
 /// <param name="second">O segundo número a ser comparado.</param>
 /// <param name="comparer">O comparador de coeficientes.</param>
 /// <returns>
 /// O valor 1 caso o primeiro número seja superior ao segundo, 0 se ambos forem iguais e -1 se o
 /// primeiro número for inferior ao segundo.
 /// </returns>
 /// <exception cref="ArgumentNullException">
 /// Se algum dos dois primeiros argumentos for nulo.
 /// </exception>
 public static int Compare(
     SimplexMaximumNumberField <ObjectType> first,
     SimplexMaximumNumberField <ObjectType> second,
     IComparer <ObjectType> comparer)
 {
     if (first == null)
     {
         throw new ArgumentNullException("first");
     }
     else if (second == null)
     {
         throw new ArgumentNullException("second");
     }
     else if (comparer == null)
     {
         return(UncheckedCompare(first, second, Comparer <ObjectType> .Default));
     }
     else
     {
         return(UncheckedCompare(first, second, comparer));
     }
 }
예제 #11
0
        /// <summary>
        /// Obtém a próxima variável de entrada.
        /// </summary>
        /// <param name="data">Os dados de entrada.</param>
        /// <returns>A variável caso exista e -1 caso contrário.</returns>
        private int GetNextEnteringVariable(SimplexInput <CoeffType, SimplexMaximumNumberField <CoeffType> > data)
        {
            var result = -1;
            var value  = new SimplexMaximumNumberField <CoeffType>(
                this.coeffsField.AdditiveUnity,
                this.coeffsField.AdditiveUnity);

            var length = data.ObjectiveFunction.Length;

            for (int i = 0; i < length; ++i)
            {
                var current = data.ObjectiveFunction[i];
                if (this.coeffsComparer.Compare(current.BigPart, this.coeffsField.AdditiveUnity) <= 0)
                {
                    if (this.ComapareBigNumbers(current, value) < 0)
                    {
                        result = i;
                        value  = current;
                    }
                }
            }

            return(result);
        }
예제 #12
0
        /// <summary>
        /// Obtém a variável de entrada.
        /// </summary>
        /// <param name="dualVector">O vector dual que irá permitir calcular os coeficientes do custo.</param>
        /// <param name="constraintsMatrix">A matriz das restrições.</param>
        /// <param name="objectiveFunction">A função objectivo.</param>
        /// <param name="nonBasicVariables">As variáveis não básicas.</param>
        /// <returns>O índice da variável a entrar.</returns>
        private int GetNextEnteringVariable(
            SimplexMaximumNumberField <CoeffType>[] dualVector,
            IMathMatrix <CoeffType> constraintsMatrix,
            IMathVector <SimplexMaximumNumberField <CoeffType> > objectiveFunction,
            int[] nonBasicVariables)
        {
            var result = -1;
            var value  = new SimplexMaximumNumberField <CoeffType>(
                this.coeffsField.AdditiveUnity,
                this.coeffsField.AdditiveUnity);
            var nonBasicLength         = nonBasicVariables.Length;
            var constraintsLinesLength = dualVector.Length;

            var syncObject = new object(); // Utilizado para sincronizar as comparações.

            Parallel.For(0, nonBasicLength, i =>
            {
                var finitePart       = this.coeffsField.AdditiveUnity;
                var bigPart          = this.coeffsField.AdditiveUnity;
                var nonBasicVariable = nonBasicVariables[i];
                if (nonBasicVariable < nonBasicLength)
                {
                    for (int j = 0; j < constraintsLinesLength; ++j)
                    {
                        var dualVectorEntry        = dualVector[j];
                        var constraintsMatrixEntry = constraintsMatrix[j, nonBasicVariable];
                        var finiteValueToAdd       = this.coeffsField.Multiply(dualVectorEntry.FinitePart, constraintsMatrixEntry);
                        var bigValueToAdd          = this.coeffsField.Multiply(dualVectorEntry.BigPart, constraintsMatrixEntry);

                        var objectiveValue = objectiveFunction[nonBasicVariable];
                        finiteValueToAdd   = this.coeffsField.Add(finiteValueToAdd, objectiveValue.FinitePart);
                        bigValueToAdd      = this.coeffsField.Add(bigValueToAdd, objectiveValue.BigPart);

                        finitePart = this.coeffsField.Add(finitePart, finiteValueToAdd);
                        bigPart    = this.coeffsField.Add(bigPart, bigValueToAdd);
                    }

                    lock (syncObject)
                    {
                        var comparisionValue = this.coeffsComparer.Compare(bigPart, value.BigPart);
                        if (comparisionValue < 0)
                        {
                            result           = i;
                            value.FinitePart = finitePart;
                            value.BigPart    = bigPart;
                        }
                        else if (comparisionValue == 0)
                        {
                            if (this.coeffsComparer.Compare(finitePart, value.FinitePart) < 0)
                            {
                                result           = i;
                                value.FinitePart = finitePart;
                                value.BigPart    = bigPart;
                            }
                        }
                    }
                }
                else
                {
                    var index     = nonBasicVariable - nonBasicLength;
                    var dualValue = dualVector[index];
                    finitePart    = dualValue.FinitePart;
                    bigPart       = dualValue.BigPart;

                    lock (syncObject)
                    {
                        var comparisionValue = this.coeffsComparer.Compare(bigPart, value.BigPart);
                        if (comparisionValue < 0)
                        {
                            result           = i;
                            value.FinitePart = finitePart;
                            value.BigPart    = bigPart;
                        }
                        else if (comparisionValue == 0)
                        {
                            if (this.coeffsComparer.Compare(finitePart, value.FinitePart) < 0)
                            {
                                result           = i;
                                value.FinitePart = finitePart;
                                value.BigPart    = bigPart;
                            }
                        }
                    }
                }
            });

            return(result);
        }
예제 #13
0
 /// <summary>
 /// Verifica se um número enorme constitui uma unidade aditiva.
 /// </summary>
 /// <param name="number">O número enorme.</param>
 /// <returns>Verdadeiro caso o número seja uma unidade aditiva e falso caso contrário.</returns>
 private bool IsAdditiveUnity(SimplexMaximumNumberField <CoeffType> number)
 {
     return(this.coeffsField.IsAdditiveUnity(number.FinitePart) &&
            this.coeffsField.IsAdditiveUnity(number.BigPart));
 }