def makeDisjunctInMultipleDisjunctions(): """This is not a transformable model! Two SimpleDisjunctions which have a shared disjunct. """ m = ConcreteModel() m.a = Var(bounds=(-10, 50)) def d1_rule(disjunct, flag): m = disjunct.model() if flag: disjunct.c = Constraint(expr=m.a == 0) else: disjunct.c = Constraint(expr=m.a >= 5) m.disjunct1 = Disjunct([0, 1], rule=d1_rule) def d2_rule(disjunct, flag): if not flag: disjunct.c = Constraint(expr=m.a >= 30) else: disjunct.c = Constraint(expr=m.a == 100) m.disjunct2 = Disjunct([0, 1], rule=d2_rule) m.disjunction1 = Disjunction(expr=[m.disjunct1[0], m.disjunct1[1]]) m.disjunction2 = Disjunction(expr=[m.disjunct2[0], m.disjunct1[1]]) # Deactivate unused disjunct like we are supposed to m.disjunct2[1].deactivate() 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 test_compute_bounds(self): """Test computation of disjunctive bounds.""" m = ConcreteModel() m.x = Var(bounds=(0, 8)) m.d1 = Disjunct() m.d1.c = Constraint(expr=m.x >= 2) m.d2 = Disjunct() m.d2.c = Constraint(expr=m.x <= 4) m.disj = Disjunction(expr=[m.d1, m.d2]) m.obj = Objective(expr=m.x) TransformationFactory('contrib.compute_disj_var_bounds').apply_to(m) self.assertEquals(m.d1._disj_var_bounds[m.x], (2, 8)) self.assertEquals(m.d2._disj_var_bounds[m.x], (0, 4)) self.assertEquals(disjunctive_lb(m.x, m.d1), 2) self.assertEquals(disjunctive_ub(m.x, m.d1), 8) self.assertEquals(disjunctive_lb(m.x, m.d2), 0) self.assertEquals(disjunctive_ub(m.x, m.d2), 4) self.assertEquals(len(m.d1._disjunctive_var_constraints), 2) self.assertEquals(len(m.d2._disjunctive_var_constraints), 2) self.assertIs(m.d1._disjunctive_var_constraints[1].body, m.x) self.assertEquals(m.d1._disjunctive_var_constraints[1].lower, 2) self.assertIs(m.d1._disjunctive_var_constraints[2].body, m.x) self.assertEquals(m.d1._disjunctive_var_constraints[2].upper, 8) self.assertIs(m.d2._disjunctive_var_constraints[1].body, m.x) self.assertEquals(m.d2._disjunctive_var_constraints[1].lower, 0) self.assertIs(m.d2._disjunctive_var_constraints[2].body, m.x) self.assertEquals(m.d2._disjunctive_var_constraints[2].upper, 4)
def create_hull_model(self): m = ConcreteModel() m.p = Var([1, 2], bounds=(0, 10)) m.time1 = Disjunction(expr=[m.p[1] >= 1, m.p[1] == 0]) m.on = Disjunct() m.on.above_min = Constraint(expr=m.p[2] >= 1) m.on.ramping = Constraint(expr=m.p[2] - m.p[1] <= 3) m.on.on_before = Constraint(expr=m.p[1] >= 1) m.startup = Disjunct() m.startup.startup_limit = Constraint(expr=(1, m.p[2], 2)) m.startup.off_before = Constraint(expr=m.p[1] == 0) m.off = Disjunct() m.off.off = Constraint(expr=m.p[2] == 0) m.time2 = Disjunction(expr=[m.on, m.startup, m.off]) m.obj = Objective(expr=m.p[1] + m.p[2]) hull = TransformationFactory('gdp.hull') hull.apply_to(m) disaggregatedVars = ComponentSet([ hull.get_disaggregated_var(m.p[1], m.time1.disjuncts[0]), hull.get_disaggregated_var(m.p[1], m.time1.disjuncts[1]), hull.get_disaggregated_var(m.p[1], m.on), hull.get_disaggregated_var(m.p[2], m.on), hull.get_disaggregated_var(m.p[1], m.startup), hull.get_disaggregated_var(m.p[2], m.startup), hull.get_disaggregated_var(m.p[1], m.off), hull.get_disaggregated_var(m.p[2], m.off) ]) return m, disaggregatedVars
def makeTwoSimpleDisjunctions(): """Two SimpleDisjunctions on the same model.""" m = ConcreteModel() m.a = Var(bounds=(-10, 50)) def d1_rule(disjunct, flag): m = disjunct.model() if flag: disjunct.c = Constraint(expr=m.a == 0) else: disjunct.c = Constraint(expr=m.a >= 5) m.disjunct1 = Disjunct([0, 1], rule=d1_rule) def d2_rule(disjunct, flag): if not flag: disjunct.c = Constraint(expr=m.a >= 30) else: disjunct.c = Constraint(expr=m.a == 100) m.disjunct2 = Disjunct([0, 1], rule=d2_rule) m.disjunction1 = Disjunction(expr=[m.disjunct1[0], m.disjunct1[1]]) m.disjunction2 = Disjunction(expr=[m.disjunct2[0], m.disjunct2[1]]) return m
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 test_log_model_size(self): """Test logging functionality.""" m = ConcreteModel() m.x = Var(domain=Integers) m.d = Disjunct() m.d.c = Constraint(expr=m.x == 1) m.d2 = Disjunct() m.d2.c = Constraint(expr=m.x == 5) m.disj = Disjunction(expr=[m.d2]) output = StringIO() with LoggingIntercept(output, 'pyomo.util.model_size', logging.INFO): log_model_size_report(m) expected_output = """ activated: binary_variables: 1 constraints: 1 continuous_variables: 0 disjunctions: 1 disjuncts: 1 integer_variables: 1 nonlinear_constraints: 0 variables: 2 overall: binary_variables: 2 constraints: 2 continuous_variables: 0 disjunctions: 1 disjuncts: 2 integer_variables: 1 nonlinear_constraints: 0 variables: 3 warning: unassociated_disjuncts: 1 """.strip() self.assertEqual(output.getvalue().strip(), expected_output)
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 makeNetworkDisjunction(minimize=True): """ creates a GDP model with pyomo.network components """ m = ConcreteModel() m.feed = feed = Block() m.wkbx = wkbx = Block() m.dest = dest = Block() m.orange = orange = Disjunct() m.blue = blue = Disjunct() m.orange_or_blue = Disjunction(expr=[orange,blue]) blue.blue_box = blue_box = Block() feed.x = Var(bounds=(0,1)) wkbx.x = Var(bounds=(0,1)) dest.x = Var(bounds=(0,1)) wkbx.inlet = ntwk.Port(initialize={"x":wkbx.x}) wkbx.outlet = ntwk.Port(initialize={"x":wkbx.x}) feed.outlet = ntwk.Port(initialize={"x":feed.x}) dest.inlet = ntwk.Port(initialize={"x":dest.x}) blue_box.x = Var(bounds=(0,1)) blue_box.x_wkbx = Var(bounds=(0,1)) blue_box.x_dest = Var(bounds=(0,1)) blue_box.inlet_feed = ntwk.Port(initialize={"x":blue_box.x}) blue_box.outlet_wkbx = ntwk.Port(initialize={"x":blue_box.x}) blue_box.inlet_wkbx = ntwk.Port(initialize={"x":blue_box.x_wkbx}) blue_box.outlet_dest = ntwk.Port(initialize={"x":blue_box.x_dest}) blue_box.multiplier_constr = Constraint(expr=blue_box.x_dest == \ 2*blue_box.x_wkbx) # orange arcs orange.a1 = ntwk.Arc(source=feed.outlet, destination=wkbx.inlet) orange.a2 = ntwk.Arc(source=wkbx.outlet, destination=dest.inlet) # blue arcs blue.a1 = ntwk.Arc(source=feed.outlet, destination=blue_box.inlet_feed) blue.a2 = ntwk.Arc(source=blue_box.outlet_wkbx, destination=wkbx.inlet) blue.a3 = ntwk.Arc(source=wkbx.outlet, destination=blue_box.inlet_wkbx) blue.a4 = ntwk.Arc(source=blue_box.outlet_dest, destination=dest.inlet) # maximize/minimize "production" if minimize: m.obj = Objective(expr=m.dest.x) else: m.obj = Objective(expr=m.dest.x, sense=maximize) # create a completely fixed model feed.x.fix(0.42) return m
def test_active_parent_block(self): m = ConcreteModel() m.d1 = Block() m.d1.sub1 = Disjunct() m.d1.sub2 = Disjunct() m.d1.disj = Disjunction(expr=[m.d1.sub1, m.d1.sub2]) with self.assertRaises(GDP_Error): TransformationFactory('gdp.reclassify').apply_to(m)
def makeNestedDisjunctions(): """Three-term SimpleDisjunction built from two IndexedDisjuncts and one SimpleDisjunct. The SimpleDisjunct and one of the DisjunctDatas each contain a nested SimpleDisjunction (the disjuncts of which are declared on the same disjunct as the disjunction). (makeNestedDisjunctions_NestedDisjuncts is a much simpler model. All this adds is that it has a nested disjunction on a DisjunctData as well as on a SimpleDisjunct. So mostly it exists for historical reasons.) """ m = ConcreteModel() m.x = Var(bounds=(-9, 9)) m.z = Var(bounds=(0, 10)) m.a = Var(bounds=(0, 23)) def disjunct_rule(disjunct, flag): m = disjunct.model() if flag: def innerdisj_rule(disjunct, flag): m = disjunct.model() if flag: disjunct.c = Constraint(expr=m.z >= 5) else: disjunct.c = Constraint(expr=m.z == 0) disjunct.innerdisjunct = Disjunct([0, 1], rule=innerdisj_rule) @disjunct.Disjunction([0]) def innerdisjunction(b, i): return [b.innerdisjunct[0], b.innerdisjunct[1]] disjunct.c = Constraint(expr=m.a <= 2) else: disjunct.c = Constraint(expr=m.x == 2) m.disjunct = Disjunct([0, 1], rule=disjunct_rule) # I want a SimpleDisjunct with a disjunction in it too def simpledisj_rule(disjunct): m = disjunct.model() @disjunct.Disjunct() def innerdisjunct0(disjunct): disjunct.c = Constraint(expr=m.x <= 2) @disjunct.Disjunct() def innerdisjunct1(disjunct): disjunct.c = Constraint(expr=m.x >= 4) disjunct.innerdisjunction = Disjunction( expr=[disjunct.innerdisjunct0, disjunct.innerdisjunct1]) m.simpledisjunct = Disjunct(rule=simpledisj_rule) m.disjunction = Disjunction( expr=[m.simpledisjunct, m.disjunct[0], m.disjunct[1]]) return m
def test_disjunction_not_sum_to_1(self): m = ConcreteModel() m.d1 = Disjunct() m.d2 = Disjunct() m.d = Disjunction(expr=[m.d1, m.d2], xor=False) m.d1.indicator_var.set_value(0) m.d2.indicator_var.set_value(0) with self.assertRaises(GDP_Error): TransformationFactory('gdp.fix_disjuncts').apply_to(m)
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 test_unassociated_disjunct(self): m = ConcreteModel() m.x = Var(domain=Integers) m.d = Disjunct() m.d.c = Constraint(expr=m.x == 1) m.d2 = Disjunct() m.d2.c = Constraint(expr=m.x == 5) m.disj = Disjunction(expr=[m.d2]) model_size = build_model_size_report(m) self.assertEqual(model_size.warning.unassociated_disjuncts, 1)
def oneVarDisj_2pts(): m = ConcreteModel() m.x = Var(bounds=(0, 10)) m.disj1 = Disjunct() m.disj1.xTrue = Constraint(expr=m.x==1) m.disj2 = Disjunct() m.disj2.xFalse = Constraint(expr=m.x==0) m.disjunction = Disjunction(expr=[m.disj1, m.disj2]) m.obj = Objective(expr=m.x) return m
def add_disj_not_on_block(m): def simpdisj_rule(disjunct): m = disjunct.model() disjunct.c = Constraint(expr=m.a >= 3) m.simpledisj = Disjunct(rule=simpdisj_rule) def simpledisj2_rule(disjunct): m = disjunct.model() disjunct.c = Constraint(expr=m.a <= 3.5) m.simpledisj2 = Disjunct(rule=simpledisj2_rule) m.disjunction2 = Disjunction(expr=[m.simpledisj, m.simpledisj2]) return m
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_disjunct_not_binary(self): m = ConcreteModel() m.d1 = Disjunct() m.d2 = Disjunct() m.d = Disjunction(expr=[m.d1, m.d2]) m.d1.indicator_var.domain = NonNegativeReals m.d2.indicator_var.domain = NonNegativeReals m.d1.indicator_var.set_value(0.5) m.d2.indicator_var.set_value(0.5) with self.assertRaises(ValueError): TransformationFactory('gdp.fix_disjuncts').apply_to(m)
def test_deactivated_parent_block(self): m = ConcreteModel() m.d1 = Block() m.d1.sub1 = Disjunct() m.d1.sub2 = Disjunct() m.d1.disj = Disjunction(expr=[m.d1.sub1, m.d1.sub2]) m.d1.deactivate() TransformationFactory('gdp.reclassify').apply_to(m) self.assertIs(m.d1.type(), Block) self.assertIs(m.d1.sub1.type(), Block) self.assertIs(m.d1.sub2.type(), Block)
def test_active_parent_disjunct_target(self): m = ConcreteModel() m.d1 = Disjunct() m.d1.sub1 = Disjunct() m.d1.sub2 = Disjunct() m.d1.disj = Disjunction(expr=[m.d1.sub1, m.d1.sub2]) TransformationFactory('gdp.bigm').apply_to(m, targets=m.d1.disj) m.d1.indicator_var.fix(1) TransformationFactory('gdp.reclassify').apply_to(m) self.assertIs(m.d1.type(), Block) self.assertIs(m.d1.sub1.type(), Block) self.assertIs(m.d1.sub2.type(), Block)
def makeDisjunctWithExpression(): """Two-term SimpleDisjunction where one of the disjuncts contains an Expression. This is used to make sure that we correctly handle types we hit in disjunct.component_objects(active=True)""" m = ConcreteModel() m.x = Var(bounds=(0, 1)) m.d1 = Disjunct() m.d1.e = Expression(expr=m.x**2) m.d1.c = Constraint(rule=lambda _: m.x == 1) m.d2 = Disjunct() m.disj = Disjunction(expr=[m.d1, m.d2]) return m
def instantiate_hierarchical_nested_model(m): """helper function to instantiate a nested version of the model with the Disjuncts and Disjunctions on blocks""" m.disj1 = Disjunct() m.disjunct_block.disj2 = Disjunct() m.disj1.c = Constraint(expr=sum(m.x[i]**2 for i in m.I) <= 1) m.disjunct_block.disj2.c = Constraint(expr=sum((3 - m.x[i])**2 for i in m.I) <= 1) m.disjunct_block.disj2.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.disjunction_block.disjunction = Disjunction( expr=[m.disj1, m.disjunct_block.disj2])
def test_disjunction_unsat(self): m = ConcreteModel() m.x1 = Var(bounds=(0, 8)) m.x2 = Var(bounds=(0, 8)) m.obj = Objective(expr=m.x1 + m.x2, sense=minimize) m.y1 = Disjunct() m.y2 = Disjunct() m.y1.c1 = Constraint(expr=m.x1 >= 9) m.y1.c2 = Constraint(expr=m.x2 >= 2) m.y2.c1 = Constraint(expr=m.x1 >= 3) m.y2.c2 = Constraint(expr=m.x2 >= 9) m.djn = Disjunction(expr=[m.y1, m.y2]) self.assertFalse(satisfiable(m))
def get_model(self): m = ConcreteModel() m.x = Var(bounds=(-100, 100)) m.obj = Objective(expr=m.x) m.disjunct1 = Disjunct() m.disjunct1.comp = Complementarity(expr=complements(m.x >= 0, 4*m.x - 3 >= 0)) m.disjunct2 = Disjunct() m.disjunct2.cons = Constraint(expr=m.x >= 2) m.disjunction = Disjunction(expr=[m.disjunct1, m.disjunct2]) return m
def twoSegments_SawayaGrossmann(): m = ConcreteModel() m.x = Var(bounds=(0, 3)) m.disj1 = Disjunct() m.disj1.c = Constraint(expr=inequality(0, m.x, 1)) m.disj2 = Disjunct() m.disj2.c = Constraint(expr=inequality(2, m.x, 3)) m.disjunction = Disjunction(expr=[m.disj1, m.disj2]) # this is my objective because I want to make sure that when I am testing # cutting planes, my first solution to rBigM is not on the convex hull. m.obj = Objective(expr=m.x - m.disj2.indicator_var) return m
def grossmann_twoDisj(): m = grossmann_oneDisj() m.disjunct3 = Disjunct() m.disjunct3.constraintx = Constraint(expr=inequality(1, m.x, 2.5)) m.disjunct3.constrainty = Constraint(expr=inequality(6.5, m.y, 8)) m.disjunct4 = Disjunct() m.disjunct4.constraintx = Constraint(expr=inequality(9, m.x, 11)) m.disjunct4.constrainty = Constraint(expr=inequality(2, m.y, 3.5)) m.disjunction2 = Disjunction(expr=[m.disjunct3, m.disjunct4]) return m
def twoDisj_twoCircles_easy(): m = ConcreteModel() m.x = Var(bounds=(0,8)) m.y = Var(bounds=(0,10)) m.upper_circle = Disjunct() m.upper_circle.cons = Constraint(expr=(m.x - 1)**2 + (m.y - 6)**2 <= 2) m.lower_circle = Disjunct() m.lower_circle.cons = Constraint(expr=(m.x - 4)**2 + (m.y - 2)**2 <= 2) m.disjunction = Disjunction(expr=[m.upper_circle, m.lower_circle]) m.obj = Objective(expr=m.x + m.y, sense=maximize) return m
def test_disjunct_not_in_disjunction(self): m = pyo.ConcreteModel() m.x = pyo.Var() m.d1 = Disjunct() m.d1.c = pyo.Constraint(expr=m.x == 1) m.d2 = Disjunct() m.d2.c = pyo.Constraint(expr=m.x == 0) pyo.TransformationFactory('gdp.bigm').apply_to(m) log = StringIO() with LoggingIntercept(log, 'pyomo.gdp', logging.WARNING): check_model_algebraic(m) self.assertRegexpMatches(log.getvalue(), '.*not found in any Disjunctions.*')
def fourCircles(): m = twoDisj_twoCircles_easy() # and add two more overlapping circles, a la the Grossmann test case with # the rectangles. (but not change my nice integral optimal solution...) m.upper_circle2 = Disjunct() m.upper_circle2.cons = Constraint(expr=(m.x - 2)**2 + (m.y - 7)**2 <= 1) m.lower_circle2 = Disjunct() m.lower_circle2.cons = Constraint(expr=(m.x - 5)**2 + (m.y - 3)**2 <= 2) m.disjunction2 = Disjunction(expr=[m.upper_circle2, m.lower_circle2]) return m
def makeNestedDisjunctions(): m = ConcreteModel() m.x = Var(bounds=(-9, 9)) m.z = Var(bounds=(0, 10)) m.a = Var(bounds=(0, 23)) def disjunct_rule(disjunct, flag): m = disjunct.model() if flag: def innerdisj_rule(disjunct, flag): m = disjunct.model() if flag: disjunct.c = Constraint(expr=m.z >= 5) else: disjunct.c = Constraint(expr=m.z == 0) disjunct.innerdisjunct = Disjunct([0, 1], rule=innerdisj_rule) @disjunct.Disjunction([0]) def innerdisjunction(b, i): return [b.innerdisjunct[0], b.innerdisjunct[1]] disjunct.c = Constraint(expr=m.a <= 2) else: disjunct.c = Constraint(expr=m.x == 2) m.disjunct = Disjunct([0, 1], rule=disjunct_rule) # I want a SimpleDisjunct with a disjunction in it too def simpledisj_rule(disjunct): m = disjunct.model() @disjunct.Disjunct() def innerdisjunct0(disjunct): disjunct.c = Constraint(expr=m.x <= 2) @disjunct.Disjunct() def innerdisjunct1(disjunct): disjunct.c = Constraint(expr=m.x >= 4) disjunct.innerdisjunction = Disjunction( expr=[disjunct.innerdisjunct0, disjunct.innerdisjunct1]) m.simpledisjunct = Disjunct(rule=simpledisj_rule) m.disjunction = Disjunction( expr=[m.simpledisjunct, m.disjunct[0], m.disjunct[1]]) return m