MathVM/Simplex.py

83 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import numpy as np
class Simplex:
def __init__(self, source):
# Инициализация объекта Simplex с исходной таблицей source
m, n = source.shape
# Инициализация таблицы и списка базисных переменных
self.table = np.zeros((m, n + m - 1))
self.basis = []
# Формирование начальной симплекс-таблицы
for i in range(m):
for j in range(self.table.shape[1]):
if j < n:
# Копирование коэффициентов из исходной таблицы
self.table[i, j] = source[i, j]
else:
# Добавление единичных столбцов для базисных переменных
self.table[i, j] = 0
if (n + i) < self.table.shape[1]:
# Установка единицы в соответствующем столбце для базисной переменной
self.table[i, n + i] = 1
# Добавление базисной переменной в список
self.basis.append(n + i)
self.m = m
self.n = self.table.shape[1]
def calculate(self, result):
# Основной цикл симплекс-метода
while not self.is_it_end():
# Нахождение ведущей колонки и строки
main_col = self.find_main_col()
main_row = self.find_main_row(main_col)
# Обновление списка базисных переменных
self.basis[main_row] = main_col
# Пересчет симплекс-таблицы
new_table = np.zeros((self.m, self.n))
for j in range(self.n):
# Нормализация ведущей строки
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):
# Обновление остальных строк таблицы
new_table[i, j] = self.table[i, j] - self.table[i, main_col] * new_table[main_row, j]
self.table = new_table
# Получение решения
for i in range(len(result)):
# Извлечение значений переменных из базиса
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):
# Проверка критерия окончания: все элементы последней строки неотрицательны
return np.all(self.table[self.m - 1, 1:] >= 0)
def find_main_col(self):
# Нахождение ведущей колонки: минимальный отрицательный коэффициент в последней строке
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):
# Нахождение ведущей строки: минимальное положительное отношение свободного члена к ведущему элементу
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