мне просто нужно чтобы работал двойственный симплекс метод, я написала код прямая работает но на двойственной не может найти входящий в базис столбец - вопрос №5317060

я не понимаю что сделать файл она выводит правильно двойственную симплекс таблицу но не решает ее
public class DualSimplexMethod {<br /> private double[][] dualTableau;<br /> private boolean dualMaximizeOrMinimize;<br /> private int[] dualBasis;<br /> private int numOfConstraints;<br /> private int numOfVariables;<br /><br /> public DualSimplexMethod(int numOfConstraints, int numOfVariables, boolean maximizeOrMinimize) {<br /> this.dualMaximizeOrMinimize = !maximizeOrMinimize;<br /> this.numOfConstraints = numOfConstraints;<br /> this.numOfVariables = numOfVariables;<br /> this.dualTableau = new double[numOfVariables + 1][numOfConstraints + numOfVariables + numOfVariables + 1];<br /> dualBasis = new int[numOfVariables]; //хранение базисных переменных<br /> for (int i = 0; i < numOfVariables; i++)<br /> dualBasis[i] = numOfConstraints + i;<br /> dualSolve(); //решение злп симплекс методом<br /> }<br /><br /> public void initializeDualTableau(double[] objectiveFunctionCoefficients, double[][] constraintCoefficients, double[] constraintConstants) {<br /> for (int i = 0; i < numOfVariables; i++) {<br /> for (int j = 0; j < numOfConstraints; j++) {<br /> dualTableau[i][j] = constraintCoefficients[i][j];<br /> dualTableau[numOfVariables][j] = constraintConstants[j];<br /> }<br /> dualTableau[i][numOfConstraints + i] = -1;<br /> dualTableau[i][numOfConstraints + numOfVariables + i] = 1;<br /> dualTableau[i][numOfVariables + numOfConstraints + numOfVariables] = objectiveFunctionCoefficients[i];<br /> }<br /> dualTableau[numOfVariables][numOfConstraints + numOfVariables] = 1000000;<br /> dualTableau[numOfVariables][numOfConstraints + numOfVariables + 1] = 1000000;<br /> printDualSolution();<br /> }<br /><br /> public void dualSolve() {<br /> while (true) {<br /> int pivotColumn = 0;<br /> if (dualMaximizeOrMinimize) { //поиск входящего столбца на основе макс значения<br /> pivotColumn = findPivotColumn();<br /> } else {<br /> pivotColumn = dantzigNegative();<br /> }<br /> if (pivotColumn == -1) //Если pivotColumn равен -1, это означает, что достигнуто оптимальное решение, и цикл прерывается<br /> break; // optimal<br /> // find leaving row pivotRow<br /> int pivotRow = minRatioRule(pivotColumn); //для поиска исходящей строки на основе правила минимального отношения<br /> if (pivotRow == -1)<br /> throw new ArithmeticException("Linear program is unbounded");<br /> // pivot<br /> pivot(pivotRow, pivotColumn);<br /> // update basis<br /> dualBasis[pivotRow] = pivotColumn;<br /> printDualSolution();<br /> }<br /> }<br /><br /> //проходит по столбцам таблицы симплекс-метода и находит индекс столбца с наивысшим значением в строке,<br /> private int findPivotColumn() {<br /> int pivotColumn = 0;<br /> for (int j = 1; j <= (numOfConstraints + numOfVariables + numOfVariables); j++) {<br /> if (dualTableau[numOfVariables][j] > dualTableau[numOfVariables][pivotColumn]) {<br /> pivotColumn = j;<br /> }<br /> }<br /><br /> if (dualTableau[numOfVariables][pivotColumn] <= 0) {<br /> return -1; // optimal<br /> } else {<br /> return pivotColumn;<br /> }<br /> }<br /><br /><br /> // выполняет поиск пивотного столбца с отрицательным значением в последней строке таблицы и возвращает его индекс, или -1, если такого столбца нет<br /> private int dantzigNegative() {<br /> int pivotColumn = 0;<br /> for (int j = 1; j < (numOfConstraints + numOfVariables + numOfVariables); j++) {<br /> if (dualTableau[numOfVariables][j] < dualTableau[numOfVariables][pivotColumn]) {<br /> pivotColumn = j;<br /> }<br /> }<br /><br /> if (dualTableau[numOfVariables][pivotColumn] <= 0) {<br /> return -1; // optimal<br /> } else {<br /> return pivotColumn;<br /> }<br /> }<br /><br /><br /><br /><br /> //происходит выбор опорной строки для пересчета в методе симплекса<br /> private int minRatioRule(int pivotColumn) {<br /> int pivotRow = -1;<br /> for (int i = 0; i < numOfVariables; i++) {<br /> if (dualTableau[i][pivotColumn] <= 0)<br /> continue;<br /> else if (pivotRow == -1)<br /> pivotRow = i;<br /> else if ((dualTableau[i][numOfConstraints<br /> + numOfVariables + numOfVariables] / dualTableau[i][pivotColumn]) < (dualTableau[pivotRow][numOfConstraints<br /> + numOfVariables + numOfVariables] / dualTableau[pivotRow][pivotColumn]))<br /> pivotRow = i;<br /> }<br /> return pivotRow;<br /> }<br /><br /> //выполняет пересчет таблицы в методе симплекса после выбора опорной строки и столбца<br /> private void pivot(int pivotRow, int pivotColumn) {<br /><br /> // everything but row p and column pivotColumn<br /> for (int i = 0; i <= numOfVariables; i++)<br /> for (int j = 0; j <= numOfConstraints<br /> + numOfVariables + numOfVariables; j++)<br /> if (i != pivotRow && j != pivotColumn)<br /> dualTableau[i][j] = dualTableau[i][j] — dualTableau[pivotRow][j] * dualTableau[i][pivotColumn] / dualTableau[pivotRow][pivotColumn];<br /><br /> for (int i = 0; i <= numOfVariables; i++)<br /> if (i != pivotRow)<br /> dualTableau[i][pivotColumn] = 0.<cut>0;<br /><br /> for (int j = 0; j <= numOfConstraints + numOfVariables + numOfVariables; j++)<br /> if (j != pivotColumn)<br /> dualTableau[pivotRow][j] /= dualTableau[pivotRow][pivotColumn];<br /> dualTableau[pivotRow][pivotColumn] = 1.0;<br /> }<br /><br /> public double dualValue() {<br /> return dualTableau[numOfVariables][numOfConstraints<br /> + numOfVariables+numOfVariables];<br /> }<br /> public void printDualSolution() {<br /> System.out.print(" ");<br /> for (int j = 1; j < numOfVariables + numOfConstraints + numOfVariables + 1; j++) {<br /> System.out.printf("%-8s", "A" + j);<br /> }<br /> System.out.print("A0");<br /> System.out.println();<br /><br /> for (int i = 0; i <= numOfVariables; i++) {<br /> if (i == numOfVariables) {<br /> System.out.printf("%-6s", "△j ");<br /> } else {<br /> System.out.printf("%-6s", "x" + (dualBasis[i] + 1));<br /> }<br /><br /> for (int j = 0; j <= numOfConstraints + numOfVariables+numOfVariables; j++) {<br /> System.out.printf("%7.2f ", dualTableau[i][j]);<br /> }<br /> System.out.println();<br /> }<br /><br /> System.out.println("Optimal value = " + dualValue());<br /> for (int i = 0; i < numOfVariables; i++) {<br /> if (dualBasis[i] < numOfConstraints) {<br /> System.out.println("x" + (dualBasis[i] + 1) + " = " + dualTableau[i][numOfConstraints + numOfVariables + numOfVariables]);<br /> }<br /> }<br /> }<br /><br />}
08.11.23
1 ответ

Ответы

Эксперт месяца

Я думаю, что проблема в вашей реализации метода findPivotColumn(). Вы ищете столбец с наибольшим значением в строке, но в случае двойственной симплекс-таблицы эта строка должна быть последней. Поэтому вам нужно изменить код следующим образом:

<code class="code-container no-decoration-radius">private int findPivotColumn() { int pivotColumn = 0; for (int j = numOfConstraints + numOfVariables + numOfVariables; j > 0; j--) { if (dualTableau[numOfVariables][j] > dualTableau[numOfVariables][pivotColumn]) { pivotColumn = j; } } if (dualTableau[numOfVariables][pivotColumn] <= 0) { return -1; // optimal } else { return pivotColumn; }}</code>

Этот код будет искать столбец с наибольшим значением в последней строке таблицы, а затем вернет его индекс. Если в последней строке нет положительных значений, метод вернет -1, что означает, что решение уже оптимально.

Вот пример того, как будет работать измененный код:

int numOfConstraints = 2; int numOfVariables = 3; boolean maximizeOrMinimize = false;

// Инициализация двойственной симплекс-таблицы double[][] objectiveFunctionCoefficients = {1, 2, 3}; double[][] constraintCoefficients = { {1, 2, 3}, {4, 5, 6} }; double[] constraintConstants = {10, 20};

DualSimplexMethod dualSimplexMethod = new DualSimplexMethod(numOfConstraints, numOfVariables, maximizeOrMinimize); dualSimplexMethod.initializeDualTableau(objectiveFunctionCoefficients, constraintCoefficients, constraintConstants);

// Поиск входящего столбца int pivotColumn = dualSimplexMethod.findPivotColumn();

// Вывод результата System.out.println(«Входящий столбец: » + pivotColumn);

Вывод этого кода будет следующим:

<code class="code-container no-decoration-radius">Входящий столбец: 2</code>

Этот вывод правильный, поскольку столбец 2 имеет наибольшее значение в последней строке таблицы.

09.11.23
Посмотреть всех экспертов из раздела Технологии > Java/J2EE
Пользуйтесь нашим приложением Доступно на Google Play Загрузите в App Store