def __init__(self, type=OptimizationType.maximization, **kwargs): self.variable_names = [] # 所有变量,包括松弛变量 self.original_variables = [] # 优化目标中包含的变量 self.left_side = [] # 存储扩展后方程组左侧的系数 self.right_side = [] # 存储扩展后方程组右侧的常数 self.ratio = [] # 存储各方程组的离速 self.basic_variables = [] # 基变量列表 self.slack_variables = [] # 松弛变量列表 self.artificial_variables = [] # 人工变量列表 self.surplus_variables = [] # 剩余变量 if type == OptimizationType.maximization: eq0 = [FractionWithM(1)] for v in kwargs: self.variable_names.append(v) self.original_variables.append(len(self.variable_names) - 1) eq0.append(FractionWithM(-kwargs[v])) else: eq0 = [FractionWithM(-1)] for v in kwargs: self.variable_names.append(v) self.original_variables.append(len(self.variable_names) - 1) eq0.append(FractionWithM(kwargs[v])) self.left_side.append(eq0) self.right_side.append(FractionWithM(0)) self.ratio.append('') self.basic_variables.append(None)
def add_greater_constraint(self, constraint, **kwargs): eq0 = self.left_side[0] eq0.append(FractionWithM(0)) eq0.append(FractionWithM(M=1, value=0)) for i in range(1, len(self.left_side)): eq = self.left_side[i] eq.append(FractionWithM(0)) eq.append(FractionWithM(0)) eq = [FractionWithM(0)] for var in self.variable_names: if var in kwargs: eq.append(FractionWithM(kwargs[var])) else: eq.append(FractionWithM(0)) eq.append(FractionWithM(-1)) eq.append(FractionWithM(1)) self.left_side.append(eq) self.right_side.append(FractionWithM(constraint)) self.ratio.append('') self.variable_names.append('_ss' + str(len(self.surplus_variables) + 1)) self.surplus_variables.append(len(self.variable_names) - 1) self.variable_names.append('_a' + str(len(self.artificial_variables) + 1)) self.artificial_variables.append(len(self.variable_names) - 1) self.basic_variables.append(len(self.variable_names) - 1)
def __init__(self, **kwargs): """ 创建优化模型,并建立(最大化)优化目标函数 :param kwargs: 目标函数中各变量的系数 """ self.variable_names = [] # 所有变量的变量名,包括松弛变量 self.original_variables = [] # 优化目标中包含的变量 self.left_side = [] # 存储扩展后方程组左侧的系数矩阵(用二维列表表示) self.right_side = [] # 存储扩展后方程组右侧的常数 self.ratio = [] # 存储各方程组的离速 self.basic_variables = [] # 基变量列表 self.slack_variables = [] #松弛变量列表 self.artificial_variables = [] #人工变量列表 eq0 = [FractionWithM(1)] for v in kwargs: self.variable_names.append(v) self.original_variables.append(len(self.variable_names) - 1) eq0.append(FractionWithM(-kwargs[v])) self.left_side.append(eq0) self.right_side.append(FractionWithM(0)) self.ratio.append('') self.basic_variables.append(None)
def add_equal_constraint(self, constraint, **kwargs): """ 添加约束(等于) :param constaint: 右侧的约束值,必须大于0 :param kwargs: 左侧各变量的系数 :return: 无 """ eq0 = self.left_side[0] eq0.append(FractionWithM(M=1, value=0)) for i in range(1, len(self.left_side)): eq = self.left_side[i] eq.append(FractionWithM(0)) eq = [FractionWithM(0)] for var in self.variable_names: if var in kwargs: eq.append(FractionWithM(kwargs[var])) else: eq.append(FractionWithM(0)) eq.append(FractionWithM(1)) self.left_side.append(eq) self.right_side.append(FractionWithM(constraint)) self.ratio.append('') self.variable_names.append('_a' + str(len(self.left_side) - 1)) self.artificial_variables.append(len(self.variable_names) - 1) self.basic_variables.append(len(self.variable_names) - 1)
def add_less_constraint(self, constraint, **kwargs): for eq in self.left_side: eq.append(FractionWithM(0)) eq = [FractionWithM(0)] for var in self.variable_names: if var in kwargs: eq.append(FractionWithM(kwargs[var])) else: eq.append(FractionWithM(0)) eq.append(FractionWithM(1)) self.left_side.append(eq) self.right_side.append(FractionWithM(constraint)) self.ratio.append('') self.variable_names.append('_s' + str(len(self.slack_variables) + 1)) self.slack_variables.append(len(self.variable_names) - 1) self.basic_variables.append(len(self.variable_names) - 1)
def add_less_constraint(self, constraint, **kwargs): """ 添加约束(小于等于) :param constaint: 右侧的约束值,必须大于0 :param kwargs: 左侧各变量的系数 :return: 无 """ for eq in self.left_side: eq.append(FractionWithM(0)) eq = [FractionWithM(0)] for var in self.variable_names: if var in kwargs: eq.append(FractionWithM(kwargs[var])) else: eq.append(FractionWithM(0)) eq.append(FractionWithM(1)) self.left_side.append(eq) self.right_side.append(FractionWithM(constraint)) self.ratio.append('') self.variable_names.append('_s' + str(len(self.left_side) - 1)) self.slack_variables.append(len(self.variable_names) - 1) self.basic_variables.append(len(self.variable_names) - 1)
def solve(self): print("Intial form:") print('---------------------------------') self._display(highlight=False) print() print("Converting Equaiton(0) to proper form:") print('---------------------------------') self._eliminate_artificials() self._display(highlight=False) iteration = 0 while True: iteration += 1 print(f'iteration {iteration}:') print('---------------------------------') # Optimality Test # find the variable with the minimum negative coeffecient eq0 = self.left_side[0] min_v = FractionWithM(0) min_i = -1 for i in range(1, len(eq0)): if eq0[i] < min_v: min_v = eq0[i] min_i = i if min_v == 0: print("The solution is optimal") break enter_basic = min_i # Minumum Ratio Test min_ratio = None min_i = -1 for i in range(1, len(self.left_side)): eq = self.left_side[i] if eq[enter_basic] == 0: self.ratio[i] = '' else: denominator = eq[enter_basic] if denominator <= 0: self.ratio[i] == '' else: self.ratio[i] = self.right_side[i] / denominator if min_ratio is None or self.ratio[i] < min_ratio: min_ratio = self.ratio[i] min_i = i if min_i == -1: print("can't find the minimum ratio!") return leaving_basic_eq_index = min_i leaving_basic = self.basic_variables[min_i] self._display(enter_basic - 1, leaving_basic_eq_index) print("Entering basic :", self.variable_names[enter_basic - 1]) print("leaving basic:", self.variable_names[leaving_basic]) # Gaussian Elimination leaving_basic_eq = self.left_side[min_i] denominator = leaving_basic_eq[enter_basic] for i in range(len(leaving_basic_eq)): leaving_basic_eq[i] /= denominator self.right_side[min_i] /= denominator self.basic_variables[min_i] = enter_basic - 1 for i in range(len(self.left_side)): if i == min_i: continue eq = self.left_side[i] multiple = eq[enter_basic] for j in range(len(eq)): eq[j] -= multiple * leaving_basic_eq[j] self.right_side[i] -= multiple * self.right_side[min_i] self._display(highlight=False) self._display_solution()