def get_col_bounds(self): 'get column bounds' lp_cols = self.get_num_cols() # column lower and upper bounds col_bounds = [] for col in range(lp_cols): col_type = glpk.glp_get_col_type(self.lp, col + 1) ub = np.inf lb = -np.inf if col_type == glpk.GLP_DB: ub = glpk.glp_get_col_ub(self.lp, col + 1) lb = glpk.glp_get_col_lb(self.lp, col + 1) elif col_type == glpk.GLP_LO: lb = glpk.glp_get_col_lb(self.lp, col + 1) elif col_type == glpk.GLP_FX: lb = ub = glpk.glp_get_col_lb(self.lp, col + 1) else: assert col_type == glpk.GLP_FR, "unsupported col type in get_col_bounds()" col_bounds.append((lb, ub)) return col_bounds
def test_change_variable_bounds(self): inner_prob = self.model.problem inner_problem_bounds = [(glp_get_col_lb(inner_prob, i), glp_get_col_ub(inner_prob, i)) for i in range(1, glp_get_num_cols(inner_prob) + 1)] bounds = [(var.lb, var.ub) for var in self.model.variables.values()] self.assertEqual(bounds, inner_problem_bounds) for var in self.model.variables.values(): var.lb = random.uniform(-1000, 1000) var.ub = random.uniform(var.lb, 1000) inner_problem_bounds_new = [(glp_get_col_lb(inner_prob, i), glp_get_col_ub(inner_prob, i)) for i in range(1, glp_get_num_cols(inner_prob) + 1)] bounds_new = [(var.lb, var.ub) for var in self.model.variables.values()] self.assertNotEqual(bounds, bounds_new) self.assertNotEqual(inner_problem_bounds, inner_problem_bounds_new) self.assertEqual(bounds_new, inner_problem_bounds_new)
def test_glpk_setting_bounds(self): self.model.add(self.var) self.model.update() var = self.var model = self.model var.lb = 1 self.assertEqual(var.lb, 1) self.assertEqual(glp_get_col_lb(model.problem, var._index), 1) var.ub = 2 self.assertEqual(var.ub, 2) self.assertEqual(glp_get_col_ub(model.problem, var._index), 2)
def test_change_variable_bounds(self): inner_prob = self.model.problem inner_problem_bounds = [ (glp_get_col_lb(inner_prob, i), glp_get_col_ub(inner_prob, i)) for i in range(1, glp_get_num_cols(inner_prob) + 1) ] bounds = [(var.lb, var.ub) for var in self.model.variables.values()] self.assertEqual(bounds, inner_problem_bounds) for var in self.model.variables.values(): var.lb = random.uniform(-1000, 1000) var.ub = random.uniform(var.lb, 1000) inner_problem_bounds_new = [ (glp_get_col_lb(inner_prob, i), glp_get_col_ub(inner_prob, i)) for i in range(1, glp_get_num_cols(inner_prob) + 1) ] bounds_new = [(var.lb, var.ub) for var in self.model.variables.values()] self.assertNotEqual(bounds, bounds_new) self.assertNotEqual(inner_problem_bounds, inner_problem_bounds_new) self.assertEqual(bounds_new, inner_problem_bounds_new)
def _column_names_str(self): 'get the line in __str__ for the column names' rv = " " dbl_max = sys.float_info.max for col, name in enumerate(self.names): name = self.names[col] lb = glpk.glp_get_col_lb(self.lp, col + 1) ub = glpk.glp_get_col_ub(self.lp, col + 1) if lb != -dbl_max or ub != dbl_max: name = "*" + name name = name.rjust(6)[:6] # fix width to exactly 6 rv += name + " " rv += "\n" return rv
def _var_bounds_str(self): 'get the variable bounds string used in __str__' rv = "" dbl_max = sys.float_info.max added_label = False for index, name in enumerate(self.names): lb = glpk.glp_get_col_lb(self.lp, index + 1) ub = glpk.glp_get_col_ub(self.lp, index + 1) if not added_label and (lb != -dbl_max or ub != dbl_max): added_label = True rv += "(*) Bounded variables:" if lb != -dbl_max or ub != dbl_max: lb = "-inf" if lb == -dbl_max else lb ub = "inf" if ub == dbl_max else ub rv += f"\n{name} in [{lb}, {ub}]" return rv
def _initialize_model_from_problem(self, problem): try: self.problem = problem glp_create_index(self.problem) except TypeError: raise TypeError("Provided problem is not a valid GLPK model.") row_num = glp_get_num_rows(self.problem) col_num = glp_get_num_cols(self.problem) for i in range(1, col_num + 1): var = Variable( glp_get_col_name(self.problem, i), lb=glp_get_col_lb(self.problem, i), ub=glp_get_col_ub(self.problem, i), problem=self, type=_GLPK_VTYPE_TO_VTYPE[ glp_get_col_kind(self.problem, i)] ) # This avoids adding the variable to the glpk problem super(Model, self)._add_variables([var]) variables = self.variables for j in range(1, row_num + 1): ia = intArray(col_num + 1) da = doubleArray(col_num + 1) nnz = glp_get_mat_row(self.problem, j, ia, da) constraint_variables = [variables[ia[i] - 1] for i in range(1, nnz + 1)] # Since constraint expressions are lazily retrieved from the solver they don't have to be built here # lhs = _unevaluated_Add(*[da[i] * constraint_variables[i - 1] # for i in range(1, nnz + 1)]) lhs = 0 glpk_row_type = glp_get_row_type(self.problem, j) if glpk_row_type == GLP_FX: row_lb = glp_get_row_lb(self.problem, j) row_ub = row_lb elif glpk_row_type == GLP_LO: row_lb = glp_get_row_lb(self.problem, j) row_ub = None elif glpk_row_type == GLP_UP: row_lb = None row_ub = glp_get_row_ub(self.problem, j) elif glpk_row_type == GLP_DB: row_lb = glp_get_row_lb(self.problem, j) row_ub = glp_get_row_ub(self.problem, j) elif glpk_row_type == GLP_FR: row_lb = None row_ub = None else: raise Exception( "Currently, optlang does not support glpk row type %s" % str(glpk_row_type) ) log.exception() if isinstance(lhs, int): lhs = symbolics.Integer(lhs) elif isinstance(lhs, float): lhs = symbolics.Real(lhs) constraint_id = glp_get_row_name(self.problem, j) for variable in constraint_variables: try: self._variables_to_constraints_mapping[variable.name].add(constraint_id) except KeyError: self._variables_to_constraints_mapping[variable.name] = set([constraint_id]) super(Model, self)._add_constraints( [Constraint(lhs, lb=row_lb, ub=row_ub, name=constraint_id, problem=self, sloppy=True)], sloppy=True ) term_generator = ( (glp_get_obj_coef(self.problem, index), variables[index - 1]) for index in range(1, glp_get_num_cols(problem) + 1) ) self._objective = Objective( symbolics.add( [symbolics.mul((symbolics.Real(term[0]), term[1])) for term in term_generator if term[0] != 0.] ), problem=self, direction={GLP_MIN: 'min', GLP_MAX: 'max'}[glp_get_obj_dir(self.problem)]) glp_scale_prob(self.problem, GLP_SF_AUTO)
def __init__(self, problem=None, *args, **kwargs): super(Model, self).__init__(*args, **kwargs) self.configuration = Configuration() if problem is None: self.problem = glp_create_prob() glp_create_index(self.problem) if self.name is not None: glp_set_prob_name(self.problem, str(self.name)) else: try: self.problem = problem glp_create_index(self.problem) except TypeError: raise TypeError("Provided problem is not a valid GLPK model.") row_num = glp_get_num_rows(self.problem) col_num = glp_get_num_cols(self.problem) for i in range(1, col_num + 1): var = Variable( glp_get_col_name(self.problem, i), lb=glp_get_col_lb(self.problem, i), ub=glp_get_col_ub(self.problem, i), problem=self, type=_GLPK_VTYPE_TO_VTYPE[ glp_get_col_kind(self.problem, i)] ) # This avoids adding the variable to the glpk problem super(Model, self)._add_variables([var]) variables = self.variables for j in range(1, row_num + 1): ia = intArray(col_num + 1) da = doubleArray(col_num + 1) nnz = glp_get_mat_row(self.problem, j, ia, da) constraint_variables = [variables[ia[i] - 1] for i in range(1, nnz + 1)] # Since constraint expressions are lazily retrieved from the solver they don't have to be built here # lhs = _unevaluated_Add(*[da[i] * constraint_variables[i - 1] # for i in range(1, nnz + 1)]) lhs = 0 glpk_row_type = glp_get_row_type(self.problem, j) if glpk_row_type == GLP_FX: row_lb = glp_get_row_lb(self.problem, j) row_ub = row_lb elif glpk_row_type == GLP_LO: row_lb = glp_get_row_lb(self.problem, j) row_ub = None elif glpk_row_type == GLP_UP: row_lb = None row_ub = glp_get_row_ub(self.problem, j) elif glpk_row_type == GLP_DB: row_lb = glp_get_row_lb(self.problem, j) row_ub = glp_get_row_ub(self.problem, j) elif glpk_row_type == GLP_FR: row_lb = None row_ub = None else: raise Exception( "Currently, optlang does not support glpk row type %s" % str(glpk_row_type) ) log.exception() if isinstance(lhs, int): lhs = sympy.Integer(lhs) elif isinstance(lhs, float): lhs = sympy.RealNumber(lhs) constraint_id = glp_get_row_name(self.problem, j) for variable in constraint_variables: try: self._variables_to_constraints_mapping[variable.name].add(constraint_id) except KeyError: self._variables_to_constraints_mapping[variable.name] = set([constraint_id]) super(Model, self)._add_constraints( [Constraint(lhs, lb=row_lb, ub=row_ub, name=constraint_id, problem=self, sloppy=True)], sloppy=True ) term_generator = ( (glp_get_obj_coef(self.problem, index), variables[index - 1]) for index in range(1, glp_get_num_cols(problem) + 1) ) self._objective = Objective( _unevaluated_Add( *[_unevaluated_Mul(sympy.RealNumber(term[0]), term[1]) for term in term_generator if term[0] != 0.]), problem=self, direction={GLP_MIN: 'min', GLP_MAX: 'max'}[glp_get_obj_dir(self.problem)]) glp_scale_prob(self.problem, GLP_SF_AUTO)