/// <summary> /// Конструктор для авто-режима с задачей /// </summary> /// <param name="problem"></param> public AutoStepWindow(LinearProgrammingProblem problem) { this.Problem = problem; // Инициализируем компоненты окна InitializeComponent(); // Заносим параметры в ячейки DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.Restrictions, true); if (Problem.CornerDot != null) { Problem.TransformColumnsForCornerDot(_dataGridViewProblem); } //Процесс выполнения. Implementation(); }
/// <summary> /// Конструктор для окна пошагового режима с задачей /// </summary> /// <param name="problem">Задача линейного программирования</param> public StepByStepWindow(LinearProgrammingProblem problem) { this.Problem = problem; // изначально мы на нулевом шаге this.Step = 0; // Инициализируем компоненты окна InitializeComponent(); // Добавляем в ячейки данные tabControl.TabPages[0].Text = "Матрица коэффициентов системы ограничения равенств."; DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.Restrictions, true); if (Problem.CornerDot != null) { Problem.TransformColumnsForCornerDot(_dataGridViewProblem); } }
/// <summary> /// Основные шаги /// </summary> public void Implementation() { try { //Прямой ход метода Гаусса для приведения к треугольному виду. Problem.Gauss(); //Выражение базисных переменных и приведение к диагональному виду. Problem.HoistingMatrix(); // Обновляем параметры в ячейках DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.Restrictions, false); } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка при решении системы методом Гаусса.", MessageBoxButtons.OK); return; } try { // Создаём симплекс таблицу Problem.TransformGridForSimplexTable(_dataGridViewProblem); Problem.SimplexTable = new SimplexTable(_dataGridViewProblem); } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка создания симплекс таблицы!", MessageBoxButtons.OK); return; } int responce; int step = 1; while (true) { // Проверяем симплекс таблицу на решённость if ((responce = Problem.SimplexTable.ResponseCheck()) == 0) { try { //выбор любого опорного Problem.SimplexTable.SelectFirstSupportElement(); //меняем местами переменные Problem.SimplexTable.ChangeHeaders(_dataGridViewProblem); // высчитывание по опорному Problem.SimplexTable.CalculateSimplexTable(); // Обновление ячеек DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.SimplexTable.SimplexTableElements, false); step++; } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка при выборе опорных элементов на {step} шаге.", MessageBoxButtons.OK); return; } } else if (responce == 1) { tabControl.TabPages[0].Text = "Ответ готов!"; if (Problem.Min == false) { labelAnswer.Text = "Ответ :" + Problem.SimplexTable.Response(); } else { labelAnswer.Text = "Ответ :" + Problem.SimplexTable.Response() * (-1); } if (cornerDotAnswerWasAdded == false) { //добавляем угловую точку решения (X*) DataGridWorker.SetParamToGrids( _dataGridViewCornerDot, Problem.ResponseCornerDot(_dataGridViewProblem), true); cornerDotAnswerWasAdded = true; } break; } else if (responce == -1) { MessageBox.Show("Задача не разрешима!"); tabControl.TabPages[0].Text = "Задача не разрешима!"; break; } } }
/// <summary> /// Кнопка "Далее" /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonNext_Click(object sender, EventArgs e) { switch (Step) { case 0: try { // Буферизируем данные BufferingTableValues(Problem.ToFractionList(DataGridWorker.ReadGridsFrom(_dataGridViewProblem))); // Прямой ход Гаусса Problem.Gauss(); // Обновляем параметры DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.Restrictions, false); Step++; tabControl.TabPages[0].Text = "Шаг 1: Прямой ход метода Гаусса."; } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка на {Step} шаге!", MessageBoxButtons.OK); } break; case 1: try { // Буферизируем данные BufferingTableValues(Problem.ToFractionList(DataGridWorker.ReadGridsFrom(_dataGridViewProblem))); // Выражение базисных переменных + обратный ход Гаусса Problem.HoistingMatrix(); // Обновляем параметры DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.Restrictions, false); Step++; tabControl.TabPages[0].Text = "Шаг 2: Выражение базисных переменных."; } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка на {Step} шаге!", MessageBoxButtons.OK); } break; case 2: try { // Буферизируем данные BufferingTableValues(Problem.ToFractionList(DataGridWorker.ReadGridsFrom(_dataGridViewProblem))); BufferingHeaders(_dataGridViewProblem); if (simplexTableWasDraw == false) { Problem.TransformGridForSimplexTable(_dataGridViewProblem); Problem.SimplexTable = new SimplexTable(_dataGridViewProblem); simplexTableWasDraw = true; } } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка создания симплекс таблицы на {Step} шаге!", MessageBoxButtons.OK); return; } // Если симплекс таблица создалась и отрисовалась успешно // Проверяеем её на ответ switch (Problem.SimplexTable.ResponseCheck()) { case 0: // Продолжаем искать решение Step++; tabControl.TabPages[0].Text = "Шаг 3: Симплекс-таблица."; break; case 1: // Если ответ готов сразу без выбора опорного элемента tabControl.TabPages[0].Text = "Ответ готов!"; Step++; labelAnswer.Visible = true; groupBoxCornerDot.Visible = true; buttonNext.Enabled = false; // Подставляем ответ if (Problem.Min == false) { labelAnswer.Text = "Ответ :" + Problem.SimplexTable.Response(); } else { labelAnswer.Text = "Ответ :" + Problem.SimplexTable.Response() * (-1); } // Выводим угловую точку ответа (X*) if (cornerDotAnswerWasAdded == false) { //добавляем точку DataGridWorker.SetParamToGrids( _dataGridViewCornerDot, Problem.ResponseCornerDot(_dataGridViewProblem), true); cornerDotAnswerWasAdded = true; } break; case -1: Step++; MessageBox.Show("Задача не разрешима!"); tabControl.TabPages[0].Text = "Задача не разрешима!"; buttonNext.Enabled = false; break; } break; case 3: try { BufferingTableValues(Problem.SimplexTable.SimplexTableElements); //выбор опорного Problem.SimplexTable.SelectionOfTheSupportElements(_dataGridViewProblem); Step++; tabControl.TabPages[0].Text = $"Шаг {Step}: Выбор опорного элемента"; } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка при выборе опорных элементов на {Step} шаге.", MessageBoxButtons.OK); } break; default: try { // Проверяем, выбран ли опорный элемент Problem.SimplexTable.SupportElementPressedOrNot(_dataGridViewProblem); // Меняем хэдэры колонки и строки местами Problem.SimplexTable.ChangeHeaders(_dataGridViewProblem); // Буферизируем симплекс таблицу BufferingTableValues(Problem.SimplexTable.SimplexTableElements); // Удаляем подсвеченные ячейки UncolorGreenGrids(_dataGridViewProblem); // Вычисление симплекс таблицы по выбранному опорному элементу Problem.SimplexTable.CalculateSimplexTable(); // Обновление ячеек DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.SimplexTable.SimplexTableElements, false); } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка при выборе опорного элемента на шаге {Step}", MessageBoxButtons.OK); return; } switch (Problem.SimplexTable.ResponseCheck()) { case 0: Step++; tabControl.TabPages[0].Text = $"Шаг {Step}: Выбор опорного элемента"; //выбор опорного Problem.SimplexTable.SelectionOfTheSupportElements(_dataGridViewProblem); break; case 1: tabControl.TabPages[0].Text = "Ответ готов!"; Step++; labelAnswer.Visible = true; groupBoxCornerDot.Visible = true; if (Problem.Min == false) { labelAnswer.Text = "Ответ :" + Problem.SimplexTable.Response(); } else { labelAnswer.Text = "Ответ :" + Problem.SimplexTable.Response() * (-1); } if (cornerDotAnswerWasAdded == false) { //добавляем угловую точку решения (X*) DataGridWorker.SetParamToGrids( _dataGridViewCornerDot, Problem.ResponseCornerDot(_dataGridViewProblem), true); cornerDotAnswerWasAdded = true; } buttonNext.Enabled = false; break; case -1: Step++; MessageBox.Show("Задача не разрешима!"); tabControl.TabPages[0].Text = "Задача не разрешима!"; buttonNext.Enabled = false; break; } break; } }
/// <summary> /// Кнопка "Назад" /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void buttonBack_Click(object sender, EventArgs e) { switch (Step) { case 0: // Отменить операцию закрытия окна bool CancelСlosing = false; var result = MessageBox.Show( "Предыдущего шага нет. Возврат приведёт к закрытию текущей задачи. Вы уверены?", "Закрыть задачу?", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (result == DialogResult.No) { // Если пользователь не хочет закрывать окно, отменяем операцию CancelСlosing = true; } if (!CancelСlosing) { this.Close(); } break; case 1: // Возвращение с шага 1 try { // Достаём данные из буфера и заносим их в ячейки DataGridWorker.SetParamToGrids(_dataGridViewProblem, GetOutOfTheBuffer(), false); // Заносим данные из буфера в данные задачи Problem.Restrictions = Problem.ToFractionList(DataGridWorker.ReadGridsFrom(_dataGridViewProblem)); // Убавляем шаг Step--; tabControl.TabPages[0].Text = "Матрица коэффициентов системы ограничений равенств."; } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка при возвращении с шага {Step}.", MessageBoxButtons.OK); } break; case 2: try { // Достаём данные из буфера и заносим их в ячейки DataGridWorker.SetParamToGrids(_dataGridViewProblem, GetOutOfTheBuffer(), false); // Заносим данные из буфера в данные задачи Problem.Restrictions = Problem.ToFractionList(DataGridWorker.ReadGridsFrom(_dataGridViewProblem)); // Убавляем шаг Step--; tabControl.TabPages[0].Text = "Шаг 1: Прямой ход метода Гаусса."; } catch (Exception ex) { MessageBox.Show(ex.Message, $"Ошибка при возвращении с шага {Step}.", MessageBoxButtons.OK); } break; case 3: // Достаём данные из буфера и заносим их в ячейки DataGridWorker.SetParamToGrids(_dataGridViewProblem, GetOutOfTheBuffer(), true); // Достаём хэдэры из буфера DataGridWorker.SetHeaders(_dataGridViewProblem, GetOutOfTheBufferHeaders()); // Обнуляем данные симплекс таблицы Problem.SimplexTable.SimplexTableElements = new List <List <Fraction> >(); simplexTableWasDraw = false; Step--; tabControl.TabPages[0].Text = "Шаг 2: Выражение базисных переменных."; // Если ответ был готов сразу и уже отобразился - скрываем его labelAnswer.Visible = false; groupBoxCornerDot.Visible = false; buttonNext.Enabled = true; break; case 4: UncolorGreenGrids(_dataGridViewProblem); GetOutOfTheBuffer(); Step--; tabControl.TabPages[0].Text = "Шаг 3: Симплекс-таблица."; break; default: UncolorGreenGrids(_dataGridViewProblem); // Достаём из буффера элементы симплекс таблицы Problem.SimplexTable.SimplexTableElements = GetOutOfTheBuffer(); // Достаём данные из буфера и заносим их в ячейки DataGridWorker.SetParamToGrids(_dataGridViewProblem, Problem.SimplexTable.SimplexTableElements, false); // Меняем хэдэры обратно, доставая их из буффера Problem.SimplexTable.ChangeHeadersFromBuffer(_dataGridViewProblem); // Выбор опорного Problem.SimplexTable.SelectionOfTheSupportElements(_dataGridViewProblem); Step--; tabControl.TabPages[0].Text = $"Шаг {Step}: Выбор опорного элемента"; labelAnswer.Visible = false; groupBoxCornerDot.Visible = false; buttonNext.Enabled = true; break; } }
/// <summary> /// Открыть задачу из файла /// </summary> /// <param name="fileName"></param> private void OpenTaskFromPath(string fileName) { string fileText = File.ReadAllText(fileName); if (fileText == "") { throw new Exception("Файл пуст.\nПожалуйста, проверьте файл и попробуйте ещё раз."); } // Чистим массив от лишних символов fileText = fileText.Replace("\r", ""); fileText = fileText.Replace("= ", ""); // Чистим от последнего /n, если пользователь вдруг нажал Enter после уравнения if (fileText[fileText.Length - 1] == '\n') { fileText = fileText.Remove(fileText.Length - 1); } // Чистим от лишних пробелов fileText = string.Join(" ", fileText.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); // Определяем макс или мин и очищаем от этого строку if (fileText.Contains("->max") || fileText.Contains("-> max")) { radioButtonMax.Checked = true; fileText = fileText.Replace(" ->max", ""); fileText = fileText.Replace(" -> max", ""); } else { if (fileText.Contains("->min") || fileText.Contains("-> min")) { radioButtonMin.Checked = true; fileText = fileText.Replace(" ->min", ""); fileText = fileText.Replace(" -> min", ""); } else { throw new Exception("В файле отсутствует условие максимизации или минимизации. Пожалуйста, установите это условие вручную."); } } // Делим цельный текст на массив строк с уравнениями string[] tmpText = fileText.Split('\n'); // Создаём список всего уравнения List <List <string> > AllTask = new List <List <string> >(); // Заносим данные в список foreach (string equation in tmpText) { AllTask.Add(new List <string>(equation.Split(' '))); } // Делим на целевую и ограничения List <List <string> > targetFunction = new List <List <string> >(); targetFunction.Add(new List <string>()); targetFunction[0] = AllTask[0]; // Удаляем целевую функцию из списка AllTask.Remove(AllTask.First()); List <List <string> > restrictions = new List <List <string> >(AllTask); // Заносим целевую функцию в Ячейки DataGridWorker.SetParamToGrids(_dataGridViewTargetFunction, targetFunction, true); // Создаём угловую точку DataGridWorker.CreateGrids(_dataGridViewCornerDot, targetFunction[0].Count, true); // Ограничения DataGridWorker.SetParamToGrids(_dataGridViewRestrictions, restrictions, true); }