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()