diff --git a/resources/simplex/initialize.py b/resources/simplex/initialize.py index 577ee84f650a13a96327054b7479976fcc606905..3a776b745e12f94fffe32be592a1d7b6d23b6e80 100644 --- a/resources/simplex/initialize.py +++ b/resources/simplex/initialize.py @@ -34,7 +34,12 @@ class Initialize(): self._basic_var_indexes = None self._nonbasic_var_indexes = None - def __call__(self, *args, **kwargs): + def __call__(self, *args, debug=False, **kwargs): + # Optionally override parent debug setting on call. + orig_debug = self._debug + if debug is True: + self._debug = debug + # Get parent data at the point of call. self._matrix_a = self._parent._matrix_a self._vector_b = self._parent._vector_b @@ -44,7 +49,12 @@ class Initialize(): self._nonbasic_var_indexes = self._parent._n_array # Run initialize function. - return self.initialize_simplex() + results = self.initialize_simplex() + + # Reset original debug settings. + self._debug = orig_debug + + return results def initialize_simplex(self): # Determine smallest constant for constraints. @@ -82,17 +92,17 @@ class Initialize(): # Optional debugging printout. if self._debug: - logger.info('') logger.info('Starting Initialize._correct_simplex()') logger.info(' n_array: {0}'.format(n_array)) logger.info(' b_array: {0}'.format(b_array)) logger.info(' matrix_a: {0}'.format(matrix_a)) logger.info(' vector_b: {0}'.format(vector_b)) logger.info(' obj_constant_index: {0}'.format(obj_const_index)) + logger.info('') # Add a "new" constraint variable. This will be set to 1 for all constants and -1 for obj func. for row_index in range(len(matrix_a)): - matrix_a[row_index].append(1) + matrix_a[row_index].append(-1) # "Reset" objective function to 0 for everything other than our new var. for col_index in range(len(vector_c)): @@ -104,16 +114,65 @@ class Initialize(): # Update our parent values for a pivot. self._parent._matrix_a = copy.deepcopy(matrix_a) self._parent._vector_c = copy.deepcopy(vector_c) - self._parent._n_array.append(len(vector_c) - 2) - # logger.info('Nonbasics: {0}'.format(self._parent._nonbasic_var_indexes)) - # logger.info('Basics: {0}'.format(self._parent._basic_var_indexes)) + temporary_col = len(vector_c) - 2 + self._parent._n_array.append(temporary_col) + self._parent._obj_constant_index += 1 # Now pivot once to get a feasible instance. - # self._parent.display_tableau() - # logger.info('Smallest Index: {0}'.format(smallest_index)) self._parent.pivot(self._parent._b_array[smallest_index], (len(vector_c) - 2)) - # Need base "Simplex" function to run further? - return None + # Run the loop part of our original "Simplex" function, but using our modified values. + self._parent._run_simplex._optimization_loop() + + # Get parent data now that we have solved our aux array. + matrix_a = self._parent._matrix_a + vector_b = self._parent._vector_b + vector_c = self._parent._vector_c + obj_const_index = self._parent._obj_constant_index + b_array = self._parent._b_array + n_array = self._parent._n_array + + # Check if we got 0 as the optimal solution. + if vector_c[obj_const_index] == 0: + # Solution exists for original simplex. Check status of temporary column. + if temporary_col in b_array: + # Temporary column is basic. Pivot one last time to make it nonbasic. + pass + + # Remove temporary columns. + obj_const_index -= 1 + for row_index in range(len(matrix_a)): + matrix_a[row_index].pop(temporary_col) + if temporary_col in b_array: + b_array.remove(temporary_col) + elif temporary_col in n_array: + n_array.remove(temporary_col) + + # "Restore" original objective, but with basic variables modified. + vector_c = self._vector_c + for row_index in range(len(b_array)): + col_value = self._vector_c[b_array[row_index]] + + # Check if value is not 0. + if col_value != 0: + # Not 0, so update with row values of aux matrix. + for col_index in range(len(vector_c) - 1): + vector_c[col_index] = vector_c[col_index] + (col_value * -matrix_a[row_index][col_index]) + + # Update constant as well. + vector_c[obj_const_index] = vector_c[obj_const_index] + (col_value * vector_b[row_index]) + + # Update parent values. + self._parent._matrix_a = matrix_a + self._parent._vector_b = vector_b + self._parent._vector_c = vector_c + self._parent._obj_constant_index = obj_const_index + self._parent._b_array = b_array + self._parent._n_array = n_array + + else: + # No solution exists for original simplex. + logger.info('Could not determine solution for simplex problem. Problem is likely infeasible.') + return None diff --git a/tests/resources/simplex/initialize.py b/tests/resources/simplex/initialize.py index 7d88d9ec7b45f4ab2bd59d3383de04781c7252af..0c57b10ff4af6556e013f74fa49c10b9b3e16d01 100644 --- a/tests/resources/simplex/initialize.py +++ b/tests/resources/simplex/initialize.py @@ -21,14 +21,8 @@ class TestInitialize(unittest.TestCase): def test__initialize(self): # Setup initial simplex. - self.simplex.set_simplex_values( - [ - [2, -1], - [1, -5], - ], - [2, -4], - [2, -1], - ) + self.simplex.read_data_from_json('./resources/json_files/ex_5.json') + # Test initial values after setup. self.assertEqual(self.simplex._matrix_a, [ [2, -1, 1, 0], @@ -41,18 +35,15 @@ class TestInitialize(unittest.TestCase): self.assertEqual(self.simplex._n_array, [0, 1]) # Call initialize method to test. - # self.simplex.display_tableau() self.simplex.initialize() - # self.simplex.display_tableau() - - # # Test initial values "initialize" method. - # self.assertEqual(self.simplex._matrix_a, [ - # [1-5, 1, 0, 1/5], - # [-9/5, 0, 1, 1/5], - # ]) - # self.assertEqual(self.simplex._constants, [4/5, 14/5]) - # self.assertEqual(self.simplex._obj_func, [9/5, 0, 0, 1/5, -4/5]) - # self.assertEqual(self.simplex._obj_constant_index, 4) - # self.assertEqual(self.simplex._basic_var_indexes, [1, 2]) - # self.assertEqual(self.simplex._nonbasic_var_indexes, [0, 3]) + # Test initial values "initialize" method. + self.assertEqual(self.simplex._matrix_a, [ + [9/5, 0, 1, (-1 + 4/5)], # We use -1/5th represented as a float. Technically is the same value. + [-1/5, 1, 0, -1/5], + ]) + self.assertEqual(self.simplex._vector_b, [14/5, 4/5]) + self.assertEqual(self.simplex._vector_c, [9/5, 0, 0, -1/5, -4/5]) + self.assertEqual(self.simplex._obj_constant_index, 4) + self.assertEqual(self.simplex._b_array, [2, 1]) + self.assertEqual(self.simplex._n_array, [0, 3])