Лабораторная работа по вычислительной математике

This commit is contained in:
Danil Markov 2023-12-18 19:02:04 +04:00
parent e1718b8ed7
commit 65c8159559
4 changed files with 110 additions and 91 deletions

View File

@ -1,83 +0,0 @@
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

17
main.py
View File

@ -1,15 +1,16 @@
import numpy as np
from Simplex import Simplex
from simplex import simplex
table = np.array([[7, 1, 1, 1, 1],
[2, -1, 1, -1, 1],
[-5, 3, -1, -2, 0],
[0, -1, 2, -3, 0]])
# в каноническом виде
table = np.array([[7, 1, 1, 1],
[2, -1, 1, -1],
[-5, 3, -1, -2],
[0, -1, 2, -3]])
result = np.zeros(3)
S = Simplex(table)
table_result = S.calculate(result)
s = simplex(table)
table_result = s.calculate(result)
print("Решенная симплекс-таблица:")
for i in range(table_result.shape[0]):
@ -21,4 +22,4 @@ print()
print("Решение:")
print("X[1] =", result[0])
print("X[2] =", result[1])
print("X[3] =", result[2])
print("X[3] =", result[2])

1
readme.md Normal file
View File

@ -0,0 +1 @@
ПИбд-31 || Марков Данил

100
simplex.py Normal file
View File

@ -0,0 +1,100 @@
import numpy as np
class simplex:
def __init__(self, source):
# m - кол-во строк, n - кол-во столбцов
m, n = source.shape
# таблица с m строк и n+m-1 столбцов, для базисных переменных
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:
# вышли за n, значит добавляем базисные столбцы
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):
# если все элементы последней строки f(x) неотрицательны,
# значит допустимое базисное решение оптиммально
return np.all(self.table[self.m - 1, 1:] >= 0)
def find_main_col(self):
# находим ведущую колонку,
# минимальный отрицательный коэффициент в последней строке f(x)
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