1#  ___________________________________________________________________________
2#
3#  Pyomo: Python Optimization Modeling Objects
4#  Copyright 2017 National Technology and Engineering Solutions of Sandia, LLC
5#  Under the terms of Contract DE-NA0003525 with National Technology and
6#  Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
7#  rights in this software.
8#  This software is distributed under the 3-clause BSD License.
9#  ___________________________________________________________________________
10#
11# Unit Tests for Elements of a Block
12#
13
14from io import StringIO
15import os
16import sys
17import types
18import json
19
20from copy import deepcopy
21from os.path import abspath, dirname, join
22
23currdir = dirname( abspath(__file__) )
24
25import pyomo.common.unittest as unittest
26
27from pyomo.environ import (AbstractModel, ConcreteModel, Var, Set,
28                           Param, Block, Suffix, Constraint, Component,
29                           Objective, Expression, SOSConstraint,
30                           SortComponents, NonNegativeIntegers,
31                           TraversalStrategy, RangeSet, SolverFactory,
32                           value, sum_product)
33from pyomo.common.log import LoggingIntercept
34from pyomo.common.tempfiles import TempfileManager
35from pyomo.core.base.block import ScalarBlock, SubclassOf, _BlockData, declare_custom_block
36from pyomo.core.expr import current as EXPR
37from pyomo.opt import check_available_solvers
38
39from pyomo.gdp import Disjunct
40
41solvers = check_available_solvers('glpk')
42
43class DerivedBlock(ScalarBlock):
44    def __init__(self, *args, **kwargs):
45        """Constructor"""
46        kwargs['ctype'] = DerivedBlock
47        super(DerivedBlock, self).__init__(*args, **kwargs)
48
49    def foo(self):
50        pass
51
52DerivedBlock._Block_reserved_words = set(dir(DerivedBlock()))
53
54
55class TestGenerators(unittest.TestCase):
56
57    @ unittest.nottest
58    def generate_model(self):
59        #
60        # ** DO NOT modify the model below without updating the
61        # component_lists and component_data_lists with the correct
62        # declaration orders
63        #
64
65        model = ConcreteModel()
66        model.q = Set(initialize=[1,2])
67        model.Q = Set(model.q,initialize=[1,2])
68        model.qq = NonNegativeIntegers*model.q
69        model.x = Var(initialize=-1)
70        model.X = Var(model.q,initialize=-1)
71        model.e = Expression(initialize=-1)
72        model.E = Expression(model.q,initialize=-1)
73        model.p = Param(mutable=True,initialize=-1)
74        model.P = Param(model.q,mutable=True,initialize=-1)
75        model.o = Objective(expr=-1)
76        model.O = Objective(model.q, rule=lambda model,i: -1)
77        model.c = Constraint(expr=model.x>=-1)
78        model.C = Constraint(model.q, rule=lambda model,i: model.X[i]>=-1)
79        model.sos = SOSConstraint(var=model.X, index=model.q, sos=1)
80        model.SOS = SOSConstraint(model.q, var=model.X, index=model.Q, sos=1)
81        model.s = Suffix()
82
83        model.b = Block()
84        model.b.q = Set(initialize=[1,2])
85        model.b.Q = Set(model.b.q,initialize=[1,2])
86        model.b.x = Var(initialize=0)
87        model.b.X = Var(model.b.q,initialize=0)
88        model.b.e = Expression(initialize=0)
89        model.b.E = Expression(model.b.q,initialize=0)
90        model.b.p = Param(mutable=True,initialize=0)
91        model.b.P = Param(model.b.q,mutable=True,initialize=0)
92        model.b.o = Objective(expr=0)
93        model.b.O = Objective(model.b.q, rule=lambda b,i: 0)
94        model.b.c = Constraint(expr=model.b.x>=0)
95        model.b.C = Constraint(model.b.q, rule=lambda b,i: b.X[i]>=0)
96        model.b.sos = SOSConstraint(var=model.b.X, index=model.b.q, sos=1)
97        model.b.SOS = SOSConstraint(model.b.q, var=model.b.X, index=model.b.Q, sos=1)
98        model.b.s = Suffix()
99        model.b.component_lists = {}
100        model.b.component_data_lists = {}
101        model.b.component_lists[Set] = [model.b.q, model.b.Q]
102        model.b.component_data_lists[Set] = [model.b.q, model.b.Q[1], model.b.Q[2]]
103        model.b.component_lists[Var] = [model.b.x, model.b.X]
104        model.b.component_data_lists[Var] = [model.b.x, model.b.X[1], model.b.X[2]]
105        model.b.component_lists[Expression] = [model.b.e, model.b.E]
106        model.b.component_data_lists[Expression] = [model.b.e, model.b.E[1], model.b.E[2]]
107        model.b.component_lists[Param] = [model.b.p, model.b.P]
108        model.b.component_data_lists[Param] = [model.b.p, model.b.P[1], model.b.P[2]]
109        model.b.component_lists[Objective] = [model.b.o, model.b.O]
110        model.b.component_data_lists[Objective] = [model.b.o, model.b.O[1], model.b.O[2]]
111        model.b.component_lists[Constraint] = [model.b.c, model.b.C]
112        model.b.component_data_lists[Constraint] = [model.b.c, model.b.C[1], model.b.C[2]]
113        model.b.component_lists[SOSConstraint] = [model.b.sos, model.b.SOS]
114        model.b.component_data_lists[SOSConstraint] = [model.b.sos, model.b.SOS[1], model.b.SOS[2]]
115        model.b.component_lists[Suffix] = [model.b.s]
116        model.b.component_data_lists[Suffix] = [model.b.s]
117        model.b.component_lists[Block] = []
118        model.b.component_data_lists[Block] = []
119
120        def B_rule(block,i):
121            block.q = Set(initialize=[1,2])
122            block.Q = Set(block.q,initialize=[1,2])
123            block.x = Var(initialize=i)
124            block.X = Var(block.q,initialize=i)
125            block.e = Expression(initialize=i)
126            block.E = Expression(block.q,initialize=i)
127            block.p = Param(mutable=True,initialize=i)
128            block.P = Param(block.q,mutable=True,initialize=i)
129            block.o = Objective(expr=i)
130            block.O = Objective(block.q, rule=lambda b,i: i)
131            block.c = Constraint(expr=block.x>=i)
132            block.C = Constraint(block.q, rule=lambda b,i: b.X[i]>=i)
133            block.sos = SOSConstraint(var=block.X, index=block.q, sos=1)
134            block.SOS = SOSConstraint(block.q, var=block.X, index=block.Q, sos=1)
135            block.s = Suffix()
136            block.component_lists = {}
137            block.component_data_lists = {}
138            block.component_lists[Set] = [block.q, block.Q]
139            block.component_data_lists[Set] = [block.q, block.Q[1], block.Q[2]]
140            block.component_lists[Var] = [block.x, block.X]
141            block.component_data_lists[Var] = [block.x, block.X[1], block.X[2]]
142            block.component_lists[Expression] = [block.e, block.E]
143            block.component_data_lists[Expression] = [block.e, block.E[1], block.E[2]]
144            block.component_lists[Param] = [block.p, block.P]
145            block.component_data_lists[Param] = [block.p, block.P[1], block.P[2]]
146            block.component_lists[Objective] = [block.o, block.O]
147            block.component_data_lists[Objective] = [block.o, block.O[1], block.O[2]]
148            block.component_lists[Constraint] = [block.c, block.C]
149            block.component_data_lists[Constraint] = [block.c, block.C[1], block.C[2]]
150            block.component_lists[SOSConstraint] = [block.sos, block.SOS]
151            block.component_data_lists[SOSConstraint] = [block.sos, block.SOS[1], block.SOS[2]]
152            block.component_lists[Suffix] = [block.s]
153            block.component_data_lists[Suffix] = [block.s]
154            block.component_lists[Block] = []
155            block.component_data_lists[Block] = []
156        model.B = Block(model.q,rule=B_rule)
157
158        model.component_lists = {}
159        model.component_data_lists = {}
160        model.component_lists[Set] = [model.q, model.Q, model.qq]
161        model.component_data_lists[Set] = [model.q, model.Q[1], model.Q[2], model.qq]
162        model.component_lists[Var] = [model.x, model.X]
163        model.component_data_lists[Var] = [model.x, model.X[1], model.X[2]]
164        model.component_lists[Expression] = [model.e, model.E]
165        model.component_data_lists[Expression] = [model.e, model.E[1], model.E[2]]
166        model.component_lists[Param] = [model.p, model.P]
167        model.component_data_lists[Param] = [model.p, model.P[1], model.P[2]]
168        model.component_lists[Objective] = [model.o, model.O]
169        model.component_data_lists[Objective] = [model.o, model.O[1], model.O[2]]
170        model.component_lists[Constraint] = [model.c, model.C]
171        model.component_data_lists[Constraint] = [model.c, model.C[1], model.C[2]]
172        model.component_lists[SOSConstraint] = [model.sos, model.SOS]
173        model.component_data_lists[SOSConstraint] = [model.sos, model.SOS[1], model.SOS[2]]
174        model.component_lists[Suffix] = [model.s]
175        model.component_data_lists[Suffix] = [model.s]
176        model.component_lists[Block] = [model.b, model.B]
177        model.component_data_lists[Block] = [model.b, model.B[1], model.B[2]]
178
179        return model
180
181    @unittest.nottest
182    def generator_test(self, ctype):
183
184        model = self.generate_model()
185
186        for block in model.block_data_objects(sort=SortComponents.indices):
187
188            # Non-nested components(active=True)
189            generator = None
190            try:
191                generator = list(block.component_objects(ctype, active=True, descend_into=False))
192            except:
193                if issubclass(ctype, Component):
194                    print("component_objects(active=True) failed with ctype %s" % ctype)
195                    raise
196            else:
197                if not issubclass(ctype, Component):
198                    self.fail("component_objects(active=True) should have failed with ctype %s" % ctype)
199                # This first check is less safe but it gives a cleaner
200                # failure message. I leave comparison of ids in the
201                # second assertEqual to make sure the tests are working
202                # as expected
203                self.assertEqual([comp.name for comp in generator],
204                                 [comp.name for comp in block.component_lists[ctype]])
205                self.assertEqual([id(comp) for comp in generator],
206                                 [id(comp) for comp in block.component_lists[ctype]])
207
208            # Non-nested components
209            generator = None
210            try:
211                generator = list(block.component_objects(ctype, descend_into=False))
212            except:
213                if issubclass(ctype, Component):
214                    print("components failed with ctype %s" % ctype)
215                    raise
216            else:
217                if not issubclass(ctype, Component):
218                    self.fail("components should have failed with ctype %s" % ctype)
219                # This first check is less safe but it gives a cleaner
220                # failure message. I leave comparison of ids in the
221                # second assertEqual to make sure the tests are working
222                # as expected
223                self.assertEqual([comp.name for comp in generator],
224                                 [comp.name for comp in block.component_lists[ctype]])
225                self.assertEqual([id(comp) for comp in generator],
226                                 [id(comp) for comp in block.component_lists[ctype]])
227
228            # Non-nested component_data_objects, active=True, sort_by_keys=False
229            generator = None
230            try:
231                generator = list(block.component_data_iterindex(ctype, active=True, sort=False, descend_into=False))
232            except:
233                if issubclass(ctype, Component):
234                    print("component_data_objects(active=True, sort_by_keys=False) failed with ctype %s" % ctype)
235                    raise
236            else:
237                if not issubclass(ctype, Component):
238                    self.fail("component_data_objects(active=True, sort_by_keys=False) should have failed with ctype %s" % ctype)
239                # This first check is less safe but it gives a cleaner
240                # failure message. I leave comparison of ids in the
241                # second assertEqual to make sure the tests are working
242                # as expected
243                self.assertEqual([comp.name for name, comp in generator],
244                                 [comp.name for comp in block.component_data_lists[ctype]])
245                self.assertEqual([id(comp) for name, comp in generator],
246                                 [id(comp) for comp in block.component_data_lists[ctype]])
247
248            # Non-nested component_data_objects, active=True, sort=True
249            generator = None
250            try:
251                generator = list(block.component_data_iterindex(ctype, active=True, sort=True, descend_into=False))
252            except:
253                if issubclass(ctype, Component):
254                    print("component_data_objects(active=True, sort=True) failed with ctype %s" % ctype)
255                    raise
256            else:
257                if not issubclass(ctype, Component):
258                    self.fail("component_data_objects(active=True, sort=True) should have failed with ctype %s" % ctype)
259                # This first check is less safe but it gives a cleaner
260                # failure message. I leave comparison of ids in the
261                # second assertEqual to make sure the tests are working
262                # as expected
263                self.assertEqual(sorted([comp.name for name, comp in generator]),
264                                 sorted([comp.name for comp in block.component_data_lists[ctype]]))
265                self.assertEqual(sorted([id(comp) for name, comp in generator]),
266                                 sorted([id(comp) for comp in block.component_data_lists[ctype]]))
267
268            # Non-nested components_data, sort_by_keys=True
269            generator = None
270            try:
271                generator = list(block.component_data_iterindex(ctype, sort=False, descend_into=False))
272            except:
273                if issubclass(ctype, Component):
274                    print("components_data(sort_by_keys=True) failed with ctype %s" % ctype)
275                    raise
276            else:
277                if not issubclass(ctype, Component):
278                    self.fail("components_data(sort_by_keys=True) should have failed with ctype %s" % ctype)
279                # This first check is less safe but it gives a cleaner
280                # failure message. I leave comparison of ids in the
281                # second assertEqual to make sure the tests are working
282                # as expected
283                self.assertEqual([comp.name for name, comp in generator],
284                                 [comp.name for comp in block.component_data_lists[ctype]])
285                self.assertEqual([id(comp) for name, comp in generator],
286                                 [id(comp) for comp in block.component_data_lists[ctype]])
287
288            # Non-nested components_data, sort_by_keys=False
289            generator = None
290            try:
291                generator = list(block.component_data_iterindex(ctype, sort=True, descend_into=False))
292            except:
293                if issubclass(ctype, Component):
294                    print("components_data(sort_by_keys=False) failed with ctype %s" % ctype)
295                    raise
296            else:
297                if not issubclass(ctype, Component):
298                    self.fail("components_data(sort_by_keys=False) should have failed with ctype %s" % ctype)
299                # This first check is less safe but it gives a cleaner
300                # failure message. I leave comparison of ids in the
301                # second assertEqual to make sure the tests are working
302                # as expected
303                self.assertEqual(sorted([comp.name for name, comp in generator]),
304                                 sorted([comp.name for comp in block.component_data_lists[ctype]]))
305                self.assertEqual(sorted([id(comp) for name, comp in generator]),
306                                 sorted([id(comp) for comp in block.component_data_lists[ctype]]))
307
308    def test_Objective(self):
309        self.generator_test(Objective)
310
311    def test_Expression(self):
312        self.generator_test(Expression)
313
314    def test_Suffix(self):
315        self.generator_test(Suffix)
316
317    def test_Constraint(self):
318        self.generator_test(Constraint)
319
320    def test_Param(self):
321        self.generator_test(Param)
322
323    def test_Var(self):
324        self.generator_test(Var)
325
326    def test_Set(self):
327        self.generator_test(Set)
328
329    def test_SOSConstraint(self):
330        self.generator_test(SOSConstraint)
331
332    def test_Block(self):
333
334        self.generator_test(Block)
335
336        model = self.generate_model()
337
338        # sorted all_blocks
339        self.assertEqual([id(comp) for comp in model.block_data_objects(sort=SortComponents.deterministic)],
340                         [id(comp) for comp in [model,]+model.component_data_lists[Block]])
341
342        # unsorted all_blocks
343        self.assertEqual(sorted([id(comp) for comp in model.block_data_objects(sort=False)]),
344                         sorted([id(comp) for comp in [model,]+model.component_data_lists[Block]]))
345
346    def test_mixed_index_type(self):
347        m = ConcreteModel()
348        m.I = Set(initialize=[1,'1',3.5,4])
349        m.x = Var(m.I)
350        v = list(m.component_data_objects(Var, sort=True))
351        self.assertEqual(len(v), 4)
352        for a,b in zip([m.x[1], m.x[3.5], m.x[4], m.x['1']], v):
353            self.assertIs(a, b)
354
355
356class HierarchicalModel(object):
357    def __init__(self):
358        m = self.model = ConcreteModel()
359        m.a1_IDX = Set(initialize=[5,4], ordered=True)
360        m.a3_IDX = Set(initialize=[6,7], ordered=True)
361
362        m.c = Block()
363        def x(b, i):
364            pass
365        def a(b, i):
366            if i == 1:
367                b.d = Block()
368                b.c = Block(b.model().a1_IDX, rule=x)
369            elif i == 3:
370                b.e = Block()
371                b.f = Block(b.model().a3_IDX, rule=x)
372        m.a = Block([1,2,3], rule=a)
373        m.b = Block()
374
375        self.PrefixDFS = [
376            'unknown',
377            'c',
378            'a[1]', 'a[1].d', 'a[1].c[5]', 'a[1].c[4]',
379            'a[2]',
380            'a[3]', 'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
381            'b',
382        ]
383
384        self.PrefixDFS_sortIdx = [
385            'unknown',
386            'c',
387            'a[1]', 'a[1].d', 'a[1].c[4]', 'a[1].c[5]',
388            'a[2]',
389            'a[3]', 'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
390            'b',
391        ]
392        self.PrefixDFS_sortName = [
393            'unknown',
394            'a[1]', 'a[1].c[5]', 'a[1].c[4]', 'a[1].d',
395            'a[2]',
396            'a[3]', 'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
397            'b',
398            'c',
399        ]
400        self.PrefixDFS_sort = [
401            'unknown',
402            'a[1]', 'a[1].c[4]', 'a[1].c[5]', 'a[1].d',
403            'a[2]',
404            'a[3]', 'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
405            'b',
406            'c',
407        ]
408
409
410        self.PostfixDFS = [
411            'c',
412            'a[1].d', 'a[1].c[5]', 'a[1].c[4]', 'a[1]',
413            'a[2]',
414            'a[3].e', 'a[3].f[6]', 'a[3].f[7]', 'a[3]',
415            'b',
416            'unknown',
417        ]
418
419        self.PostfixDFS_sortIdx = [
420            'c',
421            'a[1].d', 'a[1].c[4]', 'a[1].c[5]', 'a[1]',
422            'a[2]',
423            'a[3].e', 'a[3].f[6]', 'a[3].f[7]', 'a[3]',
424            'b',
425            'unknown',
426        ]
427        self.PostfixDFS_sortName = [
428            'a[1].c[5]', 'a[1].c[4]', 'a[1].d', 'a[1]',
429            'a[2]',
430            'a[3].e', 'a[3].f[6]', 'a[3].f[7]', 'a[3]',
431            'b',
432            'c',
433            'unknown',
434        ]
435        self.PostfixDFS_sort = [
436            'a[1].c[4]', 'a[1].c[5]', 'a[1].d', 'a[1]',
437            'a[2]',
438            'a[3].e', 'a[3].f[6]', 'a[3].f[7]', 'a[3]',
439            'b',
440            'c',
441            'unknown',
442        ]
443
444        self.BFS = [
445            'unknown',
446            'c',
447            'a[1]', 'a[2]', 'a[3]',
448            'b',
449            'a[1].d', 'a[1].c[5]', 'a[1].c[4]',
450            'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
451        ]
452
453        self.BFS_sortIdx = [
454            'unknown',
455            'c',
456            'a[1]', 'a[2]', 'a[3]',
457            'b',
458            'a[1].d', 'a[1].c[4]', 'a[1].c[5]',
459            'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
460        ]
461        self.BFS_sortName = [
462            'unknown',
463            'a[1]', 'a[2]', 'a[3]',
464            'b',
465            'c',
466            'a[1].c[5]', 'a[1].c[4]', 'a[1].d',
467            'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
468        ]
469        self.BFS_sort = [
470            'unknown',
471            'a[1]', 'a[2]', 'a[3]',
472            'b',
473            'c',
474            'a[1].c[4]', 'a[1].c[5]', 'a[1].d',
475            'a[3].e', 'a[3].f[6]', 'a[3].f[7]',
476        ]
477
478class MixedHierarchicalModel(object):
479    def __init__(self):
480        m = self.model = ConcreteModel()
481        m.a = Block()
482        m.a.c = DerivedBlock()
483        m.b = DerivedBlock()
484        m.b.d = DerivedBlock()
485        m.b.e = Block()
486        m.b.e.f = DerivedBlock()
487        m.b.e.f.g = Block()
488
489        self.PrefixDFS_block = [
490            'unknown',
491            'a',
492        ]
493        self.PostfixDFS_block = [
494            'a',
495            'unknown',
496        ]
497        self.BFS_block = [
498            'unknown',
499            'a',
500        ]
501
502        self.PrefixDFS_both = [
503            'unknown',
504            'a', 'a.c',
505            'b', 'b.d', 'b.e', 'b.e.f', 'b.e.f.g',
506        ]
507        self.PostfixDFS_both = [
508            'a.c', 'a',
509            'b.d', 'b.e.f.g', 'b.e.f', 'b.e', 'b',
510            'unknown',
511        ]
512        self.BFS_both = [
513            'unknown',
514            'a', 'b',
515            'a.c', 'b.d', 'b.e', 'b.e.f', 'b.e.f.g',
516        ]
517
518        #
519        # References for component_objects tests (note: the model
520        # doesn't appear)
521        #
522        self.PrefixDFS_block_subclass = [
523            'a',
524            'b.e',
525            'b.e.f.g',
526        ]
527        self.PostfixDFS_block_subclass = [
528            'b.e.f.g',
529            'b.e',
530            'a',
531        ]
532        self.BFS_block_subclass = [
533            'a',
534            'b.e',
535            'b.e.f.g',
536        ]
537
538class TestBlock(unittest.TestCase):
539
540    def setUp(self):
541        #
542        # Create block
543        #
544        self.block = Block()
545        self.block.construct()
546
547    def tearDown(self):
548        self.block = None
549        if os.path.exists("unknown.lp"):
550            os.unlink("unknown.lp")
551        TempfileManager.clear_tempfiles()
552
553    def test_collect_ctypes(self):
554        b = Block(concrete=True)
555        self.assertEqual(b.collect_ctypes(),
556                         set())
557        self.assertEqual(b.collect_ctypes(active=True),
558                         set())
559        b.x = Var()
560        self.assertEqual(b.collect_ctypes(),
561                         set([Var]))
562        self.assertEqual(b.collect_ctypes(active=True),
563                         set([Var]))
564        b.y = Constraint(expr=b.x >= 1)
565        self.assertEqual(b.collect_ctypes(),
566                         set([Var, Constraint]))
567        self.assertEqual(b.collect_ctypes(active=True),
568                         set([Var, Constraint]))
569        b.y.deactivate()
570        self.assertEqual(b.collect_ctypes(),
571                         set([Var, Constraint]))
572        self.assertEqual(b.collect_ctypes(active=True),
573                         set([Var]))
574        B = Block()
575        B.b = b
576        self.assertEqual(B.collect_ctypes(descend_into=False),
577                         set([Block]))
578        self.assertEqual(B.collect_ctypes(descend_into=False,
579                                          active=True),
580                         set([Block]))
581        self.assertEqual(B.collect_ctypes(),
582                         set([Block, Var, Constraint]))
583        self.assertEqual(B.collect_ctypes(active=True),
584                         set([Block, Var]))
585        b.deactivate()
586        self.assertEqual(B.collect_ctypes(descend_into=False),
587                         set([Block]))
588        self.assertEqual(B.collect_ctypes(descend_into=False,
589                                          active=True),
590                         set([]))
591        self.assertEqual(B.collect_ctypes(),
592                         set([Block, Var, Constraint]))
593        self.assertEqual(B.collect_ctypes(active=True),
594                         set([]))
595        del b.y
596
597        # a block DOES check its own .active flag apparently
598        self.assertEqual(b.collect_ctypes(),
599                         set([Var]))
600        self.assertEqual(b.collect_ctypes(active=True),
601                         set([]))
602        b.activate()
603        self.assertEqual(b.collect_ctypes(),
604                         set([Var]))
605        self.assertEqual(b.collect_ctypes(active=True),
606                         set([Var]))
607
608        del b.x
609        self.assertEqual(b.collect_ctypes(), set())
610        b.x = Var()
611        self.assertEqual(b.collect_ctypes(), set([Var]))
612        b.reclassify_component_type(b.x, Constraint)
613        self.assertEqual(b.collect_ctypes(), set([Constraint]))
614        del b.x
615        self.assertEqual(b.collect_ctypes(), set())
616
617    def test_clear_attribute(self):
618        """ Coverage of the _clear_attribute method """
619        obj = Set()
620        self.block.A = obj
621        self.assertEqual(self.block.A.local_name, "A")
622        self.assertEqual(obj.local_name, "A")
623        self.assertIs(obj, self.block.A)
624
625        obj = Var()
626        self.block.A = obj
627        self.assertEqual(self.block.A.local_name, "A")
628        self.assertEqual(obj.local_name, "A")
629        self.assertIs(obj, self.block.A)
630
631        obj = Param()
632        self.block.A = obj
633        self.assertEqual(self.block.A.local_name, "A")
634        self.assertEqual(obj.local_name, "A")
635        self.assertIs(obj, self.block.A)
636
637        obj = Objective()
638        self.block.A = obj
639        self.assertEqual(self.block.A.local_name, "A")
640        self.assertEqual(obj.local_name, "A")
641        self.assertIs(obj, self.block.A)
642
643        obj = Constraint()
644        self.block.A = obj
645        self.assertEqual(self.block.A.local_name, "A")
646        self.assertEqual(obj.local_name, "A")
647        self.assertIs(obj, self.block.A)
648
649        obj = Set()
650        self.block.A = obj
651        self.assertEqual(self.block.A.local_name, "A")
652        self.assertEqual(obj.local_name, "A")
653        self.assertIs(obj, self.block.A)
654
655    def test_set_attr(self):
656        p = Param(mutable=True)
657        self.block.x = p
658        self.block.x = 5
659        self.assertEqual(value(self.block.x), 5)
660        self.assertEqual(value(p), 5)
661        self.block.x = 6
662        self.assertEqual(value(self.block.x), 6)
663        self.assertEqual(value(p), 6)
664        self.block.x = None
665        self.assertEqual(self.block.x._value, None)
666
667        ### creation of a circular reference
668        b = Block(concrete=True)
669        b.c = Block()
670        with self.assertRaisesRegex(
671                ValueError, "Cannot assign the top-level block as a subblock "
672                r"of one of its children \(c\): creates a circular hierarchy"):
673            b.c.d = b
674
675    def test_set_value(self):
676        b = Block(concrete=True)
677        with self.assertRaisesRegex(
678                RuntimeError, "Block components do not support assignment "
679                "or set_value"):
680            b.set_value(None)
681
682        b.b = Block()
683        with self.assertRaisesRegex(
684                RuntimeError, "Block components do not support assignment "
685                "or set_value"):
686            b.b = 5
687
688    def test_clear(self):
689        class DerivedBlock(ScalarBlock):
690            _Block_reserved_words = None
691
692        DerivedBlock._Block_reserved_words \
693            = set(['a','b','c']) | _BlockData._Block_reserved_words
694
695        m = ConcreteModel()
696        m.clear()
697        self.assertEqual(m._ctypes, {})
698        self.assertEqual(m._decl, {})
699        self.assertEqual(m._decl_order, [])
700
701        m.w = 5
702        m.x = Var()
703        m.y = Param()
704        m.z = Var()
705        m.clear()
706        self.assertFalse(hasattr(m, 'w'))
707        self.assertEqual(m._ctypes, {})
708        self.assertEqual(m._decl, {})
709        self.assertEqual(m._decl_order, [])
710
711        m.b = DerivedBlock()
712        m.b.a = a = Param()
713        m.b.x = Var()
714        m.b.b = b = Var()
715        m.b.y = Var()
716        m.b.z = Param()
717        m.b.c = c = Param()
718        m.b.clear()
719        self.assertEqual(m.b._ctypes, {Var: [1, 1, 1], Param:[0,2,2]})
720        self.assertEqual(m.b._decl, {'a':0, 'b':1, 'c':2})
721        self.assertEqual(len(m.b._decl_order), 3)
722        self.assertIs(m.b._decl_order[0][0], a)
723        self.assertIs(m.b._decl_order[1][0], b)
724        self.assertIs(m.b._decl_order[2][0], c)
725        self.assertEqual(m.b._decl_order[0][1], 2)
726        self.assertEqual(m.b._decl_order[1][1], None)
727        self.assertEqual(m.b._decl_order[2][1], None)
728
729    def test_transfer_attributes_from(self):
730        b = Block(concrete=True)
731        b.x = Var()
732        b.y = Var()
733        c = Block(concrete=True)
734        c.z = Param(initialize=5)
735        c.x = c_x = Param(initialize=5)
736        c.y = c_y = 5
737
738        b.clear()
739        b.transfer_attributes_from(c)
740        self.assertEqual(list(b.component_map()), ['z','x'])
741        self.assertEqual(list(c.component_map()), [])
742        self.assertIs(b.x, c_x)
743        self.assertIs(b.y, c_y)
744
745        class DerivedBlock(ScalarBlock):
746            _Block_reserved_words = set()
747            def __init__(self, *args, **kwds):
748                super(DerivedBlock, self).__init__(*args, **kwds)
749                self.x = Var()
750                self.y = Var()
751        DerivedBlock._Block_reserved_words = set(dir(DerivedBlock()))
752
753        b = DerivedBlock(concrete=True)
754        b_x = b.x
755        b_y = b.y
756        c = Block(concrete=True)
757        c.z = Param(initialize=5)
758        c.x = c_x = Param(initialize=5)
759        c.y = c_y = 5
760
761        b.clear()
762        b.transfer_attributes_from(c)
763        self.assertEqual(list(b.component_map()), ['y','z','x'])
764        self.assertEqual(list(c.component_map()), [])
765        self.assertIs(b.x, c_x)
766        self.assertIsNot(b.y, c_y)
767        self.assertIs(b.y, b_y)
768        self.assertEqual(value(b.y), value(c_y))
769
770        ### assignment of dict
771        b = DerivedBlock(concrete=True)
772        b_x = b.x
773        b_y = b.y
774        c = { 'z': Param(initialize=5),
775              'x': Param(initialize=5),
776              'y': 5 }
777
778        b.clear()
779        b.transfer_attributes_from(c)
780        self.assertEqual(list(b.component_map()), ['y','x','z'])
781        self.assertEqual(sorted(list(c.keys())), ['x','y','z'])
782        self.assertIs(b.x, c['x'])
783        self.assertIsNot(b.y, c['y'])
784        self.assertIs(b.y, b_y)
785        self.assertEqual(value(b.y), value(c_y))
786
787        ### assignment of self
788        b = Block(concrete=True)
789        b.x = b_x = Var()
790        b.y = b_y = Var()
791        b.transfer_attributes_from(b)
792
793        self.assertEqual(list(b.component_map()), ['x','y'])
794        self.assertIs(b.x, b_x)
795        self.assertIs(b.y, b_y)
796
797        ### creation of a circular reference
798        b = Block(concrete=True)
799        b.c = Block()
800        b.c.d = Block()
801        b.c.d.e = Block()
802        with self.assertRaisesRegex(
803                ValueError, r'_BlockData.transfer_attributes_from\(\): '
804                r'Cannot set a sub-block \(c.d.e\) to a parent block \(c\):'):
805            b.c.d.e.transfer_attributes_from(b.c)
806
807        ### bad data type
808        b = Block(concrete=True)
809        with self.assertRaisesRegex(
810                ValueError,
811                r'_BlockData.transfer_attributes_from\(\): expected a Block '
812                'or dict; received str'):
813            b.transfer_attributes_from('foo')
814
815    def test_iterate_hierarchy_defaults(self):
816        self.assertIs( TraversalStrategy.BFS,
817                       TraversalStrategy.BreadthFirstSearch )
818
819        self.assertIs( TraversalStrategy.DFS,
820                       TraversalStrategy.PrefixDepthFirstSearch )
821        self.assertIs( TraversalStrategy.DFS,
822                       TraversalStrategy.PrefixDFS )
823        self.assertIs( TraversalStrategy.DFS,
824                       TraversalStrategy.ParentFirstDepthFirstSearch )
825
826        self.assertIs( TraversalStrategy.PostfixDepthFirstSearch,
827                       TraversalStrategy.PostfixDFS )
828        self.assertIs( TraversalStrategy.PostfixDepthFirstSearch,
829                       TraversalStrategy.ParentLastDepthFirstSearch )
830
831        HM = HierarchicalModel()
832        m = HM.model
833        result = [x.name for x in m._tree_iterator()]
834        self.assertEqual(HM.PrefixDFS, result)
835
836    def test_iterate_hierarchy_PrefixDFS(self):
837        HM = HierarchicalModel()
838        m = HM.model
839        result = [x.name for x in m._tree_iterator(
840            traversal=TraversalStrategy.PrefixDepthFirstSearch)]
841        self.assertEqual(HM.PrefixDFS, result)
842
843    def test_iterate_hierarchy_PrefixDFS_sortIndex(self):
844        HM = HierarchicalModel()
845        m = HM.model
846        result = [x.name for x in m._tree_iterator(
847            traversal=TraversalStrategy.PrefixDepthFirstSearch,
848            sort=SortComponents.indices,
849        )]
850        self.assertEqual(HM.PrefixDFS_sortIdx, result)
851    def test_iterate_hierarchy_PrefixDFS_sortName(self):
852        HM = HierarchicalModel()
853        m = HM.model
854        result = [x.name for x in m._tree_iterator(
855            traversal=TraversalStrategy.PrefixDepthFirstSearch,
856            sort=SortComponents.alphaOrder,
857        )]
858        self.assertEqual(HM.PrefixDFS_sortName, result)
859    def test_iterate_hierarchy_PrefixDFS_sort(self):
860        HM = HierarchicalModel()
861        m = HM.model
862        result = [x.name for x in m._tree_iterator(
863            traversal=TraversalStrategy.PrefixDepthFirstSearch,
864            sort=True
865        )]
866        self.assertEqual(HM.PrefixDFS_sort, result)
867
868
869    def test_iterate_hierarchy_PostfixDFS(self):
870        HM = HierarchicalModel()
871        m = HM.model
872        result = [x.name for x in m._tree_iterator(
873            traversal=TraversalStrategy.PostfixDepthFirstSearch)]
874        self.assertEqual(HM.PostfixDFS, result)
875
876    def test_iterate_hierarchy_PostfixDFS_sortIndex(self):
877        HM = HierarchicalModel()
878        m = HM.model
879        result = [x.name for x in m._tree_iterator(
880            traversal=TraversalStrategy.PostfixDepthFirstSearch,
881            sort=SortComponents.indices,
882        )]
883        self.assertEqual(HM.PostfixDFS_sortIdx, result)
884    def test_iterate_hierarchy_PostfixDFS_sortName(self):
885        HM = HierarchicalModel()
886        m = HM.model
887        result = [x.name for x in m._tree_iterator(
888            traversal=TraversalStrategy.PostfixDepthFirstSearch,
889            sort=SortComponents.alphaOrder,
890        )]
891        self.assertEqual(HM.PostfixDFS_sortName, result)
892    def test_iterate_hierarchy_PostfixDFS_sort(self):
893        HM = HierarchicalModel()
894        m = HM.model
895        result = [x.name for x in m._tree_iterator(
896            traversal=TraversalStrategy.PostfixDepthFirstSearch,
897            sort=True
898        )]
899        self.assertEqual(HM.PostfixDFS_sort, result)
900
901    def test_iterate_hierarchy_BFS(self):
902        HM = HierarchicalModel()
903        m = HM.model
904        result = [x.name for x in m._tree_iterator(
905            traversal=TraversalStrategy.BreadthFirstSearch)]
906        self.assertEqual(HM.BFS, result)
907
908    def test_iterate_hierarchy_BFS_sortIndex(self):
909        HM = HierarchicalModel()
910        m = HM.model
911        result = [x.name for x in m._tree_iterator(
912            traversal=TraversalStrategy.BreadthFirstSearch,
913            sort=SortComponents.indices,
914        )]
915        self.assertEqual(HM.BFS_sortIdx, result)
916
917    def test_iterate_hierarchy_BFS_sortName(self):
918        HM = HierarchicalModel()
919        m = HM.model
920        result = [x.name for x in m._tree_iterator(
921            traversal=TraversalStrategy.BreadthFirstSearch,
922            sort=SortComponents.alphaOrder,
923        )]
924        self.assertEqual(HM.BFS_sortName, result)
925
926    def test_iterate_hierarchy_BFS_sort(self):
927        HM = HierarchicalModel()
928        m = HM.model
929        result = [x.name for x in m._tree_iterator(
930            traversal=TraversalStrategy.BreadthFirstSearch,
931            sort=True
932        )]
933        self.assertEqual(HM.BFS_sort, result)
934
935    def test_iterate_mixed_hierarchy_PrefixDFS_block(self):
936        HM = MixedHierarchicalModel()
937        m = HM.model
938        result = [x.name for x in m._tree_iterator(
939            traversal=TraversalStrategy.PrefixDepthFirstSearch,
940            ctype=Block,
941        )]
942        self.assertEqual(HM.PrefixDFS_block, result)
943    def test_iterate_mixed_hierarchy_PrefixDFS_both(self):
944        HM = MixedHierarchicalModel()
945        m = HM.model
946        result = [x.name for x in m._tree_iterator(
947            traversal=TraversalStrategy.PrefixDepthFirstSearch,
948            ctype=(Block,DerivedBlock),
949        )]
950        self.assertEqual(HM.PrefixDFS_both, result)
951    def test_iterate_mixed_hierarchy_PrefixDFS_SubclassOf(self):
952        HM = MixedHierarchicalModel()
953        m = HM.model
954        result = [x.name for x in m._tree_iterator(
955            traversal=TraversalStrategy.PrefixDepthFirstSearch,
956            ctype=SubclassOf(Block),
957        )]
958        self.assertEqual(HM.PrefixDFS_both, result)
959        result = [x.name for x in m.component_objects(
960            ctype=Block,
961            descent_order=TraversalStrategy.PrefixDepthFirstSearch,
962            descend_into=SubclassOf(Block),
963        )]
964        self.assertEqual(HM.PrefixDFS_block_subclass, result)
965        result = [x.name for x in m.component_objects(
966            ctype=Block,
967            descent_order=TraversalStrategy.PrefixDepthFirstSearch,
968            descend_into=SubclassOf(Var,Block),
969        )]
970        self.assertEqual(HM.PrefixDFS_block_subclass, result)
971
972    def test_iterate_mixed_hierarchy_PostfixDFS_block(self):
973        HM = MixedHierarchicalModel()
974        m = HM.model
975        result = [x.name for x in m._tree_iterator(
976            traversal=TraversalStrategy.PostfixDepthFirstSearch,
977            ctype=Block,
978        )]
979        self.assertEqual(HM.PostfixDFS_block, result)
980    def test_iterate_mixed_hierarchy_PostfixDFS_both(self):
981        HM = MixedHierarchicalModel()
982        m = HM.model
983        result = [x.name for x in m._tree_iterator(
984            traversal=TraversalStrategy.PostfixDepthFirstSearch,
985            ctype=(Block,DerivedBlock),
986        )]
987        self.assertEqual(HM.PostfixDFS_both, result)
988    def test_iterate_mixed_hierarchy_PostfixDFS_SubclassOf(self):
989        HM = MixedHierarchicalModel()
990        m = HM.model
991        result = [x.name for x in m._tree_iterator(
992            traversal=TraversalStrategy.PostfixDepthFirstSearch,
993            ctype=SubclassOf(Block),
994        )]
995        self.assertEqual(HM.PostfixDFS_both, result)
996        result = [x.name for x in m.component_objects(
997            ctype=Block,
998            descent_order=TraversalStrategy.PostfixDepthFirstSearch,
999            descend_into=SubclassOf(Block),
1000        )]
1001        self.assertEqual(HM.PostfixDFS_block_subclass, result)
1002        result = [x.name for x in m.component_objects(
1003            ctype=Block,
1004            descent_order=TraversalStrategy.PostfixDepthFirstSearch,
1005            descend_into=SubclassOf(Var,Block),
1006        )]
1007        self.assertEqual(HM.PostfixDFS_block_subclass, result)
1008
1009    def test_iterate_mixed_hierarchy_BFS_block(self):
1010        HM = MixedHierarchicalModel()
1011        m = HM.model
1012        result = [x.name for x in m._tree_iterator(
1013            traversal=TraversalStrategy.BFS,
1014            ctype=Block,
1015        )]
1016        self.assertEqual(HM.BFS_block, result)
1017    def test_iterate_mixed_hierarchy_BFS_both(self):
1018        HM = MixedHierarchicalModel()
1019        m = HM.model
1020        result = [x.name for x in m._tree_iterator(
1021            traversal=TraversalStrategy.BFS,
1022            ctype=(Block,DerivedBlock),
1023        )]
1024        self.assertEqual(HM.BFS_both, result)
1025    def test_iterate_mixed_hierarchy_BFS_SubclassOf(self):
1026        HM = MixedHierarchicalModel()
1027        m = HM.model
1028        result = [x.name for x in m._tree_iterator(
1029            traversal=TraversalStrategy.BFS,
1030            ctype=SubclassOf(Block),
1031        )]
1032        self.assertEqual(HM.BFS_both, result)
1033        result = [x.name for x in m.component_objects(
1034            ctype=Block,
1035            descent_order=TraversalStrategy.BFS,
1036            descend_into=SubclassOf(Block),
1037        )]
1038        self.assertEqual(HM.BFS_block_subclass, result)
1039        result = [x.name for x in m.component_objects(
1040            ctype=Block,
1041            descent_order=TraversalStrategy.BFS,
1042            descend_into=SubclassOf(Var,Block),
1043        )]
1044        self.assertEqual(HM.BFS_block_subclass, result)
1045
1046
1047    def test_add_remove_component_byname(self):
1048        m = Block()
1049        self.assertFalse(m.contains_component(Var))
1050        self.assertFalse(m.component_map(Var))
1051
1052        m.x = x = Var()
1053        self.assertTrue(m.contains_component(Var))
1054        self.assertTrue(m.component_map(Var))
1055        self.assertTrue('x' in m.__dict__)
1056        self.assertIs(m.component('x'), x)
1057
1058        m.del_component('x')
1059        self.assertFalse(m.contains_component(Var))
1060        self.assertFalse(m.component_map(Var))
1061        self.assertFalse('x' in m.__dict__)
1062        self.assertIs(m.component('x'), None)
1063
1064    def test_add_remove_component_byref(self):
1065        m = Block()
1066        self.assertFalse(m.contains_component(Var))
1067        self.assertFalse(m.component_map(Var))
1068
1069        m.x = x = Var()
1070        self.assertTrue(m.contains_component(Var))
1071        self.assertTrue(m.component_map(Var))
1072        self.assertTrue('x' in m.__dict__)
1073        self.assertIs(m.component('x'), x)
1074
1075        m.del_component(m.x)
1076        self.assertFalse(m.contains_component(Var))
1077        self.assertFalse(m.component_map(Var))
1078        self.assertFalse('x' in m.__dict__)
1079        self.assertIs(m.component('x'), None)
1080
1081    def test_add_del_component(self):
1082        m = Block()
1083        self.assertFalse(m.contains_component(Var))
1084        m.x = x = Var()
1085        self.assertTrue(m.contains_component(Var))
1086        self.assertTrue('x' in m.__dict__)
1087        self.assertIs(m.component('x'), x)
1088        del m.x
1089        self.assertFalse(m.contains_component(Var))
1090        self.assertFalse('x' in m.__dict__)
1091        self.assertIs(m.component('x'), None)
1092
1093    def test_reclassify_component(self):
1094        m = Block()
1095        m.a = Var()
1096        m.b = Var()
1097        m.c = Param()
1098
1099        self.assertEqual(len(m.component_map(Var)), 2)
1100        self.assertEqual(len(m.component_map(Param)), 1)
1101        self.assertEqual( ['a', 'b'], list(m.component_map(Var)) )
1102        self.assertEqual( ['c'], list(m.component_map(Param)) )
1103
1104        # Test removing from the end of a list and appending to the beginning
1105        # of a list
1106        m.reclassify_component_type(m.b, Param)
1107        self.assertEqual(len(m.component_map(Var)), 1)
1108        self.assertEqual(len(m.component_map(Param)), 2)
1109        self.assertEqual( ['a'], list(m.component_map(Var)) )
1110        self.assertEqual( ['b','c'], list(m.component_map(Param)) )
1111
1112        # Test removing from the beginning of a list and appending to
1113        # the end of a list
1114        m.reclassify_component_type(m.b, Var)
1115        self.assertEqual(len(m.component_map(Var)), 2)
1116        self.assertEqual(len(m.component_map(Param)), 1)
1117        self.assertEqual( ['a','b'], list(m.component_map(Var)) )
1118        self.assertEqual( ['c'], list(m.component_map(Param)) )
1119
1120        # Test removing the last element of a list and creating a new list
1121        m.reclassify_component_type(m.c, Var)
1122        self.assertEqual(len(m.component_map(Var)), 3)
1123        self.assertEqual(len(m.component_map(Param)), 0)
1124        self.assertTrue(m.contains_component(Var))
1125        self.assertFalse(m.contains_component(Param))
1126        self.assertFalse(m.contains_component(Constraint))
1127        self.assertEqual( ['a','b','c'], list(m.component_map(Var)) )
1128        self.assertEqual( [], list(m.component_map(Param)) )
1129
1130        # Test removing the last element of a list and creating a new list
1131        m.reclassify_component_type(m.c, Param)
1132        self.assertEqual(len(m.component_map(Var)), 2)
1133        self.assertEqual(len(m.component_map(Param)), 1)
1134        self.assertEqual(len(m.component_map(Constraint)), 0)
1135        self.assertTrue(m.contains_component(Var))
1136        self.assertTrue(m.contains_component(Param))
1137        self.assertFalse(m.contains_component(Constraint))
1138        self.assertEqual( ['a','b'], list(m.component_map(Var)) )
1139        self.assertEqual( ['c'], list(m.component_map(Param)) )
1140
1141        # Test removing the first element of a list and creating a new list
1142        m.reclassify_component_type(m.a, Constraint)
1143        self.assertEqual(len(m.component_map(Var)), 1)
1144        self.assertEqual(len(m.component_map(Param)), 1)
1145        self.assertEqual(len(m.component_map(Constraint)), 1)
1146        self.assertTrue(m.contains_component(Var))
1147        self.assertTrue(m.contains_component(Param))
1148        self.assertTrue(m.contains_component(Constraint))
1149        self.assertEqual( ['b'], list(m.component_map(Var)) )
1150        self.assertEqual( ['c'], list(m.component_map(Param)) )
1151        self.assertEqual( ['a'], list(m.component_map(Constraint)) )
1152
1153        # Test removing the last element of a list and inserting it into
1154        # the middle of new list
1155        m.reclassify_component_type(m.a, Param)
1156        m.reclassify_component_type(m.b, Param)
1157        self.assertEqual(len(m.component_map(Var)), 0)
1158        self.assertEqual(len(m.component_map(Param)), 3)
1159        self.assertEqual(len(m.component_map(Constraint)), 0)
1160        self.assertFalse(m.contains_component(Var))
1161        self.assertTrue(m.contains_component(Param))
1162        self.assertFalse(m.contains_component(Constraint))
1163        self.assertEqual( [], list(m.component_map(Var)) )
1164        self.assertEqual( ['a','b','c'], list(m.component_map(Param)) )
1165        self.assertEqual( [], list(m.component_map(Constraint)) )
1166
1167        # Test idnoring decl order
1168        m.reclassify_component_type( 'b', Var,
1169                                        preserve_declaration_order=False )
1170        m.reclassify_component_type( 'c', Var,
1171                                        preserve_declaration_order=False )
1172        m.reclassify_component_type( 'a', Var,
1173                                        preserve_declaration_order=False )
1174        self.assertEqual(len(m.component_map(Var)), 3)
1175        self.assertEqual(len(m.component_map(Param)), 0)
1176        self.assertEqual(len(m.component_map(Constraint)), 0)
1177        self.assertTrue(m.contains_component(Var))
1178        self.assertFalse(m.contains_component(Param))
1179        self.assertFalse(m.contains_component(Constraint))
1180        self.assertEqual( ['b','c','a'], list(m.component_map(Var)) )
1181        self.assertEqual( [], list(m.component_map(Param)) )
1182        self.assertEqual( [], list(m.component_map(Constraint)) )
1183
1184    def test_replace_attribute_with_component(self):
1185        OUTPUT = StringIO()
1186        with LoggingIntercept(OUTPUT, 'pyomo.core'):
1187            self.block.x = 5
1188            self.block.x = Var()
1189        self.assertIn('Reassigning the non-component attribute',
1190                      OUTPUT.getvalue())
1191
1192    def test_replace_component_with_component(self):
1193        OUTPUT = StringIO()
1194        with LoggingIntercept(OUTPUT, 'pyomo.core'):
1195            self.block.x = Var()
1196            self.block.x = Var()
1197        self.assertIn('Implicitly replacing the Component attribute',
1198                      OUTPUT.getvalue())
1199
1200    def test_pseudomap_len(self):
1201        m = Block()
1202        m.a = Constraint()
1203        m.b = Constraint() # active=False
1204        m.c = Constraint()
1205        m.z = Objective() # active=False
1206        m.x = Objective()
1207        m.v = Objective()
1208        m.y = Objective()
1209        m.w = Objective() # active=False
1210
1211        m.b.deactivate()
1212        m.z.deactivate()
1213        m.w.deactivate()
1214
1215        self.assertEqual(len(m.component_map()), 8)
1216        self.assertEqual(len(m.component_map(active=True)), 5)
1217        self.assertEqual(len(m.component_map(active=False)), 3)
1218
1219        self.assertEqual(len(m.component_map(Constraint)), 3)
1220        self.assertEqual(len(m.component_map(Constraint, active=True)), 2)
1221        self.assertEqual(len(m.component_map(Constraint, active=False)), 1)
1222
1223        self.assertEqual(len(m.component_map(Objective)), 5)
1224        self.assertEqual(len(m.component_map(Objective, active=True)), 3)
1225        self.assertEqual(len(m.component_map(Objective, active=False)), 2)
1226
1227    def test_pseudomap_contains(self):
1228        m = Block()
1229        m.a = Constraint()
1230        m.b = Constraint() # active=False
1231        m.c = Constraint()
1232        m.s = Set()
1233        m.t = Suffix()
1234        m.z = Objective() # active=False
1235        m.x = Objective()
1236        m.b.deactivate()
1237        m.z.deactivate()
1238
1239        pm = m.component_map()
1240        self.assertTrue('a' in pm)
1241        self.assertTrue('b' in pm)
1242        self.assertTrue('c' in pm)
1243        self.assertTrue('d' not in pm)
1244        self.assertTrue('s' in pm)
1245        self.assertTrue('t' in pm)
1246        self.assertTrue('x' in pm)
1247        self.assertTrue('z' in pm)
1248
1249        pm = m.component_map(active=True)
1250        self.assertTrue('a' in pm)
1251        self.assertTrue('b' not in pm)
1252        self.assertTrue('c' in pm)
1253        self.assertTrue('d' not in pm)
1254        self.assertTrue('s' in pm)
1255        self.assertTrue('t' in pm)
1256        self.assertTrue('x' in pm)
1257        self.assertTrue('z' not in pm)
1258
1259        pm = m.component_map(active=False)
1260        self.assertTrue('a' not in pm)
1261        self.assertTrue('b' in pm)
1262        self.assertTrue('c' not in pm)
1263        self.assertTrue('d' not in pm)
1264        self.assertTrue('s' not in pm)
1265        self.assertTrue('t' not in pm)
1266        self.assertTrue('x' not in pm)
1267        self.assertTrue('z' in pm)
1268
1269
1270        pm = m.component_map(Constraint)
1271        self.assertTrue('a' in pm)
1272        self.assertTrue('b' in pm)
1273        self.assertTrue('c' in pm)
1274        self.assertTrue('d' not in pm)
1275        self.assertTrue('x' not in pm)
1276        self.assertTrue('z' not in pm)
1277
1278        pm = m.component_map(Constraint, active=True)
1279        self.assertTrue('a' in pm)
1280        self.assertTrue('b' not in pm)
1281        self.assertTrue('c' in pm)
1282        self.assertTrue('d' not in pm)
1283        self.assertTrue('x' not in pm)
1284        self.assertTrue('z' not in pm)
1285
1286        pm = m.component_map(Constraint, active=False)
1287        self.assertTrue('a' not in pm)
1288        self.assertTrue('b' in pm)
1289        self.assertTrue('c' not in pm)
1290        self.assertTrue('d' not in pm)
1291        self.assertTrue('x' not in pm)
1292        self.assertTrue('z' not in pm)
1293
1294
1295        pm = m.component_map([Constraint,Objective])
1296        self.assertTrue('a' in pm)
1297        self.assertTrue('b' in pm)
1298        self.assertTrue('c' in pm)
1299        self.assertTrue('d' not in pm)
1300        self.assertTrue('s' not in pm)
1301        self.assertTrue('t' not in pm)
1302        self.assertTrue('x' in pm)
1303        self.assertTrue('z' in pm)
1304
1305        pm = m.component_map([Constraint,Objective], active=True)
1306        self.assertTrue('a' in pm)
1307        self.assertTrue('b' not in pm)
1308        self.assertTrue('c' in pm)
1309        self.assertTrue('d' not in pm)
1310        self.assertTrue('s' not in pm)
1311        self.assertTrue('t' not in pm)
1312        self.assertTrue('x' in pm)
1313        self.assertTrue('z' not in pm)
1314
1315        pm = m.component_map([Constraint,Objective], active=False)
1316        self.assertTrue('a' not in pm)
1317        self.assertTrue('b' in pm)
1318        self.assertTrue('c' not in pm)
1319        self.assertTrue('d' not in pm)
1320        self.assertTrue('s' not in pm)
1321        self.assertTrue('t' not in pm)
1322        self.assertTrue('x' not in pm)
1323        self.assertTrue('z' in pm)
1324
1325
1326        # You should be able to pass in a set as well as a list
1327        pm = m.component_map(set([Constraint,Objective]))
1328        self.assertTrue('a' in pm)
1329        self.assertTrue('b' in pm)
1330        self.assertTrue('c' in pm)
1331        self.assertTrue('d' not in pm)
1332        self.assertTrue('s' not in pm)
1333        self.assertTrue('t' not in pm)
1334        self.assertTrue('x' in pm)
1335        self.assertTrue('z' in pm)
1336
1337        pm = m.component_map(set([Constraint,Objective]), active=True)
1338        self.assertTrue('a' in pm)
1339        self.assertTrue('b' not in pm)
1340        self.assertTrue('c' in pm)
1341        self.assertTrue('d' not in pm)
1342        self.assertTrue('s' not in pm)
1343        self.assertTrue('t' not in pm)
1344        self.assertTrue('x' in pm)
1345        self.assertTrue('z' not in pm)
1346
1347        pm = m.component_map(set([Constraint,Objective]), active=False)
1348        self.assertTrue('a' not in pm)
1349        self.assertTrue('b' in pm)
1350        self.assertTrue('c' not in pm)
1351        self.assertTrue('d' not in pm)
1352        self.assertTrue('s' not in pm)
1353        self.assertTrue('t' not in pm)
1354        self.assertTrue('x' not in pm)
1355        self.assertTrue('z' in pm)
1356
1357
1358    def test_pseudomap_getitem(self):
1359        m = Block()
1360        m.a = a = Constraint()
1361        m.b = b = Constraint() # active=False
1362        m.c = c = Constraint()
1363        m.s = s = Set()
1364        m.t = t = Suffix()
1365        m.z = z = Objective() # active=False
1366        m.x = x = Objective()
1367        m.b.deactivate()
1368        m.z.deactivate()
1369
1370        def assertWorks(self, key, pm):
1371            self.assertIs(pm[key.local_name], key)
1372        def assertFails(self, key, pm):
1373            if not isinstance(key, str):
1374                key = key.local_name
1375            self.assertRaises(KeyError, pm.__getitem__, key)
1376
1377        pm = m.component_map()
1378        assertWorks(self, a, pm)
1379        assertWorks(self, b, pm)
1380        assertWorks(self, c, pm)
1381        assertFails(self, 'd', pm)
1382        assertWorks(self, s, pm)
1383        assertWorks(self, t, pm)
1384        assertWorks(self, x, pm)
1385        assertWorks(self, z, pm)
1386
1387        pm = m.component_map(active=True)
1388        assertWorks(self, a, pm)
1389        assertFails(self, b, pm)
1390        assertWorks(self, c, pm)
1391        assertFails(self, 'd', pm)
1392        assertWorks(self, s, pm)
1393        assertWorks(self, t, pm)
1394        assertWorks(self, x, pm)
1395        assertFails(self, z, pm)
1396
1397        pm = m.component_map(active=False)
1398        assertFails(self, a, pm)
1399        assertWorks(self, b, pm)
1400        assertFails(self, c, pm)
1401        assertFails(self, 'd', pm)
1402        assertFails(self, s, pm)
1403        assertFails(self, t, pm)
1404        assertFails(self, x, pm)
1405        assertWorks(self, z, pm)
1406
1407
1408        pm = m.component_map(Constraint)
1409        assertWorks(self, a, pm)
1410        assertWorks(self, b, pm)
1411        assertWorks(self, c, pm)
1412        assertFails(self, 'd', pm)
1413        assertFails(self, s, pm)
1414        assertFails(self, t, pm)
1415        assertFails(self, x, pm)
1416        assertFails(self, z, pm)
1417
1418        pm = m.component_map(Constraint, active=True)
1419        assertWorks(self, a, pm)
1420        assertFails(self, b, pm)
1421        assertWorks(self, c, pm)
1422        assertFails(self, 'd', pm)
1423        assertFails(self, s, pm)
1424        assertFails(self, t, pm)
1425        assertFails(self, x, pm)
1426        assertFails(self, z, pm)
1427
1428        pm = m.component_map(Constraint, active=False)
1429        assertFails(self, a, pm)
1430        assertWorks(self, b, pm)
1431        assertFails(self, c, pm)
1432        assertFails(self, 'd', pm)
1433        assertFails(self, s, pm)
1434        assertFails(self, t, pm)
1435        assertFails(self, x, pm)
1436        assertFails(self, z, pm)
1437
1438
1439        pm = m.component_map([Constraint,Objective])
1440        assertWorks(self, a, pm)
1441        assertWorks(self, b, pm)
1442        assertWorks(self, c, pm)
1443        assertFails(self, 'd', pm)
1444        assertFails(self, s, pm)
1445        assertFails(self, t, pm)
1446        assertWorks(self, x, pm)
1447        assertWorks(self, z, pm)
1448
1449        pm = m.component_map([Constraint,Objective], active=True)
1450        assertWorks(self, a, pm)
1451        assertFails(self, b, pm)
1452        assertWorks(self, c, pm)
1453        assertFails(self, 'd', pm)
1454        assertFails(self, s, pm)
1455        assertFails(self, t, pm)
1456        assertWorks(self, x, pm)
1457        assertFails(self, z, pm)
1458
1459        pm = m.component_map([Constraint,Objective], active=False)
1460        assertFails(self, a, pm)
1461        assertWorks(self, b, pm)
1462        assertFails(self, c, pm)
1463        assertFails(self, 'd', pm)
1464        assertFails(self, s, pm)
1465        assertFails(self, t, pm)
1466        assertFails(self, x, pm)
1467        assertWorks(self, z, pm)
1468
1469
1470        pm = m.component_map(set([Constraint,Objective]))
1471        assertWorks(self, a, pm)
1472        assertWorks(self, b, pm)
1473        assertWorks(self, c, pm)
1474        assertFails(self, 'd', pm)
1475        assertFails(self, s, pm)
1476        assertFails(self, t, pm)
1477        assertWorks(self, x, pm)
1478        assertWorks(self, z, pm)
1479
1480        pm = m.component_map(set([Constraint,Objective]), active=True)
1481        assertWorks(self, a, pm)
1482        assertFails(self, b, pm)
1483        assertWorks(self, c, pm)
1484        assertFails(self, 'd', pm)
1485        assertFails(self, s, pm)
1486        assertFails(self, t, pm)
1487        assertWorks(self, x, pm)
1488        assertFails(self, z, pm)
1489
1490        pm = m.component_map(set([Constraint,Objective]), active=False)
1491        assertFails(self, a, pm)
1492        assertWorks(self, b, pm)
1493        assertFails(self, c, pm)
1494        assertFails(self, 'd', pm)
1495        assertFails(self, s, pm)
1496        assertFails(self, t, pm)
1497        assertFails(self, x, pm)
1498        assertWorks(self, z, pm)
1499
1500    def test_pseudomap_getitem_exceptionString(self):
1501        def tester(pm, _str):
1502            try:
1503                pm['a']
1504                self.fail("Expected PseudoMap to raise a KeyError")
1505            except KeyError:
1506                err = sys.exc_info()[1].args[0]
1507                self.assertEqual(_str, err)
1508
1509        m = Block(name='foo')
1510        tester( m.component_map(),
1511                "component 'a' not found in block foo" )
1512        tester( m.component_map(active=True),
1513                "active component 'a' not found in block foo" )
1514        tester( m.component_map(active=False),
1515                "inactive component 'a' not found in block foo" )
1516
1517        tester( m.component_map(Var),
1518                "Var component 'a' not found in block foo" )
1519        tester( m.component_map(Var, active=True),
1520                "active Var component 'a' not found in block foo" )
1521        tester( m.component_map(Var, active=False),
1522                "inactive Var component 'a' not found in block foo" )
1523
1524        tester( m.component_map(SubclassOf(Var)),
1525                "SubclassOf(Var) component 'a' not found in block foo" )
1526        tester( m.component_map(SubclassOf(Var), active=True),
1527                "active SubclassOf(Var) component 'a' not found in block foo" )
1528        tester( m.component_map(SubclassOf(Var), active=False),
1529                "inactive SubclassOf(Var) component "
1530                "'a' not found in block foo" )
1531
1532        tester( m.component_map(SubclassOf(Var,Block)),
1533                "SubclassOf(Var,Block) component 'a' not found in block foo" )
1534        tester( m.component_map(SubclassOf(Var,Block), active=True),
1535                "active SubclassOf(Var,Block) component "
1536                "'a' not found in block foo" )
1537        tester( m.component_map(SubclassOf(Var,Block), active=False),
1538                "inactive SubclassOf(Var,Block) component "
1539                "'a' not found in block foo" )
1540
1541        tester( m.component_map([Var,Param]),
1542                "Param or Var component 'a' not found in block foo" )
1543        tester( m.component_map(set([Var,Param]), active=True),
1544                "active Param or Var component 'a' not found in block foo" )
1545        tester( m.component_map(set([Var,Param]), active=False),
1546                "inactive Param or Var component 'a' not found in block foo" )
1547
1548
1549        tester(
1550            m.component_map(set([Set,Var,Param])),
1551            "Param, Set or Var component 'a' not found in block foo" )
1552        tester(
1553            m.component_map(set([Set,Var,Param]), active=True),
1554            "active Param, Set or Var component 'a' not found in block foo" )
1555        tester(
1556            m.component_map(set([Set,Var,Param]), active=False),
1557            "inactive Param, Set or Var component 'a' not found in block foo" )
1558
1559    def test_pseudomap_iteration(self):
1560        m = Block()
1561        m.a = Constraint()
1562        m.z = Objective() # active=False
1563        m.x = Objective()
1564        m.v = Objective()
1565        m.b = Constraint() # active=False
1566        m.t = Block() # active=False
1567        m.s = Block()
1568        m.c = Constraint()
1569        m.y = Objective()
1570        m.w = Objective() # active=False
1571
1572        m.b.deactivate()
1573        m.z.deactivate()
1574        m.w.deactivate()
1575        m.t.deactivate()
1576
1577        self.assertEqual( ['a','z','x','v','b','t','s','c','y','w'],
1578                          list(m.component_map()) )
1579
1580        self.assertEqual( ['a','z','x','v','b','c','y','w'],
1581                          list(m.component_map( set([Constraint,Objective]) )) )
1582
1583        # test that the order of ctypes in the argument does not affect
1584        # the order in the resulting list
1585        self.assertEqual( ['a','z','x','v','b','c','y','w'],
1586                          list(m.component_map( [Constraint,Objective] )) )
1587
1588        self.assertEqual( ['a','z','x','v','b','c','y','w'],
1589                          list(m.component_map( [Objective,Constraint] )) )
1590
1591        self.assertEqual( ['a','b','c'],
1592                          list(m.component_map( Constraint )) )
1593
1594        self.assertEqual( ['z','x','v','y','w'],
1595                          list(m.component_map( set([Objective]) )) )
1596
1597        self.assertEqual( ['a','x','v','s','c','y'],
1598                          list(m.component_map( active=True )) )
1599
1600        self.assertEqual( ['a','x','v','c','y'],
1601                          list(m.component_map( set([Constraint,Objective]), active=True )) )
1602
1603        self.assertEqual( ['a','x','v','c','y'],
1604                          list(m.component_map( [Constraint,Objective], active=True )) )
1605
1606        self.assertEqual( ['a','x','v','c','y'],
1607                          list(m.component_map( [Objective,Constraint], active=True )) )
1608
1609        self.assertEqual( ['a','c'],
1610                          list(m.component_map( Constraint, active=True )) )
1611
1612        self.assertEqual( ['x','v','y'],
1613                          list(m.component_map( set([Objective]), active=True )) )
1614
1615        self.assertEqual( ['z','b','t','w'],
1616                          list(m.component_map( active=False )) )
1617
1618        self.assertEqual( ['z','b','w'],
1619                          list(m.component_map( set([Constraint,Objective]), active=False )) )
1620
1621        self.assertEqual( ['z','b','w'],
1622                          list(m.component_map( [Constraint,Objective], active=False )) )
1623
1624        self.assertEqual( ['z','b','w'],
1625                          list(m.component_map( [Objective,Constraint], active=False )) )
1626
1627        self.assertEqual( ['b'],
1628                          list(m.component_map( Constraint, active=False )) )
1629
1630        self.assertEqual( ['z','w'],
1631                          list(m.component_map( set([Objective]), active=False )) )
1632
1633        self.assertEqual( ['a','b','c','s','t','v','w','x','y','z'],
1634                          list(m.component_map( sort=True )) )
1635
1636        self.assertEqual( ['a','b','c','v','w','x','y','z'],
1637                          list(m.component_map( set([Constraint,Objective]),sort=True )) )
1638
1639        self.assertEqual( ['a','b','c','v','w','x','y','z'],
1640                          list(m.component_map( [Constraint,Objective],sort=True )) )
1641
1642        self.assertEqual( ['a','b','c','v','w','x','y','z'],
1643                          list(m.component_map( [Objective,Constraint],sort=True )) )
1644
1645        self.assertEqual( ['a','b','c'],
1646                          list(m.component_map( Constraint,sort=True )) )
1647
1648        self.assertEqual( ['v','w','x','y','z'],
1649                          list(m.component_map( set([Objective]),sort=True )) )
1650
1651        self.assertEqual( ['a','c','s','v','x','y'],
1652                          list(m.component_map( active=True,sort=True )) )
1653
1654        self.assertEqual( ['a','c','v','x','y'],
1655                          list(m.component_map( set([Constraint,Objective]), active=True,
1656                                                sort=True )) )
1657
1658        self.assertEqual( ['a','c','v','x','y'],
1659                          list(m.component_map( [Constraint,Objective], active=True,
1660                                                sort=True )) )
1661
1662        self.assertEqual( ['a','c','v','x','y'],
1663                          list(m.component_map( [Objective,Constraint], active=True,
1664                                                sort=True )) )
1665
1666        self.assertEqual( ['a','c'],
1667                          list(m.component_map( Constraint, active=True, sort=True )) )
1668
1669        self.assertEqual( ['v','x','y'],
1670                          list(m.component_map( set([Objective]), active=True,
1671                                                sort=True )) )
1672
1673        self.assertEqual( ['b','t','w','z'],
1674                          list(m.component_map( active=False, sort=True )) )
1675
1676        self.assertEqual( ['b','w','z'],
1677                          list(m.component_map( set([Constraint,Objective]), active=False,
1678                                                sort=True )) )
1679
1680        self.assertEqual( ['b','w','z'],
1681                          list(m.component_map( [Constraint,Objective], active=False,
1682                                                sort=True )) )
1683
1684        self.assertEqual( ['b','w','z'],
1685                          list(m.component_map( [Objective,Constraint], active=False,
1686                                                sort=True )) )
1687
1688        self.assertEqual( ['b'],
1689                          list(m.component_map( Constraint, active=False,
1690                                                sort=True )) )
1691
1692        self.assertEqual( ['w','z'],
1693                          list(m.component_map( set([Objective]), active=False,
1694                                                sort=True )) )
1695
1696    def test_iterate_hierarchical_blocks(self):
1697        def def_var(b, *args):
1698            b.x = Var()
1699        def init_block(b):
1700            b.c = Block([1,2], rule=def_var)
1701            b.e = Disjunct([1,2], rule=def_var)
1702            b.b = Block(rule=def_var)
1703            b.d = Disjunct(rule=def_var)
1704
1705        m = ConcreteModel()
1706        m.x = Var()
1707        init_block(m)
1708        init_block(m.b)
1709        init_block(m.c[1])
1710        init_block(m.c[2])
1711        init_block(m.d)
1712        init_block(m.e[1])
1713        init_block(m.e[2])
1714
1715        ref = [x.name for x in (
1716            m,
1717            m.c[1], m.c[1].c[1], m.c[1].c[2], m.c[1].b,
1718            m.c[2], m.c[2].c[1], m.c[2].c[2], m.c[2].b,
1719            m.b, m.b.c[1], m.b.c[2], m.b.b,
1720        )]
1721        test = list(x.name for x in m.block_data_objects())
1722        self.assertEqual(test, ref)
1723
1724        test = list(x.name for x in m.block_data_objects(
1725            descend_into=Block ))
1726        self.assertEqual(test, ref)
1727
1728        test = list(x.name for x in m.block_data_objects(
1729            descend_into=(Block,) ))
1730        self.assertEqual(test, ref)
1731
1732
1733        ref = [x.name for x in (
1734            m,
1735            m.e[1], m.e[1].e[1], m.e[1].e[2], m.e[1].d,
1736            m.e[2], m.e[2].e[1], m.e[2].e[2], m.e[2].d,
1737            m.d, m.d.e[1], m.d.e[2], m.d.d,
1738        )]
1739        test = list(x.name for x in m.block_data_objects(
1740            descend_into=(Disjunct,) ))
1741        self.assertEqual(test, ref)
1742
1743        ref = [x.name for x in (
1744            m.d, m.d.e[1], m.d.e[2], m.d.d,
1745        )]
1746        test = list(x.name for x in m.d.block_data_objects(
1747            descend_into=(Disjunct,) ))
1748        self.assertEqual(test, ref)
1749
1750
1751        ref = [x.name for x in (
1752            m,
1753            m.c[1],
1754            m.c[1].c[1], m.c[1].c[2],
1755            m.c[1].e[1], m.c[1].e[2],
1756            m.c[1].b, m.c[1].d,
1757            m.c[2],
1758            m.c[2].c[1], m.c[2].c[2],
1759            m.c[2].e[1], m.c[2].e[2],
1760            m.c[2].b, m.c[2].d,
1761            m.e[1],
1762            m.e[1].c[1], m.e[1].c[2],
1763            m.e[1].e[1], m.e[1].e[2],
1764            m.e[1].b, m.e[1].d,
1765            m.e[2],
1766            m.e[2].c[1], m.e[2].c[2],
1767            m.e[2].e[1], m.e[2].e[2],
1768            m.e[2].b, m.e[2].d,
1769            m.b,
1770            m.b.c[1], m.b.c[2],
1771            m.b.e[1], m.b.e[2],
1772            m.b.b, m.b.d,
1773            m.d,
1774            m.d.c[1], m.d.c[2],
1775            m.d.e[1], m.d.e[2],
1776            m.d.b, m.d.d,
1777        )]
1778        test = list(x.name for x in m.block_data_objects(
1779            descend_into=(Block,Disjunct) ))
1780        self.assertEqual(test, ref)
1781
1782        test = list(x.name for x in m.block_data_objects(
1783            descend_into=(Disjunct,Block) ))
1784        self.assertEqual(test, ref)
1785
1786
1787        ref = [x.name for x in (
1788            m.x,
1789            m.c[1].x, m.c[1].c[1].x, m.c[1].c[2].x, m.c[1].b.x,
1790            m.c[2].x, m.c[2].c[1].x, m.c[2].c[2].x, m.c[2].b.x,
1791            m.b.x, m.b.c[1].x, m.b.c[2].x, m.b.b.x,
1792        )]
1793        test = list(x.name for x in m.component_data_objects(
1794            Var ))
1795        self.assertEqual(test, ref)
1796
1797        test = list(x.name for x in m.component_data_objects(
1798            Var, descend_into=Block ))
1799        self.assertEqual(test, ref)
1800
1801        test = list(x.name for x in m.component_data_objects(
1802            Var, descend_into=(Block,) ))
1803        self.assertEqual(test, ref)
1804
1805        ref = [x.name for x in (
1806            m.x,
1807            m.e[1].binary_indicator_var,      m.e[1].x,
1808            m.e[1].e[1].binary_indicator_var, m.e[1].e[1].x,
1809            m.e[1].e[2].binary_indicator_var, m.e[1].e[2].x,
1810            m.e[1].d.binary_indicator_var,    m.e[1].d.x,
1811            m.e[2].binary_indicator_var,      m.e[2].x,
1812            m.e[2].e[1].binary_indicator_var, m.e[2].e[1].x,
1813            m.e[2].e[2].binary_indicator_var, m.e[2].e[2].x,
1814            m.e[2].d.binary_indicator_var,    m.e[2].d.x,
1815            m.d.binary_indicator_var,      m.d.x,
1816            m.d.e[1].binary_indicator_var, m.d.e[1].x,
1817            m.d.e[2].binary_indicator_var, m.d.e[2].x,
1818            m.d.d.binary_indicator_var,    m.d.d.x,
1819        )]
1820        test = list(x.name for x in m.component_data_objects(
1821            Var, descend_into=Disjunct ))
1822        self.assertEqual(test, ref)
1823
1824        ref = [x.name for x in (
1825            m.x,
1826            m.c[1].x,
1827            m.c[1].c[1].x,                    m.c[1].c[2].x,
1828            m.c[1].e[1].binary_indicator_var, m.c[1].e[1].x,
1829            m.c[1].e[2].binary_indicator_var, m.c[1].e[2].x,
1830            m.c[1].b.x,
1831            m.c[1].d.binary_indicator_var,    m.c[1].d.x,
1832            m.c[2].x,
1833            m.c[2].c[1].x,                    m.c[2].c[2].x,
1834            m.c[2].e[1].binary_indicator_var, m.c[2].e[1].x,
1835            m.c[2].e[2].binary_indicator_var, m.c[2].e[2].x,
1836            m.c[2].b.x,
1837            m.c[2].d.binary_indicator_var,    m.c[2].d.x,
1838
1839            m.e[1].binary_indicator_var,      m.e[1].x,
1840            m.e[1].c[1].x,                    m.e[1].c[2].x,
1841            m.e[1].e[1].binary_indicator_var, m.e[1].e[1].x,
1842            m.e[1].e[2].binary_indicator_var, m.e[1].e[2].x,
1843            m.e[1].b.x,
1844            m.e[1].d.binary_indicator_var,    m.e[1].d.x,
1845            m.e[2].binary_indicator_var,      m.e[2].x,
1846            m.e[2].c[1].x,                    m.e[2].c[2].x,
1847            m.e[2].e[1].binary_indicator_var, m.e[2].e[1].x,
1848            m.e[2].e[2].binary_indicator_var, m.e[2].e[2].x,
1849            m.e[2].b.x,
1850            m.e[2].d.binary_indicator_var,    m.e[2].d.x,
1851
1852            m.b.x,
1853            m.b.c[1].x,                    m.b.c[2].x,
1854            m.b.e[1].binary_indicator_var, m.b.e[1].x,
1855            m.b.e[2].binary_indicator_var, m.b.e[2].x,
1856            m.b.b.x,
1857            m.b.d.binary_indicator_var,    m.b.d.x,
1858
1859            m.d.binary_indicator_var,      m.d.x,
1860            m.d.c[1].x,                    m.d.c[2].x,
1861            m.d.e[1].binary_indicator_var, m.d.e[1].x,
1862            m.d.e[2].binary_indicator_var, m.d.e[2].x,
1863            m.d.b.x,
1864            m.d.d.binary_indicator_var,    m.d.d.x,
1865        )]
1866        test = list(x.name for x in m.component_data_objects(
1867            Var, descend_into=(Block,Disjunct) ))
1868        self.assertEqual(test, ref)
1869
1870
1871    def test_deepcopy(self):
1872        m = ConcreteModel()
1873        m.x = Var()
1874        m.y = Var([1])
1875        m.c = Constraint(expr=m.x**2 + m.y[1] <= 5)
1876        m.b = Block()
1877        m.b.x = Var()
1878        m.b.y = Var([1,2])
1879        m.b.c = Constraint(expr=m.x**2 + m.y[1] + m.b.x**2 + m.b.y[1] <= 10)
1880
1881        n = deepcopy(m)
1882        self.assertNotEqual(id(m), id(n))
1883
1884        self.assertNotEqual(id(m.x), id(n.x))
1885        self.assertIs(m.x.parent_block(), m)
1886        self.assertIs(m.x.parent_component(), m.x)
1887        self.assertIs(n.x.parent_block(), n)
1888        self.assertIs(n.x.parent_component(), n.x)
1889
1890        self.assertNotEqual(id(m.y), id(n.y))
1891        self.assertIs(m.y.parent_block(), m)
1892        self.assertIs(m.y[1].parent_component(), m.y)
1893        self.assertIs(n.y.parent_block(), n)
1894        self.assertIs(n.y[1].parent_component(), n.y)
1895
1896        self.assertNotEqual(id(m.c), id(n.c))
1897        self.assertIs(m.c.parent_block(), m)
1898        self.assertIs(m.c.parent_component(), m.c)
1899        self.assertIs(n.c.parent_block(), n)
1900        self.assertIs(n.c.parent_component(), n.c)
1901        self.assertEqual(
1902            sorted(id(x) for x in EXPR.identify_variables(m.c.body)),
1903            sorted(id(x) for x in (m.x,m.y[1])),
1904        )
1905        self.assertEqual(
1906            sorted(id(x) for x in EXPR.identify_variables(n.c.body)),
1907            sorted(id(x) for x in (n.x,n.y[1])),
1908        )
1909
1910        self.assertNotEqual(id(m.b), id(n.b))
1911        self.assertIs(m.b.parent_block(), m)
1912        self.assertIs(m.b.parent_component(), m.b)
1913        self.assertIs(n.b.parent_block(), n)
1914        self.assertIs(n.b.parent_component(), n.b)
1915
1916        self.assertNotEqual(id(m.b.x), id(n.b.x))
1917        self.assertIs(m.b.x.parent_block(), m.b)
1918        self.assertIs(m.b.x.parent_component(), m.b.x)
1919        self.assertIs(n.b.x.parent_block(), n.b)
1920        self.assertIs(n.b.x.parent_component(), n.b.x)
1921
1922        self.assertNotEqual(id(m.b.y), id(n.b.y))
1923        self.assertIs(m.b.y.parent_block(), m.b)
1924        self.assertIs(m.b.y[1].parent_component(), m.b.y)
1925        self.assertIs(n.b.y.parent_block(), n.b)
1926        self.assertIs(n.b.y[1].parent_component(), n.b.y)
1927
1928        self.assertNotEqual(id(m.b.c), id(n.b.c))
1929        self.assertIs(m.b.c.parent_block(), m.b)
1930        self.assertIs(m.b.c.parent_component(), m.b.c)
1931        self.assertIs(n.b.c.parent_block(), n.b)
1932        self.assertIs(n.b.c.parent_component(), n.b.c)
1933        self.assertEqual(
1934            sorted(id(x) for x in EXPR.identify_variables(m.b.c.body)),
1935            sorted(id(x) for x in (m.x, m.y[1], m.b.x, m.b.y[1])),
1936        )
1937        self.assertEqual(
1938            sorted(id(x) for x in EXPR.identify_variables(n.b.c.body)),
1939            sorted(id(x) for x in (n.x, n.y[1], n.b.x, n.b.y[1])),
1940        )
1941
1942    def test_clone_model(self):
1943        m = ConcreteModel()
1944        m.x = Var()
1945        m.y = Var([1])
1946        m.c = Constraint(expr=m.x**2 + m.y[1] <= 5)
1947        m.b = Block()
1948        m.b.x = Var()
1949        m.b.y = Var([1,2])
1950        m.b.c = Constraint(expr=m.x**2 + m.y[1] + m.b.x**2 + m.b.y[1] <= 10)
1951
1952        n = m.clone()
1953        self.assertNotEqual(id(m), id(n))
1954
1955        self.assertNotEqual(id(m.x), id(n.x))
1956        self.assertIs(m.x.parent_block(), m)
1957        self.assertIs(m.x.parent_component(), m.x)
1958        self.assertIs(n.x.parent_block(), n)
1959        self.assertIs(n.x.parent_component(), n.x)
1960
1961        self.assertNotEqual(id(m.y), id(n.y))
1962        self.assertIs(m.y.parent_block(), m)
1963        self.assertIs(m.y[1].parent_component(), m.y)
1964        self.assertIs(n.y.parent_block(), n)
1965        self.assertIs(n.y[1].parent_component(), n.y)
1966
1967        self.assertNotEqual(id(m.c), id(n.c))
1968        self.assertIs(m.c.parent_block(), m)
1969        self.assertIs(m.c.parent_component(), m.c)
1970        self.assertIs(n.c.parent_block(), n)
1971        self.assertIs(n.c.parent_component(), n.c)
1972        self.assertEqual(
1973            sorted(id(x) for x in EXPR.identify_variables(m.c.body)),
1974            sorted(id(x) for x in (m.x,m.y[1])),
1975        )
1976        self.assertEqual(
1977            sorted(id(x) for x in EXPR.identify_variables(n.c.body)),
1978            sorted(id(x) for x in (n.x,n.y[1])),
1979        )
1980
1981        self.assertNotEqual(id(m.b), id(n.b))
1982        self.assertIs(m.b.parent_block(), m)
1983        self.assertIs(m.b.parent_component(), m.b)
1984        self.assertIs(n.b.parent_block(), n)
1985        self.assertIs(n.b.parent_component(), n.b)
1986
1987        self.assertNotEqual(id(m.b.x), id(n.b.x))
1988        self.assertIs(m.b.x.parent_block(), m.b)
1989        self.assertIs(m.b.x.parent_component(), m.b.x)
1990        self.assertIs(n.b.x.parent_block(), n.b)
1991        self.assertIs(n.b.x.parent_component(), n.b.x)
1992
1993        self.assertNotEqual(id(m.b.y), id(n.b.y))
1994        self.assertIs(m.b.y.parent_block(), m.b)
1995        self.assertIs(m.b.y[1].parent_component(), m.b.y)
1996        self.assertIs(n.b.y.parent_block(), n.b)
1997        self.assertIs(n.b.y[1].parent_component(), n.b.y)
1998
1999        self.assertNotEqual(id(m.b.c), id(n.b.c))
2000        self.assertIs(m.b.c.parent_block(), m.b)
2001        self.assertIs(m.b.c.parent_component(), m.b.c)
2002        self.assertIs(n.b.c.parent_block(), n.b)
2003        self.assertIs(n.b.c.parent_component(), n.b.c)
2004        self.assertEqual(
2005            sorted(id(x) for x in EXPR.identify_variables(m.b.c.body)),
2006            sorted(id(x) for x in (m.x, m.y[1], m.b.x, m.b.y[1])),
2007        )
2008        self.assertEqual(
2009            sorted(id(x) for x in EXPR.identify_variables(n.b.c.body)),
2010            sorted(id(x) for x in (n.x, n.y[1], n.b.x, n.b.y[1])),
2011        )
2012
2013    def test_clone_subblock(self):
2014        m = ConcreteModel()
2015        m.x = Var()
2016        m.y = Var([1])
2017        m.c = Constraint(expr=m.x**2 + m.y[1] <= 5)
2018        m.b = Block()
2019        m.b.x = Var()
2020        m.b.y = Var([1,2])
2021        m.b.c = Constraint(expr=m.x**2 + m.y[1] + m.b.x**2 + m.b.y[1] <= 10)
2022
2023        nb = m.b.clone()
2024
2025        self.assertNotEqual(id(m.b), id(nb))
2026        self.assertIs(m.b.parent_block(), m)
2027        self.assertIs(m.b.parent_component(), m.b)
2028        self.assertIs(nb.parent_block(), None)
2029        self.assertIs(nb.parent_component(), nb)
2030
2031        self.assertNotEqual(id(m.b.x), id(nb.x))
2032        self.assertIs(m.b.x.parent_block(), m.b)
2033        self.assertIs(m.b.x.parent_component(), m.b.x)
2034        self.assertIs(nb.x.parent_block(), nb)
2035        self.assertIs(nb.x.parent_component(), nb.x)
2036
2037        self.assertNotEqual(id(m.b.y), id(nb.y))
2038        self.assertIs(m.b.y.parent_block(), m.b)
2039        self.assertIs(m.b.y[1].parent_component(), m.b.y)
2040        self.assertIs(nb.y.parent_block(), nb)
2041        self.assertIs(nb.y[1].parent_component(), nb.y)
2042
2043        self.assertNotEqual(id(m.b.c), id(nb.c))
2044        self.assertIs(m.b.c.parent_block(), m.b)
2045        self.assertIs(m.b.c.parent_component(), m.b.c)
2046        self.assertIs(nb.c.parent_block(), nb)
2047        self.assertIs(nb.c.parent_component(), nb.c)
2048        self.assertEqual(
2049            sorted(id(x) for x in EXPR.identify_variables(m.b.c.body)),
2050            sorted(id(x) for x in (m.x, m.y[1], m.b.x, m.b.y[1])),
2051        )
2052        self.assertEqual(
2053            sorted(id(x) for x in EXPR.identify_variables(nb.c.body)),
2054            sorted(id(x) for x in (m.x, m.y[1], nb.x, nb.y[1])),
2055        )
2056
2057    def test_clone_unclonable_attribute(self):
2058        class foo(object):
2059            def __deepcopy__(bogus):
2060                pass
2061
2062        m = ConcreteModel()
2063        m.x = Var()
2064        m.y = Var([1])
2065        m.bad1 = foo()
2066        m.c = Constraint(expr=m.x**2 + m.y[1] <= 5)
2067        m.b = Block()
2068        m.b.x = Var()
2069        m.b.y = Var([1,2])
2070        m.b.bad2 = foo()
2071        m.b.c = Constraint(expr=m.x**2 + m.y[1] + m.b.x**2 + m.b.y[1] <= 10)
2072
2073        # Check the paranoid warning
2074        OUTPUT = StringIO()
2075        with LoggingIntercept(OUTPUT, 'pyomo.core'):
2076            nb = deepcopy(m.b)
2077        # without the scope, the whole model is cloned!
2078        self.assertIn("'unknown' contains an uncopyable field 'bad1'",
2079                      OUTPUT.getvalue())
2080        self.assertIn("'b' contains an uncopyable field 'bad2'",
2081                      OUTPUT.getvalue())
2082        self.assertIn("'__paranoid__'", OUTPUT.getvalue())
2083        self.assertTrue(hasattr(m.b, 'bad2'))
2084        self.assertFalse(hasattr(nb, 'bad2'))
2085
2086        # Simple tests for the subblock
2087        OUTPUT = StringIO()
2088        with LoggingIntercept(OUTPUT, 'pyomo.core'):
2089            nb = m.b.clone()
2090        self.assertNotIn("'unknown' contains an uncopyable field 'bad1'",
2091                         OUTPUT.getvalue())
2092        self.assertIn("'b' contains an uncopyable field 'bad2'",
2093                      OUTPUT.getvalue())
2094        self.assertNotIn("'__paranoid__'", OUTPUT.getvalue())
2095        self.assertTrue(hasattr(m.b, 'bad2'))
2096        self.assertFalse(hasattr(nb, 'bad2'))
2097
2098        # more involved tests for the model
2099        OUTPUT = StringIO()
2100        with LoggingIntercept(OUTPUT, 'pyomo.core'):
2101            n = m.clone()
2102        self.assertIn("'unknown' contains an uncopyable field 'bad1'",
2103                      OUTPUT.getvalue())
2104        self.assertIn("'b' contains an uncopyable field 'bad2'",
2105                      OUTPUT.getvalue())
2106        self.assertNotIn("'__paranoid__'", OUTPUT.getvalue())
2107        self.assertTrue(hasattr(m, 'bad1'))
2108        self.assertFalse(hasattr(n, 'bad1'))
2109        self.assertTrue(hasattr(m.b, 'bad2'))
2110        self.assertFalse(hasattr(n.b, 'bad2'))
2111
2112        self.assertNotEqual(id(m), id(n))
2113
2114        self.assertNotEqual(id(m.x), id(n.x))
2115        self.assertIs(m.x.parent_block(), m)
2116        self.assertIs(m.x.parent_component(), m.x)
2117        self.assertIs(n.x.parent_block(), n)
2118        self.assertIs(n.x.parent_component(), n.x)
2119
2120        self.assertNotEqual(id(m.y), id(n.y))
2121        self.assertIs(m.y.parent_block(), m)
2122        self.assertIs(m.y[1].parent_component(), m.y)
2123        self.assertIs(n.y.parent_block(), n)
2124        self.assertIs(n.y[1].parent_component(), n.y)
2125
2126        self.assertNotEqual(id(m.c), id(n.c))
2127        self.assertIs(m.c.parent_block(), m)
2128        self.assertIs(m.c.parent_component(), m.c)
2129        self.assertIs(n.c.parent_block(), n)
2130        self.assertIs(n.c.parent_component(), n.c)
2131        self.assertEqual(
2132            sorted(id(x) for x in EXPR.identify_variables(m.c.body)),
2133            sorted(id(x) for x in (m.x,m.y[1])),
2134        )
2135        self.assertEqual(
2136            sorted(id(x) for x in EXPR.identify_variables(n.c.body)),
2137            sorted(id(x) for x in (n.x,n.y[1])),
2138        )
2139
2140        self.assertNotEqual(id(m.b), id(n.b))
2141        self.assertIs(m.b.parent_block(), m)
2142        self.assertIs(m.b.parent_component(), m.b)
2143        self.assertIs(n.b.parent_block(), n)
2144        self.assertIs(n.b.parent_component(), n.b)
2145
2146        self.assertNotEqual(id(m.b.x), id(n.b.x))
2147        self.assertIs(m.b.x.parent_block(), m.b)
2148        self.assertIs(m.b.x.parent_component(), m.b.x)
2149        self.assertIs(n.b.x.parent_block(), n.b)
2150        self.assertIs(n.b.x.parent_component(), n.b.x)
2151
2152        self.assertNotEqual(id(m.b.y), id(n.b.y))
2153        self.assertIs(m.b.y.parent_block(), m.b)
2154        self.assertIs(m.b.y[1].parent_component(), m.b.y)
2155        self.assertIs(n.b.y.parent_block(), n.b)
2156        self.assertIs(n.b.y[1].parent_component(), n.b.y)
2157
2158        self.assertNotEqual(id(m.b.c), id(n.b.c))
2159        self.assertIs(m.b.c.parent_block(), m.b)
2160        self.assertIs(m.b.c.parent_component(), m.b.c)
2161        self.assertIs(n.b.c.parent_block(), n.b)
2162        self.assertIs(n.b.c.parent_component(), n.b.c)
2163        self.assertEqual(
2164            sorted(id(x) for x in EXPR.identify_variables(m.b.c.body)),
2165            sorted(id(x) for x in (m.x, m.y[1], m.b.x, m.b.y[1])),
2166        )
2167        self.assertEqual(
2168            sorted(id(x) for x in EXPR.identify_variables(n.b.c.body)),
2169            sorted(id(x) for x in (n.x, n.y[1], n.b.x, n.b.y[1])),
2170        )
2171
2172    def test_pprint(self):
2173        m = HierarchicalModel().model
2174        buf = StringIO()
2175        m.pprint(ostream=buf)
2176        ref = """3 Set Declarations
2177    a1_IDX : Size=1, Index=None, Ordered=Insertion
2178        Key  : Dimen : Domain : Size : Members
2179        None :     1 :    Any :    2 : {5, 4}
2180    a3_IDX : Size=1, Index=None, Ordered=Insertion
2181        Key  : Dimen : Domain : Size : Members
2182        None :     1 :    Any :    2 : {6, 7}
2183    a_index : Size=1, Index=None, Ordered=Insertion
2184        Key  : Dimen : Domain : Size : Members
2185        None :     1 :    Any :    3 : {1, 2, 3}
2186
21873 Block Declarations
2188    a : Size=3, Index=a_index, Active=True
2189        a[1] : Active=True
2190            2 Block Declarations
2191                c : Size=2, Index=a1_IDX, Active=True
2192                    a[1].c[4] : Active=True
2193                        0 Declarations:
2194                    a[1].c[5] : Active=True
2195                        0 Declarations:
2196                d : Size=1, Index=None, Active=True
2197                    0 Declarations:
2198
2199            2 Declarations: d c
2200        a[2] : Active=True
2201            0 Declarations:
2202        a[3] : Active=True
2203            2 Block Declarations
2204                e : Size=1, Index=None, Active=True
2205                    0 Declarations:
2206                f : Size=2, Index=a3_IDX, Active=True
2207                    a[3].f[6] : Active=True
2208                        0 Declarations:
2209                    a[3].f[7] : Active=True
2210                        0 Declarations:
2211
2212            2 Declarations: e f
2213    b : Size=1, Index=None, Active=True
2214        0 Declarations:
2215    c : Size=1, Index=None, Active=True
2216        0 Declarations:
2217
22186 Declarations: a1_IDX a3_IDX c a_index a b
2219"""
2220        print(buf.getvalue())
2221        self.assertEqual(ref, buf.getvalue())
2222
2223    @unittest.skipIf(not 'glpk' in solvers, "glpk solver is not available")
2224    def test_solve1(self):
2225        model = Block(concrete=True)
2226        model.A = RangeSet(1,4)
2227        model.x = Var(model.A, bounds=(-1,1))
2228        def obj_rule(model):
2229            return sum_product(model.x)
2230        model.obj = Objective(rule=obj_rule)
2231        def c_rule(model):
2232            expr = 0
2233            for i in model.A:
2234                expr += i*model.x[i]
2235            return expr == 0
2236        model.c = Constraint(rule=c_rule)
2237        opt = SolverFactory('glpk')
2238        results = opt.solve(model, symbolic_solver_labels=True)
2239        model.solutions.store_to(results)
2240        results.write(filename=join(currdir,"solve1.out"), format='json')
2241        with open(join(currdir,"solve1.out"), 'r') as out, \
2242            open(join(currdir,"solve1.txt"), 'r') as txt:
2243            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2244                                             abstol=1e-4,
2245                                             allow_second_superset=True)
2246        #
2247        def d_rule(model):
2248            return model.x[1] >= 0
2249        model.d = Constraint(rule=d_rule)
2250        model.d.deactivate()
2251        results = opt.solve(model)
2252        model.solutions.store_to(results)
2253        results.write(filename=join(currdir,"solve1x.out"), format='json')
2254        with open(join(currdir,"solve1x.out"), 'r') as out, \
2255            open(join(currdir,"solve1.txt"), 'r') as txt:
2256            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2257                                             abstol=1e-4,
2258                                             allow_second_superset=True)
2259        #
2260        model.d.activate()
2261        results = opt.solve(model)
2262        model.solutions.store_to(results)
2263        results.write(filename=join(currdir,"solve1a.out"), format='json')
2264        with open(join(currdir,"solve1a.out"), 'r') as out, \
2265            open(join(currdir,"solve1a.txt"), 'r') as txt:
2266            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2267                                             abstol=1e-4,
2268                                             allow_second_superset=True)
2269        #
2270        model.d.deactivate()
2271        def e_rule(model, i):
2272            return model.x[i] >= 0
2273        model.e = Constraint(model.A, rule=e_rule)
2274        for i in model.A:
2275            model.e[i].deactivate()
2276        results = opt.solve(model)
2277        model.solutions.store_to(results)
2278        results.write(filename=join(currdir,"solve1y.out"), format='json')
2279        with open(join(currdir,"solve1y.out"), 'r') as out, \
2280            open(join(currdir,"solve1.txt"), 'r') as txt:
2281            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2282                                             abstol=1e-4,
2283                                             allow_second_superset=True)
2284        #
2285        model.e.activate()
2286        results = opt.solve(model)
2287        model.solutions.store_to(results)
2288        results.write(filename=join(currdir,"solve1b.out"), format='json')
2289        with open(join(currdir,"solve1b.out"), 'r') as out, \
2290            open(join(currdir,"solve1b.txt"), 'r') as txt:
2291            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2292                                             abstol=1e-4,
2293                                             allow_second_superset=True)
2294
2295    @unittest.skipIf(not 'glpk' in solvers, "glpk solver is not available")
2296    def test_solve4(self):
2297        model = Block(concrete=True)
2298        model.A = RangeSet(1,4)
2299        model.x = Var(model.A, bounds=(-1,1))
2300        def obj_rule(model):
2301            return sum_product(model.x)
2302        model.obj = Objective(rule=obj_rule)
2303        def c_rule(model):
2304            expr = 0
2305            for i in model.A:
2306                expr += i*model.x[i]
2307            return expr == 0
2308        model.c = Constraint(rule=c_rule)
2309        opt = SolverFactory('glpk')
2310        results = opt.solve(model, symbolic_solver_labels=True)
2311        model.solutions.store_to(results)
2312        results.write(filename=join(currdir,'solve4.out'), format='json')
2313        with open(join(currdir,"solve4.out"), 'r') as out, \
2314            open(join(currdir,"solve1.txt"), 'r') as txt:
2315            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2316                                             abstol=1e-4,
2317                                             allow_second_superset=True)
2318
2319    @unittest.skipIf(not 'glpk' in solvers, "glpk solver is not available")
2320    def test_solve6(self):
2321        #
2322        # Test that solution values have complete block names:
2323        #   b.obj
2324        #   b.x
2325        #
2326        model = Block(concrete=True)
2327        model.y = Var(bounds=(-1,1))
2328        model.b = Block()
2329        model.b.A = RangeSet(1,4)
2330        model.b.x = Var(model.b.A, bounds=(-1,1))
2331        def obj_rule(block):
2332            return sum_product(block.x)
2333        model.b.obj = Objective(rule=obj_rule)
2334        def c_rule(model):
2335            expr = model.y
2336            for i in model.b.A:
2337                expr += i*model.b.x[i]
2338            return expr == 0
2339        model.c = Constraint(rule=c_rule)
2340        opt = SolverFactory('glpk')
2341        results = opt.solve(model, symbolic_solver_labels=True)
2342        model.solutions.store_to(results)
2343        results.write(filename=join(currdir,'solve6.out'), format='json')
2344        with open(join(currdir,"solve6.out"), 'r') as out, \
2345            open(join(currdir,"solve6.txt"), 'r') as txt:
2346            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2347                                             abstol=1e-4,
2348                                             allow_second_superset=True)
2349
2350    @unittest.skipIf(not 'glpk' in solvers, "glpk solver is not available")
2351    def test_solve7(self):
2352        #
2353        # Test that solution values are writen with appropriate
2354        # quotations in results
2355        #
2356        model = Block(concrete=True)
2357        model.y = Var(bounds=(-1,1))
2358        model.A = RangeSet(1,4)
2359        model.B = Set(initialize=['A B', 'C,D', 'E'])
2360        model.x = Var(model.A, model.B, bounds=(-1,1))
2361        def obj_rule(model):
2362            return sum_product(model.x)
2363        model.obj = Objective(rule=obj_rule)
2364        def c_rule(model):
2365            expr = model.y
2366            for i in model.A:
2367                for j in model.B:
2368                    expr += i*model.x[i,j]
2369            return expr == 0
2370        model.c = Constraint(rule=c_rule)
2371        opt = SolverFactory('glpk')
2372        results = opt.solve(model, symbolic_solver_labels=True)
2373        #model.display()
2374        model.solutions.store_to(results)
2375        results.write(filename=join(currdir,'solve7.out'), format='json')
2376        with open(join(currdir,"solve7.out"), 'r') as out, \
2377            open(join(currdir,"solve7.txt"), 'r') as txt:
2378            self.assertStructuredAlmostEqual(json.load(txt), json.load(out),
2379                                             abstol=1e-4,
2380                                             allow_second_superset=True)
2381
2382
2383    def test_abstract_index(self):
2384        model = AbstractModel()
2385        model.A = Set()
2386        model.B = Set()
2387        model.C = model.A | model.B
2388        model.x = Block(model.C)
2389
2390    def test_decorated_definition(self):
2391        model = ConcreteModel()
2392        model.I = Set(initialize=[1,2,3])
2393        model.x = Var(model.I)
2394
2395        @model.Constraint()
2396        def scalar_constraint(m):
2397            return m.x[1]**2 <= 0
2398
2399        self.assertTrue(hasattr(model, 'scalar_constraint'))
2400        self.assertIs(model.scalar_constraint.ctype, Constraint)
2401        self.assertEqual(len(model.scalar_constraint), 1)
2402        self.assertIs(type(scalar_constraint), types.FunctionType)
2403
2404        @model.Constraint(model.I)
2405        def vector_constraint(m, i):
2406            return m.x[i]**2 <= 0
2407
2408        self.assertTrue(hasattr(model, 'vector_constraint'))
2409        self.assertIs(model.vector_constraint.ctype, Constraint)
2410        self.assertEqual(len(model.vector_constraint), 3)
2411        self.assertIs(type(vector_constraint), types.FunctionType)
2412
2413    def test_reserved_words(self):
2414        m = ConcreteModel()
2415        self.assertRaisesRegex(
2416            ValueError, ".*using the name of a reserved attribute",
2417            m.add_component, "add_component", Var())
2418        with self.assertRaisesRegex(
2419                ValueError, ".*using the name of a reserved attribute"):
2420            m.add_component = Var()
2421        m.foo = Var()
2422
2423        m.b = DerivedBlock()
2424        self.assertRaisesRegex(
2425            ValueError, ".*using the name of a reserved attribute",
2426            m.b.add_component, "add_component", Var())
2427        self.assertRaisesRegex(
2428            ValueError, ".*using the name of a reserved attribute",
2429            m.b.add_component, "foo", Var())
2430        with self.assertRaisesRegex(
2431                ValueError, ".*using the name of a reserved attribute"):
2432            m.b.foo = Var()
2433
2434        #
2435        # Overriding attributes with non-components is (currently) allowed
2436        #
2437        m.add_component = 5
2438        self.assertIs(m.add_component, 5)
2439        m.b.add_component = 6
2440        self.assertIs(m.b.add_component, 6)
2441        m.b.foo = 7
2442        self.assertIs(m.b.foo, 7)
2443
2444    def test_write_exceptions(self):
2445        m = Block()
2446        with self.assertRaisesRegex(
2447                ValueError, ".*Could not infer file format from file name"):
2448            m.write(filename="foo.bogus")
2449
2450        with self.assertRaisesRegex(
2451                ValueError, ".*Cannot write model in format"):
2452            m.write(format="bogus")
2453
2454    def test_override_pprint(self):
2455        @declare_custom_block('TempBlock')
2456        class TempBlockData(_BlockData):
2457            def pprint(self, ostream=None, verbose=False, prefix=""):
2458                ostream.write('Testing pprint of a custom block.')
2459
2460        correct_s = 'Testing pprint of a custom block.'
2461        b = TempBlock(concrete=True)
2462        stream = StringIO()
2463        b.pprint(ostream=stream)
2464        self.assertEqual(correct_s, stream.getvalue())
2465
2466    def test_block_rules(self):
2467        m = ConcreteModel()
2468        m.I = Set()
2469        _rule_ = []
2470        def _block_rule(b,i):
2471            _rule_.append(i)
2472            b.x = Var(range(i))
2473        m.b = Block(m.I, rule=_block_rule)
2474        # I is empty: no rules called
2475        self.assertEqual(_rule_, [])
2476        m.I.update([1,3,5])
2477        # Fetching a new block will call the rule
2478        _b = m.b[3]
2479        self.assertEqual(len(m.b), 1)
2480        self.assertEqual(_rule_, [3])
2481        self.assertIn('x', _b.component_map())
2482        self.assertIn('x', m.b[3].component_map())
2483
2484        # If you transfer the attributes directly, the rule will still
2485        # be called.
2486        _tmp = Block()
2487        _tmp.y = Var(range(3))
2488        m.b[5].transfer_attributes_from(_tmp)
2489        self.assertEqual(len(m.b), 2)
2490        self.assertEqual(_rule_, [3,5])
2491        self.assertIn('x', m.b[5].component_map())
2492        self.assertIn('y', m.b[5].component_map())
2493
2494        # We do not support block assignment (and the rule will NOT be
2495        # called)
2496        _tmp = Block()
2497        _tmp.y = Var(range(3))
2498        with self.assertRaisesRegex(
2499                RuntimeError, "Block components do not support "
2500                "assignment or set_value"):
2501            m.b[1] = _tmp
2502        self.assertEqual(len(m.b), 2)
2503        self.assertEqual(_rule_, [3,5])
2504
2505        # Blocks with non-finite indexing sets cannot be automatically
2506        # populated (even if they have a rule!)
2507        def _bb_rule(b, i, j):
2508            _rule_.append((i,j))
2509            b.x = Var(RangeSet(i))
2510            b.y = Var(RangeSet(j))
2511        m.bb = Block(m.I, NonNegativeIntegers, rule=_bb_rule)
2512        self.assertEqual(_rule_, [3,5])
2513        _b = m.bb[3,5]
2514        self.assertEqual(_rule_, [3,5,(3,5)])
2515        self.assertEqual(len(m.bb), 1)
2516        self.assertEqual(len(_b.x), 3)
2517        self.assertEqual(len(_b.y), 5)
2518
2519    def test_derived_block_construction(self):
2520        # This tests a case where a derived block doesn't follow the
2521        # assumption that unconstructed scalar blocks initialize
2522        # `_data[None] = self` (therefore doesn't fully support abstract
2523        # models).  At one point, that was causing the block rule to
2524        # fire twice during construction.
2525        class ConcreteBlock(Block):
2526            pass
2527
2528        class ScalarConcreteBlock(_BlockData, ConcreteBlock):
2529            def __init__(self, *args, **kwds):
2530                _BlockData.__init__(self, component=self)
2531                ConcreteBlock.__init__(self, *args, **kwds)
2532
2533        _buf = []
2534        def _rule(b):
2535            _buf.append(1)
2536
2537        m = ConcreteModel()
2538        m.b = ScalarConcreteBlock(rule=_rule)
2539        self.assertEqual(_buf, [1])
2540
2541    def test_abstract_construction(self):
2542        m = AbstractModel()
2543        m.I = Set()
2544        def b_rule(b, i):
2545            b.p = Param(default=i)
2546            b.J = Set(initialize=range(i))
2547        m.b = Block(m.I, rule=b_rule)
2548
2549        i = m.create_instance({None: {
2550            'I': {None: [1,2,3,4]},
2551            'b': {1: {'p': {None: 10}, 'J': {None: [7,8]}},
2552                  2: {'p': {None: 12}},
2553                  3: {'J': {None: [9]}},
2554              }
2555        }})
2556        self.assertEqual(list(i.I), [1,2,3,4])
2557        self.assertEqual(len(i.b), 4)
2558        self.assertEqual(list(i.b[1].J), [7,8])
2559        self.assertEqual(list(i.b[2].J), [0,1])
2560        self.assertEqual(list(i.b[3].J), [9])
2561        self.assertEqual(list(i.b[4].J), [0,1,2,3])
2562        self.assertEqual(value(i.b[1].p), 10)
2563        self.assertEqual(value(i.b[2].p), 12)
2564        self.assertEqual(value(i.b[3].p), 3)
2565        self.assertEqual(value(i.b[4].p), 4)
2566
2567    def test_abstract_transfer_construction(self):
2568        m = AbstractModel()
2569        m.I = Set()
2570        def b_rule(_b, i):
2571            b = Block()
2572            b.p = Param(default=i)
2573            b.J = Set(initialize=range(i))
2574            return b
2575        m.b = Block(m.I, rule=b_rule)
2576
2577        i = m.create_instance({None: {
2578            'I': {None: [1,2,3,4]},
2579            'b': {1: {'p': {None: 10}, 'J': {None: [7,8]}},
2580                  2: {'p': {None: 12}},
2581                  3: {'J': {None: [9]}},
2582              }
2583        }})
2584        self.assertEqual(list(i.I), [1,2,3,4])
2585        self.assertEqual(len(i.b), 4)
2586        self.assertEqual(list(i.b[1].J), [7,8])
2587        self.assertEqual(list(i.b[2].J), [0,1])
2588        self.assertEqual(list(i.b[3].J), [9])
2589        self.assertEqual(list(i.b[4].J), [0,1,2,3])
2590        self.assertEqual(value(i.b[1].p), 10)
2591        self.assertEqual(value(i.b[2].p), 12)
2592        self.assertEqual(value(i.b[3].p), 3)
2593        self.assertEqual(value(i.b[4].p), 4)
2594
2595    def test_deprecated_options(self):
2596        m = ConcreteModel()
2597        def b_rule(b, a=None):
2598            b.p = Param(initialize=a)
2599        OUTPUT = StringIO()
2600        with LoggingIntercept(OUTPUT, 'pyomo.core'):
2601            m.b = Block(rule=b_rule, options={'a': 5})
2602        self.assertIn("The Block 'options=' keyword is deprecated.",
2603                      OUTPUT.getvalue())
2604        self.assertEqual(value(m.b.p), 5)
2605
2606        m = ConcreteModel()
2607        def b_rule(b, i, **kwds):
2608            b.p = Param(initialize=kwds.get('a', {}).get(i, 0))
2609        OUTPUT = StringIO()
2610        with LoggingIntercept(OUTPUT, 'pyomo.core'):
2611            m.b = Block([1,2,3], rule=b_rule, options={'a': {1:5, 2:10}})
2612        self.assertIn("The Block 'options=' keyword is deprecated.",
2613                      OUTPUT.getvalue())
2614        self.assertEqual(value(m.b[1].p), 5)
2615        self.assertEqual(value(m.b[2].p), 10)
2616        self.assertEqual(value(m.b[3].p), 0)
2617
2618if __name__ == "__main__":
2619    unittest.main()
2620