def makeLogicalConstraintsOnDisjuncts_NonlinearConvex(): # same game as the previous model, but include some nonlinear # constraints. This is to test gdpopt because it needs to handle the logical # things even when they are on the same Disjunct as a nonlinear thing m = ConcreteModel() m.s = RangeSet(4) m.ds = RangeSet(2) m.d = Disjunct(m.s) m.djn = Disjunction(m.ds) m.djn[1] = [m.d[1], m.d[2]] m.djn[2] = [m.d[3], m.d[4]] m.x = Var(bounds=(-5, 10)) m.y = Var(bounds=(-5, 10)) m.Y = BooleanVar([1, 2]) m.d[1].c = Constraint(expr=m.x**2 + m.y**2 <= 2) m.d[1].logical = LogicalConstraint(expr=~m.Y[1]) m.d[2].c1 = Constraint(expr=m.x >= -3) m.d[2].c2 = Constraint(expr=m.x**2 <= 16) m.d[2].logical = LogicalConstraint(expr=m.Y[1].land(m.Y[2])) m.d[3].c = Constraint(expr=m.x >= 4) m.d[4].logical = LogicalConstraint(expr=exactly(1, m.Y[1])) m.d[4].logical2 = LogicalConstraint(expr=~m.Y[2]) m.d[4].c = Constraint(expr=m.x == 3) m.o = Objective(expr=m.x) return m
def _generate_model(self): self.model = None self.model = ConcreteModel() model = self.model model._name = self.description n = 7 m = 7 model.N = RangeSet(1, n) model.M = RangeSet(1, m) model.c = Param(model.N, rule=c_rule) model.b = Param(model.M, rule=b_rule) model.A = Param(model.M, model.N, rule=A_rule) model.x = Var(model.N, within=NonNegativeReals) model.y = Var(model.M, within=NonNegativeReals) model.cost = Objective(expr=sum_product(model.c, model.x)) model.primalcon = Constraint(model.M, rule=primalcon_rule) #model.dual = Suffix(direction=Suffix.IMPORT) #model.rc = Suffix(direction=Suffix.IMPORT) model.slack = Suffix(direction=Suffix.IMPORT) model.urc = Suffix(direction=Suffix.IMPORT) model.lrc = Suffix(direction=Suffix.IMPORT)
def makeLogicalConstraintsOnDisjuncts(): m = ConcreteModel() m.s = RangeSet(4) m.ds = RangeSet(2) m.d = Disjunct(m.s) m.djn = Disjunction(m.ds) m.djn[1] = [m.d[1], m.d[2]] m.djn[2] = [m.d[3], m.d[4]] m.x = Var(bounds=(-2, 10)) m.Y = BooleanVar([1, 2]) m.d[1].c = Constraint(expr=m.x >= 2) m.d[1].logical = LogicalConstraint(expr=~m.Y[1]) m.d[2].c = Constraint(expr=m.x >= 3) m.d[3].c = Constraint(expr=m.x >= 8) m.d[4].logical = LogicalConstraint(expr=m.Y[1].equivalent_to(m.Y[2])) m.d[4].c = Constraint(expr=m.x == 2.5) m.o = Objective(expr=m.x) # Add the logical proposition m.p = LogicalConstraint( expr=m.d[1].indicator_var.implies(m.d[4].indicator_var)) # Use the logical stuff to make choosing d1 and d4 infeasible: m.bwahaha = LogicalConstraint(expr=m.Y[1].xor(m.Y[2])) return m
def makeBooleanVarsOnDisjuncts(): # same as linear model above, but declare the BooleanVar on one of the # Disjuncts, just to make sure we make references and stuff correctly. m = ConcreteModel() m.s = RangeSet(4) m.ds = RangeSet(2) m.d = Disjunct(m.s) m.djn = Disjunction(m.ds) m.djn[1] = [m.d[1], m.d[2]] m.djn[2] = [m.d[3], m.d[4]] m.x = Var(bounds=(-2, 10)) m.d[1].Y = BooleanVar([1, 2]) m.d[1].c = Constraint(expr=m.x >= 2) m.d[1].logical = LogicalConstraint(expr=~m.d[1].Y[1]) m.d[2].c = Constraint(expr=m.x >= 3) m.d[3].c = Constraint(expr=m.x >= 8) m.d[4].logical = LogicalConstraint( expr=m.d[1].Y[1].equivalent_to(m.d[1].Y[2])) m.d[4].c = Constraint(expr=m.x == 2.5) m.o = Objective(expr=m.x) # Add the logical proposition m.p = LogicalConstraint( expr=m.d[1].indicator_var.implies(m.d[4].indicator_var)) # Use the logical stuff to make choosing d1 and d4 infeasible: m.bwahaha = LogicalConstraint(expr=m.d[1].Y[1].xor(m.d[1].Y[2])) return m
def createParam(self): self.TRF.ind_lx = RangeSet(0, self.lx - 1) self.TRF.ind_ly = RangeSet(0, self.ly - 1) self.TRF.ind_lz = RangeSet(0, self.lz - 1) self.TRF.px0 = Param(self.TRF.ind_lx, mutable=True, default=0) self.TRF.py0 = Param(self.TRF.ind_ly, mutable=True, default=0) self.TRF.pz0 = Param(self.TRF.ind_lz, mutable=True, default=0) self.TRF.ppenaltyComp = Param(mutable=True, default=0)
def createParam(self): self.TRF.ind_lx=RangeSet(0,self.lx-1) self.TRF.ind_ly=RangeSet(0,self.ly-1) self.TRF.ind_lz=RangeSet(0,self.lz-1) self.TRF.px0 = Param(self.TRF.ind_lx,mutable=True,default=0) self.TRF.py0 = Param(self.TRF.ind_ly,mutable=True,default=0) self.TRF.pz0 = Param(self.TRF.ind_lz,mutable=True,default=0) self.TRF.plrom = Param(self.TRF.ind_ly,range(self.lx+1),mutable=True,default=0) self.TRF.pqrom = Param(self.TRF.ind_ly,range(int((self.lx*self.lx+self.lx*3)/2. + 1)),mutable=True,default=0) self.TRF.ppenaltyComp = Param(mutable=True,default=0)
def create_model(df_data, timesteps): m = ConcreteModel() # I defined "t" and "T" from 1 to 30 # L = 3, Cdo & Cup = 10, also from paper # n and R = 1, no idea about the real values of these parameters. # All variables and letters are the same with the ones in paper. m.tm = RangeSet(1, timesteps + 1, 1) # TimePeriod (Hours) m.Tm = RangeSet(1, timesteps + 1, 1) # TimePeriod (Hours)(in paper tt) m.L = 5 # Delay Time (Hours) m.n = 1 # Zerrahn Parameter eta (---) m.R = 1 # Zerrahn Parameter Recovery (Hours) #m.Cdo = 40 # Zerrahn Parameter DSM Capacity down (MWh) -> Demand-shift up #m.Cup = 40 # Zerrahn Parameter DSM Capacity up(MWh) -> Demand-shift down m.DSMdo = Var( m.tm, m.Tm, initialize=0, within=NonNegativeReals) # Zerrahn Variable load shift down (MWh) m.DSMup = Var( m.tm, initialize=0, within=NonNegativeReals) # Zerrahn Variable load shift up(MWh) #################### For OBJECTIVE factor_demand = 1 temp = df_data.demand_el[:timesteps + 1] * factor_demand m.Demand = temp.tolist() # Demand from input_data m.Cdo = (df_data.Cap_do).tolist() m.Cup = (df_data.Cap_up).tolist() m.C = [0, 10, 20, 40] # Cost constant of all Power Generators, P1, P2, P3, ... m.Cap = [1, 100, 100, 70] # Capacity of all Generators Wind/PV, P1, P2, P3, ... m.Wind = (df_data.wind * m.Cap[0]).round().tolist() m.PV = (df_data.pv * m.Cap[0]).round().tolist() m.P1 = Var(m.tm, initialize=0, within=NonNegativeReals) # Power Generator 1 (cheap) m.P2 = Var(m.tm, initialize=0, within=NonNegativeReals) # Power Generator 2 (expensive) return m
def test_gdp_tree_indexed_disjunction(self): # This is to check that indexed components never actually appear as # nodes in the tree. We should only have DisjunctionDatas and # DisjunctDatas. m = ConcreteModel() m.I = RangeSet(1, 4) m.x = Var(m.I, bounds=(-2, 6)) self.add_indexed_disjunction(m, m) targets = (m.indexed, ) knownBlocks = {} tree = get_gdp_tree(targets, m, knownBlocks) vertices = tree.vertices self.assertEqual(len(vertices), 6) in_degrees = { m.indexed[0]: 0, m.indexed[1]: 0, m.indexed[0].disjuncts[0]: 1, m.indexed[0].disjuncts[1]: 1, m.indexed[1].disjuncts[0]: 1, m.indexed[1].disjuncts[1]: 1 } for key, val in in_degrees.items(): self.assertEqual(tree.in_degree(key), val) topo_sort = [ m.indexed[0], m.indexed[0].disjuncts[1], m.indexed[0].disjuncts[0], m.indexed[1], m.indexed[1].disjuncts[1], m.indexed[1].disjuncts[0] ] sort = tree.topological_sort() for i, node in enumerate(sort): self.assertIs(node, topo_sort[i])
def _generate_model(self): self.model = None self.model = ConcreteModel() model = self.model model._name = self.description model.s = RangeSet(1, 12) model.x = Var(model.s) model.x[1].setlb(-1) model.x[1].setub(1) model.x[2].setlb(-1) model.x[2].setub(1) model.obj = Objective(expr=sum(model.x[i] * ((-1)**(i + 1)) for i in model.x.index_set())) model.c = ConstraintList() # to make the variable used in the constraint match the name model.c.add(Constraint.Skip) model.c.add(Constraint.Skip) model.c.add(model.x[3] >= -1.) model.c.add(model.x[4] <= 1.) model.c.add(model.x[5] == -1.) model.c.add(model.x[6] == -1.) model.c.add(model.x[7] == 1.) model.c.add(model.x[8] == 1.) model.c.add((-1., model.x[9], -1.)) model.c.add((-1., model.x[10], -1.)) model.c.add((1., model.x[11], 1.)) model.c.add((1., model.x[12], 1.)) model.c_inactive = ConstraintList() # to make the variable used in the constraint match the name model.c_inactive.add(Constraint.Skip) model.c_inactive.add(Constraint.Skip) model.c_inactive.add(model.x[3] >= -2.) model.c_inactive.add(model.x[4] <= 2.)
def makeDisjunctWithRangeSet(): m = ConcreteModel() m.x = Var(bounds=(0, 1)) m.d1 = Disjunct() m.d1.s = RangeSet(1) m.d1.c = Constraint(rule=lambda _: m.x == 1) m.d2 = Disjunct() m.disj = Disjunction(expr=[m.d1, m.d2]) return m
def makeNonQuadraticNonlinearGDP(): """We use this in testing between steps--Needed non-quadratic and not additively separable constraint expressions on a Disjunct.""" m = ConcreteModel() m.I = RangeSet(1, 4) m.I1 = RangeSet(1, 2) m.I2 = RangeSet(3, 4) m.x = Var(m.I, bounds=(-2, 6)) # sum of 4-norms... m.disjunction = Disjunction( expr=[[sum(m.x[i]**4 for i in m.I1)**(1/4) + \ sum(m.x[i]**4 for i in m.I2)**(1/4) <= 1], [sum((3 - m.x[i])**4 for i in m.I1)**(1/4) + sum((3 - m.x[i])**4 for i in m.I2)**(1/4) <= 1]]) m.obj = Objective(expr=m.x[2] - m.x[1], sense=maximize) return m
def solve_sudoku(board): model = ConcreteModel() model.X = RangeSet(9) model.Y = RangeSet(9) model.DIGIT = RangeSet(9) model.value = Var(model.X, model.Y, model.DIGIT, within=Binary) for (x, y, v) in board: model.value[x, y, v].fix(1) model.obj = Objective(expr=1) model.digit_constraint = Constraint( model.X, model.Y, rule=lambda m, x, y: sum(m.value[x, y, d] for d in model.DIGIT) == 1) model.row_level_constraint = Constraint( model.X, model.DIGIT, rule=lambda m, x, d: sum(m.value[x, y, d] for y in model.Y) == 1) model.column_level_constraint = Constraint( model.Y, model.DIGIT, rule=lambda m, y, d: sum(m.value[x, y, d] for x in model.X) == 1) model.subsquare_level_constraint = Constraint( range(1, 9, 3), range(1, 9, 3), model.DIGIT, rule=lambda m, i, j, d: sum(m.value[x, y, d] for x in range(i, i + 3) for y in range(j, j + 3)) == 1) solver = solver_factory.get_solver(Solver.BONMIN) solver.solve(model) for v in model.component_data_objects(Var): print(str(v), v.value) for i in model.X: row = '' for j in model.Y: row += '{} '.format(get_value(model, i, j)) print(row)
def makeDisjunctWithRangeSet(): """Two-term SimpleDisjunction where one of the disjuncts contains a RangeSet""" m = ConcreteModel() m.x = Var(bounds=(0, 1)) m.d1 = Disjunct() m.d1.s = RangeSet(1) m.d1.c = Constraint(rule=lambda _: m.x == 1) m.d2 = Disjunct() m.disj = Disjunction(expr=[m.d1, m.d2]) return m
def test_do_not_reactivate_disjuncts_with_abandon(self): m = ConcreteModel() m.x = Var() m.s = RangeSet(4) m.d = Disjunct(m.s) m.d[2].bad_constraint_should_not_be_active = Constraint(expr=m.x >= 1) m.disj1 = Disjunction(expr=[m.d[1], m.d[2]]) m.disj2 = Disjunction(expr=[m.d[3], m.d[4]]) m.d[1].indicator_var.fix(1) m.d[2].deactivate() TransformationFactory('gdp.bigm').apply_to(m) self.assertFalse(m.d[2].active)
def makeHierarchicalNested_DeclOrderMatchesInstantationOrder(): """Here, we put the disjunctive components on Blocks, but we do it in the same order that we declared the blocks, that is, on each block, decl order matches instantiation order.""" m = ConcreteModel() m.I = RangeSet(1, 4) m.x = Var(m.I, bounds=(-2, 6)) m.disjunct_block = Block() m.disjunction_block = Block() instantiate_hierarchical_nested_model(m) return m
def n_queens(board_size=4): model = ConcreteModel() model.ROWS = RangeSet(board_size) model.COLS = RangeSet(board_size) model.x = Var(model.ROWS, model.COLS, within=Binary) model.obj = Objective(expr=sum(model.x[i, j] for i in model.ROWS for j in model.COLS), sense=maximize) model.constraint_row_level = Constraint( model.ROWS, rule=lambda m, i: sum(m.x[i, j] for j in m.COLS) <= 1) model.constraint_column_level = Constraint( model.COLS, rule=lambda m, j: sum(m.x[i, j] for i in m.ROWS) <= 1) # remove cases like (4,4) model.constraint_diagonal_first_column = Constraint( model.ROWS, rule=lambda m, i: sum(m.x[i + j, 1 + j] for j in range(board_size - i + 1)) <= 1) model.constraint_diagonal_first_row = Constraint( model.COLS, rule=lambda m, j: sum(m.x[i + 1, j + i] for i in range(board_size - j + 1)) <= 1) model.constraint_back_diagonal = Constraint( model.COLS, rule=lambda m, j: sum(m.x[1 + i, j - i] for i in range(j)) <= 1) model.constraint_back_diagonal_last_row = Constraint( model.ROWS, rule=lambda m, i: sum(m.x[i + j, board_size - j] for j in range(board_size - i + 1)) <= 1) solver = solver_factory.get_solver(Solver.BONMIN) solver.solve(model) return [(i, j) for i in range(1, board_size + 1) for j in range(1, board_size + 1) if model.x[i, j] == 1]
def makeHierarchicalNested_DeclOrderOppositeInstantationOrder(): """Here, we declare the Blocks in the opposite order. This means that decl order will be *opposite* instantiation order, which means that we can break our targets preprocessing without even using targets if we are not correctly identifying what is nested in what!""" m = ConcreteModel() m.I = RangeSet(1, 4) m.x = Var(m.I, bounds=(-2, 6)) m.disjunction_block = Block() m.disjunct_block = Block() instantiate_hierarchical_nested_model(m) return m
def makeBetweenStepsPaperExample(): """Original example model, implicit disjunction""" m = ConcreteModel() m.I = RangeSet(1, 4) m.x = Var(m.I, bounds=(-2, 6)) m.disjunction = Disjunction(expr=[[sum( m.x[i]**2 for i in m.I) <= 1], [sum((3 - m.x[i])**2 for i in m.I) <= 1]]) m.obj = Objective(expr=m.x[2] - m.x[1], sense=maximize) return m
def _create_model(self): model = ConcreteModel() model.dual = Suffix(direction=Suffix.IMPORT,default=0.0) for stage in self._ph._scenario_tree._stages[:-1]: # all blended stages for tree_node in stage._tree_nodes: setattr(model,tree_node._name,Block()) block = getattr(model,tree_node._name) block.var_to_id = {} block.id_to_var = [] for cntr, (var,index) in enumerate((name,idx) for name, indices in iteritems(tree_node._variable_indices) for idx in indices): block.var_to_id[var,index] = cntr block.id_to_var.append((var,index)) block.var_index = RangeSet(0,len(block.id_to_var)-1) self._model = model
def generate_norm1_norm_constraint(model, setpoint_model, config, discrete_only=True): r"""This function generates constraint (PF-OA main problem) for minimum Norm1 distance to setpoint_model. Norm constraint is used to guarantees the monotonicity of the norm objective value sequence of all iterations Norm1 distance of (x,y) = \sum_i |x_i - y_i|. Ref: Paper 'A storm of feasibility pumps for nonconvex MINLP' Eq. (16). Parameters ---------- model : Pyomo model The model that needs the norm constraint. setpoint_model : Pyomo model The model that provides the base point for us to calculate the distance. config : ConfigBlock The specific configurations for MindtPy. discrete_only : bool, optional Whether to only optimize on distance between the discrete variables, by default True. """ var_filter = (lambda v: v.is_integer()) if discrete_only \ else (lambda v: True) model_vars = list(filter(var_filter, model.MindtPy_utils.variable_list)) setpoint_vars = list( filter(var_filter, setpoint_model.MindtPy_utils.variable_list)) assert len(model_vars) == len( setpoint_vars ), 'Trying to generate Norm1 norm constraint for models with different number of variables' norm_constraint_blk = model.MindtPy_utils.L1_norm_constraint = Block() norm_constraint_blk.L1_slack_idx = RangeSet(len(model_vars)) norm_constraint_blk.L1_slack_var = Var(norm_constraint_blk.L1_slack_idx, domain=Reals, bounds=(0, None)) norm_constraint_blk.abs_reform = ConstraintList() for idx, v_model, v_setpoint in zip(norm_constraint_blk.L1_slack_idx, model_vars, setpoint_vars): norm_constraint_blk.abs_reform.add( expr=v_model - v_setpoint.value >= -norm_constraint_blk.L1_slack_var[idx]) norm_constraint_blk.abs_reform.add( expr=v_model - v_setpoint.value <= norm_constraint_blk.L1_slack_var[idx]) rhs = config.fp_norm_constraint_coef * \ sum(abs(v_model.value-v_setpoint.value) for v_model, v_setpoint in zip(model_vars, setpoint_vars)) norm_constraint_blk.sum_slack = Constraint( expr=sum(norm_constraint_blk.L1_slack_var[idx] for idx in norm_constraint_blk.L1_slack_idx) <= rhs)
def makeBetweenStepsPaperExample_DeclareVarOnDisjunct(): """Exactly the same model as above, but declaring the Disjuncts explicitly and declaring the variables on one of them. """ m = ConcreteModel() m.I = RangeSet(1, 4) m.disj1 = Disjunct() m.disj1.x = Var(m.I, bounds=(-2, 6)) m.disj1.c = Constraint(expr=sum(m.disj1.x[i]**2 for i in m.I) <= 1) m.disj2 = Disjunct() m.disj2.c = Constraint(expr=sum((3 - m.disj1.x[i])**2 for i in m.I) <= 1) m.disjunction = Disjunction(expr=[m.disj1, m.disj2]) m.obj = Objective(expr=m.disj1.x[2] - m.disj1.x[1], sense=maximize) return m
def generate_norm1_objective_function(model, setpoint_model, discrete_only=False): r"""This function generates objective (PF-OA main problem) for minimum Norm1 distance to setpoint_model. Norm1 distance of (x,y) = \sum_i |x_i - y_i|. Parameters ---------- model : Pyomo model The model that needs new objective function. setpoint_model : Pyomo model The model that provides the base point for us to calculate the distance. discrete_only : bool, optional Whether to only optimize on distance between the discrete variables, by default False. Returns ------- Objective The norm1 objective function. """ # skip objective_value variable and slack_var variables var_filter = (lambda v: v.is_integer()) if discrete_only \ else (lambda v: 'MindtPy_utils.objective_value' not in v.name and 'MindtPy_utils.feas_opt.slack_var' not in v.name) model_vars = list(filter(var_filter, model.MindtPy_utils.variable_list)) setpoint_vars = list( filter(var_filter, setpoint_model.MindtPy_utils.variable_list)) assert len(model_vars) == len( setpoint_vars ), 'Trying to generate Norm1 objective function for models with different number of variables' model.MindtPy_utils.del_component('L1_obj') obj_blk = model.MindtPy_utils.L1_obj = Block() obj_blk.L1_obj_idx = RangeSet(len(model_vars)) obj_blk.L1_obj_var = Var(obj_blk.L1_obj_idx, domain=Reals, bounds=(0, None)) obj_blk.abs_reform = ConstraintList() for idx, v_model, v_setpoint in zip(obj_blk.L1_obj_idx, model_vars, setpoint_vars): obj_blk.abs_reform.add( expr=v_model - v_setpoint.value >= -obj_blk.L1_obj_var[idx]) obj_blk.abs_reform.add( expr=v_model - v_setpoint.value <= obj_blk.L1_obj_var[idx]) return Objective(expr=sum(obj_blk.L1_obj_var[idx] for idx in obj_blk.L1_obj_idx))
def do_setup(self): global tmpdir tmpdir = os.getcwd() os.chdir(currdir) TempfileManager.sequential_files(0) self.asl = pyomo.opt.SolverFactory('asl:ipopt', keepfiles=True) self.ipopt = pyomo.opt.SolverFactory('ipopt', keepfiles=True) # The sisser CUTEr instance # Formulated in Pyomo by Carl D. Laird, Daniel P. Word, Brandon C. Barrera and Saumyajyoti Chaudhuri # Taken from: # Source: # F.S. Sisser, # "Elimination of bounds in optimization problems by transforming # variables", # Mathematical Programming 20:110-121, 1981. # See also Buckley#216 (p. 91) # SIF input: Ph. Toint, Dec 1989. # classification OUR2-AN-2-0 sisser_instance = ConcreteModel() sisser_instance.N = RangeSet(1, 2) sisser_instance.xinit = Param(sisser_instance.N, initialize={ 1: 1.0, 2: 0.1 }) def fa(model, i): return value(model.xinit[i]) sisser_instance.x = Var(sisser_instance.N, initialize=fa) def f(model): return 3 * model.x[1]**4 - 2 * (model.x[1] * model.x[2])**2 + 3 * model.x[2]**4 sisser_instance.f = Objective(rule=f, sense=minimize) self.sisser_instance = sisser_instance
def get_mock_model_with_priorities(self): m = ConcreteModel() m.x = Var(domain=Integers) m.s = RangeSet(10) m.y = Var(m.s, domain=Integers) m.o = Objective(expr=m.x + sum(m.y), sense=minimize) m.c = Constraint(expr=m.x >= 1) m.c2 = Constraint(expr=quicksum(m.y[i] for i in m.s) >= 10) m.priority = Suffix(direction=Suffix.EXPORT, datatype=Suffix.INT) m.direction = Suffix(direction=Suffix.EXPORT, datatype=Suffix.INT) m.priority.set_value(m.x, 1) # Ensure tests work for both options of `expand` m.priority.set_value(m.y, 2, expand=False) m.direction.set_value(m.y, BranchDirection.down, expand=True) m.direction.set_value(m.y[10], BranchDirection.up) return m
def _generate_model(self): self.model = None self.model = ConcreteModel() model = self.model model._name = self.description model.x = Var(domain=RangeSet(float('-inf'), None, 0)) model.y = Var(bounds=(None, float('inf'))) model.obj = Objective(expr=model.x - model.y) model.c = ConstraintList() model.c.add(model.x >= -2) model.c.add(model.y <= 3) cdata = model.c.add((0, 1, 3)) assert cdata.lower == 0 assert cdata.upper == 3 assert cdata.body() == 1 assert not cdata.equality cdata = model.c.add((0, 2, 3)) assert cdata.lower == 0 assert cdata.upper == 3 assert cdata.body() == 2 assert not cdata.equality cdata = model.c.add((0, 1, None)) assert cdata.lower is None assert cdata.upper == 1 assert cdata.body() == 0 assert not cdata.equality cdata = model.c.add((None, 0, 1)) assert cdata.lower is None assert cdata.upper == 1 assert cdata.body() == 0 assert not cdata.equality cdata = model.c.add((1, 1)) assert cdata.lower == 1 assert cdata.upper == 1 assert cdata.body() == 1 assert cdata.equality model.d = Constraint(rule=lambda m: (float('-inf'), m.x, float('inf'))) assert not model.d.equality
def _generate_model(self): self.model = ConcreteModel() model = self.model model._name = self.description model.neg1 = Param(initialize=-1.0, mutable=True) model.pos1 = Param(initialize=1.0, mutable=True) model.s = RangeSet(1, 12) model.x = Var(model.s) model.x[1].setlb(model.neg1) model.x[1].setub(model.pos1) model.x[2].setlb(model.neg1) model.x[2].setub(model.pos1) model.obj = Objective(expr=sum(model.x[i] * ((-1)**(i)) for i in model.x.index_set()), sense=maximize) model.c = ConstraintList() # to make the variable used in the constraint match the name model.c.add(Constraint.Skip) model.c.add(Constraint.Skip) model.c.add(model.x[3] >= -1.) model.c.add(model.x[4] <= 1.) model.c.add(model.x[5] == -1.) model.c.add(model.x[6] == -1.) model.c.add(model.x[7] == 1.) model.c.add(model.x[8] == 1.) model.c.add((model.neg1, model.x[9], model.neg1)) model.c.add((-1., model.x[10], -1.)) model.c.add((1., model.x[11], 1.)) model.c.add((1., model.x[12], 1.)) model.c_inactive = ConstraintList() # to make the variable used in the constraint match the name model.c_inactive.add(Constraint.Skip) model.c_inactive.add(Constraint.Skip) model.c_inactive.add(model.x[3] >= -2.) model.c_inactive.add(model.x[4] <= 2.)
def _generate_model(self): self.model = None self.model = pmo.block() model = self.model model._name = self.description model.x = pmo.variable(domain=RangeSet(float('-inf'), None, 0)) model.y = pmo.variable(ub=float('inf')) model.obj = pmo.objective(model.x - model.y) model.c = pmo.constraint_dict() model.c[1] = pmo.constraint(model.x >= -2) model.c[2] = pmo.constraint(model.y <= 3) cdata = model.c[3] = pmo.constraint((0, 1, 3)) assert cdata.lb == 0 assert cdata.ub == 3 assert cdata.body() == 1 assert not cdata.equality cdata = model.c[4] = pmo.constraint((0, 2, 3)) assert cdata.lb == 0 assert cdata.ub == 3 assert cdata.body() == 2 assert not cdata.equality cdata = model.c[5] = pmo.constraint((0, 1, None)) assert cdata.lb is None assert cdata.ub == 1 assert cdata.body() == 0 assert not cdata.equality cdata = model.c[6] = pmo.constraint((None, 0, 1)) assert cdata.lb is None assert cdata.ub == 1 assert cdata.body() == 0 assert not cdata.equality cdata = model.c[7] = pmo.constraint((1, 1)) assert cdata.lb == 1 assert cdata.ub == 1 assert cdata.body() == 1 assert cdata.equality
def _apply_to(self, model, **kwds): """Apply the transformation to the given model.""" config = self.CONFIG(kwds.pop('options', {})) config.set_value(kwds) integer_vars = list(v for v in model.component_data_objects( ctype=Var, descend_into=(Block, Disjunct)) if v.is_integer() and not v.fixed) if len(integer_vars) == 0: logger.info( "Model has no free integer variables. No reformulation needed." ) return vars_on_constr = ComponentSet() for c in model.component_data_objects(ctype=Constraint, descend_into=(Block, Disjunct), active=True): vars_on_constr.update( v for v in identify_variables(c.body, include_fixed=False) if v.is_integer()) if config.ignore_unused: num_vars_not_on_constr = len(integer_vars) - len(vars_on_constr) if num_vars_not_on_constr > 0: logger.info( "%s integer variables on the model are not attached to any constraints. " "Ignoring unused variables.") integer_vars = list(vars_on_constr) logger.info("Reformulating integer variables using the %s strategy." % config.strategy) # Set up reformulation block blk_name = unique_component_name(model, "_int_to_binary_reform") reform_block = Block( doc="Holds variables and constraints for reformulating " "integer variables to binary variables.") setattr(model, blk_name, reform_block) reform_block.int_var_set = RangeSet(0, len(integer_vars) - 1) reform_block.new_binary_var = Var( Any, domain=Binary, dense=False, initialize=0, doc="Binary variable with index (int_var_idx, idx)") reform_block.integer_to_binary_constraint = Constraint( reform_block.int_var_set, doc="Equality constraints mapping the binary variable values " "to the integer variable value.") # check that variables are bounded for idx, int_var in enumerate(integer_vars): if not (int_var.has_lb() and int_var.has_ub()): raise ValueError( "Integer variable %s is missing an " "upper or lower bound. LB: %s; UB: %s. " "Integer to binary reformulation does not support unbounded integer variables." % (int_var.name, int_var.lb, int_var.ub)) # do the reformulation highest_power = int(floor(log(value(int_var.ub - int_var.lb), 2))) # TODO potentially fragile due to floating point reform_block.integer_to_binary_constraint.add( idx, expr=int_var == sum(reform_block.new_binary_var[idx, pwr] * (2**pwr) for pwr in range(0, highest_power + 1)) + int_var.lb) # Relax the original integer variable if config.relax_integrality: int_var.domain = Reals logger.info("Reformulated %s integer variables using " "%s binary variables and %s constraints." % (len(integer_vars), len(reform_block.new_binary_var), len(reform_block.integer_to_binary_constraint)))
def test_handle_termination_condition(self): """Test the outer approximation decomposition algorithm.""" model = SimpleMINLP() config = _get_MindtPy_config() solve_data = set_up_solve_data(model, config) with time_code(solve_data.timing, 'total', is_main_timer=True), \ create_utility_block(solve_data.working_model, 'MindtPy_utils', solve_data): MindtPy = solve_data.working_model.MindtPy_utils MindtPy = solve_data.working_model.MindtPy_utils setup_results_object(solve_data, config) process_objective( solve_data, config, move_linear_objective=(config.init_strategy == 'FP' or config.add_regularization is not None), use_mcpp=config.use_mcpp, update_var_con_list=config.add_regularization is None) feas = MindtPy.feas_opt = Block() feas.deactivate() feas.feas_constraints = ConstraintList( doc='Feasibility Problem Constraints') lin = MindtPy.cuts = Block() lin.deactivate() if config.feasibility_norm == 'L1' or config.feasibility_norm == 'L2': feas.nl_constraint_set = RangeSet( len(MindtPy.nonlinear_constraint_list), doc='Integer index set over the nonlinear constraints.') # Create slack variables for feasibility problem feas.slack_var = Var(feas.nl_constraint_set, domain=NonNegativeReals, initialize=1) else: feas.slack_var = Var(domain=NonNegativeReals, initialize=1) # no-good cuts exclude particular discrete decisions lin.no_good_cuts = ConstraintList(doc='no-good cuts') fixed_nlp = solve_data.working_model.clone() TransformationFactory('core.fix_integer_vars').apply_to(fixed_nlp) MindtPy_initialize_main(solve_data, config) # test handle_subproblem_other_termination termination_condition = tc.maxIterations config.add_no_good_cuts = True handle_subproblem_other_termination(fixed_nlp, termination_condition, solve_data, config) self.assertEqual( len(solve_data.mip.MindtPy_utils.cuts.no_good_cuts), 1) # test handle_main_other_conditions main_mip, main_mip_results = solve_main(solve_data, config) main_mip_results.solver.termination_condition = tc.infeasible handle_main_other_conditions(solve_data.mip, main_mip_results, solve_data, config) self.assertIs(solve_data.results.solver.termination_condition, tc.feasible) main_mip_results.solver.termination_condition = tc.unbounded handle_main_other_conditions(solve_data.mip, main_mip_results, solve_data, config) self.assertIn(main_mip.MindtPy_utils.objective_bound, main_mip.component_data_objects(ctype=Constraint)) main_mip.MindtPy_utils.del_component('objective_bound') main_mip_results.solver.termination_condition = tc.infeasibleOrUnbounded handle_main_other_conditions(solve_data.mip, main_mip_results, solve_data, config) self.assertIn(main_mip.MindtPy_utils.objective_bound, main_mip.component_data_objects(ctype=Constraint)) main_mip_results.solver.termination_condition = tc.maxTimeLimit handle_main_other_conditions(solve_data.mip, main_mip_results, solve_data, config) self.assertIs(solve_data.results.solver.termination_condition, tc.maxTimeLimit) main_mip_results.solver.termination_condition = tc.other main_mip_results.solution.status = SolutionStatus.feasible handle_main_other_conditions(solve_data.mip, main_mip_results, solve_data, config) for v1, v2 in zip( main_mip.MindtPy_utils.variable_list, solve_data.working_model.MindtPy_utils.variable_list): self.assertEqual(v1.value, v2.value) # test handle_feasibility_subproblem_tc feas_subproblem = solve_data.working_model.clone() add_feas_slacks(feas_subproblem, config) MindtPy = feas_subproblem.MindtPy_utils MindtPy.feas_opt.activate() if config.feasibility_norm == 'L1': MindtPy.feas_obj = Objective(expr=sum( s for s in MindtPy.feas_opt.slack_var[...]), sense=minimize) elif config.feasibility_norm == 'L2': MindtPy.feas_obj = Objective(expr=sum( s * s for s in MindtPy.feas_opt.slack_var[...]), sense=minimize) else: MindtPy.feas_obj = Objective(expr=MindtPy.feas_opt.slack_var, sense=minimize) handle_feasibility_subproblem_tc(tc.optimal, MindtPy, solve_data, config) handle_feasibility_subproblem_tc(tc.infeasible, MindtPy, solve_data, config) self.assertIs(solve_data.should_terminate, True) self.assertIs(solve_data.results.solver.status, SolverStatus.error) solve_data.should_terminate = False solve_data.results.solver.status = None handle_feasibility_subproblem_tc(tc.maxIterations, MindtPy, solve_data, config) self.assertIs(solve_data.should_terminate, True) self.assertIs(solve_data.results.solver.status, SolverStatus.error) solve_data.should_terminate = False solve_data.results.solver.status = None handle_feasibility_subproblem_tc(tc.solverFailure, MindtPy, solve_data, config) self.assertIs(solve_data.should_terminate, True) self.assertIs(solve_data.results.solver.status, SolverStatus.error) # test NLP subproblem infeasible solve_data.working_model.Y[1].value = 0 solve_data.working_model.Y[2].value = 0 solve_data.working_model.Y[3].value = 0 fixed_nlp, fixed_nlp_results = solve_subproblem(solve_data, config) solve_data.working_model.Y[1].value = None solve_data.working_model.Y[2].value = None solve_data.working_model.Y[3].value = None # test handle_nlp_subproblem_tc fixed_nlp_results.solver.termination_condition = tc.maxTimeLimit handle_nlp_subproblem_tc(fixed_nlp, fixed_nlp_results, solve_data, config) self.assertIs(solve_data.should_terminate, True) self.assertIs(solve_data.results.solver.termination_condition, tc.maxTimeLimit) fixed_nlp_results.solver.termination_condition = tc.maxEvaluations handle_nlp_subproblem_tc(fixed_nlp, fixed_nlp_results, solve_data, config) self.assertIs(solve_data.should_terminate, True) self.assertIs(solve_data.results.solver.termination_condition, tc.maxEvaluations) fixed_nlp_results.solver.termination_condition = tc.maxIterations handle_nlp_subproblem_tc(fixed_nlp, fixed_nlp_results, solve_data, config) self.assertIs(solve_data.should_terminate, True) self.assertIs(solve_data.results.solver.termination_condition, tc.maxEvaluations) # test handle_fp_main_tc config.init_strategy = 'FP' solve_data.fp_iter = 1 init_rNLP(solve_data, config) feas_main, feas_main_results = solve_main(solve_data, config, fp=True) feas_main_results.solver.termination_condition = tc.optimal fp_should_terminate = handle_fp_main_tc(feas_main_results, solve_data, config) self.assertIs(fp_should_terminate, False) feas_main_results.solver.termination_condition = tc.maxTimeLimit fp_should_terminate = handle_fp_main_tc(feas_main_results, solve_data, config) self.assertIs(fp_should_terminate, True) self.assertIs(solve_data.results.solver.termination_condition, tc.maxTimeLimit) feas_main_results.solver.termination_condition = tc.infeasible fp_should_terminate = handle_fp_main_tc(feas_main_results, solve_data, config) self.assertIs(fp_should_terminate, True) feas_main_results.solver.termination_condition = tc.unbounded fp_should_terminate = handle_fp_main_tc(feas_main_results, solve_data, config) self.assertIs(fp_should_terminate, True) feas_main_results.solver.termination_condition = tc.other feas_main_results.solution.status = SolutionStatus.feasible fp_should_terminate = handle_fp_main_tc(feas_main_results, solve_data, config) self.assertIs(fp_should_terminate, False) feas_main_results.solver.termination_condition = tc.solverFailure fp_should_terminate = handle_fp_main_tc(feas_main_results, solve_data, config) self.assertIs(fp_should_terminate, True) # test generate_norm_constraint fp_nlp = solve_data.working_model.clone() config.fp_main_norm = 'L1' generate_norm_constraint(fp_nlp, solve_data, config) self.assertIsNotNone( fp_nlp.MindtPy_utils.find_component('L1_norm_constraint')) config.fp_main_norm = 'L2' generate_norm_constraint(fp_nlp, solve_data, config) self.assertIsNotNone(fp_nlp.find_component('norm_constraint')) fp_nlp.del_component('norm_constraint') config.fp_main_norm = 'L_infinity' generate_norm_constraint(fp_nlp, solve_data, config) self.assertIsNotNone(fp_nlp.find_component('norm_constraint')) # test set_solver_options config.mip_solver = 'gams' config.threads = 1 opt = SolverFactory(config.mip_solver) set_solver_options(opt, solve_data, config, 'mip', regularization=False) config.mip_solver = 'gurobi' config.mip_regularization_solver = 'gurobi' config.regularization_mip_threads = 1 opt = SolverFactory(config.mip_solver) set_solver_options(opt, solve_data, config, 'mip', regularization=True) config.nlp_solver = 'gams' config.nlp_solver_args['solver'] = 'ipopt' set_solver_options(opt, solve_data, config, 'nlp', regularization=False) config.nlp_solver_args['solver'] = 'ipopth' set_solver_options(opt, solve_data, config, 'nlp', regularization=False) config.nlp_solver_args['solver'] = 'conopt' set_solver_options(opt, solve_data, config, 'nlp', regularization=False) config.nlp_solver_args['solver'] = 'msnlp' set_solver_options(opt, solve_data, config, 'nlp', regularization=False) config.nlp_solver_args['solver'] = 'baron' set_solver_options(opt, solve_data, config, 'nlp', regularization=False) # test algorithm_should_terminate solve_data.should_terminate = True solve_data.UB = float('inf') self.assertIs( algorithm_should_terminate(solve_data, config, check_cycling=False), True) self.assertIs(solve_data.results.solver.termination_condition, tc.noSolution) solve_data.UB = 100 self.assertIs( algorithm_should_terminate(solve_data, config, check_cycling=False), True) self.assertIs(solve_data.results.solver.termination_condition, tc.feasible) solve_data.objective_sense = maximize solve_data.LB = float('-inf') self.assertIs( algorithm_should_terminate(solve_data, config, check_cycling=False), True) self.assertIs(solve_data.results.solver.termination_condition, tc.noSolution) solve_data.LB = 100 self.assertIs( algorithm_should_terminate(solve_data, config, check_cycling=False), True) self.assertIs(solve_data.results.solver.termination_condition, tc.feasible)
def _generate_model(self): self.model = ConcreteModel() model = self.model model._name = self.description model.s = Set(initialize=[1, 2]) model.x_unused = Var(within=Integers) model.x_unused.stale = False model.x_unused_initialy_stale = Var(within=Integers) model.x_unused_initialy_stale.stale = True model.X_unused = Var(model.s, within=Integers) model.X_unused_initialy_stale = Var(model.s, within=Integers) for i in model.s: model.X_unused[i].stale = False model.X_unused_initialy_stale[i].stale = True model.x = Var(within=RangeSet(None, None)) model.x.stale = False model.x_initialy_stale = Var(within=Integers) model.x_initialy_stale.stale = True model.X = Var(model.s, within=Integers) model.X_initialy_stale = Var(model.s, within=Integers) for i in model.s: model.X[i].stale = False model.X_initialy_stale[i].stale = True model.obj = Objective(expr= model.x + \ model.x_initialy_stale + \ sum_product(model.X) + \ sum_product(model.X_initialy_stale)) model.c = ConstraintList() model.c.add(model.x >= 1) model.c.add(model.x_initialy_stale >= 1) model.c.add(model.X[1] >= 0) model.c.add(model.X[2] >= 1) model.c.add(model.X_initialy_stale[1] >= 0) model.c.add(model.X_initialy_stale[2] >= 1) # Test that stale flags get set # on inactive blocks (where "inactive blocks" mean blocks # that do NOT follow a path of all active parent blocks # up to the top-level model) flat_model = model.clone() model.b = Block() model.B = Block(model.s) model.b.b = flat_model.clone() model.B[1].b = flat_model.clone() model.B[2].b = flat_model.clone() model.b.deactivate() model.B.deactivate() model.b.b.activate() model.B[1].b.activate() model.B[2].b.deactivate() assert model.b.active is False assert model.B[1].active is False assert model.B[1].active is False assert model.b.b.active is True assert model.B[1].b.active is True assert model.B[2].b.active is False