149 lines
5.3 KiB
Python
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()
|
|
|
|
|