mirror of
https://github.com/mrfluffy-dev/lpr.git
synced 2026-01-17 02:10:33 +00:00
Lets gooooo
This commit is contained in:
15
BusinessLogic/Algorithms/Algorithm.cs
Normal file
15
BusinessLogic/Algorithms/Algorithm.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic.Algorithms
|
||||
{
|
||||
public abstract class Algorithm
|
||||
{
|
||||
public abstract void PutModelInCanonicalForm(Model model);
|
||||
public abstract void Solve(Model model);
|
||||
}
|
||||
}
|
||||
293
BusinessLogic/Algorithms/BranchAndBoundSimplex.cs
Normal file
293
BusinessLogic/Algorithms/BranchAndBoundSimplex.cs
Normal file
@@ -0,0 +1,293 @@
|
||||
using Common;
|
||||
using Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic.Algorithms
|
||||
{
|
||||
public class BranchAndBoundSimplex : Algorithm
|
||||
{
|
||||
private Model model;
|
||||
public BinaryTree Results { get; set; } = new BinaryTree();
|
||||
private DualSimplex dualSimplex = new DualSimplex();
|
||||
private List<List<List<double>>> candidateSolutions = new List<List<List<double>>>();
|
||||
|
||||
public override void PutModelInCanonicalForm(Model model)
|
||||
{
|
||||
dualSimplex.PutModelInCanonicalForm(model);
|
||||
Results.Add(model.Result);
|
||||
}
|
||||
|
||||
public override void Solve(Model model)
|
||||
{
|
||||
this.model = model;
|
||||
|
||||
int level = 1;
|
||||
while (level <= Results.GetHeight(Results.Root))
|
||||
{
|
||||
SolveCurrentLevel(Results.Root, level);
|
||||
level++;
|
||||
}
|
||||
}
|
||||
|
||||
private void SolveCurrentLevel(BinaryTreeNode root, int level)
|
||||
{
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
if (level == 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
Solve(root);
|
||||
Branch(root);
|
||||
}
|
||||
catch (InfeasibleException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (level > 1)
|
||||
{
|
||||
SolveCurrentLevel(root.LeftNode, level - 1);
|
||||
SolveCurrentLevel(root.RightNode, level - 1);
|
||||
}
|
||||
}
|
||||
|
||||
public List<List<double>> GetBestCandidate()
|
||||
{
|
||||
double bestRHS = candidateSolutions[0][0][candidateSolutions[0][0].Count - 1];
|
||||
List<List<double>> bestSolution = candidateSolutions[0];
|
||||
|
||||
for (int i = 1; i < candidateSolutions.Count; i++)
|
||||
{
|
||||
if (model.ProblemType == ProblemType.Maximization)
|
||||
{
|
||||
if (candidateSolutions[i][0][candidateSolutions[i][0].Count - 1] > bestRHS)
|
||||
{
|
||||
bestRHS = candidateSolutions[i][0][candidateSolutions[i][0].Count - 1];
|
||||
bestSolution = candidateSolutions[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (candidateSolutions[i][0][candidateSolutions[i][0].Count - 1] < bestRHS)
|
||||
{
|
||||
bestRHS = candidateSolutions[i][0][candidateSolutions[i][0].Count - 1];
|
||||
bestSolution = candidateSolutions[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bestSolution;
|
||||
}
|
||||
|
||||
private void Solve(BinaryTreeNode root)
|
||||
{
|
||||
var model = new Model() { ProblemType = this.model.ProblemType, Result = root.Data };
|
||||
dualSimplex.Solve(model);
|
||||
}
|
||||
|
||||
private void Branch(BinaryTreeNode root)
|
||||
{
|
||||
if (CanBranch(root).Count == 0)
|
||||
{
|
||||
candidateSolutions.Add(root.Data[root.Data.Count - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the variable we need to branch on
|
||||
int branchVariableIndex = GetBranchVariable(root.Data[root.Data.Count - 1], CanBranch(root));
|
||||
// Add the new constraints to the old table and add that resulting table to the binary tree
|
||||
AddSubProblems(root, branchVariableIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private void AddSubProblems(BinaryTreeNode root, int branchVariableIndex)
|
||||
{
|
||||
var table = root.Data[root.Data.Count - 1];
|
||||
double rhs = GetRhsOfVariable(branchVariableIndex, table);
|
||||
|
||||
int constraintOneRhs;
|
||||
int constraintTwoRhs;
|
||||
|
||||
constraintOneRhs = (int)Math.Truncate(rhs);
|
||||
constraintTwoRhs = constraintOneRhs + 1;
|
||||
|
||||
var subProblemOneTable = ListCloner.CloneList(table);
|
||||
var subProblemTwoTable = ListCloner.CloneList(table);
|
||||
|
||||
subProblemOneTable.Add(new List<double>());
|
||||
subProblemTwoTable.Add(new List<double>());
|
||||
|
||||
for (int i = 0; i < subProblemOneTable[0].Count - 1; i++)
|
||||
{
|
||||
if (i == branchVariableIndex)
|
||||
{
|
||||
subProblemOneTable[subProblemOneTable.Count - 1].Add(1);
|
||||
subProblemTwoTable[subProblemTwoTable.Count - 1].Add(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
subProblemOneTable[subProblemOneTable.Count - 1].Add(0);
|
||||
subProblemTwoTable[subProblemTwoTable.Count - 1].Add(0);
|
||||
}
|
||||
}
|
||||
|
||||
subProblemOneTable[subProblemOneTable.Count - 1].Add(constraintOneRhs);
|
||||
subProblemTwoTable[subProblemTwoTable.Count - 1].Add(constraintTwoRhs * -1);
|
||||
|
||||
for (int i = 0; i < subProblemOneTable.Count; i++)
|
||||
{
|
||||
var tempOne = subProblemOneTable[i][subProblemOneTable[i].Count - 1];
|
||||
var tempTwo = subProblemTwoTable[i][subProblemTwoTable[i].Count - 1];
|
||||
|
||||
if (i == subProblemOneTable.Count - 1)
|
||||
{
|
||||
subProblemOneTable[i][subProblemOneTable[i].Count - 1] = 1;
|
||||
subProblemTwoTable[i][subProblemTwoTable[i].Count - 1] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
subProblemOneTable[i][subProblemOneTable[i].Count - 1] = 0;
|
||||
subProblemTwoTable[i][subProblemTwoTable[i].Count - 1] = 0;
|
||||
}
|
||||
|
||||
subProblemOneTable[i].Add(tempOne);
|
||||
subProblemTwoTable[i].Add(tempTwo);
|
||||
}
|
||||
|
||||
int subProblemBasicRow = GetBasicRow(table, branchVariableIndex);
|
||||
|
||||
for (int i = 0; i < subProblemOneTable[subProblemBasicRow].Count; i++)
|
||||
{
|
||||
subProblemOneTable[subProblemOneTable.Count - 1][i] -= subProblemOneTable[subProblemBasicRow][i];
|
||||
subProblemTwoTable[subProblemTwoTable.Count - 1][i] += subProblemTwoTable[subProblemBasicRow][i];
|
||||
}
|
||||
|
||||
Results.Add(new List<List<List<double>>>() { subProblemOneTable }, root.Data);
|
||||
Results.Add(new List<List<List<double>>>() { subProblemTwoTable }, root.Data);
|
||||
}
|
||||
|
||||
private int GetBasicRow(List<List<double>> table, int branchVariableIndex)
|
||||
{
|
||||
int basicRow = -1;
|
||||
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
if (table[i][branchVariableIndex] == 1)
|
||||
{
|
||||
basicRow = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return basicRow;
|
||||
}
|
||||
|
||||
private int GetBranchVariable(List<List<double>> table, List<int> intBinVarIndexes)
|
||||
{
|
||||
if (intBinVarIndexes.Count == 1)
|
||||
return intBinVarIndexes[0];
|
||||
|
||||
int branchVariableIndex = -1;
|
||||
decimal smallestFractionalPart = 1;
|
||||
|
||||
foreach (var intBinVar in intBinVarIndexes)
|
||||
{
|
||||
var rhs = (Decimal)GetRhsOfVariable(intBinVar, table);
|
||||
decimal fractionalPart = rhs - Math.Truncate(rhs);
|
||||
if (Math.Abs(0.5m - fractionalPart) < smallestFractionalPart)
|
||||
{
|
||||
smallestFractionalPart = Math.Abs(0.5m - fractionalPart);
|
||||
branchVariableIndex = intBinVar;
|
||||
}
|
||||
}
|
||||
|
||||
return branchVariableIndex;
|
||||
}
|
||||
|
||||
private List<int> CanBranch(BinaryTreeNode root)
|
||||
{
|
||||
var intBinVarIndexes = new List<int>();
|
||||
var indexesToDiscard = new List<int>();
|
||||
|
||||
for (int i = 0; i < model.SignRestrictions.Count; i++)
|
||||
{
|
||||
if (model.SignRestrictions[i] == SignRestriction.Integer || model.SignRestrictions[i] == SignRestriction.Binary)
|
||||
{
|
||||
intBinVarIndexes.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var table = root.Data[root.Data.Count - 1];
|
||||
|
||||
foreach (var intBinVar in intBinVarIndexes)
|
||||
{
|
||||
|
||||
if (!IsVariableBasic(intBinVar, table))
|
||||
{
|
||||
indexesToDiscard.Add(intBinVar);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
double rhs = GetRhsOfVariable(intBinVar, table);
|
||||
|
||||
if (rhs - Math.Truncate(rhs) < 0.00001)
|
||||
{
|
||||
indexesToDiscard.Add(intBinVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intBinVarIndexes.RemoveAll(v => indexesToDiscard.Contains(v) == true);
|
||||
|
||||
return intBinVarIndexes;
|
||||
}
|
||||
|
||||
private double GetRhsOfVariable(int intBinVar, List<List<double>> table)
|
||||
{
|
||||
if (!IsVariableBasic(intBinVar, table))
|
||||
return 0;
|
||||
|
||||
double rhs = 0;
|
||||
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
if (table[i][intBinVar] == 1)
|
||||
{
|
||||
rhs = table[i][table[i].Count - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rhs;
|
||||
}
|
||||
|
||||
private bool IsVariableBasic(int intBinVar, List<List<double>> table)
|
||||
{
|
||||
bool isBasic = true;
|
||||
|
||||
for (int i = 0; i < table.Count; i++)
|
||||
{
|
||||
int numberOfOnes = 0;
|
||||
|
||||
if (table[i][intBinVar] == 1)
|
||||
numberOfOnes++;
|
||||
|
||||
if ((table[i][intBinVar] != 0 && table[i][intBinVar] != 1) || numberOfOnes > 1)
|
||||
{
|
||||
isBasic = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isBasic;
|
||||
}
|
||||
}
|
||||
}
|
||||
203
BusinessLogic/Algorithms/CuttingPlane.cs
Normal file
203
BusinessLogic/Algorithms/CuttingPlane.cs
Normal file
@@ -0,0 +1,203 @@
|
||||
using Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic.Algorithms
|
||||
{
|
||||
public class CuttingPlane : Algorithm
|
||||
{
|
||||
|
||||
|
||||
private DualSimplex dualSimplex = new DualSimplex();
|
||||
|
||||
public override void PutModelInCanonicalForm(Model model)
|
||||
{
|
||||
dualSimplex.PutModelInCanonicalForm(model);
|
||||
|
||||
dualSimplex.Solve(model);
|
||||
}
|
||||
|
||||
public override void Solve(Model model)
|
||||
{
|
||||
while (CanCut(model).Count > 0)
|
||||
{
|
||||
Cut(model);
|
||||
dualSimplex.Solve(model);
|
||||
}
|
||||
}
|
||||
|
||||
private void Cut(Model model)
|
||||
{
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
|
||||
int cutVariableIndex = GetCutVariable(table, CanCut(model));
|
||||
|
||||
|
||||
int basicRow = GetBasicRow(table, cutVariableIndex);
|
||||
|
||||
List<double> cutConstraint = GetCutConstraint(table, basicRow);
|
||||
|
||||
var newTable = ListCloner.CloneList(table);
|
||||
|
||||
newTable.Add(cutConstraint);
|
||||
|
||||
|
||||
for (int i = 0; i < newTable.Count; i++)
|
||||
{
|
||||
if (i == newTable.Count - 1)
|
||||
{
|
||||
newTable[i].Insert(newTable[i].Count - 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
newTable[i].Insert(newTable[i].Count - 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
model.Result.Add(newTable);
|
||||
}
|
||||
|
||||
private List<double> GetCutConstraint(List<List<double>> table, int basicRow)
|
||||
{
|
||||
List<double> cutConstraint = new List<double>();
|
||||
|
||||
for (int i = 0; i < table[basicRow].Count; i++)
|
||||
{
|
||||
|
||||
if (table[basicRow][i] == Math.Truncate(table[basicRow][i]))
|
||||
{
|
||||
cutConstraint.Add(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
double fractionalPart = Math.Abs(Math.Floor(table[basicRow][i]) - table[basicRow][i]);
|
||||
cutConstraint.Add(-1 * fractionalPart);
|
||||
}
|
||||
}
|
||||
|
||||
return cutConstraint;
|
||||
}
|
||||
|
||||
private List<int> CanCut(Model model)
|
||||
{
|
||||
List<int> intBinVarIndexes = new List<int>();
|
||||
List<int> indexesToDiscard = new List<int>();
|
||||
var lastTable = model.Result[model.Result.Count - 1];
|
||||
|
||||
for (int i = 0; i < model.SignRestrictions.Count; i++)
|
||||
{
|
||||
if (model.SignRestrictions[i] == SignRestriction.Integer || model.SignRestrictions[i] == SignRestriction.Binary)
|
||||
{
|
||||
intBinVarIndexes.Add(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var intBinVar in intBinVarIndexes)
|
||||
{
|
||||
|
||||
if (!IsVariableBasic(intBinVar, lastTable))
|
||||
{
|
||||
indexesToDiscard.Add(intBinVar);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
double rhs = GetRhsOfVariable(intBinVar, lastTable);
|
||||
|
||||
if (rhs - Math.Truncate(rhs) < 0.00001)
|
||||
{
|
||||
indexesToDiscard.Add(intBinVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
intBinVarIndexes.RemoveAll(v => indexesToDiscard.Contains(v) == true);
|
||||
|
||||
return intBinVarIndexes;
|
||||
}
|
||||
|
||||
private double GetRhsOfVariable(int intBinVar, List<List<double>> table)
|
||||
{
|
||||
if (!IsVariableBasic(intBinVar, table))
|
||||
return 0;
|
||||
|
||||
double rhs = 0;
|
||||
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
if (table[i][intBinVar] == 1)
|
||||
{
|
||||
rhs = table[i][table[i].Count - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rhs;
|
||||
}
|
||||
|
||||
private bool IsVariableBasic(int intBinVar, List<List<double>> table)
|
||||
{
|
||||
bool isBasic = true;
|
||||
|
||||
for (int i = 0; i < table.Count; i++)
|
||||
{
|
||||
int numberOfOnes = 0;
|
||||
|
||||
if (table[i][intBinVar] == 1)
|
||||
numberOfOnes++;
|
||||
|
||||
if ((table[i][intBinVar] != 0 && table[i][intBinVar] != 1) || numberOfOnes > 1)
|
||||
{
|
||||
isBasic = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isBasic;
|
||||
}
|
||||
|
||||
private int GetCutVariable(List<List<double>> table, List<int> intBinVarIndexes)
|
||||
{
|
||||
if (intBinVarIndexes.Count == 1)
|
||||
return intBinVarIndexes[0];
|
||||
|
||||
int branchVariableIndex = -1;
|
||||
decimal smallestFractionalPart = 1;
|
||||
|
||||
foreach (var intBinVar in intBinVarIndexes)
|
||||
{
|
||||
var rhs = (Decimal)GetRhsOfVariable(intBinVar, table);
|
||||
decimal fractionalPart = rhs - Math.Truncate(rhs);
|
||||
if (Math.Abs(0.5m - fractionalPart) < smallestFractionalPart)
|
||||
{
|
||||
smallestFractionalPart = Math.Abs(0.5m - fractionalPart);
|
||||
branchVariableIndex = intBinVar;
|
||||
}
|
||||
}
|
||||
|
||||
return branchVariableIndex;
|
||||
}
|
||||
|
||||
private int GetBasicRow(List<List<double>> table, int variableIndex)
|
||||
{
|
||||
int basicRow = -1;
|
||||
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
if (table[i][variableIndex] == 1)
|
||||
{
|
||||
basicRow = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return basicRow;
|
||||
}
|
||||
}
|
||||
}
|
||||
223
BusinessLogic/Algorithms/DualSimplex.cs
Normal file
223
BusinessLogic/Algorithms/DualSimplex.cs
Normal file
@@ -0,0 +1,223 @@
|
||||
using Common;
|
||||
using Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic.Algorithms
|
||||
{
|
||||
public class DualSimplex : Algorithm
|
||||
{
|
||||
public override void PutModelInCanonicalForm(Model model)
|
||||
{
|
||||
|
||||
List<List<double>> tableZero = new List<List<double>>();
|
||||
|
||||
tableZero.Add(new List<double>());
|
||||
|
||||
foreach (var decVar in model.ObjectiveFunction.DecisionVariables)
|
||||
{
|
||||
tableZero[0].Add(decVar.Coefficient * -1);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < model.Constraints.Count; i++)
|
||||
{
|
||||
tableZero[0].Add(0);
|
||||
if (model.Constraints[i].InequalitySign == InequalitySign.EqualTo)
|
||||
tableZero[0].Add(0);
|
||||
}
|
||||
|
||||
tableZero[0].Add(0);
|
||||
|
||||
var equalsConstraints = model.Constraints.Where(c => c.InequalitySign == InequalitySign.EqualTo).ToList();
|
||||
if (equalsConstraints?.Count() > 0)
|
||||
{
|
||||
for (int i = 0; i < equalsConstraints.Count(); i++)
|
||||
{
|
||||
model.Constraints[model.Constraints.FindIndex(c => c == equalsConstraints[i])].InequalitySign = InequalitySign.LessThanOrEqualTo;
|
||||
var newConstraint = new Constraint();
|
||||
newConstraint.InequalitySign = InequalitySign.GreaterThanOrEqualTo;
|
||||
newConstraint.RightHandSide = equalsConstraints[i].RightHandSide;
|
||||
|
||||
foreach (var decVar in equalsConstraints[i].DecisionVariables)
|
||||
{
|
||||
newConstraint.DecisionVariables.Add(new DecisionVariable() { Coefficient = decVar.Coefficient });
|
||||
}
|
||||
|
||||
model.Constraints.Add(newConstraint);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < model.Constraints.Count; i++)
|
||||
{
|
||||
List<double> constraintValues = new List<double>();
|
||||
|
||||
|
||||
foreach (var decVar in model.Constraints[i].DecisionVariables)
|
||||
{
|
||||
if (model.Constraints[i].InequalitySign == InequalitySign.LessThanOrEqualTo)
|
||||
{
|
||||
constraintValues.Add(decVar.Coefficient);
|
||||
}
|
||||
else
|
||||
{
|
||||
constraintValues.Add(decVar.Coefficient * -1);
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < model.Constraints.Count; j++)
|
||||
{
|
||||
if (j == i)
|
||||
{
|
||||
constraintValues.Add(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
constraintValues.Add(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (model.Constraints[i].InequalitySign == InequalitySign.LessThanOrEqualTo)
|
||||
{
|
||||
constraintValues.Add(model.Constraints[i].RightHandSide);
|
||||
}
|
||||
else
|
||||
{
|
||||
constraintValues.Add(model.Constraints[i].RightHandSide * -1);
|
||||
}
|
||||
|
||||
tableZero.Add(constraintValues);
|
||||
}
|
||||
|
||||
model.Result.Add(tableZero);
|
||||
}
|
||||
|
||||
public override void Solve(Model model)
|
||||
{
|
||||
Iterate(model);
|
||||
var primalSimplex = new PrimalSimplex();
|
||||
primalSimplex.Solve(model);
|
||||
}
|
||||
|
||||
private void Iterate(Model model)
|
||||
{
|
||||
|
||||
if (!CanPivot(model))
|
||||
return;
|
||||
|
||||
|
||||
int pivotRow = GetPivotRow(model);
|
||||
|
||||
int pivotColumn = GetPivotColumn(model, pivotRow);
|
||||
|
||||
if (pivotColumn == -1)
|
||||
throw new InfeasibleException("There is no suitable column to pivot on - the problem is infeasible");
|
||||
|
||||
Pivot(model, pivotRow, pivotColumn);
|
||||
|
||||
|
||||
Iterate(model);
|
||||
}
|
||||
|
||||
private bool CanPivot(Model model)
|
||||
{
|
||||
|
||||
bool canPivot = false;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
|
||||
if (table[i][table[i].Count - 1] < -0.000000000001)
|
||||
{
|
||||
canPivot = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return canPivot;
|
||||
}
|
||||
|
||||
private int GetPivotRow(Model model)
|
||||
{
|
||||
int pivotRow = -1;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
double mostNegative = 0;
|
||||
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
if (table[i][table[i].Count - 1] < 0 && table[i][table[i].Count - 1] < mostNegative)
|
||||
{
|
||||
mostNegative = table[i][table[i].Count - 1];
|
||||
pivotRow = i;
|
||||
}
|
||||
}
|
||||
|
||||
return pivotRow;
|
||||
}
|
||||
|
||||
private int GetPivotColumn(Model model, int pivotRow)
|
||||
{
|
||||
int pivotColumn = -1;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
double lowestRatio = double.MaxValue;
|
||||
for (int i = 0; i < table[0].Count - 1; i++)
|
||||
{
|
||||
if (table[pivotRow][i] < 0)
|
||||
{
|
||||
double ratio = Math.Abs(table[0][i] / table[pivotRow][i]);
|
||||
if (ratio < lowestRatio)
|
||||
{
|
||||
lowestRatio = ratio;
|
||||
pivotColumn = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pivotColumn;
|
||||
}
|
||||
|
||||
private void Pivot(Model model, int pivotRow, int pivotColumn)
|
||||
{
|
||||
var previousTable = model.Result[model.Result.Count - 1];
|
||||
var newTable = new List<List<double>>();
|
||||
|
||||
for (int i = 0; i < previousTable.Count; i++)
|
||||
{
|
||||
newTable.Add(new List<double>());
|
||||
|
||||
for (int j = 0; j < previousTable[i].Count; j++)
|
||||
{
|
||||
newTable[i].Add(previousTable[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double factor = 1 / newTable[pivotRow][pivotColumn];
|
||||
for (int i = 0; i < newTable[pivotRow].Count; i++)
|
||||
{
|
||||
newTable[pivotRow][i] *= factor;
|
||||
}
|
||||
|
||||
double pivotColumnValue;
|
||||
for (int i = 0; i < newTable.Count; i++)
|
||||
{
|
||||
pivotColumnValue = newTable[i][pivotColumn];
|
||||
|
||||
if (i != pivotRow && pivotColumnValue != 0)
|
||||
{
|
||||
for (int j = 0; j < newTable[i].Count; j++)
|
||||
{
|
||||
newTable[i][j] += (-1 * pivotColumnValue * newTable[pivotRow][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.Result.Add(newTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
212
BusinessLogic/Algorithms/PrimalSimplex.cs
Normal file
212
BusinessLogic/Algorithms/PrimalSimplex.cs
Normal file
@@ -0,0 +1,212 @@
|
||||
using Common;
|
||||
using Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic.Algorithms
|
||||
{
|
||||
public class PrimalSimplex : Algorithm
|
||||
{
|
||||
public override void PutModelInCanonicalForm(Model model)
|
||||
{
|
||||
|
||||
List<List<double>> tableZero = new List<List<double>>();
|
||||
|
||||
|
||||
tableZero.Add(new List<double>());
|
||||
|
||||
foreach (var decVar in model.ObjectiveFunction.DecisionVariables)
|
||||
{
|
||||
tableZero[0].Add(decVar.Coefficient * -1);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i <= model.Constraints.Count; i++)
|
||||
{
|
||||
tableZero[0].Add(0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < model.Constraints.Count; i++)
|
||||
{
|
||||
List<double> constraintValues = new List<double>();
|
||||
|
||||
foreach (var decVar in model.Constraints[i].DecisionVariables)
|
||||
{
|
||||
constraintValues.Add(decVar.Coefficient);
|
||||
}
|
||||
|
||||
for (int j = 0; j < model.Constraints.Count; j++)
|
||||
{
|
||||
if (j == i)
|
||||
{
|
||||
constraintValues.Add(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
constraintValues.Add(0);
|
||||
}
|
||||
}
|
||||
|
||||
constraintValues.Add(model.Constraints[i].RightHandSide);
|
||||
|
||||
tableZero.Add(constraintValues);
|
||||
}
|
||||
|
||||
model.Result.Add(tableZero);
|
||||
}
|
||||
|
||||
public override void Solve(Model model)
|
||||
{
|
||||
Iterate(model);
|
||||
}
|
||||
|
||||
private bool IsOptimal(Model model)
|
||||
{
|
||||
bool isOptimal = true;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
if (model.ProblemType == ProblemType.Maximization)
|
||||
{
|
||||
for (int i = 0; i < table[0].Count - 1; i++)
|
||||
{
|
||||
if (table[0][i] < 0)
|
||||
{
|
||||
isOptimal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < table[0].Count - 1; i++)
|
||||
{
|
||||
if (table[0][i] > 0)
|
||||
{
|
||||
isOptimal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isOptimal;
|
||||
}
|
||||
|
||||
private void Iterate(Model model)
|
||||
{
|
||||
|
||||
if (IsOptimal(model))
|
||||
return;
|
||||
|
||||
|
||||
int pivotColumn = GetPivotColumn(model);
|
||||
// Then get the pivot row
|
||||
int pivotRow = GetPivotRow(model, pivotColumn);
|
||||
|
||||
if (pivotRow == -1)
|
||||
throw new InfeasibleException("There is no suitable row to pivot on - the problem is infeasible");
|
||||
|
||||
Pivot(model, pivotRow, pivotColumn);
|
||||
|
||||
Iterate(model);
|
||||
}
|
||||
|
||||
private void Pivot(Model model, int pivotRow, int pivotColumn)
|
||||
{
|
||||
var previousTable = model.Result[model.Result.Count - 1];
|
||||
var newTable = new List<List<double>>();
|
||||
|
||||
for (int i = 0; i < previousTable.Count; i++)
|
||||
{
|
||||
newTable.Add(new List<double>());
|
||||
|
||||
for (int j = 0; j < previousTable[i].Count; j++)
|
||||
{
|
||||
newTable[i].Add(previousTable[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double factor = 1 / newTable[pivotRow][pivotColumn];
|
||||
for (int i = 0; i < newTable[pivotRow].Count; i++)
|
||||
{
|
||||
newTable[pivotRow][i] *= factor;
|
||||
}
|
||||
|
||||
double pivotColumnValue;
|
||||
for (int i = 0; i < newTable.Count; i++)
|
||||
{
|
||||
pivotColumnValue = newTable[i][pivotColumn];
|
||||
|
||||
if (i != pivotRow && pivotColumnValue != 0)
|
||||
{
|
||||
for (int j = 0; j < newTable[i].Count; j++)
|
||||
{
|
||||
newTable[i][j] += (-1 * pivotColumnValue * newTable[pivotRow][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.Result.Add(newTable);
|
||||
}
|
||||
|
||||
private int GetPivotColumn(Model model)
|
||||
{
|
||||
int colIndex = -1;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
if (model.ProblemType == ProblemType.Maximization)
|
||||
{
|
||||
double mostNegative = 0;
|
||||
|
||||
for (int i = 0; i < table[0].Count - 1; i++)
|
||||
{
|
||||
if (table[0][i] < 0 && table[0][i] < mostNegative)
|
||||
{
|
||||
mostNegative = table[0][i];
|
||||
colIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double mostPositive = 0;
|
||||
|
||||
for (int i = 0; i < table[0].Count - 1; i++)
|
||||
{
|
||||
if (table[0][i] > 0 && table[0][i] > mostPositive)
|
||||
{
|
||||
mostPositive = table[0][i];
|
||||
colIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return colIndex;
|
||||
}
|
||||
|
||||
private int GetPivotRow(Model model, int pivotColumn)
|
||||
{
|
||||
int rowIndex = -1;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
double lowestRatio = double.MaxValue;
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
if (table[i][pivotColumn] > 0)
|
||||
{
|
||||
double ratio = table[i][table[i].Count - 1] / table[i][pivotColumn];
|
||||
if (ratio < lowestRatio && ratio >= 0)
|
||||
{
|
||||
lowestRatio = ratio;
|
||||
rowIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rowIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
346
BusinessLogic/Algorithms/TwoPhaseSimplex.cs
Normal file
346
BusinessLogic/Algorithms/TwoPhaseSimplex.cs
Normal file
@@ -0,0 +1,346 @@
|
||||
using Common;
|
||||
using Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic.Algorithms
|
||||
{
|
||||
public class TwoPhaseSimplex : Algorithm
|
||||
{
|
||||
private int numberOfArtificialVars = 0;
|
||||
|
||||
public override void PutModelInCanonicalForm(Model model)
|
||||
{
|
||||
|
||||
for (int i = 0; i < model.Constraints.Count; i++)
|
||||
{
|
||||
if (model.Constraints[i].RightHandSide < 0)
|
||||
{
|
||||
for (int j = 0; j < model.Constraints[i].DecisionVariables.Count; j++)
|
||||
{
|
||||
model.Constraints[i].DecisionVariables[j].Coefficient *= -1;
|
||||
}
|
||||
|
||||
model.Constraints[i].RightHandSide *= -1;
|
||||
|
||||
if (model.Constraints[i].InequalitySign == InequalitySign.LessThanOrEqualTo)
|
||||
{
|
||||
model.Constraints[i].InequalitySign = InequalitySign.GreaterThanOrEqualTo;
|
||||
}
|
||||
else if (model.Constraints[i].InequalitySign == InequalitySign.GreaterThanOrEqualTo)
|
||||
{
|
||||
model.Constraints[i].InequalitySign = InequalitySign.LessThanOrEqualTo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<List<double>> tableZero = new List<List<double>>();
|
||||
|
||||
|
||||
tableZero.Add(new List<double>());
|
||||
|
||||
foreach (var decVar in model.ObjectiveFunction.DecisionVariables)
|
||||
{
|
||||
tableZero[0].Add(decVar.Coefficient * -1);
|
||||
}
|
||||
|
||||
foreach (var constraint in model.Constraints)
|
||||
{
|
||||
if (constraint.InequalitySign == InequalitySign.LessThanOrEqualTo ||
|
||||
constraint.InequalitySign == InequalitySign.GreaterThanOrEqualTo)
|
||||
{
|
||||
tableZero[0].Add(0);
|
||||
}
|
||||
|
||||
if (constraint.InequalitySign == InequalitySign.EqualTo ||
|
||||
constraint.InequalitySign == InequalitySign.GreaterThanOrEqualTo)
|
||||
{
|
||||
tableZero[0].Add(0);
|
||||
}
|
||||
}
|
||||
|
||||
tableZero[0].Add(0);
|
||||
|
||||
for (int i = 0; i < model.Constraints.Count; i++)
|
||||
{
|
||||
List<double> constraintValues = new List<double>();
|
||||
|
||||
foreach (var decVar in model.Constraints[i].DecisionVariables)
|
||||
{
|
||||
constraintValues.Add(decVar.Coefficient);
|
||||
}
|
||||
|
||||
for (int j = 0; j < model.Constraints.Count; j++)
|
||||
{
|
||||
if (model.Constraints[j].InequalitySign == InequalitySign.LessThanOrEqualTo)
|
||||
{
|
||||
if (j == i)
|
||||
{
|
||||
constraintValues.Add(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
constraintValues.Add(0);
|
||||
}
|
||||
}
|
||||
else if (model.Constraints[j].InequalitySign == InequalitySign.GreaterThanOrEqualTo)
|
||||
{
|
||||
if (j == i)
|
||||
{
|
||||
constraintValues.Add(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
constraintValues.Add(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constraintValues.Add(model.Constraints[i].RightHandSide);
|
||||
|
||||
for (int j = 0; j < model.Constraints.Count; j++)
|
||||
{
|
||||
if (model.Constraints[j].InequalitySign == InequalitySign.EqualTo ||
|
||||
model.Constraints[j].InequalitySign == InequalitySign.GreaterThanOrEqualTo)
|
||||
{
|
||||
if (j == i)
|
||||
{
|
||||
constraintValues.Insert(constraintValues.Count - 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
constraintValues.Insert(constraintValues.Count - 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tableZero.Add(constraintValues);
|
||||
}
|
||||
|
||||
numberOfArtificialVars = model.Constraints.Where(c => c.InequalitySign ==
|
||||
InequalitySign.EqualTo || c.InequalitySign == InequalitySign.GreaterThanOrEqualTo).Count();
|
||||
|
||||
List<double> wRow = new List<double>();
|
||||
for (int i = 0; i < tableZero[0].Count; i++)
|
||||
{
|
||||
wRow.Add(0);
|
||||
}
|
||||
|
||||
for (int i = 1; i < tableZero.Count; i++)
|
||||
{
|
||||
if (model.Constraints[i - 1].InequalitySign == InequalitySign.EqualTo ||
|
||||
model.Constraints[i - 1].InequalitySign == InequalitySign.GreaterThanOrEqualTo)
|
||||
{
|
||||
for (int j = 0; j < (tableZero[i].Count - numberOfArtificialVars - 1); j++)
|
||||
{
|
||||
wRow[j] += tableZero[i][j];
|
||||
}
|
||||
|
||||
wRow[wRow.Count - 1] += tableZero[i][tableZero[i].Count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
tableZero.Insert(0, wRow);
|
||||
model.Result.Add(tableZero);
|
||||
}
|
||||
|
||||
public override void Solve(Model model)
|
||||
{
|
||||
Iterate(model);
|
||||
var lastTable = model.Result[model.Result.Count - 1];
|
||||
|
||||
if (lastTable[0][lastTable[0].Count - 1] > 0)
|
||||
{
|
||||
throw new InfeasibleException("The problem is infeasible");
|
||||
}
|
||||
|
||||
bool allArtificialsNonBasic = true;
|
||||
for (int i = lastTable[0].Count - (numberOfArtificialVars + 1); i < lastTable[0].Count - 1; i++)
|
||||
{
|
||||
if (IsVariableBasic(i, lastTable))
|
||||
{
|
||||
allArtificialsNonBasic = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allArtificialsNonBasic)
|
||||
{
|
||||
lastTable.RemoveAt(0);
|
||||
|
||||
for (int i = 0; i < lastTable.Count; i++)
|
||||
{
|
||||
for (int j = 0; j < numberOfArtificialVars; j++)
|
||||
{
|
||||
lastTable[i].RemoveAt(lastTable[i].Count - 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < model.ObjectiveFunction.DecisionVariables.Count; i++)
|
||||
{
|
||||
if (lastTable[0][i] < 0)
|
||||
{
|
||||
for (int j = 0; j < lastTable.Count; j++)
|
||||
{
|
||||
lastTable[j].RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = lastTable[0].Count - (numberOfArtificialVars + 1); i < lastTable[0].Count - 1; i++)
|
||||
{
|
||||
if (!IsVariableBasic(i, lastTable))
|
||||
{
|
||||
for (int j = 0; j < lastTable.Count; j++)
|
||||
{
|
||||
lastTable[j].RemoveAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lastTable.RemoveAt(0);
|
||||
}
|
||||
|
||||
var primalSimplex = new PrimalSimplex();
|
||||
primalSimplex.Solve(model);
|
||||
}
|
||||
|
||||
private bool IsOptimal(Model model)
|
||||
{
|
||||
bool isOptimal = true;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
for (int i = 0; i < table[0].Count - 1; i++)
|
||||
{
|
||||
if (table[0][i] > 0)
|
||||
{
|
||||
isOptimal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isOptimal;
|
||||
}
|
||||
|
||||
private void Iterate(Model model)
|
||||
{
|
||||
if (IsOptimal(model))
|
||||
return;
|
||||
|
||||
int pivotColumn = GetPivotColumn(model);
|
||||
int pivotRow = GetPivotRow(model, pivotColumn);
|
||||
|
||||
if (pivotRow == -1)
|
||||
throw new InfeasibleException("There is no suitable row to pivot on - the problem is infeasible");
|
||||
|
||||
Pivot(model, pivotRow, pivotColumn);
|
||||
|
||||
Iterate(model);
|
||||
}
|
||||
|
||||
private void Pivot(Model model, int pivotRow, int pivotColumn)
|
||||
{
|
||||
var previousTable = model.Result[model.Result.Count - 1];
|
||||
var newTable = new List<List<double>>();
|
||||
|
||||
for (int i = 0; i < previousTable.Count; i++)
|
||||
{
|
||||
newTable.Add(new List<double>());
|
||||
|
||||
for (int j = 0; j < previousTable[i].Count; j++)
|
||||
{
|
||||
newTable[i].Add(previousTable[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
double factor = 1 / newTable[pivotRow][pivotColumn];
|
||||
for (int i = 0; i < newTable[pivotRow].Count; i++)
|
||||
{
|
||||
newTable[pivotRow][i] *= factor;
|
||||
}
|
||||
|
||||
double pivotColumnValue;
|
||||
for (int i = 0; i < newTable.Count; i++)
|
||||
{
|
||||
pivotColumnValue = newTable[i][pivotColumn];
|
||||
|
||||
if (i != pivotRow && pivotColumnValue != 0)
|
||||
{
|
||||
for (int j = 0; j < newTable[i].Count; j++)
|
||||
{
|
||||
newTable[i][j] += (-1 * pivotColumnValue * newTable[pivotRow][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
model.Result.Add(newTable);
|
||||
}
|
||||
|
||||
private int GetPivotColumn(Model model)
|
||||
{
|
||||
int colIndex = -1;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
double mostPositive = 0;
|
||||
|
||||
for (int i = 0; i < table[0].Count - 1; i++)
|
||||
{
|
||||
if (table[0][i] > 0 && table[0][i] > mostPositive)
|
||||
{
|
||||
mostPositive = table[0][i];
|
||||
colIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return colIndex;
|
||||
}
|
||||
|
||||
private int GetPivotRow(Model model, int pivotColumn)
|
||||
{
|
||||
int rowIndex = -1;
|
||||
var table = model.Result[model.Result.Count - 1];
|
||||
|
||||
double lowestRatio = double.MaxValue;
|
||||
for (int i = 1; i < table.Count; i++)
|
||||
{
|
||||
if (table[i][pivotColumn] > 0)
|
||||
{
|
||||
double ratio = table[i][table[i].Count - 1] / table[i][pivotColumn];
|
||||
if (ratio < lowestRatio && ratio >= 0)
|
||||
{
|
||||
lowestRatio = ratio;
|
||||
rowIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rowIndex;
|
||||
}
|
||||
|
||||
private bool IsVariableBasic(int index, List<List<double>> table)
|
||||
{
|
||||
bool isBasic = true;
|
||||
|
||||
for (int i = 0; i < table.Count; i++)
|
||||
{
|
||||
int numberOfOnes = 0;
|
||||
|
||||
if (table[i][index] == 1)
|
||||
numberOfOnes++;
|
||||
|
||||
if ((table[i][index] != 0 && table[i][index] != 1) || numberOfOnes > 1)
|
||||
{
|
||||
isBasic = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return isBasic;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
BusinessLogic/BinaryTree.cs
Normal file
69
BusinessLogic/BinaryTree.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic
|
||||
{
|
||||
public class BinaryTree
|
||||
{
|
||||
public BinaryTreeNode Root { get; set; }
|
||||
|
||||
public void Add(List<List<List<double>>> subProblem, List<List<List<double>>> parentProblem = null)
|
||||
{
|
||||
BinaryTreeNode newNode = new BinaryTreeNode();
|
||||
newNode.Data = subProblem;
|
||||
|
||||
if (Root == null)
|
||||
{
|
||||
Root = newNode;
|
||||
return;
|
||||
}
|
||||
|
||||
if (parentProblem != null)
|
||||
{
|
||||
BinaryTreeNode parentNode = Find(parentProblem);
|
||||
if (parentNode != null && parentNode.LeftNode == null)
|
||||
{
|
||||
parentNode.LeftNode = newNode;
|
||||
return;
|
||||
}
|
||||
|
||||
if (parentNode != null && parentNode.RightNode == null)
|
||||
{
|
||||
parentNode.RightNode = newNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BinaryTreeNode Find(List<List<List<double>>> subProblem)
|
||||
{
|
||||
return this.Find(subProblem, this.Root);
|
||||
}
|
||||
|
||||
private BinaryTreeNode Find(List<List<List<double>>> subProblem, BinaryTreeNode parent)
|
||||
{
|
||||
if (parent == null)
|
||||
return null;
|
||||
|
||||
if (parent.Data == subProblem)
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
|
||||
return Find(subProblem, parent.LeftNode) == null ? Find(subProblem, parent.RightNode) : Find(subProblem, parent.LeftNode);
|
||||
}
|
||||
|
||||
public int GetHeight(BinaryTreeNode root)
|
||||
{
|
||||
if (root == null)
|
||||
return 0;
|
||||
|
||||
int leftHeight = GetHeight(root.LeftNode);
|
||||
int rightHeight = GetHeight(root.RightNode);
|
||||
|
||||
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
BusinessLogic/BinaryTreeNode.cs
Normal file
15
BusinessLogic/BinaryTreeNode.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic
|
||||
{
|
||||
public class BinaryTreeNode
|
||||
{
|
||||
public BinaryTreeNode LeftNode { get; set; }
|
||||
public BinaryTreeNode RightNode { get; set; }
|
||||
public List<List<List<double>>> Data { get; set; }
|
||||
}
|
||||
}
|
||||
67
BusinessLogic/BusinessLogic.csproj
Normal file
67
BusinessLogic/BusinessLogic.csproj
Normal file
@@ -0,0 +1,67 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F904DA9B-8BA5-4803-88C1-24A6471C7FEF}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>BusinessLogic</RootNamespace>
|
||||
<AssemblyName>BusinessLogic</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Algorithms\Algorithm.cs" />
|
||||
<Compile Include="Algorithms\BranchAndBoundSimplex.cs" />
|
||||
<Compile Include="Algorithms\CuttingPlane.cs" />
|
||||
<Compile Include="Algorithms\DualSimplex.cs" />
|
||||
<Compile Include="Algorithms\PrimalSimplex.cs" />
|
||||
<Compile Include="Algorithms\TwoPhaseSimplex.cs" />
|
||||
<Compile Include="BinaryTree.cs" />
|
||||
<Compile Include="BinaryTreeNode.cs" />
|
||||
<Compile Include="ListCloner.cs" />
|
||||
<Compile Include="ModelSolver.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DataAccess\DataAccess.csproj">
|
||||
<Project>{02E85643-5DA8-4A1E-AF07-10184FC132A0}</Project>
|
||||
<Name>DataAccess</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Models\Common.csproj">
|
||||
<Project>{04C11623-F02E-45C6-8C51-82244CFF4780}</Project>
|
||||
<Name>Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
57
BusinessLogic/ListCloner.cs
Normal file
57
BusinessLogic/ListCloner.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic
|
||||
{
|
||||
public class ListCloner
|
||||
{
|
||||
public static List<List<List<double>>> CloneList(List<List<List<double>>> oldList)
|
||||
{
|
||||
List<List<List<double>>> newList = new List<List<List<double>>>();
|
||||
|
||||
int iterationCount = oldList.Count;
|
||||
int rowCount = oldList[0].Count;
|
||||
int colCount = oldList[0][0].Count;
|
||||
|
||||
for (int i = 0; i < iterationCount; i++)
|
||||
{
|
||||
var table = new List<List<double>>();
|
||||
for (int j = 0; j < rowCount; j++)
|
||||
{
|
||||
var row = new List<double>();
|
||||
for (int k = 0; k < colCount; k++)
|
||||
{
|
||||
row.Add(oldList[i][j][k]);
|
||||
}
|
||||
table.Add(row);
|
||||
}
|
||||
newList.Add(table);
|
||||
}
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
public static List<List<double>> CloneList(List<List<double>> oldList)
|
||||
{
|
||||
List<List<double>> newList = new List<List<double>>();
|
||||
|
||||
int rowCount = oldList.Count;
|
||||
int colCount = oldList[0].Count;
|
||||
|
||||
for (int i = 0; i < rowCount; i++)
|
||||
{
|
||||
var newRow = new List<double>();
|
||||
for (int j = 0; j < colCount; j++)
|
||||
{
|
||||
newRow.Add(oldList[i][j]);
|
||||
}
|
||||
newList.Add(newRow);
|
||||
}
|
||||
|
||||
return newList;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
BusinessLogic/ModelSolver.cs
Normal file
25
BusinessLogic/ModelSolver.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using BusinessLogic.Algorithms;
|
||||
using Common;
|
||||
using DataAccess;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BusinessLogic
|
||||
{
|
||||
public class ModelSolver
|
||||
{
|
||||
public static void Solve(Model model, Algorithm algorithm)
|
||||
{
|
||||
algorithm.PutModelInCanonicalForm(model);
|
||||
|
||||
algorithm.Solve(model);
|
||||
|
||||
Console.Clear();
|
||||
Console.WriteLine("Here is the solution:");
|
||||
Console.WriteLine("=========================================================================================================");
|
||||
}
|
||||
}
|
||||
}
|
||||
36
BusinessLogic/Properties/AssemblyInfo.cs
Normal file
36
BusinessLogic/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("BusinessLogic")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("BusinessLogic")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("f904da9b-8ba5-4803-88c1-24a6471c7fef")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
Reference in New Issue
Block a user