-
-
Save mik30s/f285b99ad96589be60553d83a48d85c1 to your computer and use it in GitHub Desktop.
// The Following solves a linear programming problem | |
// In standardized form using the simplex method | |
// Please the read below. | |
/************************************************USAGE************************************************************* | |
* 1.Create an instance of the simplex class | |
* 2.Fill in the table with the standardized form of the problem by calling simplex.fillTable() | |
* 3.Create a while loop and call the simplex.compute() method until it returns ERROR.IS_OPTIMAL or ERROR.UNBOUNDED | |
* ****************************************************************************************************************/ | |
public class Simplex { | |
private int rows, cols; // row and column | |
private float[][] table; // simplex tableau | |
private boolean solutionIsUnbounded = false; | |
public static enum ERROR{ | |
NOT_OPTIMAL, | |
IS_OPTIMAL, | |
UNBOUNDED | |
}; | |
public Simplex(int numOfConstraints, int numOfUnknowns){ | |
rows = numOfConstraints+1; // row number + 1 | |
cols = numOfUnknowns+1; // column number + 1 | |
table = new float[rows][]; // create a 2d array | |
// initialize references to arrays | |
for(int i = 0; i < rows; i++){ | |
table[i] = new float[cols]; | |
} | |
} | |
// prints out the simplex tableau | |
public void print(){ | |
for(int i = 0; i < rows; i++){ | |
for(int j = 0; j < cols; j++){ | |
String value = String.format("%.2f", table[i][j]); | |
System.out.print(value + "\t"); | |
} | |
System.out.println(); | |
} | |
System.out.println(); | |
} | |
// fills the simplex tableau with coefficients | |
public void fillTable(float[][] data){ | |
for(int i = 0; i < table.length; i++){ | |
System.arraycopy(data[i], 0, this.table[i], 0, data[i].length); | |
} | |
} | |
// computes the values of the simplex tableau | |
// should be use in a loop to continously compute until | |
// an optimal solution is found | |
public ERROR compute(){ | |
// step 1 | |
if(checkOptimality()){ | |
return ERROR.IS_OPTIMAL; // solution is optimal | |
} | |
// step 2 | |
// find the entering column | |
int pivotColumn = findEnteringColumn(); | |
System.out.println("Pivot Column: "+pivotColumn); | |
// step 3 | |
// find departing value | |
float[] ratios = calculateRatios(pivotColumn); | |
if(solutionIsUnbounded == true) | |
return ERROR.UNBOUNDED; | |
int pivotRow = findSmallestValue(ratios); | |
//System.out.println("Pivot row: "+ pivotRow); | |
// step 4 | |
// form the next tableau | |
formNextTableau(pivotRow, pivotColumn); | |
// since we formed a new table so return NOT_OPTIMAL | |
return ERROR.NOT_OPTIMAL; | |
} | |
// Forms a new tableau from precomuted values. | |
private void formNextTableau(int pivotRow, int pivotColumn){ | |
float pivotValue = table[pivotRow][pivotColumn]; | |
float[] pivotRowVals = new float[cols]; | |
float[] pivotColumnVals = new float[cols]; | |
float[] rowNew = new float[cols]; | |
// divide all entries in pivot row by entry inpivot column | |
// get entry in pivot row | |
System.arraycopy(table[pivotRow], 0, pivotRowVals, 0, cols); | |
// get entry inpivot colum | |
for(int i = 0; i < rows; i++) | |
pivotColumnVals[i] = table[i][pivotColumn]; | |
// divide values in pivot row by pivot value | |
for(int i = 0; i < cols; i++) | |
rowNew[i] = pivotRowVals[i] / pivotValue; | |
// subtract from each of the other rows | |
for(int i = 0; i < rows; i++){ | |
if(i != pivotRow){ | |
for(int j = 0; j < cols; j++){ | |
float c = pivotColumnVals[i]; | |
table[i][j] = table[i][j] - (c * rowNew[j]); | |
} | |
} | |
} | |
// replace the row | |
System.arraycopy(rowNew, 0, table[pivotRow], 0, rowNew.length); | |
} | |
// calculates the pivot row ratios | |
private float[] calculateRatios(int column){ | |
float[] positiveEntries = new float[rows]; | |
float[] res = new float[rows]; | |
int allNegativeCount = 0; | |
for(int i = 0; i < rows; i++){ | |
if(table[i][column] > 0){ | |
positiveEntries[i] = table[i][column]; | |
} | |
else{ | |
positiveEntries[i] = 0; | |
allNegativeCount++; | |
} | |
//System.out.println(positiveEntries[i]); | |
} | |
if(allNegativeCount == rows) | |
this.solutionIsUnbounded = true; | |
else{ | |
for(int i = 0; i < rows; i++){ | |
float val = positiveEntries[i]; | |
if(val > 0){ | |
res[i] = table[i][cols -1] / val; | |
} | |
} | |
} | |
return res; | |
} | |
// finds the next entering column | |
private int findEnteringColumn(){ | |
float[] values = new float[cols]; | |
int location = 0; | |
int pos, count = 0; | |
for(pos = 0; pos < cols-1; pos++){ | |
if(table[rows-1][pos] < 0){ | |
//System.out.println("negative value found"); | |
count++; | |
} | |
} | |
if(count > 1){ | |
for(int i = 0; i < cols-1; i++) | |
values[i] = Math.abs(table[rows-1][i]); | |
location = findLargestValue(values); | |
} else location = count - 1; | |
return location; | |
} | |
// finds the smallest value in an array | |
private int findSmallestValue(float[] data){ | |
float minimum ; | |
int c, location = 0; | |
minimum = data[0]; | |
for(c = 1; c < data.length; c++){ | |
if(data[c] > 0){ | |
if(Float.compare(data[c], minimum) < 0){ | |
minimum = data[c]; | |
location = c; | |
} | |
} | |
} | |
return location; | |
} | |
// finds the largest value in an array | |
private int findLargestValue(float[] data){ | |
float maximum = 0; | |
int c, location = 0; | |
maximum = data[0]; | |
for(c = 1; c < data.length; c++){ | |
if(Float.compare(data[c], maximum) > 0){ | |
maximum = data[c]; | |
location = c; | |
} | |
} | |
return location; | |
} | |
// checks if the table is optimal | |
public boolean checkOptimality(){ | |
boolean isOptimal = false; | |
int vCount = 0; | |
for(int i = 0; i < cols-1; i++){ | |
float val = table[rows-1][i]; | |
if(val >= 0){ | |
vCount++; | |
} | |
} | |
if(vCount == cols-1){ | |
isOptimal = true; | |
} | |
return isOptimal; | |
} | |
// returns the simplex tableau | |
public float[][] getTable() { | |
return table; | |
} | |
} |
@frozzyk You can check here https://github.com/kennyledet/Algorithm-Implementations/tree/master/Simplex_Method/Java/mike168m
Can it Solve Any Number of variables with any number of Equations or just the Example's alike problems ! and what did u mean by setting the number of
colms= number of unknowns +1 ???
Can you explain for case of minimization ? and thank you
hey! mike where is that package michael
@cheikhtourad This implementation does not handle minimization.
@heshamh96 I have only tested on a few algorithms and I have not used this code in any repositories so i can't be sure.
Where is the main method?
In calculateRatios you can set positiveEntries[i] = 0 if table[i][column] <= 0.
Then, if at least for one i there is table[i][column] > 0, you continue the algo, and calculate res[i] = table[i][cols -1] / positiveEntries[i];
So you can divide by 0 at some point, right?
Does this work really>?
Can you explain for case of minimization ? and thank you
Minimize is the same as maximize objective times -1.
For minimization, you only need to make the matrix, transpose it and change it to maximization problem. the maximum value of the converted problem will be the minimum value of the minimization problem. you can search it on youtube there are a lot of brilliant videos.
Hey micheal,thanks for the code.But the implementation is quiet hard to guess on the 2D array Data and the contructor arg numOfUnknowns Is the Z row party of the @d array Data?
Does the constructor parameter numOfUnknowns include the slack variables?
Do you have an implementation class or link to help me as reference?
i am trying to dissolve the code but it seems wrong
Hi guys, I'm sorry I haven't been of much help. github doesn't ping me when people comment here.
I'll try my best to simplify the code. Didn't mean to leave you hanging :(
Can you provide an example of using this class, please?