Exemplo n.º 1
0
        public InternalModel GetNextPhaseModel()
        {
            // this process is essentially the same computation as an iteration of the revised method
            // esentiall, just create (allthethings) p primes
            var basicInverse = DenseMatrix.OfColumnVectors(PrevModel.PColumns.Where(p => p.IsBasic).ToArray()).Inverse();

            var zPrime = DenseVector.OfEnumerable((basicInverse * PrevModel.PColumns[0].ToColumnMatrix()).ToColumnWiseArray());

            var zIndex = zPrime.MaximumIndex();


            var xPrime = (basicInverse * (PrevModel.XColumn.ToColumnMatrix())).ToColumnWiseArray().ToList();

            xPrime.RemoveAt(zIndex);

            var newXColumn = DenseVector.OfEnumerable(xPrime);


            var newPColumns = new List <PVector>();

            foreach (var col in PrevModel.PColumns.Skip(1))
            {
                var pPrime  = (basicInverse * col.ToColumnMatrix()).ToColumnWiseArray().Select(x => Math.Round(x, 6)).ToList();
                var newZVal = pPrime.ElementAt(zIndex);
                pPrime.RemoveAt(zIndex);


                var newP = new PVector(DenseVector.OfEnumerable(pPrime), col.IsBasic, col.IsDecision, col.IsArtificial);
                newP.ZValue = newZVal;

                newPColumns.Add(newP);
            }

            var artificialCount = PrevModel.PColumns.Count(p => p.IsArtificial);

            newPColumns = newPColumns.Take(newPColumns.Count - artificialCount).ToList();

            var nextModel = new InternalModel()
            {
                IsTwoPhase     = false,
                IsStandardized = true,
                XColumn        = newXColumn,
                PColumns       = newPColumns,
                GoalKind       = PrevModel.GoalKind,
                Goal           = PrevModel.Goal
            };

            return(nextModel);
        }
Exemplo n.º 2
0
        public InternalSolution Solve()
        {
            // first thing's first!
            if (!IsStandardized)
            {
                try
                {
                    Standardize();
                }
                catch
                {
                    var effff = SolutionHelper.Infeasible();
                    return(new InternalSolution(effff, this));
                }
            }

            // Loop over finding new basic variables until terminating conditions found
            for (var badUniqueVariableName = 0; badUniqueVariableName < 300; badUniqueVariableName++)
            {
                // create matrix of basics
                var basicInverse = DenseMatrix.OfColumnVectors(PColumns.Where(p => p.IsBasic).ToArray()).Inverse();

                // compute product of inverse and RHS values
                var xPrime = DenseVector.OfEnumerable((basicInverse * (XColumn.ToColumnMatrix())).ToColumnWiseArray().Select(x => Math.Round(x, 6)));


                var pPrimes = new List <PVectorPrime>();
                var zCoefs  = DenseVector.OfEnumerable(PColumns.Where(p => p.IsBasic).Select(p => p.ZValue));
                foreach (var col in PColumns.Where(p => !p.IsBasic))
                {
                    //was getting some weird precision issues... so chop 'em short
                    var pPrime = DenseVector.OfEnumerable((basicInverse * col.ToColumnMatrix()).ToColumnWiseArray().Select(x => Math.Round(x, 6)));
                    var cPrime = Math.Round(col.ZValue - (zCoefs * pPrime), 6);

                    pPrimes.Add(new PVectorPrime(col, pPrime, cPrime));
                }

                //var anyNegative = cPrimes.Any(x => x < 0);
                var anyNegative = pPrimes.Any(x => Math.Round(x.CPrime, 2) < 0);
                if (anyNegative)
                {
                    PVector entering, exiting = null;


                    // determine entering basic variable (using Bland's method. inefficient, but reliable)
                    var tempPrime = pPrimes.First(p => Math.Round(p.CPrime, 4) < 0);
                    entering = tempPrime.PColumn;

                    // compute ratio of x prime to p prime assosiated with new basic variable
                    var ratios = (xPrime / tempPrime.PColumnPrime).Select(x => Math.Round(x, 6)).ToList();

                    // make sure there are positives, if not, then the entire problem unbounded
                    var anyPositive = ratios.Any(x => x > 0 && !double.IsInfinity(x));
                    if (anyPositive)
                    {
                        var min = ratios.Min(x => x > 0 ? x : double.PositiveInfinity);

                        var minIndexes = Enumerable.Range(0, ratios.Count).Where(i => ratios[i] == min).ToArray();
                        if (minIndexes.Length > 1)
                        {
                            var potentialExits = PColumns.Where(p => p.IsBasic).Where((x, i) => minIndexes.Contains(i));
                            var artificalCount = PColumns.Count(p => p.IsArtificial);

                            exiting = potentialExits.OrderByDescending(p => PColumns.Skip(PColumns.Count - artificalCount).Take(artificalCount - 1).Contains(p)).First();
                        }
                        else
                        {
                            exiting = PColumns.Where(p => p.IsBasic).ElementAt(minIndexes[0]);
                        }
                    }
                    else
                    {
                        var anyPositiveOrZeros = ratios.Any(x => x >= 0 && !double.IsInfinity(x));
                        if (anyPositiveOrZeros)
                        {
                            var min = ratios.Min(x => x >= 0 ? x : double.PositiveInfinity);

                            var minIndexes = Enumerable.Range(0, ratios.Count).Where(i => ratios[i] == min).ToArray();
                            if (minIndexes.Length > 1)
                            {
                                var potentialExits = PColumns.Where(p => p.IsBasic).Where((x, i) => minIndexes.Contains(i));
                                var artificalCount = PColumns.Count(p => p.IsArtificial);

                                exiting = potentialExits.OrderByDescending(p => PColumns.Skip(PColumns.Count - artificalCount).Take(artificalCount - 1).Contains(p)).First();
                            }
                            else
                            {
                                exiting = PColumns.Where(p => p.IsBasic).ElementAt(minIndexes[0]);
                            }
                        }
                        else
                        {
                            return(new InternalSolution(SolutionHelper.Unbounded()));
                        }
                    }

                    // actually change the basic-ness
                    entering.IsBasic = true;
                    exiting.IsBasic  = false;
                }
                // infeasible
                else if (PColumns.Any(p => p.IsArtificial && p.IsBasic))
                {
                    return(new InternalSolution(SolutionHelper.Infeasible(), this));
                }
                // optimal
                else
                {
                    var targetNumDecisions = Goal.Coefficients.Length;

                    var decisions = new List <double>();
                    var xIndex    = 0;
                    foreach (var p in PColumns.Where(x => x.IsDecision))
                    {
                        if (p.IsBasic)
                        {
                            decisions.Add(xPrime[xIndex]);
                            xIndex++;
                        }
                        else
                        {
                            decisions.Add(0);
                        }
                    }
                    var value = decisions.Select((x, i) => x * Goal.Coefficients[i]).Sum();
                    value += Goal.ConstantTerm;

                    var allPPrimes = new List <PVectorPrime>();
                    foreach (var col in PColumns)
                    {
                        //was getting some weird precision issues... so chop 'em short
                        var pPrime = DenseVector.OfEnumerable((basicInverse * col.ToColumnMatrix()).ToColumnWiseArray());
                        var cPrime = Math.Round(col.ZValue - (zCoefs * pPrime), 6);

                        allPPrimes.Add(new PVectorPrime(col, pPrime, cPrime));
                    }
                    var infiniteSols = pPrimes.Count(p => Math.Round(p.CPrime, 4) == 0) >= Goal.Coefficients.Length;

                    var sol = SolutionHelper.Optimal(decisions.ToArray(), value, infiniteSols);
                    return(new InternalSolution(sol, this));
                }
            }
            var uhoh = SolutionHelper.TimedOut();

            return(new InternalSolution(uhoh, this));
        }
Exemplo n.º 3
0
 public PVectorPrime(PVector PColumn, DenseVector PColumnPrime, double CPrime)
 {
     this.PColumn      = PColumn;
     this.PColumnPrime = PColumnPrime;
     this.CPrime       = CPrime;
 }