/// <summary> /// Симплексная таблица в каноническом виде /// </summary> /// <param name="x_i">вектор номеров базисных элементов</param> /// <param name="c_j">коефициенты при неизвестных в целевой функции</param> /// <param name="equationSystem">ситема уравнений</param> /// <param name="b">вектор свободных членов</param> public CanonicalSimplexTable(int[] x_i, SimplexNumber[] c_j, double[,] equationSystem, double[] b) { //сохраняем номера базисных переменых X_I = x_i; //создаем симплекс-таблицу SimplexTable = new SimplexNumber[equationSystem.GetLength(0)+1, equationSystem.GetLength(1)+1]; //добавляем в таблицу a_ij for (int i = 0; i < equationSystem.GetLength(0); i++) for (int j = 0; j < equationSystem.GetLength(1); j++) SimplexTable[i, j] = new SimplexNumber(equationSystem[i, j]); //... b_i for (int i = 0; i < b.Length; i++) SimplexTable[i, equationSystem.GetLength(1)] = new SimplexNumber(b[i]); //... delta_j for (int j = 0; j < equationSystem.GetLength(1); j++) { SimplexTable[equationSystem.GetLength(0), j] = -c_j[j]; for (int i = 0; i < equationSystem.GetLength(0); i++) SimplexTable[equationSystem.GetLength(0), j] += c_j[x_i[i]] * SimplexTable[i, j]; } //... Z(b_i) for (int i = 0; i < b.Length; i++) SimplexTable[equationSystem.GetLength(0), equationSystem.GetLength(1)] += c_j[x_i[i]] * b[i]; }
/// <summary> /// находит значения независимых переменных при которых целевая функция максимизируется /// </summary> public void Maximize(bool showSteps = true) { while (true) { bool rowWasFound = false; bool colWasFound = false; //отображаем текущее состояние если нужно if (showSteps) { ShowTable(DisplayMode.InConsole); Console.WriteLine(); } //находим номер столбца с отрицательной delta int col_min = 0; for (int j = 0; j < SimplexTable.GetLength(1) - 1; j++) if (SimplexTable[SimplexTable.GetLength(0) - 1, j].Round(roundTo) < 0 && SimplexTable[SimplexTable.GetLength(0) - 1, j] <= SimplexTable[SimplexTable.GetLength(0) - 1, col_min]) { var t = SimplexTable[SimplexTable.GetLength(0) - 1, j]; var vg = SimplexTable[SimplexTable.GetLength(0) - 1, j].Round(roundTo) < 0; col_min = j; colWasFound = true; } //если полученая на предыдущем шаге таблица оптимальна выводим результат и выходим из функции if (!colWasFound) { SimplexNumber[] rez = new SimplexNumber[SimplexTable.GetLength(1)-1]; for (int j = 0; j < SimplexTable.GetLength(1)-1; j++) { int k = -1; for (int i = 0; i < X_I.Length; i++) { if (X_I[i] == j) k = i; } rez[j] = k == -1 ? new SimplexNumber(0) : SimplexTable[k, SimplexTable.GetLength(1) - 1].Round(4); } MessageBox.Show("Целевая функция имеет максимум при X=(" + String.Join("; ",rez) + "), при этом Z(X)=" + SimplexTable[SimplexTable.GetLength(0) - 1, SimplexTable.GetLength(1) - 1] + ".", "Вот так вот!", MessageBoxButtons.OK); return; } //находим номер строки с минимальной b_i/a_is int row_min = 0; for (int i = 0; i < SimplexTable.GetLength(0) - 1; i++) { if (SimplexTable[i, col_min].Round(roundTo) > 0 && (SimplexTable[i, SimplexTable.GetLength(1) - 1] / SimplexTable[i, col_min] <= SimplexTable[row_min, SimplexTable.GetLength(1) - 1] / SimplexTable[row_min, col_min] || SimplexTable[row_min, col_min].Round(roundTo)<=0)) { row_min = i; rowWasFound = true; } } //если все a_is не положительны выводим соответствующее сообщение if (!rowWasFound) { MessageBox.Show("Функция неограничена в даной области решений.", "Вот так вот!", MessageBoxButtons.OK); return; } //в противном случае делаем еще один шаг MakeStep(row_min,col_min); } }
/// <summary> /// выполняет одну итерацию симплекс-метода /// </summary> /// <param name="row_min">номер строки разрешающего элемента</param> /// <param name="col_min">номер столбца разрешающего элемента</param> public void MakeStep(int row_min, int col_min) { SimplexNumber[,] newSimplexTable = new SimplexNumber[SimplexTable.GetLength(0), SimplexTable.GetLength(1)]; //выполняем одну итерацию симплексного метода SimplexNumber rElement = SimplexTable[row_min, col_min]; for (int i = 0; i < SimplexTable.GetLength(0); i++) for (int j = 0; j < SimplexTable.GetLength(1); j++) { if (i == row_min) { newSimplexTable[i, j] = SimplexTable[i, j] / rElement; continue; } newSimplexTable[i, j] = SimplexTable[i, j] - SimplexTable[row_min, j] * SimplexTable[i, col_min] / rElement;//from caet } //устанавливаем новый базис X_I[row_min] = col_min; //фиксируем полученый результат SimplexTable = newSimplexTable; }