protected override bool IsDone(SimplexTable table) { bool integerVector = true; table.bVector.ForEach(b => integerVector = integerVector && b.value.Fract() == 0); return(integerVector); }
public string MakeTransform(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { outputTable = new SimplexTable(inputTable); string result = ""; if (multNegRows) { var invertedLines = false; for (int i = 0; i < outputTable.NumOfConstrains; i++) { if (outputTable.bVector[i].value >= 0) { continue; } invertedLines = true; outputTable.bVector[i].value *= BigRational.MinusOne; for (int j = 0; j < outputTable.NumOfVariables; j++) { outputTable.aMatrix[i][j].value *= BigRational.MinusOne; } } if (invertedLines) { result += "Some of constrains equations were multiplied by -1.<br>"; } } success = true; return(result + AddBasisVariables(outputTable)); }
public string MakeTransform(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { outputTable = new SimplexTable(inputTable); var a = inputTable.aMatrix; for (int i = 0; i < outputTable.NumOfConstrains; i++) { for (int j = 0; j < outputTable.NumOfVariables; j++) { if (i == tarI) { outputTable.aMatrix[i][j] /= a[tarI][tarJ]; } else { outputTable.aMatrix[i][j] -= (a[i][tarJ] * a[tarI][j]) / a[tarI][tarJ]; } } if (i == tarI) { outputTable.bVector[i] /= a[tarI][tarJ]; } else { outputTable.bVector[i] -= (a[i][tarJ] * inputTable.bVector[tarI]) / a[tarI][tarJ]; } } success = true; return(""); }
private bool CanContinue(SimplexTable outputTable, List <SimplexCoef> delta, out string result, out bool success) { bool hasNegative = false; delta.ForEach(c => hasNegative = hasNegative || c.value.Sign < 0); if (!hasNegative) { result = "All simplex deltas aren't negative.<br>"; success = true; return(false); } for (int j = 0; j < outputTable.NumOfVariables; j++) { bool allNegative = delta[j].value.Sign < 0; for (int i = 0; i < outputTable.NumOfConstrains; i++) { allNegative = allNegative && outputTable.aMatrix[i][j].value.Sign < 0; } if (allNegative) { result = "Problem has Infinite solution. Simplex method was ended.<br>"; success = false; return(false); } } result = ""; success = false; return(true); }
protected string PrintTableToHTML(SimplexTable table, List <int> basis, List <SimplexCoef> delta) { var resBuilder = new StringBuilder(); resBuilder.Append("<table><tr>"); resBuilder.Append("<th>C(i)</th><th>X(basis)</th>"); table.cLables.ForEach(lable => resBuilder.Append($"<th>{lable.Value}</th>")); resBuilder.Append("<th>B</th></tr>"); for (int i = 0; i < table.NumOfConstrains; i++) { resBuilder.Append("<tr>"); resBuilder.Append($"<td class='cValue'>{table.cVector[basis[i]].ToString()}</td>"); resBuilder.Append($"<td class='cLabel'>{table.cLables[basis[i]].Value}</td>"); for (int j = 0; j < table.NumOfVariables; j++) { resBuilder.Append($"<td class='aMatrixElement'>{table.aMatrix[i][j].ToString()}</td>"); } resBuilder.Append($"<td class='bVector'>{table.bVector[i].ToString()}</td>"); resBuilder.Append("</tr>"); } resBuilder.Append("<tr><td></td><td></td>"); for (int j = 0; j < table.NumOfVariables; j++) { resBuilder.Append($"<td class='deltaElement'>{delta[j].ToString()}</td>"); } resBuilder.Append("<td></td></tr></table>"); return(resBuilder.ToString()); }
protected string FormAnswer(SimplexTable table, List <int> basis) { var result = ""; for (int j = 0; j < table.NumOfVariables; j++) { if (basis.Contains(j)) { result += $"{table.cLables[j].Value} = {table.bVector[basis.IndexOf(j)].ToString()}"; } else { result += $"{table.cLables[j].Value} = 0"; } if (j + 1 < table.NumOfVariables) { result += ", "; } } var costValue = new SimplexCoef(); ReevaluateBasisAndDeltas(table); for (int i = 0; i < table.NumOfConstrains; i++) { costValue += table.cVector[basis[i]] * table.bVector[i]; } costValue += table.constantValue; result += $"<br>L = {((table.costFIsInverted) ? (-costValue).ToString() : costValue.ToString())}<br>"; return(result); }
protected override string AddConstrain(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { outputTable = new SimplexTable(inputTable); success = true; var bFracts = FormBFractVector(outputTable); int selectedI = FindIndexOfMin(bFracts); int nwI = outputTable.NumOfConstrains; ReevaluateBasisAndDeltas(outputTable); var result = $"Let's use {outputTable.cLables[curBasis[selectedI]].Value} row to form new constrain.<br>"; outputTable.NumOfConstrains += 1; for (int j = 0; j < outputTable.NumOfVariables; j++) { outputTable.aMatrix[nwI][j].value = -outputTable.aMatrix[selectedI][j].value.Fract(); } outputTable.bVector[nwI].value = bFracts[selectedI].value; outputTable.NumOfVariables += 1; outputTable.aMatrix[nwI][outputTable.NumOfVariables - 1].value = BigRational.One; return(result); }
protected string RemoveUnusedSinteticVariables(SimplexTable inputTable, out SimplexTable outputTable, List <int> basis) { outputTable = new SimplexTable(inputTable); string result = ""; for (int p = 0; p < outputTable.sinteticVariables.Count; p++) { int sintInd = outputTable.sinteticVariables[p]; if (basis.Contains(sintInd)) { continue; } if (result.Length == 0) { result += "We have some sintetic variables out of basis, let's remove them: "; } result += $"{outputTable.cLables[sintInd].Value} "; for (int j = sintInd; j < outputTable.NumOfVariables - 1; j++) { outputTable.cLables[j] = outputTable.cLables[j + 1]; outputTable.cVector[j] = outputTable.cVector[j + 1]; for (int i = 0; i < outputTable.NumOfConstrains; i++) { outputTable.aMatrix[i][j] = outputTable.aMatrix[i][j + 1]; } } for (int k = 0; k < basis.Count; k++) { if (basis[k] < sintInd) { continue; } --basis[k]; } for (int k = 0; k < outputTable.sinteticVariables.Count; k++) { if (outputTable.sinteticVariables[k] < sintInd) { continue; } --outputTable.sinteticVariables[k]; } outputTable.sinteticVariables.RemoveAt(p--); outputTable.NumOfVariables -= 1; } return(result); }
protected override bool IsDone(SimplexTable table) { ReevaluateBasisAndDeltas(table); for (int i = 0; i < table.NumOfConstrains; i++) { int ind = curBasis[i]; if (table.cLables[ind].IsSelected && table.bVector[i].value.Fract() != 0) { return(false); } } return(true); }
protected override string AddConstrain(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { outputTable = new SimplexTable(inputTable); success = true; ReevaluateBasisAndDeltas(outputTable); var bFracts = FormBFractVector(outputTable); int selectedI = FindIndexOfMin(bFracts); int nwI = outputTable.NumOfConstrains; outputTable.NumOfConstrains += 1; var result = $"Let's use {outputTable.cLables[curBasis[selectedI]].Value} row to form new constrain.<br>"; var bFract = outputTable.bVector[selectedI].value.Fract(); for (int j = 0; j < outputTable.NumOfVariables; j++) { BigRational tarA = outputTable.aMatrix[selectedI][j].value; if (!outputTable.cLables[j].IsSelected) { if (tarA.Sign >= 0) { outputTable.aMatrix[nwI][j].value = -tarA; } else { outputTable.aMatrix[nwI][j].value = -((bFract / (BigRational.One - bFract)) * (-tarA)); } } else { if (tarA.Fract() <= bFract) { outputTable.aMatrix[nwI][j].value = -tarA.Fract(); } else { outputTable.aMatrix[nwI][j].value = -((bFract / (BigRational.One - bFract)) * (BigRational.One - tarA)); } } } outputTable.bVector[nwI].value = -bFract; outputTable.NumOfVariables += 1; outputTable.aMatrix[nwI][outputTable.NumOfVariables - 1].value = BigRational.One; return(result); }
protected List <SimplexCoef> EvaluateDeltas(List <SimplexCoef> basisC, SimplexTable table) { var simplexDeltes = new List <SimplexCoef>(); for (int j = 0; j < table.NumOfVariables; j++) { var dotProd = new SimplexCoef(); for (int i = 0; i < table.NumOfConstrains; i++) { dotProd += basisC[i] * table.aMatrix[i][j]; } simplexDeltes.Add(table.cVector[j] - dotProd); } return(simplexDeltes); }
private List <SimplexCoef> FormGamasVector(SimplexTable table, List <int?> nuVec, List <int> basis) { var gamas = new List <SimplexCoef>(); for (int i = 0; i < table.NumOfConstrains; i++) { if (nuVec[i] == null || nuVec[i].Value < 0) { gamas.Add(null); } else { gamas.Add(-(table.bVector[i] - table.discreteSet[basis[i]][nuVec[i].Value])); } } return(gamas); }
protected void ReevaluateBasisAndDeltas(SimplexTable table) { if (!table.TryFindBasis(out int[] basis)) { Debug.Fail("Can't find basis after."); } curBasis = new List <int>(basis); var basisC = new List <SimplexCoef>(); foreach (int ind in basis) { basisC.Add(table.cVector[ind]); } curDelta = EvaluateDeltas(basisC, table); }
private void PrepareForMethod(SimplexTable inputTable, out SimplexTable outputTable, ref string result) { outputTable = new SimplexTable(inputTable); if (!outputTable.MinimisationTask) { result += "Let's Invert Cost function so that we can solve minimization problem<br>"; outputTable.MinimisationTask = true; outputTable.cVector.ForEach(coef => coef.value *= BigRational.MinusOne); outputTable.constantValue.value *= BigRational.MinusOne; } if (!outputTable.TryFindBasis(out int[] ind)) { throw new ArgumentException("Dual simplex method can't find basis."); } ReevaluateBasisAndDeltas(outputTable); }
private void PrepareForMethod(SimplexTable inputTable, out SimplexTable outputTable, ref string result) { outputTable = new SimplexTable(inputTable); if (!outputTable.MinimisationTask) { result += "Let's Invert Cost function so that we can solve minimization problem<br>"; outputTable.costFIsInverted = true; outputTable.MinimisationTask = true; outputTable.cVector.ForEach(coef => coef.value *= BigRational.MinusOne); outputTable.constantValue.value *= BigRational.MinusOne; } var basisFormer = new MMethod(); result += basisFormer.MakeTransform(outputTable, out outputTable, out bool s); ReevaluateBasisAndDeltas(outputTable); }
private List <SimplexCoef> FormBFractVector(SimplexTable table) { var bFracts = new List <SimplexCoef>(); foreach (var b in table.bVector) { var curBFract = b.value.Fract(); if (curBFract == 0) { bFracts.Add(null); } else { var nwCoef = new SimplexCoef(b); nwCoef.value = -curBFract; bFracts.Add(nwCoef); } } return(bFracts); }
private string AddBasisVariables(SimplexTable table) { if (table.TryFindBasis(out int[] basisIndex)) { var basisVariables = ""; foreach (var ind in basisIndex) { basisVariables += $"{table.cLables[ind].Value} "; } return("Table has basis: " + basisVariables + "<br>"); } string result = "Let's use M method to add some new variables.<br>"; result += "So ..... our new sintetic variables will be: "; for (int i = 0; i < basisIndex.Length; i++) { if (basisIndex[i] >= 0) { continue; } table.NumOfVariables += 1; table.sinteticVariables.Add(table.cVector.Count - 1); var l_coef = table.cVector[table.cVector.Count - 1]; l_coef.isM = true; l_coef.value = (table.MinimisationTask) ? BigRational.One : BigRational.MinusOne; l_coef.UpdateStringValue(); table.cLables[table.cLables.Count - 1].Value = $"y{table.cLables.Count}"; result += $"{table.cLables[table.cLables.Count - 1].Value} "; table.aMatrix[i][table.aMatrix[i].Count - 1].value = BigRational.One; table.aMatrix[i][table.aMatrix[i].Count - 1].UpdateStringValue(); } result += "<br>"; return(result); }
protected override bool IsDone(SimplexTable table) { ReevaluateBasisAndDeltas(table); for (int i = 0; i < table.NumOfConstrains; i++) { int ind = curBasis[i]; if (table.cLables[ind].IsSelected) { bool contains = false; foreach (var c in table.discreteSet[ind]) { contains = contains || (table.bVector[i].value == c.value); } if (!contains) { return(false); } } } return(true); }
private List <SimplexCoef> FormBFractVector(SimplexTable table) { var bFracts = new List <SimplexCoef>(); for (int i = 0; i < table.NumOfConstrains; i++) { var curBFract = table.bVector[i].value.Fract(); if (curBFract == 0 || !table.cLables[curBasis[i]].IsSelected) { bFracts.Add(null); } else { var nwCoef = new SimplexCoef(table.bVector[i]); nwCoef.value = -curBFract; bFracts.Add(nwCoef); } } return(bFracts); }
private bool CanContinue(SimplexTable outputTable, out string result, out bool success) { bool hasNegative = false; var b = outputTable.bVector; b.ForEach(c => hasNegative = hasNegative || c.value.Sign < 0); if (!hasNegative) { result = "All dual simplex b aren't negative.<br>"; success = true; return(false); } for (int i = 0; i < outputTable.NumOfConstrains; i++) { if (b[i].value.Sign >= 0) { continue; } hasNegative = false; for (int j = 0; j < outputTable.NumOfVariables; j++) { hasNegative = hasNegative || outputTable.aMatrix[i][j].value.Sign < 0; } if (!hasNegative) { result = "Solution doesn't exist."; success = false; return(false); } } result = ""; success = false; return(true); }
private string PrintCostFunction(SimplexTable table) { var result = "L = "; bool isFirst = true; for (int j = 0; j < table.NumOfVariables; j++) { if (table.cVector[j].value == BigRational.Zero) { continue; } var coefStr = table.cVector[j].ToString(); if (coefStr[0] == '-') { coefStr = coefStr.Substring(1).Trim(); } result += (table.cVector[j].value.Sign >= 0) ? ((isFirst) ? coefStr : $"+ {coefStr}"): $"- {coefStr}"; result += $"*{table.cLables[j].Value} "; isFirst = false; } if (table.constantValue.value != BigRational.Zero) { var coefStr = table.constantValue.ToString(); if (coefStr[0] == '-') { coefStr = coefStr.Substring(1).Trim(); } result += (table.constantValue.value.Sign >= 0) ? $"+ {coefStr}" : $"- {coefStr}"; } result += "<br>"; return(result); }
private List <int?> FormNuVector(SimplexTable table, List <int> basis, out bool success) { var nuVec = new List <int?>(); success = true; for (int i = 0; i < table.NumOfConstrains; i++) { if (!table.cLables[basis[i]].IsSelected || table.discreteSet[basis[i]].Contains(table.bVector[i])) { nuVec.Add(null); continue; } else { int nu = -1; for (int k = 1; k < table.discreteSet[basis[i]].Count; k++) { if (table.bVector[i].value < table.discreteSet[basis[i]][k].value) { nu = k - 1; } } if (table.discreteSet[basis[i]][table.discreteSet[basis[i]].Count - 1].value == table.bVector[i].value) { nu = table.discreteSet[basis[i]].Count - 1; } success = success && (nu >= 0); nuVec.Add(nu); } } return(nuVec); }
private List <int?> GetValidNuVector(SimplexTable inputTable, out SimplexTable outputTable, out string result) { outputTable = inputTable; result = ""; List <int?> nuVector = null; bool foundAllNus = false; while (!foundAllNus) { ReevaluateBasisAndDeltas(outputTable); nuVector = FormNuVector(outputTable, curBasis, out foundAllNus); if (!foundAllNus) { var tarJ = curBasis[nuVector.IndexOf(-1)]; result += $"{outputTable.cLables[tarJ].Value} became bigger than any element of its set.<br>"; var maxElem = outputTable.discreteSet[tarJ].Max(); result += $"So, let's add constrain '{outputTable.cLables[tarJ].Value}' < {maxElem.ToString()} and run MMethod.<br>"; outputTable = new SimplexTable(outputTable); outputTable.NumOfConstrains += 1; outputTable.NumOfVariables += 1; outputTable.aMatrix[outputTable.NumOfConstrains - 1][tarJ].value = BigRational.One; outputTable.aMatrix[outputTable.NumOfConstrains - 1][outputTable.NumOfVariables - 1].value = BigRational.One; outputTable.bVector[outputTable.NumOfConstrains - 1].value = maxElem.value; var simplexMethod = new SimplexMethod(); result += simplexMethod.MakeTransform(outputTable, out outputTable, out bool success); if (!success) { return(null); } } } return(nuVector); }
public override string MakeTransform(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { var result = "<h3>Let's ignore integer constrain:</h3><br>"; var simplex = new SimplexMethod(); result += simplex.MakeTransform(inputTable, out outputTable, out success); int counter = 1; while (success && !IsDone(outputTable)) { result += $"<br><br><h4>Step {counter++}:</h4><br>"; result += "BVector has fractional components. Let's add another constrain.<br>"; result += AddConstrain(outputTable, out outputTable, out success); if (!success) { break; } result += "So new Table looks like this:<br>"; ReevaluateBasisAndDeltas(outputTable); result += PrintTableToHTML(outputTable, curBasis, curDelta); result += "<br><br>Using dual Simplex method:<br>"; var dualSimplex = new DualSimplexMethod(); result += dualSimplex.MakeTransform(outputTable, out outputTable, out success); } if (success) { result += "That's it. Now we have integer solution.<br>"; } return(result); }
protected override string AddConstrain(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { outputTable = new SimplexTable(inputTable); foreach (var set in outputTable.discreteSet) { set.Sort(); for (int i = 0; i < set.Count - 1; i++) { if (set[i] == set[i + 1]) { set.RemoveAt(i--); } } } ReevaluateBasisAndDeltas(outputTable); var nuVector = GetValidNuVector(outputTable, out outputTable, out string result); if (nuVector == null) { success = false; return("Can't solve task with such discrete set.<br>"); } var gamas = FormGamasVector(outputTable, nuVector, curBasis); var selectedI = FindIndexOfMin(gamas); var nwI = outputTable.NumOfConstrains; result += $"Let's use {outputTable.cLables[curBasis[selectedI]].Value} row to form new constrain.<br>"; outputTable.NumOfConstrains += 1; for (int j = 0; j < outputTable.NumOfVariables; j++) { if (curBasis.Contains(j)) { continue; } if (outputTable.aMatrix[selectedI][j].value.Sign >= 0) { outputTable.aMatrix[nwI][j].value = (-outputTable.aMatrix[selectedI][j]).value; } else { var b = outputTable.bVector[selectedI]; var nu = outputTable.discreteSet[curBasis[selectedI]][nuVector[selectedI].Value]; if (b != nu) { var next_nu = outputTable.discreteSet[curBasis[selectedI]][nuVector[selectedI].Value + 1]; outputTable.aMatrix[nwI][j].value = (-(((b - nu) / (next_nu - b)) * (-outputTable.aMatrix[selectedI][j]))).value; } else { outputTable.aMatrix[nwI][j].value = BigRational.Zero; } } } outputTable.bVector[nwI].value = gamas[selectedI].value; outputTable.NumOfVariables += 1; outputTable.aMatrix[nwI][outputTable.NumOfVariables - 1].value = BigRational.One; success = true; return(result); }
public virtual string MakeTransform(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { outputTable = new SimplexTable(inputTable); string result = "<h3>Simplex method: </h3><br>Let's use simplex method.<br>"; PrepareForMethod(outputTable, out outputTable, ref result); result += "<br>"; if (outputTable.costFIsInverted) { result += "Cost function is inverted: <br>"; } result += PrintCostFunction(outputTable); result += "<br>Step 0:<br>"; result += PrintTableToHTML(outputTable, curBasis, curDelta); result += "<br><br>"; int iterNum = 0; string checkResult; while (CanContinue(outputTable, curDelta, out checkResult, out success)) { if (iterNum++ > 0) { result += $"Step {iterNum}:<br>"; } int minDeltaIndex = FindIndexOfMin(curDelta); var tetas = new List <SimplexCoef>(); for (int i = 0; i < outputTable.NumOfConstrains; i++) { if (outputTable.aMatrix[i][minDeltaIndex].value.Sign <= 0) { tetas.Add(null); continue; } tetas.Add(outputTable.bVector[i] / outputTable.aMatrix[i][minDeltaIndex]); } int minTetaIndex = FindIndexOfMin(tetas); result += $"{outputTable.cLables[minDeltaIndex].Value} going inside the basis.<br>"; result += $"{outputTable.cLables[curBasis[minTetaIndex]].Value} going outside the basis.<br>"; var jordanTransform = new JordanTransform(minTetaIndex, minDeltaIndex); result += jordanTransform.MakeTransform(outputTable, out outputTable, out bool s); ReevaluateBasisAndDeltas(outputTable); int numOfVariablesBeforeRemovingUnused = outputTable.NumOfVariables; result += RemoveUnusedSinteticVariables(outputTable, out outputTable, curBasis); if (outputTable.NumOfVariables != numOfVariablesBeforeRemovingUnused) { ReevaluateBasisAndDeltas(outputTable); } result += PrintTableToHTML(outputTable, curBasis, curDelta); result += "<br><br>"; } result += checkResult; if (success) { result += FormAnswer(outputTable, curBasis); } result += "<br>"; return(result); }
protected abstract string AddConstrain(SimplexTable inputTable, out SimplexTable outputTable, out bool success);
protected abstract bool IsDone(SimplexTable table);
public override string MakeTransform(SimplexTable inputTable, out SimplexTable outputTable, out bool success) { outputTable = new SimplexTable(inputTable); string result = "<h3>Dual simplex method</h3><br>Let's use dual simplex method.<br>"; PrepareForMethod(outputTable, out outputTable, ref result); result += "Step 0:<br>"; result += PrintTableToHTML(outputTable, curBasis, curDelta); result += "<br><br>"; int iterNum = 0; string checkResult = ""; while (CanContinue(outputTable, out checkResult, out success)) { if (iterNum++ > 0) { result += $"Step {iterNum}:<br>"; } int minBIndex = FindIndexOfMin(outputTable.bVector); var gamas = new List <SimplexCoef>(); for (int j = 0; j < outputTable.NumOfVariables; j++) { if (outputTable.aMatrix[minBIndex][j].value.Sign >= 0) { gamas.Add(null); continue; } gamas.Add(curDelta[j] / (-outputTable.aMatrix[minBIndex][j])); } int minGamaIndex = FindIndexOfMin(gamas); result += $"{outputTable.cLables[minGamaIndex].Value} going inside the basis.<br>"; result += $"{outputTable.cLables[curBasis[minBIndex]].Value} going outside the basis.<br>"; var jordanTransform = new JordanTransform(minBIndex, minGamaIndex); result += jordanTransform.MakeTransform(outputTable, out outputTable, out bool s); ReevaluateBasisAndDeltas(outputTable); int numOfVariablesBeforeRemovingUnused = outputTable.NumOfVariables; result += RemoveUnusedSinteticVariables(outputTable, out outputTable, curBasis); if (outputTable.NumOfVariables != numOfVariablesBeforeRemovingUnused) { ReevaluateBasisAndDeltas(outputTable); } result += PrintTableToHTML(outputTable, curBasis, curDelta); result += "<br><br>"; } result += checkResult; if (success) { result += FormAnswer(outputTable, curBasis); } return(result); }