public void Restore(LinearProgram linearProgram, double[] originalCoeficients, int[] originalIndices) { var newObjective = new double[linearProgram.ObjectiveCoefficients.Length]; for (var i = 1; i < originalIndices.Length; i++) { var originalIndice = originalIndices[i]; var originalCoef = originalCoeficients[i]; if (linearProgram.NonBasicIndices.Contains(originalIndice)) { var index = Array.FindIndex(linearProgram.NonBasicIndices, n => n == originalIndice); var ttmp = new double[linearProgram.ObjectiveCoefficients.Length]; ttmp[index] = originalCoef; AddArray(newObjective, ttmp); } else { var index = Array.FindIndex(linearProgram.BasicIndices, b => b == originalIndice); var tmp = new double[linearProgram.ObjectiveCoefficients.Length]; linearProgram.Coefficients[index].CopyTo(tmp, 0); AddArray(newObjective, tmp, originalCoef); } } linearProgram.ObjectiveCoefficients = newObjective; }
public LinearProgamSolution Solve(LinearProgram linearProgram) { //check if needs initialization bool needsInit = linearProgram.Coefficients.Any(c => c[0] < 0); if (needsInit) { //solve dual var dual = _mapPrimalToDual.Map(linearProgram); var dualSol = SolveSingle(dual); //todo: check if feasbile if (dualSol.SolutionType != LinearProgramSolutionType.Solved) { return(new LinearProgamSolution(0, 0, LinearProgramSolutionType.Infeasible)); } //map back to primal var primal = _mapDualToPrimal.Map(dual); //restore objective _restoreObjective.Restore(primal, dual.OriginalObjectiveCoefficients, dual.OriginalNonBasicIndices); //solve var primalSol = SolveSingle(primal); return(primalSol); } else { return(SolveSingle(linearProgram)); } }
private LinearProgamSolution SolveSingle(LinearProgram linearProgram) { var pivotCount = 0; while (true) { //do this until no entering, or stop if unbounded _analyze.Analyze(linearProgram); //no entering, must be solved if (_analyze.Entering == 0) { break; } //if unbounded if (_analyze.Leaving == 0) { return(new LinearProgamSolution(0, 0, LinearProgramSolutionType.Unbounded)); } //if here, we can pivot ++pivotCount; _pivotor.Pivot(_analyze.Entering, _analyze.Leaving, linearProgram); } return(new LinearProgamSolution(linearProgram.ObjectiveValue, pivotCount, LinearProgramSolutionType.Solved)); }
private int GetEntering(LinearProgram linearProgram) { var objectiveCoefficients = linearProgram.ObjectiveCoefficients; var nonbasic = linearProgram.NonBasicIndices; var n = linearProgram.N; //pick entering var (coeff > 0) var enteringPos = int.MaxValue; for (var j = 1; j <= n; j++) { if (objectiveCoefficients[j] > 0.0) { if (enteringPos == int.MaxValue || nonbasic[j] < nonbasic[enteringPos]) { enteringPos = j; } } } if (enteringPos == int.MaxValue) { return(0); } _enteringPos = enteringPos; return(nonbasic[enteringPos]); }
public void Analyze(LinearProgram linearProgram) { Entering = GetEntering(linearProgram); //if unbounded if (Entering == 0) { return; } Leaving = GetLeaving(linearProgram); }
public LinearProgram Read(string fileName) { var lp = new LinearProgram(); var lines = File.ReadAllLines(fileName); var sizeVars = GetInts(lines[0]); lp.M = sizeVars[0]; lp.N = sizeVars[1]; var basic = GetInts(lines[1]); lp.BasicIndices = new int[basic.Length + 1]; basic.CopyTo(lp.BasicIndices, 1); var nonBasic = GetInts(lines[2]); lp.NonBasicIndices = new int[nonBasic.Length + 1]; nonBasic.CopyTo(lp.NonBasicIndices, 1); var bVars = GetDoubles(lines[3]); lp.Coefficients = new double[bVars.Length + 1][]; int m = 0; for (int i = 4; i < lines.Length; i++) { var values = GetDoubles(lines[i]); if (i == lines.Length - 1) { lp.ObjectiveCoefficients = values; } else { if (m == 0) { lp.Coefficients[m] = new double[values.Length + 1]; } ++m; lp.Coefficients[m] = new double[values.Length + 1]; lp.Coefficients[m][0] = bVars[m - 1]; values.CopyTo(lp.Coefficients[m], 1); } } return(lp); }
public void Pivot(int entering, int leaving, LinearProgram linearProgram) { var enteringPos = Array.FindIndex(linearProgram.NonBasicIndices, i => i == entering); var leavingPos = Array.FindIndex(linearProgram.BasicIndices, i => i == leaving); var a = linearProgram.ObjectiveCoefficients; var b = linearProgram.Coefficients[leavingPos]; var m = a[enteringPos]; var n = b[enteringPos]; var objValue = a[0] + m * b[0] / -n; linearProgram.ObjectiveCoefficients[0] = objValue; }
public void Pivot(int entering, int leaving, LinearProgram linearProgram) { var enteringPos = Array.FindIndex(linearProgram.NonBasicIndices, i => i == entering); var leavingPos = Array.FindIndex(linearProgram.BasicIndices, i => i == leaving); var a = linearProgram.ObjectiveCoefficients; var b = linearProgram.Coefficients[leavingPos]; //update leaving row: // - calculate new coefficients var n = b[enteringPos]; b[enteringPos] = -1.0; var multiplier = 1 / -n; MultiplyArray(b, multiplier); //update other rows for (var i = 1; i < linearProgram.Coefficients.Length; i++) { //already updated leaving row if (i == leavingPos) { continue; } //the row to update var bb = linearProgram.Coefficients[i]; //the coefficient in this row var c = bb[enteringPos]; //reset coefficient for array addition bb[enteringPos] = 0.0; AddArray(bb, b, c); } //update objective row var oc = a[enteringPos]; a[enteringPos] = 0; AddArray(a, b, oc); //update basic / non-basic indices linearProgram.BasicIndices[leavingPos] = entering; linearProgram.NonBasicIndices[enteringPos] = leaving; }
private int GetLeaving(LinearProgram linearProgram) { var coefficients = linearProgram.Coefficients; var m = linearProgram.M; var basic = linearProgram.BasicIndices; var enteringPos = _enteringPos; //pick leaving var (coeff <= 0, value within constraints) var leavingPos = int.MaxValue; var leavingValue = double.MaxValue; for (var i = 1; i <= m; i++) { var c = coefficients[i][enteringPos]; if (c < 0) { var value = coefficients[i][0] / -c; if (value < leavingValue) { leavingValue = value; leavingPos = i; } else if (Math.Abs(value - leavingValue) < .00001) { if (basic[i] < basic[leavingPos]) { leavingPos = i; } } } } if (leavingPos == int.MaxValue) { return(0); } return(basic[leavingPos]); }
//[Line 1] m n //[Line 2] B1 B2 ... Bm [the list of basic indices m integers] //[Line 3] N1 N2 ... Nn [the list of non-basic indices n integers] //[Line 4] b1 .. bm (m floating point numbers) //[Line 5] a11 ... a1n (first row coefficients. See dictionary notation above.) //.... //[Line m+4] am1 ... amn (mth row coefficients. See dictionary notation above.) //[Line m+5] z0 c1 .. cn (objective coefficients (n+1 floating point numbers)) public DualLinearProgram Map(LinearProgram primal) { var dual = new DualLinearProgram(); dual.M = primal.N; dual.N = primal.M; dual.OriginalObjectiveCoefficients = primal.ObjectiveCoefficients; dual.OriginalNonBasicIndices = primal.NonBasicIndices; dual.BasicIndices = new int[primal.NonBasicIndices.Length]; dual.NonBasicIndices = new int[primal.BasicIndices.Length]; dual.Coefficients = new double[primal.Coefficients[0].Length][]; dual.ObjectiveCoefficients = new double[primal.BasicIndices.Length]; //map primal coefficients to dual coefficients var a = primal.Coefficients.Length; for (var i = 0; i < dual.Coefficients.Length; i++) { dual.Coefficients[i] = new double[a];//empty row for 1-based indexes if (i == 0) { continue; } for (var k = 1; k < primal.Coefficients.Length; k++) { dual.Coefficients[i][k] = -primal.Coefficients[k][i]; } } //map 1 to dual coefficients b-value for (var i = 1; i < primal.ObjectiveCoefficients.Length; i++) { dual.Coefficients[i][0] = 1; } //map primal b values to dual objective coefficients for (var i = 1; i < primal.Coefficients.Length; i++) { dual.ObjectiveCoefficients[i] = -primal.Coefficients[i][0]; } //set basic / non basic indices var y = 0; for (var i = 1; i < dual.BasicIndices.Length; i++) { dual.BasicIndices[i] = ++y; } for (var i = 1; i < dual.NonBasicIndices.Length; i++) { dual.NonBasicIndices[i] = ++y; } //set complements dual.Complements = new int[2][]; dual.Complements[0] = primal.NonBasicIndices.Skip(1).Concat(primal.BasicIndices.Skip(1)).ToArray(); dual.Complements[1] = dual.NonBasicIndices.Skip(1).Concat(dual.BasicIndices.Skip(1)).ToArray(); return(dual); }