//Compute SolverIteration from preceding iteration private static SolverIteration ComputeIteration(SolverIteration previous) { SolverIteration iteration = previous.Copy(); var column = IncomingVariable(iteration.DecisionVariables); var row = LeavingVariable(GetColumn(iteration.InputGrid, column), iteration.BaseVariables); var variable = iteration.InputGrid[row][column]; var rowArray = iteration.InputGrid[row]; for (int i = 0; i < rowArray.Length; i++) { rowArray[i] /= variable; } iteration.BaseVariables[row] /= variable; for (int i = 0; i < iteration.InputGrid.Length; i++) { if (i == row) { continue; } var value = iteration.InputGrid[i][column]; for (int j = 0; j < iteration.InputGrid[i].Length; j++) { iteration.InputGrid[i][j] -= value * iteration.InputGrid[row][j]; } iteration.BaseVariables[i] -= value * iteration.BaseVariables[row]; } var val = iteration.DecisionVariables[column]; for (int i = 0; i < iteration.DecisionVariables.Length; i++) { iteration.DecisionVariables[i] -= val * iteration.InputGrid[row][i]; } iteration.Bases[row] = iteration.Variables[column]; iteration.Z = 0; for (var i = 0; i < iteration.Bases.Length; i++) { var baseVar = iteration.Bases[i]; iteration.Z += GetVariableObjective(baseVar, iteration) * iteration.BaseVariables[i]; } previous.SelectedGridPositions = (row, column); return(iteration); }
//Remove artificial variable indexes after two-phases finishes public static SolverIteration RemoveIndexes(SolverIteration iteration, int cutoffIndex) { var cutIteration = iteration.Copy(); var variables = iteration.Variables.Take(cutoffIndex).ToArray(); var objectiveVariables = iteration.ObjectiveVariables.Take(cutoffIndex) .ToArray(); var decisionVariables = iteration.DecisionVariables.Take(cutoffIndex) .ToArray(); var inputGrid = new List <BigRational[]>(); for (int i = 0; i < iteration.InputGrid.Length; i++) { inputGrid.Add(iteration.InputGrid[i].Take(cutoffIndex).ToArray()); } cutIteration.Variables = variables; cutIteration.ObjectiveVariables = objectiveVariables; cutIteration.DecisionVariables = decisionVariables; cutIteration.InputGrid = inputGrid.ToArray(); return(cutIteration); }
//Run two-phases simplex algorithm starting from an initial SolverIteration public static SolvedModel TwoPhases(SolverIteration initialIteration, List <Constraint> constraints) { var twoPhasesInitialIteration = initialIteration.Copy(); int artificialCutoff = -1; for (int i = 0; i < initialIteration.Variables.Length; i++) { if (initialIteration.Variables[i].Type == VariableType.Artificial) { artificialCutoff = i; break; } } if (artificialCutoff == -1) { throw new ArgumentException(); } var twoPhasesObjective = Enumerable.Repeat <BigRational>( BigRational.One, twoPhasesInitialIteration.Variables.Length).ToArray(); for (int i = 0; i < artificialCutoff; i++) { twoPhasesObjective[i] = 0; } twoPhasesInitialIteration.ObjectiveVariables = twoPhasesObjective; var twoPhaseBases = twoPhasesInitialIteration .Variables.Skip( twoPhasesInitialIteration.Variables.Length - twoPhasesInitialIteration.Bases.Length) .ToArray(); twoPhasesInitialIteration.Bases = twoPhaseBases; for (int i = 0; i < twoPhasesInitialIteration.Variables.Length; i++) { BigRational Zj = BigRational.Zero; for (int j = 0; j < twoPhasesInitialIteration.Bases.Length; j++) { var rowVariable = twoPhasesInitialIteration.Bases[j]; var rowObjectiveIndex = Array.IndexOf(twoPhasesInitialIteration.Variables, rowVariable); var rowObjective = twoPhasesInitialIteration.ObjectiveVariables[rowObjectiveIndex]; Zj += twoPhasesInitialIteration.InputGrid[j][i] * rowObjective; } twoPhasesInitialIteration.DecisionVariables[i] = twoPhasesInitialIteration.ObjectiveVariables[i] - Zj; } twoPhasesInitialIteration.Z = 0; for (var i = 0; i < twoPhasesInitialIteration.Bases.Length; i++) { var baseVar = twoPhasesInitialIteration.Bases[i]; var columnIndex = Array.IndexOf(twoPhasesInitialIteration.Variables, baseVar); twoPhasesInitialIteration.Z += twoPhasesInitialIteration.BaseVariables[i] * twoPhasesInitialIteration.ObjectiveVariables[columnIndex]; } var solvedTwoPhases = Simplex(twoPhasesInitialIteration, constraints); solvedTwoPhases.TwoPhasesIterations = solvedTwoPhases.SimplexIterations; solvedTwoPhases.SimplexIterations = new List <SolverIteration>(); if (solvedTwoPhases.Result != SolvedResult.Optimized) { return(solvedTwoPhases); } if (solvedTwoPhases.Z != 0) { solvedTwoPhases.Result = SolvedResult.Unbounded; return(solvedTwoPhases); } var finalIteration = solvedTwoPhases.TwoPhasesIterations.Last(); for (int i = 0; i < finalIteration.Bases.Length; i++) { if (finalIteration.Bases[i].Type == VariableType.Artificial && finalIteration.BaseVariables[i] > 0) { solvedTwoPhases.Result = SolvedResult.Infeasible; return(solvedTwoPhases); } } finalIteration = RemoveIndexes( finalIteration.Copy(), artificialCutoff); finalIteration.ObjectiveVariables = initialIteration.ObjectiveVariables.Take(artificialCutoff).ToArray(); finalIteration.Z = 0; for (var i = 0; i < finalIteration.Bases.Length; i++) { var baseVar = finalIteration.Bases[i]; var columnIndex = Array.IndexOf(finalIteration.Variables, baseVar); if (columnIndex == -1) { finalIteration.Z += 0; } else { finalIteration.Z += finalIteration.BaseVariables[i] * finalIteration.ObjectiveVariables[columnIndex]; } } for (int i = 0; i < finalIteration.Variables.Length; i++) { var zj = -GetColumn(finalIteration.InputGrid, i).Sum(); var cj = finalIteration.ObjectiveVariables[i]; finalIteration.DecisionVariables[i] = -GetColumn(finalIteration.InputGrid, i).Sum() - finalIteration.ObjectiveVariables[i]; } var simplexResult = Simplex(finalIteration, constraints); simplexResult.TwoPhasesIterations = solvedTwoPhases.TwoPhasesIterations; return(simplexResult); }