1from pyomo.core import (Block, ConcreteModel, Constraint, Objective, Param, Set, 2 Var, inequality, RangeSet, Any, Expression, maximize, TransformationFactory) 3from pyomo.gdp import Disjunct, Disjunction 4 5import pyomo.network as ntwk 6 7def oneVarDisj_2pts(): 8 m = ConcreteModel() 9 m.x = Var(bounds=(0, 10)) 10 m.disj1 = Disjunct() 11 m.disj1.xTrue = Constraint(expr=m.x==1) 12 m.disj2 = Disjunct() 13 m.disj2.xFalse = Constraint(expr=m.x==0) 14 m.disjunction = Disjunction(expr=[m.disj1, m.disj2]) 15 m.obj = Objective(expr=m.x) 16 return m 17 18def twoSegments_SawayaGrossmann(): 19 m = ConcreteModel() 20 m.x = Var(bounds=(0, 3)) 21 m.disj1 = Disjunct() 22 m.disj1.c = Constraint(expr=inequality(0, m.x, 1)) 23 m.disj2 = Disjunct() 24 m.disj2.c = Constraint(expr=inequality(2, m.x, 3)) 25 m.disjunction = Disjunction(expr=[m.disj1, m.disj2]) 26 27 # this is my objective because I want to make sure that when I am testing 28 # cutting planes, my first solution to rBigM is not on the convex hull. 29 m.obj = Objective(expr=m.x - m.disj2.indicator_var) 30 31 return m 32 33def makeTwoTermDisj(): 34 """Single two-term disjunction which has all of ==, <=, and >= constraints 35 """ 36 m = ConcreteModel() 37 m.a = Var(bounds=(2, 7)) 38 m.x = Var(bounds=(4, 9)) 39 40 def d_rule(disjunct, flag): 41 m = disjunct.model() 42 if flag: 43 disjunct.c1 = Constraint(expr=m.a == 0) 44 disjunct.c2 = Constraint(expr=m.x <= 7) 45 else: 46 disjunct.c = Constraint(expr=m.a >= 5) 47 m.d = Disjunct([0, 1], rule=d_rule) 48 m.disjunction = Disjunction(expr=[m.d[0], m.d[1]]) 49 return m 50 51 52def makeTwoTermDisj_Nonlinear(): 53 """Single two-term disjunction which has all of ==, <=, and >= and 54 one nonlinear constraint. 55 """ 56 m = ConcreteModel() 57 m.w = Var(bounds=(2, 7)) 58 m.x = Var(bounds=(1, 8)) 59 m.y = Var(bounds=(-10, -3)) 60 61 def d_rule(disjunct, flag): 62 m = disjunct.model() 63 if flag: 64 disjunct.c1 = Constraint(expr=m.x >= 2) 65 disjunct.c2 = Constraint(expr=m.w == 3) 66 disjunct.c3 = Constraint(expr=(1, m.x, 3)) 67 else: 68 disjunct.c = Constraint(expr=m.x + m.y**2 <= 14) 69 m.d = Disjunct([0, 1], rule=d_rule) 70 m.disjunction = Disjunction(expr=[m.d[0], m.d[1]]) 71 return m 72 73 74def makeTwoTermDisj_IndexedConstraints(): 75 """Single two-term disjunction with IndexedConstraints on both disjuncts. 76 Does not bound the variables, so cannot be transformed by hull at all and 77 requires specifying m values in bigm. 78 """ 79 m = ConcreteModel() 80 m.s = Set(initialize=[1, 2]) 81 m.a = Var(m.s) 82 m.b = Block() 83 84 def disj1_rule(disjunct): 85 m = disjunct.model() 86 87 def c_rule(d, s): 88 return m.a[s] == 0 89 disjunct.c = Constraint(m.s, rule=c_rule) 90 m.b.simpledisj1 = Disjunct(rule=disj1_rule) 91 92 def disj2_rule(disjunct): 93 m = disjunct.model() 94 95 def c_rule(d, s): 96 return m.a[s] <= 3 97 disjunct.c = Constraint(m.s, rule=c_rule) 98 m.b.simpledisj2 = Disjunct(rule=disj2_rule) 99 m.b.disjunction = Disjunction(expr=[m.b.simpledisj1, m.b.simpledisj2]) 100 return m 101 102 103def makeTwoTermDisj_IndexedConstraints_BoundedVars(): 104 """Single two-term disjunction with IndexedConstraints on both disjuncts. 105 """ 106 m = ConcreteModel() 107 m.s = Set(initialize=[1, 2]) 108 m.lbs = Param(m.s, initialize={1: 2, 2: 4}) 109 m.ubs = Param(m.s, initialize={1: 7, 2: 6}) 110 111 def bounds_rule(m, s): 112 return (m.lbs[s], m.ubs[s]) 113 m.a = Var(m.s, bounds=bounds_rule) 114 115 def d_rule(disjunct, flag): 116 m = disjunct.model() 117 118 def true_rule(d, s): 119 return m.a[s] == 0 120 121 def false_rule(d, s): 122 return m.a[s] >= 5 123 if flag: 124 disjunct.c = Constraint(m.s, rule=true_rule) 125 else: 126 disjunct.c = Constraint(m.s, rule=false_rule) 127 m.disjunct = Disjunct([0, 1], rule=d_rule) 128 m.disjunction = Disjunction(expr=[m.disjunct[0], m.disjunct[1]]) 129 return m 130 131def localVar(): 132 """Two-term disjunction which declares a local variable y on one of the 133 disjuncts, which is used in the objective function as well. 134 135 Used to test that we will treat y as global in the transformations, 136 despite where it is declared. 137 """ 138 # y appears in a global constraint and a single disjunct. 139 m = ConcreteModel() 140 m.x = Var(bounds=(0,3)) 141 142 m.disj1 = Disjunct() 143 m.disj1.cons = Constraint(expr=m.x >= 1) 144 145 m.disj2 = Disjunct() 146 m.disj2.y = Var(bounds=(1,3)) 147 m.disj2.cons = Constraint(expr=m.x + m.disj2.y == 3) 148 149 m.disjunction = Disjunction(expr=[m.disj1, m.disj2]) 150 151 # This makes y global actually... But in disguise. 152 m.objective = Objective(expr=m.x + m.disj2.y) 153 return m 154 155 156def makeThreeTermIndexedDisj(): 157 """Three-term indexed disjunction""" 158 m = ConcreteModel() 159 m.s = Set(initialize=[1, 2]) 160 m.a = Var(m.s, bounds=(2, 7)) 161 162 def d_rule(disjunct, flag, s): 163 m = disjunct.model() 164 if flag == 0: 165 disjunct.c = Constraint(expr=m.a[s] == 0) 166 elif flag == 1: 167 disjunct.c = Constraint(expr=m.a[s] >= 5) 168 else: 169 disjunct.c = Constraint(expr=inequality(2, m.a[s], 4)) 170 m.disjunct = Disjunct([0, 1, 2], m.s, rule=d_rule) 171 172 def disj_rule(m, s): 173 return [m.disjunct[0, s], m.disjunct[1, s], m.disjunct[2, s]] 174 m.disjunction = Disjunction(m.s, rule=disj_rule) 175 return m 176 177 178def makeTwoTermDisj_boxes(): 179 m = ConcreteModel() 180 m.x = Var(bounds=(0,5)) 181 m.y = Var(bounds=(0,5)) 182 def d_rule(disjunct, flag): 183 m = disjunct.model() 184 if flag: 185 disjunct.c1 = Constraint(expr=inequality(1, m.x, 2)) 186 disjunct.c2 = Constraint(expr=inequality(3, m.y, 4)) 187 else: 188 disjunct.c1 = Constraint(expr=inequality(3, m.x, 4)) 189 disjunct.c2 = Constraint(expr=inequality(1, m.y, 2)) 190 m.d = Disjunct([0,1], rule=d_rule) 191 def disj_rule(m): 192 return [m.d[0], m.d[1]] 193 m.disjunction = Disjunction(rule=disj_rule) 194 m.obj = Objective(expr=m.x + 2*m.y) 195 return m 196 197 198def makeThreeTermDisj_IndexedConstraints(): 199 """Three-term disjunction with indexed constraints on the disjuncts""" 200 m = ConcreteModel() 201 m.I = [1, 2, 3] 202 m.x = Var(m.I, bounds=(0, 10)) 203 204 def c_rule(b, i): 205 m = b.model() 206 return m.x[i] >= i 207 208 def d_rule(d, j): 209 m = d.model() 210 d.c = Constraint(m.I[:j], rule=c_rule) 211 m.d = Disjunct(m.I, rule=d_rule) 212 m.disjunction = Disjunction(expr=[m.d[i] for i in m.I]) 213 return m 214 215 216def makeTwoTermIndexedDisjunction(): 217 """Two-term indexed disjunction""" 218 m = ConcreteModel() 219 m.A = Set(initialize=[1, 2, 3]) 220 m.B = Set(initialize=['a', 'b']) 221 m.x = Var(m.A, bounds=(-10, 10)) 222 223 def disjunct_rule(d, i, k): 224 m = d.model() 225 if k == 'a': 226 d.cons_a = Constraint(expr=m.x[i] >= 5) 227 if k == 'b': 228 d.cons_b = Constraint(expr=m.x[i] <= 0) 229 m.disjunct = Disjunct(m.A, m.B, rule=disjunct_rule) 230 231 def disj_rule(m, i): 232 return [m.disjunct[i, k] for k in m.B] 233 m.disjunction = Disjunction(m.A, rule=disj_rule) 234 return m 235 236 237def makeTwoTermIndexedDisjunction_BoundedVars(): 238 """Two-term indexed disjunction. 239 Adds nothing to above--exists for historic reasons""" 240 m = ConcreteModel() 241 m.s = Set(initialize=[1, 2, 3]) 242 m.a = Var(m.s, bounds=(-100, 100)) 243 244 def disjunct_rule(d, s, flag): 245 m = d.model() 246 if flag: 247 d.c = Constraint(expr=m.a[s] >= 6) 248 else: 249 d.c = Constraint(expr=m.a[s] <= 3) 250 m.disjunct = Disjunct(m.s, [0, 1], rule=disjunct_rule) 251 252 def disjunction_rule(m, s): 253 return [m.disjunct[s, flag] for flag in [0, 1]] 254 m.disjunction = Disjunction(m.s, rule=disjunction_rule) 255 return m 256 257 258def makeIndexedDisjunction_SkipIndex(): 259 """Two-term indexed disjunction where one of the two indices is skipped""" 260 m = ConcreteModel() 261 m.x = Var(bounds=(0, 10)) 262 @m.Disjunct([0,1]) 263 def disjuncts(d, i): 264 m = d.model() 265 d.cons = Constraint(expr=m.x == i) 266 267 @m.Disjunction([0,1]) 268 def disjunctions(m, i): 269 if i == 0: 270 return Disjunction.Skip 271 return [m.disjuncts[i], m.disjuncts[0]] 272 273 return m 274 275def makeTwoTermMultiIndexedDisjunction(): 276 """Two-term indexed disjunction with tuple indices""" 277 m = ConcreteModel() 278 m.s = Set(initialize=[1, 2]) 279 m.t = Set(initialize=['A', 'B']) 280 m.a = Var(m.s, m.t, bounds=(2, 7)) 281 282 def d_rule(disjunct, flag, s, t): 283 m = disjunct.model() 284 if flag: 285 disjunct.c = Constraint(expr=m.a[s, t] == 0) 286 else: 287 disjunct.c = Constraint(expr=m.a[s, t] >= 5) 288 m.disjunct = Disjunct([0, 1], m.s, m.t, rule=d_rule) 289 290 def disj_rule(m, s, t): 291 return [m.disjunct[0, s, t], m.disjunct[1, s, t]] 292 m.disjunction = Disjunction(m.s, m.t, rule=disj_rule) 293 return m 294 295 296def makeTwoTermDisjOnBlock(): 297 """Two-term SimpleDisjunction on a block""" 298 m = ConcreteModel() 299 m.b = Block() 300 m.a = Var(bounds=(0, 5)) 301 302 @m.b.Disjunct([0, 1]) 303 def disjunct(disjunct, flag): 304 m = disjunct.model() 305 if flag: 306 disjunct.c = Constraint(expr=m.a <= 3) 307 else: 308 disjunct.c = Constraint(expr=m.a == 0) 309 310 @m.b.Disjunction() 311 def disjunction(m): 312 return [m.disjunct[0], m.disjunct[1]] 313 314 return m 315 316def add_disj_not_on_block(m): 317 def simpdisj_rule(disjunct): 318 m = disjunct.model() 319 disjunct.c = Constraint(expr=m.a >= 3) 320 m.simpledisj = Disjunct(rule=simpdisj_rule) 321 def simpledisj2_rule(disjunct): 322 m = disjunct.model() 323 disjunct.c = Constraint(expr=m.a <= 3.5) 324 m.simpledisj2 = Disjunct(rule=simpledisj2_rule) 325 m.disjunction2 = Disjunction(expr=[m.simpledisj, m.simpledisj2]) 326 return m 327 328def makeDisjunctionsOnIndexedBlock(): 329 """Two disjunctions (one indexed an one not), each on a separate 330 BlockData of an IndexedBlock of length 2 331 """ 332 m = ConcreteModel() 333 m.s = Set(initialize=[1, 2]) 334 m.a = Var(m.s, bounds=(0, 70)) 335 336 @m.Disjunct(m.s, [0, 1]) 337 def disjunct1(disjunct, s, flag): 338 m = disjunct.model() 339 if not flag: 340 disjunct.c = Constraint(expr=m.a[s] == 0) 341 else: 342 disjunct.c = Constraint(expr=m.a[s] >= 7) 343 344 def disjunction1_rule(m, s): 345 return [m.disjunct1[s, flag] for flag in [0, 1]] 346 m.disjunction1 = Disjunction(m.s, rule=disjunction1_rule) 347 348 m.b = Block([0, 1]) 349 m.b[0].x = Var(bounds=(-2, 2)) 350 351 def disjunct2_rule(disjunct, flag): 352 if not flag: 353 disjunct.c = Constraint(expr=m.b[0].x <= 0) 354 else: 355 disjunct.c = Constraint(expr=m.b[0].x >= 0) 356 m.b[0].disjunct = Disjunct([0, 1], rule=disjunct2_rule) 357 358 def disjunction(b, i): 359 return [b.disjunct[0], b.disjunct[1]] 360 m.b[0].disjunction = Disjunction([0], rule=disjunction) 361 362 m.b[1].y = Var(bounds=(-3, 3)) 363 m.b[1].disjunct0 = Disjunct() 364 m.b[1].disjunct0.c = Constraint(expr=m.b[1].y <= 0) 365 m.b[1].disjunct1 = Disjunct() 366 m.b[1].disjunct1.c = Constraint(expr=m.b[1].y >= 0) 367 m.b[1].disjunction = Disjunction( 368 expr=[m.b[1].disjunct0, m.b[1].disjunct1]) 369 return m 370 371 372def makeTwoTermDisj_BlockOnDisj(): 373 """SimpleDisjunction where one of the Disjuncts contains three different 374 blocks: two simple and one indexed""" 375 m = ConcreteModel() 376 m.x = Var(bounds=(0, 1000)) 377 m.y = Var(bounds=(0, 800)) 378 379 def disj_rule(d, flag): 380 m = d.model() 381 if flag: 382 d.b = Block() 383 d.b.c = Constraint(expr=m.x == 0) 384 d.add_component('b.c', Constraint(expr=m.y >= 9)) 385 d.b.anotherblock = Block() 386 d.b.anotherblock.c = Constraint(expr=m.y >= 11) 387 d.bb = Block([1]) 388 d.bb[1].c = Constraint(expr=m.x == 0) 389 else: 390 d.c = Constraint(expr=m.x >= 80) 391 m.evil = Disjunct([0, 1], rule=disj_rule) 392 m.disjunction = Disjunction(expr=[m.evil[0], m.evil[1]]) 393 return m 394 395 396def makeNestedDisjunctions(): 397 """Three-term SimpleDisjunction built from two IndexedDisjuncts and one 398 SimpleDisjunct. The SimpleDisjunct and one of the DisjunctDatas each 399 contain a nested SimpleDisjunction (the disjuncts of which are declared 400 on the same disjunct as the disjunction). 401 402 (makeNestedDisjunctions_NestedDisjuncts is a much simpler model. All 403 this adds is that it has a nested disjunction on a DisjunctData as well 404 as on a SimpleDisjunct. So mostly it exists for historical reasons.) 405 """ 406 m = ConcreteModel() 407 m.x = Var(bounds=(-9, 9)) 408 m.z = Var(bounds=(0, 10)) 409 m.a = Var(bounds=(0, 23)) 410 411 def disjunct_rule(disjunct, flag): 412 m = disjunct.model() 413 if flag: 414 def innerdisj_rule(disjunct, flag): 415 m = disjunct.model() 416 if flag: 417 disjunct.c = Constraint(expr=m.z >= 5) 418 else: 419 disjunct.c = Constraint(expr=m.z == 0) 420 disjunct.innerdisjunct = Disjunct([0, 1], rule=innerdisj_rule) 421 422 @disjunct.Disjunction([0]) 423 def innerdisjunction(b, i): 424 return [b.innerdisjunct[0], b.innerdisjunct[1]] 425 disjunct.c = Constraint(expr=m.a <= 2) 426 else: 427 disjunct.c = Constraint(expr=m.x == 2) 428 m.disjunct = Disjunct([0, 1], rule=disjunct_rule) 429 # I want a SimpleDisjunct with a disjunction in it too 430 431 def simpledisj_rule(disjunct): 432 m = disjunct.model() 433 434 @disjunct.Disjunct() 435 def innerdisjunct0(disjunct): 436 disjunct.c = Constraint(expr=m.x <= 2) 437 438 @disjunct.Disjunct() 439 def innerdisjunct1(disjunct): 440 disjunct.c = Constraint(expr=m.x >= 4) 441 442 disjunct.innerdisjunction = Disjunction( 443 expr=[disjunct.innerdisjunct0, disjunct.innerdisjunct1]) 444 m.simpledisjunct = Disjunct(rule=simpledisj_rule) 445 m.disjunction = Disjunction( 446 expr=[m.simpledisjunct, m.disjunct[0], m.disjunct[1]]) 447 return m 448 449 450def makeNestedDisjunctions_FlatDisjuncts(): 451 """Two-term SimpleDisjunction where one of the disjuncts contains a nested 452 SimpleDisjunction, the disjuncts of which are declared on the model""" 453 m = ConcreteModel() 454 m.x = Var(bounds=(0, 2)) 455 m.obj = Objective(expr=m.x) 456 m.d1 = Disjunct() 457 m.d1.c = Constraint(expr=m.x >= 1) 458 m.d2 = Disjunct() 459 m.d2.c = Constraint(expr=m.x >= 1.1) 460 m.d3 = Disjunct() 461 m.d3.c = Constraint(expr=m.x >= 1.2) 462 m.d4 = Disjunct() 463 m.d4.c = Constraint(expr=m.x >= 1.3) 464 m.disj = Disjunction(expr=[m.d1, m.d2]) 465 m.d1.disj = Disjunction(expr=[m.d3, m.d4]) 466 return m 467 468 469def makeNestedDisjunctions_NestedDisjuncts(): 470 """Same as makeNestedDisjunctions_FlatDisjuncts except that the disjuncts 471 of the nested disjunction are declared on the parent disjunct.""" 472 m = ConcreteModel() 473 m.x = Var(bounds=(0, 2)) 474 m.obj = Objective(expr=m.x) 475 m.d1 = Disjunct() 476 m.d1.c = Constraint(expr=m.x >= 1) 477 m.d2 = Disjunct() 478 m.d2.c = Constraint(expr=m.x >= 1.1) 479 m.d1.d3 = Disjunct() 480 m.d1.d3.c = Constraint(expr=m.x >= 1.2) 481 m.d1.d4 = Disjunct() 482 m.d1.d4.c = Constraint(expr=m.x >= 1.3) 483 m.disj = Disjunction(expr=[m.d1, m.d2]) 484 m.d1.disj2 = Disjunction(expr=[m.d1.d3, m.d1.d4]) 485 return m 486 487 488def makeTwoSimpleDisjunctions(): 489 """Two SimpleDisjunctions on the same model.""" 490 m = ConcreteModel() 491 m.a = Var(bounds=(-10, 50)) 492 493 def d1_rule(disjunct, flag): 494 m = disjunct.model() 495 if flag: 496 disjunct.c = Constraint(expr=m.a == 0) 497 else: 498 disjunct.c = Constraint(expr=m.a >= 5) 499 m.disjunct1 = Disjunct([0, 1], rule=d1_rule) 500 501 def d2_rule(disjunct, flag): 502 if not flag: 503 disjunct.c = Constraint(expr=m.a >= 30) 504 else: 505 disjunct.c = Constraint(expr=m.a == 100) 506 m.disjunct2 = Disjunct([0, 1], rule=d2_rule) 507 508 m.disjunction1 = Disjunction(expr=[m.disjunct1[0], m.disjunct1[1]]) 509 m.disjunction2 = Disjunction(expr=[m.disjunct2[0], m.disjunct2[1]]) 510 return m 511 512 513def makeDisjunctInMultipleDisjunctions(): 514 """This is not a transformable model! Two SimpleDisjunctions which have 515 a shared disjunct. 516 """ 517 m = ConcreteModel() 518 m.a = Var(bounds=(-10, 50)) 519 520 def d1_rule(disjunct, flag): 521 m = disjunct.model() 522 if flag: 523 disjunct.c = Constraint(expr=m.a == 0) 524 else: 525 disjunct.c = Constraint(expr=m.a >= 5) 526 m.disjunct1 = Disjunct([0, 1], rule=d1_rule) 527 528 def d2_rule(disjunct, flag): 529 if not flag: 530 disjunct.c = Constraint(expr=m.a >= 30) 531 else: 532 disjunct.c = Constraint(expr=m.a == 100) 533 m.disjunct2 = Disjunct([0, 1], rule=d2_rule) 534 535 m.disjunction1 = Disjunction(expr=[m.disjunct1[0], m.disjunct1[1]]) 536 m.disjunction2 = Disjunction(expr=[m.disjunct2[0], m.disjunct1[1]]) 537 # Deactivate unused disjunct like we are supposed to 538 m.disjunct2[1].deactivate() 539 return m 540 541 542def makeDuplicatedNestedDisjunction(): 543 """Not a transformable model (because of disjuncts shared between 544 disjunctions): A SimpleDisjunction where one of the disjuncts contains 545 two SimpleDisjunctions with the same Disjuncts. 546 """ 547 m = ConcreteModel() 548 m.x = Var(bounds=(0, 8)) 549 550 def outerdisj_rule(d, flag): 551 m = d.model() 552 if flag: 553 def innerdisj_rule(d, flag): 554 m = d.model() 555 if flag: 556 d.c = Constraint(expr=m.x >= 2) 557 else: 558 d.c = Constraint(expr=m.x == 0) 559 d.innerdisjunct = Disjunct([0, 1], rule=innerdisj_rule) 560 d.innerdisjunction = Disjunction(expr=[d.innerdisjunct[0], 561 d.innerdisjunct[1]]) 562 d.duplicateddisjunction = Disjunction(expr=[d.innerdisjunct[0], 563 d.innerdisjunct[1]]) 564 else: 565 d.c = Constraint(expr=m.x == 8) 566 m.outerdisjunct = Disjunct([0, 1], rule=outerdisj_rule) 567 m.disjunction = Disjunction(expr=[m.outerdisjunct[0], 568 m.outerdisjunct[1]]) 569 return m 570 571def makeDisjunctWithRangeSet(): 572 """Two-term SimpleDisjunction where one of the disjuncts contains a 573 RangeSet""" 574 m = ConcreteModel() 575 m.x = Var(bounds=(0, 1)) 576 m.d1 = Disjunct() 577 m.d1.s = RangeSet(1) 578 m.d1.c = Constraint(rule=lambda _: m.x == 1) 579 m.d2 = Disjunct() 580 m.disj = Disjunction(expr=[m.d1, m.d2]) 581 return m 582 583########################## 584# Grossmann lecture models 585########################## 586 587def grossmann_oneDisj(): 588 m = ConcreteModel() 589 m.x = Var(bounds=(0,20)) 590 m.y = Var(bounds=(0, 20)) 591 m.disjunct1 = Disjunct() 592 m.disjunct1.constraintx = Constraint(expr=inequality(0, m.x, 2)) 593 m.disjunct1.constrainty = Constraint(expr=inequality(7, m.y, 10)) 594 595 m.disjunct2 = Disjunct() 596 m.disjunct2.constraintx = Constraint(expr=inequality(8, m.x, 10)) 597 m.disjunct2.constrainty = Constraint(expr=inequality(0, m.y, 3)) 598 599 m.disjunction = Disjunction(expr=[m.disjunct1, m.disjunct2]) 600 601 m.objective = Objective(expr=m.x + 2*m.y, sense=maximize) 602 603 return m 604 605def to_break_constraint_tolerances(): 606 m = ConcreteModel() 607 m.x = Var(bounds=(0, 130)) 608 m.y = Var(bounds=(0, 130)) 609 m.disjunct1 = Disjunct() 610 m.disjunct1.constraintx = Constraint(expr=inequality(0, m.x, 2)) 611 m.disjunct1.constrainty = Constraint(expr=inequality(117, m.y, 127)) 612 613 m.disjunct2 = Disjunct() 614 m.disjunct2.constraintx = Constraint(expr=inequality(118, m.x, 120)) 615 m.disjunct2.constrainty = Constraint(expr=inequality(0, m.y, 3)) 616 617 m.disjunction = Disjunction(expr=[m.disjunct1, m.disjunct2]) 618 619 m.objective = Objective(expr=m.x + 2*m.y, sense=maximize) 620 621 return m 622 623def grossmann_twoDisj(): 624 m = grossmann_oneDisj() 625 626 m.disjunct3 = Disjunct() 627 m.disjunct3.constraintx = Constraint(expr=inequality(1, m.x, 2.5)) 628 m.disjunct3.constrainty = Constraint(expr=inequality(6.5, m.y, 8)) 629 630 m.disjunct4 = Disjunct() 631 m.disjunct4.constraintx = Constraint(expr=inequality(9, m.x, 11)) 632 m.disjunct4.constrainty = Constraint(expr=inequality(2, m.y, 3.5)) 633 634 m.disjunction2 = Disjunction(expr=[m.disjunct3, m.disjunct4]) 635 636 return m 637 638def twoDisj_twoCircles_easy(): 639 m = ConcreteModel() 640 m.x = Var(bounds=(0,8)) 641 m.y = Var(bounds=(0,10)) 642 643 m.upper_circle = Disjunct() 644 m.upper_circle.cons = Constraint(expr=(m.x - 1)**2 + (m.y - 6)**2 <= 2) 645 m.lower_circle = Disjunct() 646 m.lower_circle.cons = Constraint(expr=(m.x - 4)**2 + (m.y - 2)**2 <= 2) 647 648 m.disjunction = Disjunction(expr=[m.upper_circle, m.lower_circle]) 649 650 m.obj = Objective(expr=m.x + m.y, sense=maximize) 651 return m 652 653def fourCircles(): 654 m = twoDisj_twoCircles_easy() 655 656 # and add two more overlapping circles, a la the Grossmann test case with 657 # the rectangles. (but not change my nice integral optimal solution...) 658 m.upper_circle2 = Disjunct() 659 m.upper_circle2.cons = Constraint(expr=(m.x - 2)**2 + (m.y - 7)**2 <= 1) 660 661 m.lower_circle2 = Disjunct() 662 m.lower_circle2.cons = Constraint(expr=(m.x - 5)**2 + (m.y - 3)**2 <= 2) 663 664 m.disjunction2 = Disjunction(expr=[m.upper_circle2, m.lower_circle2]) 665 666 return m 667 668def makeDisjunctWithExpression(): 669 """Two-term SimpleDisjunction where one of the disjuncts contains an 670 Expression. This is used to make sure that we correctly handle types we 671 hit in disjunct.component_objects(active=True)""" 672 m = ConcreteModel() 673 m.x = Var(bounds=(0, 1)) 674 m.d1 = Disjunct() 675 m.d1.e = Expression(expr=m.x**2) 676 m.d1.c = Constraint(rule=lambda _: m.x == 1) 677 m.d2 = Disjunct() 678 m.disj = Disjunction(expr=[m.d1, m.d2]) 679 return m 680 681def makeDisjunctionOfDisjunctDatas(): 682 """Two SimpleDisjunctions, where each are disjunctions of DisjunctDatas. 683 This adds nothing to makeTwoSimpleDisjunctions but exists for convenience 684 because it has the same mathematical meaning as 685 makeAnyIndexedDisjunctionOfDisjunctDatas 686 """ 687 m = ConcreteModel() 688 m.x = Var(bounds=(-100, 100)) 689 690 m.obj = Objective(expr=m.x) 691 692 m.idx = Set(initialize=[1,2]) 693 m.firstTerm = Disjunct(m.idx) 694 m.firstTerm[1].cons = Constraint(expr=m.x == 0) 695 m.firstTerm[2].cons = Constraint(expr=m.x == 2) 696 m.secondTerm = Disjunct(m.idx) 697 m.secondTerm[1].cons = Constraint(expr=m.x >= 2) 698 m.secondTerm[2].cons = Constraint(expr=m.x >= 3) 699 700 m.disjunction = Disjunction(expr=[m.firstTerm[1], m.secondTerm[1]]) 701 m.disjunction2 = Disjunction(expr=[m.firstTerm[2], m.secondTerm[2]]) 702 return m 703 704def makeAnyIndexedDisjunctionOfDisjunctDatas(): 705 """An IndexedDisjunction indexed by Any, with two two-term DisjunctionDatas 706 build from DisjunctDatas. Identical mathematically to 707 makeDisjunctionOfDisjunctDatas. 708 709 Used to test that the right things happen for a case where soemone 710 implements an algorithm which iteratively generates disjuncts and 711 retransforms""" 712 m = ConcreteModel() 713 m.x = Var(bounds=(-100, 100)) 714 715 m.obj = Objective(expr=m.x) 716 717 m.idx = Set(initialize=[1,2]) 718 m.firstTerm = Disjunct(m.idx) 719 m.firstTerm[1].cons = Constraint(expr=m.x == 0) 720 m.firstTerm[2].cons = Constraint(expr=m.x == 2) 721 m.secondTerm = Disjunct(m.idx) 722 m.secondTerm[1].cons = Constraint(expr=m.x >= 2) 723 m.secondTerm[2].cons = Constraint(expr=m.x >= 3) 724 725 m.disjunction = Disjunction(Any) 726 m.disjunction[1] = [m.firstTerm[1], m.secondTerm[1]] 727 m.disjunction[2] = [m.firstTerm[2], m.secondTerm[2]] 728 return m 729 730def makeNetworkDisjunction(minimize=True): 731 """ creates a GDP model with pyomo.network components """ 732 m = ConcreteModel() 733 734 m.feed = feed = Block() 735 m.wkbx = wkbx = Block() 736 m.dest = dest = Block() 737 738 m.orange = orange = Disjunct() 739 m.blue = blue = Disjunct() 740 741 m.orange_or_blue = Disjunction(expr=[orange,blue]) 742 743 blue.blue_box = blue_box = Block() 744 745 feed.x = Var(bounds=(0,1)) 746 wkbx.x = Var(bounds=(0,1)) 747 dest.x = Var(bounds=(0,1)) 748 749 wkbx.inlet = ntwk.Port(initialize={"x":wkbx.x}) 750 wkbx.outlet = ntwk.Port(initialize={"x":wkbx.x}) 751 752 feed.outlet = ntwk.Port(initialize={"x":feed.x}) 753 dest.inlet = ntwk.Port(initialize={"x":dest.x}) 754 755 blue_box.x = Var(bounds=(0,1)) 756 blue_box.x_wkbx = Var(bounds=(0,1)) 757 blue_box.x_dest = Var(bounds=(0,1)) 758 759 760 blue_box.inlet_feed = ntwk.Port(initialize={"x":blue_box.x}) 761 blue_box.outlet_wkbx = ntwk.Port(initialize={"x":blue_box.x}) 762 763 blue_box.inlet_wkbx = ntwk.Port(initialize={"x":blue_box.x_wkbx}) 764 blue_box.outlet_dest = ntwk.Port(initialize={"x":blue_box.x_dest}) 765 766 blue_box.multiplier_constr = Constraint(expr=blue_box.x_dest == 2*blue_box.x_wkbx) 767 768 # orange arcs 769 orange.a1 = ntwk.Arc(source=feed.outlet, destination=wkbx.inlet) 770 orange.a2 = ntwk.Arc(source=wkbx.outlet, destination=dest.inlet) 771 772 # blue arcs 773 blue.a1 = ntwk.Arc(source=feed.outlet, destination=blue_box.inlet_feed) 774 blue.a2 = ntwk.Arc(source=blue_box.outlet_wkbx, destination=wkbx.inlet) 775 blue.a3 = ntwk.Arc(source=wkbx.outlet, destination=blue_box.inlet_wkbx) 776 blue.a4 = ntwk.Arc(source=blue_box.outlet_dest, destination=dest.inlet) 777 778 # maximize/minimize "production" 779 if minimize: 780 m.obj = Objective(expr=m.dest.x) 781 else: 782 m.obj = Objective(expr=m.dest.x, sense=maximize) 783 784 # create a completely fixed model 785 feed.x.fix(0.42) 786 787 return m 788 789def makeExpandedNetworkDisjunction(minimize=True): 790 m = makeNetworkDisjunction(minimize) 791 TransformationFactory('network.expand_arcs').apply_to(m) 792 return m 793 794def makeThreeTermDisjunctionWithOneVarInOneDisjunct(): 795 """This is to make sure hull doesn't create more disaggregated variables 796 than it needs to: Here, x only appears in the first Disjunct, so we only 797 need two copies: one as usual for that disjunct and then one other that is 798 free if either of the second two Disjuncts is active and 0 otherwise. 799 """ 800 m = ConcreteModel() 801 m.x = Var(bounds=(-2,8)) 802 m.y = Var(bounds=(3,4)) 803 m.d1 = Disjunct() 804 m.d1.c1 = Constraint(expr=m.x <= 3) 805 m.d1.c2 = Constraint(expr=m.y >= 3.5) 806 m.d2 = Disjunct() 807 m.d2.c1 = Constraint(expr=m.y >= 3.7) 808 m.d3 = Disjunct() 809 m.d3.c1 = Constraint(expr=m.y >= 3.9) 810 811 m.disjunction = Disjunction(expr=[m.d1, m.d2, m.d3]) 812 813 return m 814