MathVM/Simplex.py

83 lines
4.0 KiB
Python
Raw Normal View History

2023-12-13 15:36:58 +04:00
import numpy as np
2023-12-15 11:24:50 +04:00
2023-12-13 15:36:58 +04:00
class Simplex:
def __init__(self, source):
2023-12-15 11:24:50 +04:00
# Инициализация объекта Simplex с исходной таблицей source
2023-12-13 15:36:58 +04:00
m, n = source.shape
2023-12-15 11:24:50 +04:00
# Инициализация таблицы и списка базисных переменных
2023-12-13 15:36:58 +04:00
self.table = np.zeros((m, n + m - 1))
self.basis = []
2023-12-15 11:24:50 +04:00
# Формирование начальной симплекс-таблицы
2023-12-13 15:36:58 +04:00
for i in range(m):
for j in range(self.table.shape[1]):
if j < n:
2023-12-15 11:24:50 +04:00
# Копирование коэффициентов из исходной таблицы
2023-12-13 15:36:58 +04:00
self.table[i, j] = source[i, j]
else:
2023-12-15 11:24:50 +04:00
# Добавление единичных столбцов для базисных переменных
2023-12-13 15:36:58 +04:00
self.table[i, j] = 0
if (n + i) < self.table.shape[1]:
2023-12-15 11:24:50 +04:00
# Установка единицы в соответствующем столбце для базисной переменной
2023-12-13 15:36:58 +04:00
self.table[i, n + i] = 1
2023-12-15 11:24:50 +04:00
# Добавление базисной переменной в список
2023-12-13 15:36:58 +04:00
self.basis.append(n + i)
self.m = m
self.n = self.table.shape[1]
def calculate(self, result):
2023-12-15 11:24:50 +04:00
# Основной цикл симплекс-метода
2023-12-13 15:36:58 +04:00
while not self.is_it_end():
2023-12-15 11:24:50 +04:00
# Нахождение ведущей колонки и строки
2023-12-13 15:36:58 +04:00
main_col = self.find_main_col()
main_row = self.find_main_row(main_col)
2023-12-15 11:24:50 +04:00
# Обновление списка базисных переменных
2023-12-13 15:36:58 +04:00
self.basis[main_row] = main_col
2023-12-15 11:24:50 +04:00
# Пересчет симплекс-таблицы
2023-12-13 15:36:58 +04:00
new_table = np.zeros((self.m, self.n))
for j in range(self.n):
2023-12-15 11:24:50 +04:00
# Нормализация ведущей строки
2023-12-13 15:36:58 +04:00
new_table[main_row, j] = self.table[main_row, j] / self.table[main_row, main_col]
for i in range(self.m):
if i == main_row:
continue
for j in range(self.n):
2023-12-15 11:24:50 +04:00
# Обновление остальных строк таблицы
2023-12-13 15:36:58 +04:00
new_table[i, j] = self.table[i, j] - self.table[i, main_col] * new_table[main_row, j]
self.table = new_table
2023-12-15 11:24:50 +04:00
# Получение решения
2023-12-13 15:36:58 +04:00
for i in range(len(result)):
2023-12-15 11:24:50 +04:00
# Извлечение значений переменных из базиса
2023-12-13 15:36:58 +04:00
k = self.basis.index(i + 1) if i + 1 in self.basis else -1
result[i] = self.table[k, 0] if k != -1 else 0
return self.table
def is_it_end(self):
2023-12-15 11:24:50 +04:00
# Проверка критерия окончания: все элементы последней строки неотрицательны
2023-12-13 15:36:58 +04:00
return np.all(self.table[self.m - 1, 1:] >= 0)
def find_main_col(self):
2023-12-15 11:24:50 +04:00
# Нахождение ведущей колонки: минимальный отрицательный коэффициент в последней строке
2023-12-13 15:36:58 +04:00
main_col = 1
for j in range(2, self.n):
if self.table[self.m - 1, j] < self.table[self.m - 1, main_col]:
main_col = j
return main_col
def find_main_row(self, main_col):
2023-12-15 11:24:50 +04:00
# Нахождение ведущей строки: минимальное положительное отношение свободного члена к ведущему элементу
2023-12-13 15:36:58 +04:00
main_row = 0
for i in range(self.m - 1):
if self.table[i, main_col] > 0:
main_row = i
break
for i in range(main_row + 1, self.m - 1):
if self.table[i, main_col] > 0 and (self.table[i, 0] / self.table[i, main_col]) < (self.table[main_row, 0] / self.table[main_row, main_col]):
main_row = i
return main_row