diff --git a/resources/simplex/base.py b/resources/simplex/base.py index 7c101f104127d71fbe2bd12a0e98911140f5f7bd..a6973feb386f5cedfef839da48c653b15b0f84c0 100644 --- a/resources/simplex/base.py +++ b/resources/simplex/base.py @@ -38,6 +38,7 @@ import json # User Class Imports. from .initialize import Initialize from .pivot import Pivot +from .run_simplex import RunSimplex from resources import logging as init_logging @@ -58,6 +59,7 @@ class SimplexBase(): self._n_array = None self._description = None + self._run_simplex = RunSimplex(self) self._initialize = Initialize(self) self._pivot = Pivot(self) @@ -398,7 +400,17 @@ class SimplexBase(): #region Child Class Functions + def solve(self): + """ + Solves simplex. + :return: Solution, in format of (max_value, location of max value). + """ + return self._run_simplex() + def initialize(self): + """ + Initializes simplex. + """ self._initialize() def pivot(self, old_basic_index, new_basic_index): diff --git a/resources/simplex/run_simplex.py b/resources/simplex/run_simplex.py index 145d0e792311c3875be1e1d5250d6a11bf354f87..06750c3394b0edaccf3f0cc9bffb1ea418a90381 100644 --- a/resources/simplex/run_simplex.py +++ b/resources/simplex/run_simplex.py @@ -32,7 +32,7 @@ class RunSimplex(): self._basic_var_indexes = None self._nonbasic_var_indexes = None - def __call__(self, old_basic_col, new_basic_col, *args, **kwargs): + def __call__(self, *args, **kwargs): # Run pivot function. return self._simplex() @@ -40,41 +40,68 @@ class RunSimplex(): # Run "Initialize-Simplex" function before we do any work. self._parent.initialize() - # Get parent data, after initialized. - matrix_a = self._parent._matrix_a - vector_b = self._parent._vector_b - vector_c = self._parent._vector_c - obj_constant_index = self._parent._obj_constant_index - basic_var_indexes = self._parent._b_array - nonbasic_var_indexes = self._parent._n_array - # Create loop to continually improve simplex until optimized. still_optimizable = True while still_optimizable: still_optimizable = False highest_obj_index = -1 + + # Update parent data, after each loop. + matrix_a = self._parent._matrix_a + vector_b = self._parent._vector_b + vector_c = self._parent._vector_c + obj_constant_index = self._parent._obj_constant_index + basic_var_indexes = self._parent._b_array + nonbasic_var_indexes = self._parent._n_array + # Check that we actually can still optimize values. for col_index in range(len(nonbasic_var_indexes)): # Check if value is greater than 0. + logger.info('vector_c: {0}'.format(vector_c)) + logger.info('vector_c[{0}]: {1}'.format(col_index, vector_c[col_index])) if vector_c[col_index] > 0: still_optimizable = True # Check if current index is larger than previously found one. if highest_obj_index == -1 or vector_c[col_index] > vector_c[highest_obj_index]: + logger.info('Updating index to: {0}'.format(col_index)) highest_obj_index = col_index # Check that we found something to optimize. if still_optimizable: self._optimize_on_index(highest_obj_index) + # If we got this far, then it should be solved. Get parent values once more. + matrix_a = self._parent._matrix_a + vector_b = self._parent._vector_b + vector_c = self._parent._vector_c + obj_constant_index = self._parent._obj_constant_index + basic_var_indexes = self._parent._b_array + + # Get solution. + solution = [] + for col_index in range(len(vector_b)): + # Check if col is basic or not. + if col_index in basic_var_indexes: + # Col is basic. Find associated row where basic value exists. + for row_index in range(len(matrix_a)): + if matrix_a[row_index][col_index] == 1: + # Found row where basic value exists. Return row's constant value. + solution.append(vector_b[row_index]) + else: + # Col is not basic. Return 0. + solution.append(0) + + return (-vector_c[obj_constant_index], solution) + def _optimize_on_index(self, col_index): # Get parent data, after initialized. matrix_a = self._parent._matrix_a vector_b = self._parent._vector_b vector_c = self._parent._vector_c - obj_constant_index = self._parent._obj_constant_index basic_var_indexes = self._parent._b_array - nonbasic_var_indexes = self._parent._n_array + + logger.info('Attempting to pivot on index {0}: {1}'.format(col_index, vector_c[col_index])) # Loop through all rows, finding best one to pivot on. delta = [] @@ -95,3 +122,6 @@ class RunSimplex(): smallest_valid_index = row_index # Now pivot on our found values. + self._parent.pivot(basic_var_indexes[smallest_valid_index], col_index) + + self._parent.display_tableau() diff --git a/tests/resources/simplex/run_simplex.py b/tests/resources/simplex/run_simplex.py index 3b5f8a4f94814ccd13cdbfde885ca53d56f5047a..990e451890029875b1fca296ac997e891f62e9b9 100644 --- a/tests/resources/simplex/run_simplex.py +++ b/tests/resources/simplex/run_simplex.py @@ -20,5 +20,24 @@ class TestPivot(unittest.TestCase): self.simplex = SimplexBase() def test__run_simplex(self): - # Setup initial simplex. - pass + # Setup initial simplex, using JSON data. + self.simplex.read_data_from_json('./resources/json_files/ex_1.json') + + # Test initial values after setup. + self.assertEqual(self.simplex._matrix_a, [ + [1, 1, 1, 0], + [1, 1, 0, 1] + ]) + self.assertEqual(self.simplex._vector_b, [1, 1]) + self.assertEqual(self.simplex._vector_c, [1, 1, 0, 0, 0]) + self.assertEqual(self.simplex._obj_constant_index, 4) + self.assertEqual(self.simplex._b_array, [2, 3]) + self.assertEqual(self.simplex._n_array, [0, 1]) + + # Attempt to fully solve simplex. + self.simplex.display_tableau() + results = self.simplex.solve() + + # Test values after solving. + self.assertEqual(results[0], 1) + self.assertEqual(results[1], (1, 0))