Simplex/main.py
2023-12-18 04:08:40 +04:00

149 lines
5.3 KiB
Python

import numpy as np
class Config:
lst: list[[np.ndarray, str, float]] = []
def add(self, a: np.array, sim: str, b: float):
self.lst.append([a, sim, b])
def lst_to_canon(self):
for row in self.lst:
if row[2] < 0:
row[0] *= -1
if row[1] == ">=":
row[1] = "<="
elif row[1] == "<=":
row[1] = ">="
row[2] *= -1
for index_row in range(len(self.lst)):
if self.lst[index_row][1] == "<=":
self.lst[index_row][0] = np.append(self.lst[index_row][0], 1)
elif self.lst[index_row][1] == ">=":
self.lst[index_row][0] = np.append(self.lst[index_row][0], -1)
self.lst[index_row][1] = "="
for index_extra_row in range(len(self.lst)):
if index_row == index_extra_row:
continue
self.lst[index_extra_row][0] = np.append(self.lst[index_extra_row][0], 0)
class Simplex:
canon_conf: list[[np.ndarray, float, int | None]] = []
func: np.ndarray
count: int
lst_header: list = ["ind", "bas", "Cb", "b"]
def __init__(self, canon_cfg, func):
self.func = func
for row in canon_cfg:
self.canon_conf.append([row[0], row[2], None])
self.count = len(canon_cfg[0][0])
for i in range(self.count):
self.lst_header.append(f"x{i}")
def find_basis(self):
busy = set()
for i in range(len(self.canon_conf)):
for j in range(len(self.canon_conf[i][0])):
if self.canon_conf[i][0][j] == 0:
continue
if self.canon_conf[i][1] / self.canon_conf[i][0][j] < 0:
continue
for k in range(len(self.canon_conf)):
if k == i:
continue
if self.canon_conf[k][0][j] != 0:
break
else:
busy.add(i)
self.canon_conf[i][2] = j
self.canon_conf[i][1] /= self.canon_conf[i][0][self.canon_conf[i][2]]
self.canon_conf[i][0] /= self.canon_conf[i][0][self.canon_conf[i][2]]
break
if self.canon_conf[i][2] is None:
raise Exception("No basis")
def method(self):
while True:
m = [sum([i[1] * self.func[i[2]] if i[2] < len(self.func) else 0 for i in self.canon_conf]),
[sum([row[0][i] * self.func[row[2]] if row[2] < len(self.func) else 0 for row in self.canon_conf])
- (self.func[i] if i < len(self.func) else 0) for i in range(self.count)]]
self.print_table(m)
col = -1
for i in range(len(m[1])):
if m[1][i] > 0:
col = i
break
else:
return
mi = 999999
row = -1
for i in range(len(self.canon_conf)):
if self.canon_conf[i][0][col] <= 0:
continue
buff = self.canon_conf[i][1] / self.canon_conf[i][0][col]
if buff < mi:
row = i
mi = buff
if row < 0:
raise Exception("strange")
k = self.canon_conf[row][0][col]
self.canon_conf[row][2] = col
lst = []
for i in range(len(self.canon_conf)):
lst.append(np.append([self.canon_conf[i][1]], self.canon_conf[i][0]).tolist())
self.canon_conf[row][1] /= k
self.canon_conf[row][0] /= k
for i in range(len(self.canon_conf)):
if i == row:
continue
self.canon_conf[i][1] = self.canon_conf[i][1] - ((lst[row][0] * lst[i][col + 1]) / k)
for j in range(len(self.canon_conf[i][0])):
if j == col:
self.canon_conf[i][0][j] = 0
else:
self.canon_conf[i][0][j] = self.canon_conf[i][0][j] - ((lst[row][j + 1] * lst[i][col + 1]) / k)
def print_table(self, m: list | None = None):
print("Table:")
print("-" * 100)
print("".join([f"{i:<10}" for i in self.lst_header]))
for i in range(len(self.canon_conf)):
lst_data_row = [f"{i + 1}", f"{self.canon_conf[i][2]}"]
if self.canon_conf[i][2] >= len(self.func):
lst_data_row.append("0")
else:
lst_data_row.append(f"{self.func[self.canon_conf[i][2]]}")
lst_data_row.append(f"{self.canon_conf[i][1]}")
lst_data_row = np.append(lst_data_row, self.canon_conf[i][0])
print("".join([f"{i:<10.7}" for i in lst_data_row]))
if m is not None:
lst_m = ["m + 1", " ", " ", m[0]] + m[1]
print("".join([f"{i:<10.7}" for i in lst_m]))
print("-" * 100)
if __name__ == "__main__":
Z = np.array([18, 16, 5, 21], dtype="float64")
conf = Config()
conf.add(np.array([1, 2, 0, 3], dtype="float64"), ">=", 2)
conf.add(np.array([3, 1, 1, 0], dtype="float64"), ">=", 3)
conf.lst_to_canon()
simp = Simplex(conf.lst, np.array([18, 16, 5, 21]))
simp.find_basis()
# simp.print_table()
simp.method()