Skip to content

Instantly share code, notes, and snippets.

@mik30s
Created April 17, 2016 01:39
Show Gist options
  • Save mik30s/f285b99ad96589be60553d83a48d85c1 to your computer and use it in GitHub Desktop.
Save mik30s/f285b99ad96589be60553d83a48d85c1 to your computer and use it in GitHub Desktop.
Simplex Method in Java
// 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;
}
}
@SebastienCoste
Copy link

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?

@kyawlinnthant
Copy link

Does this work really>?

@yuana97
Copy link

yuana97 commented Oct 19, 2018

Can you explain for case of minimization ? and thank you

Minimize is the same as maximize objective times -1.

@sinusee
Copy link

sinusee commented Nov 11, 2018

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.

@isaacpitwa
Copy link

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?

@isaacpitwa
Copy link

i am trying to dissolve the code but it seems wrong

@mik30s
Copy link
Author

mik30s commented Oct 24, 2019

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 :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment