PIbd-31_Abrosimova_Khaibull.../Simplex.py

102 lines
5.5 KiB
Python
Raw Permalink Normal View History

2023-12-18 17:14:01 +04:00
import numpy as np
class Simplex:
def __init__(self, source):
# Получение размеров матрицы source в переменные
# m (количество строк) и n (количество столбцов).
m, n = source.shape
self.table = np.zeros((m, n + m - 1))
# Будет содержать индексы базисных переменных.
self.basis = []
# Заполнение матрицы table значениями из матрицы source до столбца n.
# Остальные элементы инициализируются нулями.
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)
# Сохранение значений m и n в атрибуты объекта.
self.m = m
self.n = self.table.shape[1]
# Метод calculate, который выполняет итерации симплекс-метода до достижения оптимального решения
# или обнаружения отсутствия решения.
def calculate(self, result):
# Цикл, выполняющийся до тех пор, пока не будет достигнут критерий окончания
# (проверяется методом is_it_end()).
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
# Инициализация новой матрицы нулями той же размерности, что и self.table.
new_table = np.zeros((self.m, self.n))
# Заполнение строки main_row новой матрицы значениями,
# полученными делением соответствующих элементов из исходной матрицы.
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
# Заполнение массива result значениями переменных в соответствии с текущим базисом.
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):
# sВозвращает True, если все элементы последней строки матрицы больше
# или равны нулю (условие оптимальности).
return np.all(self.table[self.m - 1, 1:] >= 0)
# Метод нахождения ведущего столбца методом find_main_col().
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
# Поиск строки с минимальным отношением элемента в столбце 0 к элементу в заданном столбце
# Отношение используется для выбора оптимальной строки для ведущей.
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