I'm trying to write a simplex algorithm in java for an assignment. My code works for certain inputs, but quite often, the algorithm gets stuck in a cycle, recalculating from state A to state B, then back to state A. Into an infinite loop.
At first I thought it was a degeneracy problem. But I'm actually using Bland's rule, and further brainstorming and attempted debugging made me realize it's the negative coefficients in the constraint inequalities that are causing the cycling.
So I think I understand why the error is occurring. But I'm not sure how I should change my algorithm to fix the problem.
Here's my entire code...
public class Main {
// initialize tableau
static double tableau[][] = new double[101][201];
static int variable[] = new int[100];
static int nCount, mCount, totalColumnCount;
public static void main(String[] args) {
try {
// read from file
Scanner s = new Scanner(new File("c:\\hw6\\input.txt"));
// for formatting double values to two decimal places
DecimalFormat oneDigit = new DecimalFormat("#,###0.00");
// ----------------------------------------initialize tableau---------------------------------------------------
// read number of n(variables) and m(constraints)
nCount = s.nextInt();
mCount = s.nextInt();
totalColumnCount = nCount + mCount + 1;
// fill variable[] with arbitrarily large values
for (int j = 0; j < mCount; j++) {
variable[j] = 200;
}
// get coefficients for objective function and store into tableau
for (int j = 0; j < nCount; j++) {
tableau[mCount][j] = -s.nextInt();
}
for (int j = nCount; j < nCount + mCount; j++) {
tableau[mCount][j] = 0;
}
tableau[mCount][nCount + mCount] = 1; // value of MAX (P)
tableau[mCount][nCount + mCount + 1] = 0; // RHS (which should be 0)
// get coefficients of constraint inequalities
for (int j = 0; j < mCount; j++) {
for (int k = 0; k < nCount; k++) {
tableau[j][k] = s.nextInt();
}
for (int k = nCount; k < nCount + mCount; k++) {
if (k - nCount == j)
tableau[j][k] = 1;
else
tableau[j][k] = 0;
}
// get the RHS
tableau[j][nCount + mCount + 1] = s.nextInt();
}
// store variables that each constraint refers to
for (int j = 0; j < mCount; j++) {
variable[j] = j + 1;
}
// ----------------------------------------initialize tableau---------------------------------------------------
// look for any negative values in the objective function
for (int j = 0; j <= totalColumnCount; j++) {
if (tableau[mCount][j] < 0) {
Coordinate pivot = findPivot();
pivotTo1(pivot);
pivotColumnTo0(pivot);
// for checking that this iteration of converting constraints has been calculated correctly
for (int k = 0; k <= mCount; k++) {
System.out.print("[ ");
for (int l = 0; l <= totalColumnCount; l++) {
System.out.print(oneDigit.format(tableau[k][l]) + " ");
}
System.out.println(" ]");
}
System.out.println();
// repeat looking for any negative values in the objective function
j = 0;
continue;
}
}
// get solutions
getSolution();
} catch (IOException e) {
System.out.println(e);
}
}
public static Coordinate findPivot() {
double currentMinColumn = Integer.MAX_VALUE;
double currentCalculation = Integer.MAX_VALUE;
int pivotColumn = 0;
int pivotRow = 0;
// find pivot column
for (int i = 0; i < totalColumnCount; i++) {
if (currentMinColumn > tableau[mCount][i]) {
currentMinColumn = tableau[mCount][i];
pivotColumn = i;
}
}
// find pivot
for (int i = 0; i < mCount; i++) {
if (currentCalculation > tableau[i][totalColumnCount] / tableau[i][pivotColumn]) {
currentCalculation = tableau[i][totalColumnCount] / tableau[i][pivotColumn];
pivotRow = i;
}
}
// return coordinate of pivot value
return new Coordinate(pivotRow, pivotColumn);
}
public static void pivotTo1(Coordinate pivot) {
double pivotValue = tableau[pivot.row()][pivot.column()];
// find factor to multiply to pivot's row to convert pivot to 1
double multFactor = 1.0 / pivotValue;
// convert the pivot's row
for (int i = 0; i <= totalColumnCount; i++) {
tableau[pivot.row()][i] *= multFactor;
}
// update variable for the constraint
variable[pivot.row()] = pivot.column();
}
public static void pivotColumnTo0(Coordinate pivot) {
double multFactor = 0;
// for all constraints
for (int i = 0; i < mCount + 1; i++) {
// skip constraint containing pivot
if (i == pivot.row())
continue;
// get multFactor of constraint
multFactor = -tableau[i][pivot.column()];
// update each constraint by making pivot column values become zero
for (int j = 0; j <= totalColumnCount; j++) {
tableau[i][j] = tableau[i][j] + (multFactor * tableau[pivot.row()][j]);
}
}
}
public static void getSolution() {
int solutionExists;
// for all variables
for (int i = 0; i < nCount; i++) {
solutionExists = 0;
// for all variables in the variable[] array
for (int j = 0; j < mCount; j++) {
// if the variable exists in the variable[] array print the value
if (i == variable[j]) {
System.out.println(tableau[j][totalColumnCount]);
solutionExists = 1;
break;
}
}
// if it does not exist print 0
if (solutionExists == 0) {
System.out.println(0);
}
}
}
}
(I would have liked to post only the relevant snippet of code so that you guys would have less of a hard time trying to decipher this, I thought that you guys would need the entire code anyway to find where my error is. I tried to put comments as specifically as possible.)
I used this video as reference in understanding the simplex method: https://www.youtube.com/watch?v=gRgsT9BB5-8
The input.txt looks like this:
This one works
3 3 // number of variables (n), number of constraints (m)
6 5 4 // objective function: 6x1 + 5x2 + 4x3
2 1 1 180 // constraint 1: 2x1 + 1x2 + 1x3 <= 180
1 3 2 300
2 1 2 240
Giving the solution
48.0
84.0
0
This one doesn't work
2 2
2 5
2 -1 4
-1 2 9
Any help or advice will be greatly appreciated. Thank you very much!