def run(self) -> dict: parent_simplex = Simplexx(self.matr, self.b, self.lambdas, self.condition) parent_solution = parent_simplex.run() print(f'Решение: {parent_solution}') non_int_value = self.first_non_integer_solution(parent_solution) if non_int_value is not None: print(f'Нецелочисленное решение: {non_int_value}. Разветвляем') branch1, branch2 = BranchAndBound.split(parent_simplex, non_int_value) try: print('\n\nРешаем ветку 1') child1_solution = branch1.run() except (NoPivotalSolutionExists, NoOptimalSolutionExists) as e: print(e) child1_solution = None try: print('\n\nРешаем ветку 2') child2_solution = branch2.run() except (NoPivotalSolutionExists, NoOptimalSolutionExists) as e: print(e) child2_solution = None # обе ветки решились if child1_solution is not None and child2_solution is not None: if self.condition is Condition.MAX: if child1_solution['F'] > child2_solution['F']: return child1_solution else: return child2_solution else: if child1_solution['F'] < child2_solution['F']: return child1_solution else: return child2_solution # ветка 1 не решилась, 2 - решилась elif child1_solution is None and child2_solution is not None: return child2_solution # ветка 1 решилась, 2 - не решилась elif child1_solution is not None and child2_solution is None: return child1_solution # обе ветки не решились else: raise NoIntegerSolutionExists() else: print('Решение целочисленное. Ветка закончена') return parent_solution
def create_simplex_with_additional_bound(simplex: Simplexx, new_bound_key: str, new_bound_value: int, new_bound_sign: Sign) -> Simplexx: # находим колонку, которая соответстует нецелому "x_i". нумерация x - с единицы new_bound_column = int(new_bound_key.split('_')[1]) - 1 matr_columns = simplex.matr.shape[1] additional_a_row = [0] * matr_columns if new_bound_sign is Sign.PLUS: additional_a_row[new_bound_column] = 1 else: additional_a_row[new_bound_column] = -1 additional_a_row = np.array(additional_a_row) # дпоисываем строку в низ матрицы А curr_a = simplex.matr new_a = np.vstack((curr_a, additional_a_row)) additional_b_row = None if new_bound_sign is Sign.PLUS: additional_b_row = np.array([new_bound_value]) else: additional_b_row = np.array([-1 * new_bound_value]) # дописываем значение ограничения в низ столбца b curr_b = simplex.b new_b = np.vstack((curr_b, additional_b_row)) return Simplexx(new_a, new_b, simplex.lambdas, simplex.condition)
def test_no_allowed_solution(self): # given a = np.array([[2, 1], [-3, -4]]) b = np.array([[2], [-12]]) lambdas = np.array([[3, 2]]) # expect self.assertRaises(NoPivotalSolutionExists, Simplexx(a, b, lambdas, Condition.MAX).run)
def test_unbounded_solution(self): # given a = np.array([[1, -1], [1, 0]]) b = np.array([[10], [20]]) lambdas = np.array([[1, 2]]) # expect self.assertRaises(NoOptimalSolutionExists, Simplexx(a, b, lambdas, Condition.MAX).run)
def play_as_a(self) -> Optional[dict]: print('Стратегия игрока A') try: self.solution_a = Simplexx(self.matrix, self.b, self.lambdas, Condition.MIN).run() return self.solution_a except (NoPivotalSolutionExists, NoOptimalSolutionExists) as e: print(e) return None
def test_example_2_from_book(self): a = np.array([[3, 1, -4, -1], [-2, -4, -1, 1]]) b = np.array([[-3], [-3]]) lambdas = np.array([[-4, -18, -30, -5]]) # when solution = Simplexx(a, b, lambdas, Condition.MAX).run() # then actual_f_value = solution['F'] self.assertEqual(-36, actual_f_value)
def test_example_1_from_book(self): a = np.array([[1, -2], [-2, 1], [1, 1]]) b = np.array([[2], [-2], [5]]) lambdas = np.array([[-1, 1]]) # when solution = Simplexx(a, b, lambdas, Condition.MIN).run() # then actual_f_value = solution['F'] self.assertEqual(-3, actual_f_value)
def test_var_3_MAX_MIN(self): a = np.array([[2, 1, 1], [1, 2, 0], [0, 0.5, 1]]) b = np.array([[4], [6], [2]]) lambdas = np.array([[2, 8, 3]]) # when print('=== MAX ===') solution = Simplexx(a, b, lambdas, Condition.MAX).run() # then actual_f_value = solution['F'] self.assertEqual(25.5, actual_f_value) # when print('=== MIN ===') solution = Simplexx(a, b, lambdas, Condition.MIN).run() # then actual_f_value = solution['F'] self.assertEqual(0, actual_f_value)
def test_branch_1(self): a = np.array([[6, -1], [2, 5], [1, 0]]) b = np.array([[12], [20], [2]]) lambdas = np.array([[12, -1]]) # when solution = Simplexx(a, b, lambdas, Condition.MAX).run() # then actual_f_value = solution['F'] self.assertEqual(24, actual_f_value)
def test_var_10(self): a = np.array([[4, 1, 1], [1, 2, 0], [0, 0.5, 1]]) b = np.array([[4], [3], [2]]) lambdas = np.array([[7, 5, 3]]) # when print('=== Прямая ===') primary_solution = Simplexx(a, b, lambdas, Condition.MAX).run() # then expected_f_value = 13 self.assertEqual(expected_f_value, primary_solution['F'])
def test_unbounded_solution(self): # given a = np.array([[1, -1], [1, 0]]) b = np.array([[10], [20]]) lambdas = np.array([[1, 2]]) # по первой теореме двойственности, если у прямой нет опорного решения, # то у двойственной нет оптимального print('=== Прямая ===') self.assertRaises(NoOptimalSolutionExists, Simplexx(a, b, lambdas, Condition.MAX).run) print('\n\n\n=== Двойственная ===') self.assertRaises(NoPivotalSolutionExists, DualSimplexx(a, b, lambdas, Condition.MAX).run)
def test_example_2_from_book(self): a = np.array([[3, 1, -4, -1], [-2, -4, -1, 1]]) b = np.array([[-3], [-3]]) lambdas = np.array([[-4, -18, -30, -5]]) # when print('=== Прямая ===') primary_solution = Simplexx(a, b, lambdas, Condition.MAX).run() # when print('\n\n\n=== Двойственная ===') dual_solution = DualSimplexx(a, b, lambdas, Condition.MAX).run() # then expected_f_value = -36 self.assertEqual(expected_f_value, primary_solution['F']) self.assertEqual(expected_f_value, dual_solution['F'])
def test_example_1_from_book(self): a = np.array([[1, -2], [-2, 1], [1, 1]]) b = np.array([[2], [-2], [5]]) lambdas = np.array([[-1, 1]]) # when print('=== Прямая ===') primary_solution = Simplexx(a, b, lambdas, Condition.MIN).run() # when print('\n\n\n=== Двойственная ===') dual_solution = DualSimplexx(a, b, lambdas, Condition.MIN).run() # then expected_f_value = -3 self.assertEqual(expected_f_value, primary_solution['F']) self.assertEqual(expected_f_value, dual_solution['F'])
def test_var_3(self): a = np.array([[2, 1, 1], [1, 2, 0], [0, 0.5, 1]]) b = np.array([[4], [6], [2]]) lambdas = np.array([[2, 8, 3]]) # when print('=== Прямая ===') primary_solution = Simplexx(a, b, lambdas, Condition.MAX).run() # when print('\n\n\n=== Двойственная ===') dual_solution = DualSimplexx(a, b, lambdas, Condition.MAX).run() # then expected_f_value = 25.5 self.assertEqual(expected_f_value, primary_solution['F']) self.assertEqual(expected_f_value, dual_solution['F'])
def test_variable_mapping(self): # given a = np.array([[1, -2], [-2, 1], [1, 1]]) b = np.array([[2], [-2], [5]]) lambdas = np.array([[1, -1]]) # when solutions = Simplexx(a, b, lambdas, Condition.MAX).run() # then expected_best_solution = ({ 'x_1': 4.0, 'x_2': 1.0, 'x_3': 0, 'x_4': 5.0, 'x_5': 0, 'F': 3.0 }) self.assertEqual(expected_best_solution, solutions)