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); }
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)); }
public PVectorPrime(PVector PColumn, DenseVector PColumnPrime, double CPrime) { this.PColumn = PColumn; this.PColumnPrime = PColumnPrime; this.CPrime = CPrime; }