0

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!

hollaholl
  • 93
  • 1
  • 2
  • 10

1 Answers1

0

I had the exact same problem (expect for that I was programming with python. but the issue was the same). I found the solution in the answer in here. As it states, when for example we have such table: enter image description here

when we choose x4 column because of the negative value (-1 in z row), then between s1, x1 and s3 rows, we could only choose s1 because the corresponding value for x4 column, can not be negative, since the RHS value can not become negative by later dividing.