def CreateAbstractScenarioTreeModel(): from pyomo.core import (AbstractModel, Set, Param, Boolean) model = AbstractModel() # all set/parameter values are strings, representing the # names of various entities/variables. model.Stages = Set(ordered=True) model.Nodes = Set(ordered=True) model.NodeStage = Param(model.Nodes, within=model.Stages, mutable=True) model.Children = Set(model.Nodes, within=model.Nodes, initialize=[], ordered=True) model.ConditionalProbability = Param(model.Nodes, mutable=True) model.Scenarios = Set(ordered=True) model.ScenarioLeafNode = Param(model.Scenarios, within=model.Nodes, mutable=True) model.StageVariables = Set(model.Stages, initialize=[], ordered=True) model.NodeVariables = Set(model.Nodes, initialize=[], ordered=True) model.StageCost = Param(model.Stages, mutable=True) # DEPRECATED model.StageCostVariable = Param(model.Stages, mutable=True) # it is often the case that a subset of the stage variables are strictly "derived" # variables, in that their values are computable once the values of other variables # in that stage are known. it generally useful to know which variables these are, # as it is unnecessary to post non-anticipativity constraints for these variables. # further, attempting to force non-anticipativity - either implicitly or explicitly - # on these variables can cause issues with decomposition algorithms. model.StageDerivedVariables = Set(model.Stages, initialize=[], ordered=True) model.NodeDerivedVariables = Set(model.Nodes, initialize=[], ordered=True) # scenario data can be populated in one of two ways. the first is "scenario-based", # in which a single .dat file contains all of the data for each scenario. the .dat # file prefix must correspond to the scenario name. the second is "node-based", # in which a single .dat file contains only the data for each node in the scenario # tree. the node-based method is more compact, but the scenario-based method is # often more natural when parameter data is generated via simulation. the default # is scenario-based. model.ScenarioBasedData = Param(within=Boolean, default=True, mutable=True) # do we bundle, and if so, how? model.Bundling = Param(within=Boolean, default=False, mutable=True) # bundle names model.Bundles = Set(ordered=True) model.BundleScenarios = Set(model.Bundles, ordered=True) return model
def create_abstract_model(self): """Build the model <b>object</b>.""" if not self.built: def jk_init(m): return [(j, k) for j in m.J for k in m.K[j]] model = AbstractModel() model.J = Set() model.K = Set(model.J) model.JK = Set(initialize=jk_init, dimen=None) model.y_pred = Param() model.epsilon = Param() model.max_cost = Var() model.w = Param(model.J) model.a = Param(model.JK) model.c = Param(model.JK) model.u = Var(model.JK, within=Binary) # Make sure only one action is on at a time. def c1Rule(m, j): return sum([m.u[j, k] for k in m.K[j]]) == 1 # 2.b: Action sets must flip the prediction of a linear classifier. def c2Rule(m): return sum((m.u[j, k] * m.a[j, k] * m.w[j]) for j, k in m.JK) >= -m.y_pred # instantiate max cost def maxcost_rule(m, j, k): return m.max_cost >= (m.u[j, k] * m.c[j, k]) # Set up objective for total sum. def obj_rule_percentile(m): return sum(m.u[j, k] * m.c[j, k] for j, k in m.JK) # Set up objective for max cost. def obj_rule_max(m): return sum(m.epsilon * m.u[j, k] * m.c[j, k] for j, k in m.JK) + (1 - m.epsilon) * m.max_cost ## set up objective function. if self.mip_cost_type == "max": model.g = Objective(rule=obj_rule_max, sense=minimize) model.c3 = Constraint(model.JK, rule=maxcost_rule) else: model.g = Objective(rule=obj_rule_percentile, sense=minimize) ## model.c1 = Constraint(model.J, rule=c1Rule) model.c2 = Constraint(rule=c2Rule) self.model = model self.built = True return self.model
def _create_model(self, ctype, **kwds): self.model = ConcreteModel() self.model.x = Var() self.model.IDX = Set(initialize=sorted(range(1000000))) self.model.del_component('test_component') self.model.test_component = \ ctype(self.model.IDX, **kwds)
def _create(self, group=None): """ Creates set, variables, constraints for all flow object with a attribute flow of type class:`.DiscreteFlow`. Parameters ---------- group : list List of oemof.solph.DiscreteFlow objects for which the constraints are build. """ if group is None: return None m = self.parent_block() # ########################## SETS ##################################### self.DISCRETE_FLOWS = Set(initialize=[(g[0], g[1]) for g in group]) self.discrete_flow = Var(self.DISCRETE_FLOWS, m.TIMESTEPS, within=NonNegativeIntegers) def _discrete_flow_rule(block, i, o, t): """Force flow variable to discrete (NonNegativeInteger) values. """ expr = (self.discrete_flow[i, o, t] == m.flow[i, o, t]) return expr self.integer_flow = Constraint(self.DISCRETE_FLOWS, m.TIMESTEPS, rule=_discrete_flow_rule)
def test_indexedvar_noindextemplate(self): st_model = CreateConcreteTwoStageScenarioTreeModel(1) st_model.StageVariables['Stage1'].add("x") st_model.StageDerivedVariables['Stage1'].add("y") st_model.NodeVariables['RootNode'].add("z") st_model.NodeDerivedVariables['RootNode'].add("q") st_model.StageCost['Stage1'] = "FirstStageCost" st_model.StageCost['Stage2'] = "SecondStageCost" scenario_tree = ScenarioTree(scenariotreeinstance=st_model) self.assertEqual(len(scenario_tree.stages), 2) self.assertEqual(len(scenario_tree.nodes), 2) self.assertEqual(len(scenario_tree.scenarios), 1) model = ConcreteModel() model.s = Set(initialize=[1, 2, 3]) model.x = Var(model.s) model.y = Var(model.s) model.z = Var(model.s) model.q = Var(model.s) model.FirstStageCost = Expression(expr=0.0) model.SecondStageCost = Expression(expr=0.0) model.obj = Objective(expr=0.0) scenario_tree.linkInInstances({'Scenario1': model}) root = scenario_tree.findRootNode() self.assertEqual(len(root._variable_ids), 12) self.assertEqual(len(root._standard_variable_ids), 6) self.assertEqual(len(root._derived_variable_ids), 6) for name in ("x", "y", "z", "q"): for index in model.s: self.assertEqual((name, index) in root._name_index_to_id, True)
def create_nodal_ph_parameters(scenario_tree): for stage in scenario_tree._stages[:-1]: for tree_node in stage._tree_nodes: new_nodal_index_set_name = "PHINDEX_" + str(tree_node._name) new_xbar_parameter_name = "PHXBAR_" + str(tree_node._name) new_blend_parameter_name = "PHBLEND_" + str(tree_node._name) # only create nodal index sets for non-derived variables. new_nodal_index_set = Set(name=new_nodal_index_set_name, initialize=list( tree_node._standard_variable_ids)) for scenario in tree_node._scenarios: instance = scenario._instance # avoid the warnings generated by adding Set to # multiple components, and learn to live with the fact # that these Params will point to some arbitrary # instance as their "parent" in the end new_nodal_index_set._parent = None # Add the shared parameter to the instance instance.add_component(new_nodal_index_set_name, new_nodal_index_set) ### dlw Jan 2014 nochecking=True, mutable=True) new_xbar_parameter = Param(new_nodal_index_set, name=new_xbar_parameter_name, default=0.0, mutable=True) ### dlw Jan 2014 nochecking=True, mutable=True) new_blend_parameter = Param(new_nodal_index_set, name=new_blend_parameter_name, within=Binary, default=False, mutable=True) for scenario in tree_node._scenarios: instance = scenario._instance # avoid the warnings generated by adding Param to # multiple components, and learn to live with the fact # that these Params will point to some arbitrary # instance as their "parent" in the end new_xbar_parameter._parent = None new_blend_parameter._parent = None # Add the shared parameter to the instance instance.add_component(new_xbar_parameter_name, new_xbar_parameter) instance.add_component(new_blend_parameter_name, new_blend_parameter) new_xbar_parameter.store_values(0.0) tree_node._xbars.update(dict.fromkeys(tree_node._xbars, 0.0)) new_blend_parameter.store_values(1) tree_node._blend.update(dict.fromkeys(tree_node._blend, 1))
def makeTwoTermDisj_IndexedConstraints_BoundedVars(): # same concept as above, but bounded variables m = ConcreteModel() m.s = Set(initialize=[1, 2]) m.lbs = Param(m.s, initialize={1: 2, 2: 4}) m.ubs = Param(m.s, initialize={1: 7, 2: 6}) def bounds_rule(m, s): return (m.lbs[s], m.ubs[s]) m.a = Var(m.s, bounds=bounds_rule) def d_rule(disjunct, flag): m = disjunct.model() def true_rule(d, s): return m.a[s] == 0 def false_rule(d, s): return m.a[s] >= 5 if flag: disjunct.c = Constraint(m.s, rule=true_rule) else: disjunct.c = Constraint(m.s, rule=false_rule) m.disjunct = Disjunct([0, 1], rule=d_rule) m.disjunction = Disjunction(expr=[m.disjunct[0], m.disjunct[1]]) return m
def _generate_model(self): self.model = ConcreteModel() model = self.model model._name = self.description model.s = Set(initialize=[1,2]) model.x = Var() model.y = Var() model.z = Var(bounds=(0,None)) model.obj = Objective(model.s, rule=inactive_index_LP_obj_rule) model.OBJ = Objective(expr=model.x+model.y) model.obj[1].deactivate() model.OBJ.deactivate() model.c1 = ConstraintList() model.c1.add(model.x<=1) # index=1 model.c1.add(model.x>=-1) # index=2 model.c1.add(model.y<=1) # index=3 model.c1.add(model.y>=-1) # index=4 model.c1[1].deactivate() model.c1[4].deactivate() model.c2 = Constraint(model.s, rule=inactive_index_LP_c2_rule) model.b = Block() model.b.c = Constraint(expr=model.z >= 2) model.B = Block(model.s) model.B[1].c = Constraint(expr=model.z >= 3) model.B[2].c = Constraint(expr=model.z >= 1) model.b.deactivate() model.B.deactivate() model.B[2].activate()
def _apply_to(self, instance, **kwds): # TODO: This data should be stored differently. We cannot nest this transformation with itself if getattr(instance, 'bilinear_data_', None) is None: instance.bilinear_data_ = Block() instance.bilinear_data_.cache = {} instance.bilinear_data_.vlist = VarList() instance.bilinear_data_.vlist_boolean = [] instance.bilinear_data_.IDX = Set() instance.bilinear_data_.disjuncts_ = Disjunct( instance.bilinear_data_.IDX * [0, 1]) instance.bilinear_data_.disjunction_data = {} instance.bilinear_data_.o_expr = {} instance.bilinear_data_.c_body = {} # # Iterate over all blocks # for block in instance.block_data_objects( active=True, sort=SortComponents.deterministic): self._transformBlock(block, instance) # # WEH: I wish I had a DisjunctList and DisjunctionList object... # def rule(block, i): return instance.bilinear_data_.disjunction_data[i] instance.bilinear_data_.disjunction_ = Disjunction( instance.bilinear_data_.IDX, rule=rule)
def makeTwoTermDisj_IndexedConstraints(): m = ConcreteModel() m.s = Set(initialize=[1, 2]) m.a = Var(m.s) m.b = Block() def disj1_rule(disjunct): m = disjunct.model() def c_rule(d, s): return m.a[s] == 0 disjunct.c = Constraint(m.s, rule=c_rule) m.b.simpledisj1 = Disjunct(rule=disj1_rule) def disj2_rule(disjunct): m = disjunct.model() def c_rule(d, s): return m.a[s] <= 3 disjunct.c = Constraint(m.s, rule=c_rule) m.b.simpledisj2 = Disjunct(rule=disj2_rule) m.b.disjunction = Disjunction(expr=[m.b.simpledisj1, m.b.simpledisj2]) return m
def test_construct(self): model = AbstractModel() model.a = Set(initialize=[1, 2, 3]) model.A = Param(initialize=1) model.B = Param(model.a) model.x = Var(initialize=1, within=Reals, dense=False) model.y = Var(model.a, initialize=1, within=Reals, dense=False) model.obj = Objective(rule=lambda model: model.x + model.y[1]) model.obj2 = Objective(model.a, rule=lambda model, i: i + model.x + model.y[1]) model.con = Constraint(rule=rule1) model.con2 = Constraint(model.a, rule=rule2) instance = model.create_instance() expr = instance.x + 1 OUTPUT = open(currdir + "/display.out", "w") display(instance, ostream=OUTPUT) display(instance.obj, ostream=OUTPUT) display(instance.x, ostream=OUTPUT) display(instance.con, ostream=OUTPUT) OUTPUT.write(expr.to_string()) model = AbstractModel() instance = model.create_instance() display(instance, ostream=OUTPUT) OUTPUT.close() try: display(None) self.fail("test_construct - expected TypeError") except TypeError: pass self.assertFileEqualsBaseline(currdir + "/display.out", currdir + "/display.txt")
def test_construct2(self): model = AbstractModel() model.a = Set(initialize=[1,2,3]) model.A = Param(initialize=1) model.B = Param(model.a) model.x = Var(initialize=1, within=Reals, dense=True) model.y = Var(model.a, initialize=1, within=Reals, dense=True) model.obj = Objective(rule=lambda model: model.x+model.y[1]) model.obj2 = Objective(model.a,rule=lambda model, i: i+model.x+model.y[1]) model.con = Constraint(rule=rule1) model.con2 = Constraint(model.a, rule=rule2) instance = model.create_instance() expr = instance.x + 1 OUTPUT = open(join(currdir, "display2.out"), "w") display(instance,ostream=OUTPUT) display(instance.obj,ostream=OUTPUT) display(instance.x,ostream=OUTPUT) display(instance.con,ostream=OUTPUT) OUTPUT.write(expr.to_string()) model = AbstractModel() instance = model.create_instance() display(instance,ostream=OUTPUT) OUTPUT.close() try: display(None) self.fail("test_construct - expected TypeError") except TypeError: pass _out, _txt = join(currdir, "display2.out"), join(currdir, "display2.txt") self.assertTrue(cmp(_out, _txt), msg="Files %s and %s differ" % (_out, _txt))
def makeTwoTermDisj_IndexedConstraints_BoundedVars(): """Single two-term disjunction with IndexedConstraints on both disjuncts. """ m = ConcreteModel() m.s = Set(initialize=[1, 2]) m.lbs = Param(m.s, initialize={1: 2, 2: 4}) m.ubs = Param(m.s, initialize={1: 7, 2: 6}) def bounds_rule(m, s): return (m.lbs[s], m.ubs[s]) m.a = Var(m.s, bounds=bounds_rule) def d_rule(disjunct, flag): m = disjunct.model() def true_rule(d, s): return m.a[s] == 0 def false_rule(d, s): return m.a[s] >= 5 if flag: disjunct.c = Constraint(m.s, rule=true_rule) else: disjunct.c = Constraint(m.s, rule=false_rule) m.disjunct = Disjunct([0, 1], rule=d_rule) m.disjunction = Disjunction(expr=[m.disjunct[0], m.disjunct[1]]) return m
def EXTERNAL_initialize_for_admm(manager, scenario): if manager.get_option("verbose"): print("Initializing scenario %s for admm algorithm" % (scenario.name)) admm_block = Block(concrete=True) assert not hasattr(scenario._instance, ".admm") scenario._instance.add_component(".admm", admm_block) # Augment the objective with lagrangian and penalty terms # and weight the original objective by the scenario probability. # The langrangian and penalty terms will be computed after # the parameters are created. user_cost_expression = scenario._instance_cost_expression admm_block.cost_expression = Expression(initialize=\ scenario.probability * user_cost_expression) admm_block.lagrangian_expression = Expression(initialize=0.0) admm_block.penalty_expression = Expression(initialize=0.0) # these are used in the objective, they can be toggled # between the expression above or something else (e.g., 0.0) admm_block.cost_term = Expression(initialize=admm_block.cost_expression) admm_block.lagrangian_term = Expression( initialize=admm_block.lagrangian_expression) admm_block.penalty_term = Expression( initialize=admm_block.penalty_expression) objective_direction = 1 if manager.objective_sense == maximize: objective_direction = -1 scenario._instance_objective.expr = \ admm_block.cost_term + \ admm_block.lagrangian_term * objective_direction + \ admm_block.penalty_term * objective_direction # add objective parameters to admm block for tree_node in scenario.node_list[:-1]: assert not tree_node.is_leaf_node() node_block = Block(concrete=True) admm_block.add_component(tree_node.name, node_block) node_block.node_index_set = Set(ordered=True, initialize=sorted( tree_node._standard_variable_ids)) node_block.z = Param(node_block.node_index_set, initialize=0.0, mutable=True) node_block.y = Param(node_block.node_index_set, initialize=0.0, mutable=True) node_block.rho = Param(node_block.node_index_set, initialize=0.0, mutable=True) for id_ in node_block.node_index_set: varname, index = tree_node._variable_ids[id_] var = scenario._instance.find_component(varname)[index] admm_block.lagrangian_expression.expr += \ node_block.y[id_] * (var - node_block.z[id_]) admm_block.penalty_expression.expr += \ (node_block.rho[id_] / 2.0) * (var - node_block.z[id_])**2 # The objective has changed so flag this if necessary. if manager.preprocessor is not None: manager.preprocessor.objective_updated[scenario.name] = True
def makeAnyIndexedDisjunctionOfDisjunctDatas(): """An IndexedDisjunction indexed by Any, with two two-term DisjunctionDatas build from DisjunctDatas. Identical mathematically to makeDisjunctionOfDisjunctDatas. Used to test that the right things happen for a case where soemone implements an algorithm which iteratively generates disjuncts and retransforms""" m = ConcreteModel() m.x = Var(bounds=(-100, 100)) m.obj = Objective(expr=m.x) m.idx = Set(initialize=[1, 2]) m.firstTerm = Disjunct(m.idx) m.firstTerm[1].cons = Constraint(expr=m.x == 0) m.firstTerm[2].cons = Constraint(expr=m.x == 2) m.secondTerm = Disjunct(m.idx) m.secondTerm[1].cons = Constraint(expr=m.x >= 2) m.secondTerm[2].cons = Constraint(expr=m.x >= 3) m.disjunction = Disjunction(Any) m.disjunction[1] = [m.firstTerm[1], m.secondTerm[1]] m.disjunction[2] = [m.firstTerm[2], m.secondTerm[2]] return m
def makeTwoTermDisj_IndexedConstraints(): """Single two-term disjunction with IndexedConstraints on both disjuncts. Does not bound the variables, so cannot be transformed by hull at all and requires specifying m values in bigm. """ m = ConcreteModel() m.s = Set(initialize=[1, 2]) m.a = Var(m.s) m.b = Block() def disj1_rule(disjunct): m = disjunct.model() def c_rule(d, s): return m.a[s] == 0 disjunct.c = Constraint(m.s, rule=c_rule) m.b.simpledisj1 = Disjunct(rule=disj1_rule) def disj2_rule(disjunct): m = disjunct.model() def c_rule(d, s): return m.a[s] <= 3 disjunct.c = Constraint(m.s, rule=c_rule) m.b.simpledisj2 = Disjunct(rule=disj2_rule) m.b.disjunction = Disjunction(expr=[m.b.simpledisj1, m.b.simpledisj2]) return m
def makeTwoTermIndexedDisjunction(): m = ConcreteModel() m.A = Set(initialize=[1, 2, 3]) m.B = Set(initialize=['a', 'b']) m.x = Var(m.A, bounds=(-10, 10)) def disjunct_rule(d, i, k): m = d.model() if k == 'a': d.cons_a = Constraint(expr=m.x[i] >= 5) if k == 'b': d.cons_b = Constraint(expr=m.x[i] <= 0) m.disjunct = Disjunct(m.A, m.B, rule=disjunct_rule) def disj_rule(m, i): return [m.disjunct[i, k] for k in m.B] m.disjunction = Disjunction(m.A, rule=disj_rule) return m
def makeTwoTermMultiIndexedDisjunction(): m = ConcreteModel() m.s = Set(initialize=[1, 2]) m.t = Set(initialize=['A', 'B']) m.a = Var(m.s, m.t, bounds=(2, 7)) def d_rule(disjunct, flag, s, t): m = disjunct.model() if flag: disjunct.c = Constraint(expr=m.a[s, t] == 0) else: disjunct.c = Constraint(expr=m.a[s, t] >= 5) m.disjunct = Disjunct([0, 1], m.s, m.t, rule=d_rule) def disj_rule(m, s, t): return [m.disjunct[0, s, t], m.disjunct[1, s, t]] m.disjunction = Disjunction(m.s, m.t, rule=disj_rule) return m
def __init__(self, **kwargs): """Constructor""" args = (Set(), ) self._nconditions = 0 Complementarity.__init__(self, *args, **kwargs) # disable the implicit rule; construct will exhaust the # user-provided rule, and then subsequent attempts to add a CC # will bypass the rule self._rule = None
def _get_block_model(self): model = ConcreteModel() model.s = Set(initialize=[1, 2]) b = Block(concrete=True) b.s = Set(initialize=[1, 2]) b.x = Var() b.X = Var(model.s) model.b1 = b.clone() model.b2 = b.clone() model.b3 = b.clone() model.b4 = b.clone() model.B1 = Block(model.s, rule=lambda _, i: b.clone()) model.B2 = Block(model.s, rule=lambda _, i: b.clone()) model.B3 = Block(model.s, rule=lambda _, i: b.clone()) model.B4 = Block(model.s, rule=lambda _, i: b.clone()) model.FirstStageCost = Expression(expr=0.0) model.SecondStageCost = Expression(expr=0.0) model.obj = Objective(expr=0.0) return model
def _create(self, group=None): """ Parameters ---------- group : list List containing storage objects. e.g. groups=[storage1, storage2,..] """ m = self.parent_block() if group is None: return None I = {n: [i for i in n.inputs][0] for n in group} O = {n: [o for o in n.outputs][0] for n in group} self.STORAGES = Set(initialize=[n for n in group]) def _storage_capacity_bound_rule(block, n, t): """Rule definition for bounds of capacity variable of storage n in timestep t """ bounds = (n.nominal_capacity * n.capacity_min[t], n.nominal_capacity * n.capacity_max[t]) return bounds self.capacity = Var(self.STORAGES, m.TIMESTEPS, bounds=_storage_capacity_bound_rule) # set the initial capacity of the storage for n in group: if n.initial_capacity is not None: self.capacity[n, m.timesteps[-1]] = (n.initial_capacity * n.nominal_capacity) self.capacity[n, m.timesteps[-1]].fix() # storage balance constraint def _storage_balance_rule(block, n, t): """Rule definition for the storage balance of every storage n and timestep t """ expr = 0 expr += block.capacity[n, t] expr += -block.capacity[n, m.previous_timesteps[t]] * ( 1 - n.capacity_loss[t]) expr += (-m.flow[I[n], n, t] * n.inflow_conversion_factor[t]) * m.timeincrement[t] expr += (m.flow[n, O[n], t] / n.outflow_conversion_factor[t]) * m.timeincrement[t] return expr == 0 self.balance = Constraint(self.STORAGES, m.TIMESTEPS, rule=_storage_balance_rule)
def _add_transformation_block(self, instance): # make a transformation block on instance to put transformed disjuncts # on transBlockName = unique_component_name(instance, '_pyomo_gdp_bigm_relaxation') transBlock = Block() instance.add_component(transBlockName, transBlock) transBlock.relaxedDisjuncts = Block(NonNegativeIntegers) transBlock.lbub = Set(initialize=['lb', 'ub']) return transBlock
def _process_bilinear_constraints(block, v1, v2, var_values, bilinear_constrs): # TODO check that the appropriate variable bounds exist. if not (v2.has_lb() and v2.has_ub()): logger.warning( textwrap.dedent("""\ Attempting to transform bilinear term {v1} * {v2} using effectively discrete variable {v1}, but {v2} is missing a lower or upper bound: ({v2lb}, {v2ub}). """.format(v1=v1, v2=v2, v2lb=v2.lb, v2ub=v2.ub)).strip()) return False blk = Block() unique_name = unique_component_name( block, ("%s_%s_bilinear" % (v1.local_name, v2.local_name)).replace( '[', '').replace(']', '')) block._induced_linearity_info.add_component(unique_name, blk) # TODO think about not using floats as indices in a set blk.valid_values = Set(initialize=sorted(var_values)) blk.x_active = Var(blk.valid_values, domain=Binary, initialize=1) blk.v_increment = Var(blk.valid_values, domain=v2.domain, bounds=(v2.lb, v2.ub), initialize=v2.value) blk.v_defn = Constraint(expr=v2 == summation(blk.v_increment)) @blk.Constraint(blk.valid_values) def v_lb(blk, val): return v2.lb * blk.x_active[val] <= blk.v_increment[val] @blk.Constraint(blk.valid_values) def v_ub(blk, val): return blk.v_increment[val] <= v2.ub * blk.x_active[val] blk.select_one_value = Constraint(expr=summation(blk.x_active) == 1) # Categorize as case 1 or case 2 for bilinear_constr in bilinear_constrs: # repn = generate_standard_repn(bilinear_constr.body) # Case 1: no other variables besides bilinear term in constraint. v1 # (effectively discrete variable) is positive. # if (len(repn.quadratic_vars) == 1 and len(repn.linear_vars) == 0 # and repn.nonlinear_expr is None): # _reformulate_case_1(v1, v2, discrete_constr, bilinear_constr) # NOTE: Case 1 is left unimplemented for now, because it involves some # messier logic with respect to how the transformation needs to happen. # Case 2: this is everything else, but do we want to have a special # case if there are nonlinear expressions involved with the constraint? pass _reformulate_case_2(blk, v1, v2, bilinear_constr) pass
def makeTwoTermIndexedDisjunction_BoundedVars(): m = ConcreteModel() m.s = Set(initialize=[1, 2, 3]) m.a = Var(m.s, bounds=(-100, 100)) def disjunct_rule(d, s, flag): m = d.model() if flag: d.c = Constraint(expr=m.a[s] >= 6) else: d.c = Constraint(expr=m.a[s] <= 3) m.disjunct = Disjunct(m.s, [0, 1], rule=disjunct_rule) def disjunction_rule(m, s): return [m.disjunct[s, flag] for flag in [0, 1]] m.disjunction = Disjunction(m.s, rule=disjunction_rule) return m
def add_cut(self, first=False): self._iter += 1 model = self._model self._wprod[self._iter] = self._compute_weight_weight_inner_product() if first is True: self._alphas[self._iter] = -( self._compute_objective_term() + (self._ph._rho / 2.0) * self._wprod[self._iter]) else: self._alphas[self._iter] = -(self._compute_objective_term( )) + self._compute_xbar_weight_inner_product() if self._solved is True: if self._compute_convergence() is True: return True model.del_component('cuts') model.cuts = Set(initialize=sorted(self._alphas.keys())) model.del_component('beta') model.beta = Var(model.cuts, within=NonNegativeReals) model.del_component('beta_sum_one') model.beta_sum_one = Constraint(expr=sum_product(model.beta) == 1) model.del_component('obj') model.obj = Objective(expr=sum(self._alphas[i] * model.beta[i] for i in model.cuts)) self._wbars[self._iter] = {} for stage in self._ph._scenario_tree._stages[: -1]: # all blended stages for tree_node in stage._tree_nodes: self._wbars[self._iter][tree_node._name] = copy.deepcopy( tree_node._wbars) block = getattr(model, tree_node._name) def _c_rule(block, i): lhs = sum(model.beta[k] * self._wbars[k][tree_node._name][ block.id_to_var[i][0]][block.id_to_var[i][1]] for k in model.beta.index_set()) if not isinstance(lhs, ExpressionBase): return Constraint.Skip return lhs == 0 block.del_component('con') block.con = Constraint(block.var_index, rule=_c_rule) return False
def makeDisjunctionsOnIndexedBlock(): """Two disjunctions (one indexed an one not), each on a separate BlockData of an IndexedBlock of length 2 """ m = ConcreteModel() m.s = Set(initialize=[1, 2]) m.a = Var(m.s, bounds=(0, 70)) @m.Disjunct(m.s, [0, 1]) def disjunct1(disjunct, s, flag): m = disjunct.model() if not flag: disjunct.c = Constraint(expr=m.a[s] == 0) else: disjunct.c = Constraint(expr=m.a[s] >= 7) def disjunction1_rule(m, s): return [m.disjunct1[s, flag] for flag in [0, 1]] m.disjunction1 = Disjunction(m.s, rule=disjunction1_rule) m.b = Block([0, 1]) m.b[0].x = Var(bounds=(-2, 2)) def disjunct2_rule(disjunct, flag): if not flag: disjunct.c = Constraint(expr=m.b[0].x <= 0) else: disjunct.c = Constraint(expr=m.b[0].x >= 0) m.b[0].disjunct = Disjunct([0, 1], rule=disjunct2_rule) def disjunction(b, i): return [b.disjunct[0], b.disjunct[1]] m.b[0].disjunction = Disjunction([0], rule=disjunction) m.b[1].y = Var(bounds=(-3, 3)) m.b[1].disjunct0 = Disjunct() m.b[1].disjunct0.c = Constraint(expr=m.b[1].y <= 0) m.b[1].disjunct1 = Disjunct() m.b[1].disjunct1.c = Constraint(expr=m.b[1].y >= 0) m.b[1].disjunction = Disjunction(expr=[m.b[1].disjunct0, m.b[1].disjunct1]) return m
def makeThreeTermIndexedDisj(): m = ConcreteModel() m.s = Set(initialize=[1, 2]) m.a = Var(m.s, bounds=(2, 7)) def d_rule(disjunct, flag, s): m = disjunct.model() if flag == 0: disjunct.c = Constraint(expr=m.a[s] == 0) elif flag == 1: disjunct.c = Constraint(expr=m.a[s] >= 5) else: disjunct.c = Constraint(expr=inequality(2, m.a[s], 4)) m.disjunct = Disjunct([0, 1, 2], m.s, rule=d_rule) def disj_rule(m, s): return [m.disjunct[0, s], m.disjunct[1, s], m.disjunct[2, s]] m.disjunction = Disjunction(m.s, rule=disj_rule) return m
def _add_transformation_block(self, instance): # make a transformation block on instance where we will store # transformed components transBlockName = unique_component_name( instance, '_pyomo_gdp_hull_reformulation') transBlock = Block() instance.add_component(transBlockName, transBlock) transBlock.relaxedDisjuncts = Block(NonNegativeIntegers) transBlock.lbub = Set(initialize=['lb', 'ub', 'eq']) # We will store all of the disaggregation constraints for any # Disjunctions we transform onto this block here. transBlock.disaggregationConstraints = Constraint( NonNegativeIntegers, Any) # This will map from srcVar to a map of srcDisjunction to the # disaggregation constraint corresponding to srcDisjunction transBlock._disaggregationConstraintMap = ComponentMap() return transBlock
def test_indexedvar_noindextemplate(self): st_model = CreateConcreteTwoStageScenarioTreeModel(1) st_model.StageVariables['Stage1'].add("x") st_model.StageDerivedVariables['Stage1'].add("y") st_model.NodeVariables['RootNode'].add("z") st_model.NodeDerivedVariables['RootNode'].add("q") st_model.StageCost['Stage1'] = "FirstStageCost" st_model.StageCost['Stage2'] = "SecondStageCost" scenario_tree = ScenarioTree(scenariotreeinstance=st_model) self.assertEqual(len(scenario_tree.stages), 2) self.assertEqual(len(scenario_tree.nodes), 2) self.assertEqual(len(scenario_tree.scenarios), 1) model = ConcreteModel() model.s = Set(initialize=[1, 2, 3]) model.x = Var(model.s) model.y = Var(model.s) model.z = Var(model.s) model.q = Var(model.s) model.FirstStageCost = Expression(expr=0.0) model.SecondStageCost = Expression(expr=0.0) model.obj = Objective(expr=0.0) root = scenario_tree.findRootNode() root_nonant_names = _get_names(_get_nonant_list(model, root)) root_derived_nonant_names = _get_names( _get_derived_nonant_list(model, root)) assert len(root_nonant_names) == 6 assert len(root_derived_nonant_names) == 6 for name in ("x", "z"): indexed_var = model.find_component(name) for index in model.s: var = indexed_var[index] assert var.name in root_nonant_names for name in ("y", "q"): indexed_var = model.find_component(name) for index in model.s: var = indexed_var[index] assert var.name in root_derived_nonant_names
def makeDisjunctionOfDisjunctDatas(): """Two SimpleDisjunctions, where each are disjunctions of DisjunctDatas. This adds nothing to makeTwoSimpleDisjunctions but exists for convenience because it has the same mathematical meaning as makeAnyIndexedDisjunctionOfDisjunctDatas """ m = ConcreteModel() m.x = Var(bounds=(-100, 100)) m.obj = Objective(expr=m.x) m.idx = Set(initialize=[1, 2]) m.firstTerm = Disjunct(m.idx) m.firstTerm[1].cons = Constraint(expr=m.x == 0) m.firstTerm[2].cons = Constraint(expr=m.x == 2) m.secondTerm = Disjunct(m.idx) m.secondTerm[1].cons = Constraint(expr=m.x >= 2) m.secondTerm[2].cons = Constraint(expr=m.x >= 3) m.disjunction = Disjunction(expr=[m.firstTerm[1], m.secondTerm[1]]) m.disjunction2 = Disjunction(expr=[m.firstTerm[2], m.secondTerm[2]]) return m