diff --git a/doc/OnlineDocs/src/kernel/examples.txt b/doc/OnlineDocs/src/kernel/examples.txt index 8ba072d28b1..7d5d2b34820 100644 --- a/doc/OnlineDocs/src/kernel/examples.txt +++ b/doc/OnlineDocs/src/kernel/examples.txt @@ -76,29 +76,22 @@ 3 : -5.0 : vl[3] - v : 5.0 : True 3 SOSConstraint Declarations - sd : Size=2 Index= OrderedScalarSet - 1 - Type=1 - Weight : Variable - 1 : vd[1] - 2 : vd[2] - 2 - Type=1 - Weight : Variable - 1 : vl[1] - 2 : vl[2] - 3 : vl[3] - sos1 : Size=1 - Type=1 - Weight : Variable - 1 : vl[1] - 2 : vl[2] - 3 : vl[3] - sos2 : Size=1 - Type=2 - Weight : Variable - 1 : vd[1] - 2 : vd[2] + sd : Size=2, Index={1, 2} + Key : Type : Weight : Variable + 1 : 1 : 1 : vd[1] + : : 2 : vd[2] + 2 : 1 : 1 : vl[1] + : : 2 : vl[2] + : : 3 : vl[3] + sos1 : Size=1, Index=None + Key : Type : Weight : Variable + None : 1 : 1 : vl[1] + : : 2 : vl[2] + : : 3 : vl[3] + sos2 : Size=1, Index=None + Key : Type : Weight : Variable + None : 2 : 1 : vd[1] + : : 2 : vd[2] 2 Block Declarations b : Size=1, Index=None, Active=True @@ -120,13 +113,12 @@ 3 : 1.0 : pw.SOS2_y[0] + pw.SOS2_y[1] + pw.SOS2_y[2] + pw.SOS2_y[3] : 1.0 : True 1 SOSConstraint Declarations - SOS2_sosconstraint : Size=1 - Type=2 - Weight : Variable - 1 : pw.SOS2_y[0] - 2 : pw.SOS2_y[1] - 3 : pw.SOS2_y[2] - 4 : pw.SOS2_y[3] + SOS2_sosconstraint : Size=1, Index=None + Key : Type : Weight : Variable + None : 2 : 1 : pw.SOS2_y[0] + : : 2 : pw.SOS2_y[1] + : : 3 : pw.SOS2_y[2] + : : 4 : pw.SOS2_y[3] 3 Declarations: SOS2_y SOS2_constraint SOS2_sosconstraint diff --git a/pyomo/common/formatting.py b/pyomo/common/formatting.py index 710116a98fe..0583993fd3a 100644 --- a/pyomo/common/formatting.py +++ b/pyomo/common/formatting.py @@ -150,8 +150,11 @@ def tabular_writer(ostream, prefix, data, header, row_generator): _rows[_key] = None continue + # Include the key for only the first line in a rowset, and only + # if we printed out a header (if there is no header, then then + # key is not included) _rows[_key] = [ - ((tostr("" if i else _key),) if header else ()) + (("" if i else tostr(_key),) if header else ()) + tuple(tostr(x) for x in _r) for i, _r in enumerate(_rowSet) ] @@ -186,7 +189,7 @@ def tabular_writer(ostream, prefix, data, header, row_generator): if any(' ' in r[-1] for x in _rows.values() if x is not None for r in x): _width[-1] = '%s' - for _key in sorted_robust(_rows): + for _key in _rows: _rowSet = _rows[_key] if not _rowSet: _rowSet = [[_key] + [None] * (len(_width) - 1)] diff --git a/pyomo/common/tests/test_formatting.py b/pyomo/common/tests/test_formatting.py index 0798a80589c..38fe939f295 100644 --- a/pyomo/common/tests/test_formatting.py +++ b/pyomo/common/tests/test_formatting.py @@ -96,8 +96,8 @@ def test_no_header(self): data = {(2,): (["a", 1], 1), (1, 3): ({1: 'a', 2: '2'}, '2')} tabular_writer(os, "", data.items(), [], lambda k, v: v) ref = u""" -{1: 'a', 2: '2'} : 2 ['a', 1] : 1 +{1: 'a', 2: '2'} : 2 """ self.assertEqual(ref.strip(), os.getvalue().strip()) diff --git a/pyomo/contrib/cp/sequence_var.py b/pyomo/contrib/cp/sequence_var.py index 57f555d36bf..46181e4607e 100644 --- a/pyomo/contrib/cp/sequence_var.py +++ b/pyomo/contrib/cp/sequence_var.py @@ -134,7 +134,7 @@ def _pprint(self): ] return ( headers, - self._data.items(), + self.items, ("IntervalVars",), lambda k, v: ['[' + ', '.join(iv.name for iv in v.interval_vars) + ']'], ) diff --git a/pyomo/core/base/block.py b/pyomo/core/base/block.py index 97b2dee721b..6028d3272db 100644 --- a/pyomo/core/base/block.py +++ b/pyomo/core/base/block.py @@ -1851,7 +1851,7 @@ def is_constructed(self): return False return True - def _pprint_blockdata_components(self, ostream): + def _pprint_blockdata_components(self, ostream, sort): # # We hard-code the order of the core Pyomo modeling # components, to ensure that the output follows the logical order @@ -1877,7 +1877,10 @@ def _pprint_blockdata_components(self, ostream): indented_ostream = StreamIndenter(ostream, self._PPRINT_INDENT) for item in items: - keys = sorted(self.component_map(item)) + if SortComponents.ALPHABETICAL in sort: + keys = sorted(self.component_map(item)) + else: + keys = list(self.component_map(item)) if not keys: continue # @@ -1885,7 +1888,7 @@ def _pprint_blockdata_components(self, ostream): # ostream.write("%d %s Declarations\n" % (len(keys), item.__name__)) for key in keys: - self.component(key).pprint(ostream=indented_ostream) + self.component(key).pprint(ostream=indented_ostream, sort=sort) ostream.write("\n") # # Model Order @@ -2252,25 +2255,26 @@ def construct(self, data=None): _BlockConstruction.data.pop(id(self), None) timer.report() - def _pprint_callback(self, ostream, idx, data): + def _pprint_callback(self, ostream, sort, idx, data): if not self.is_indexed(): - data._pprint_blockdata_components(ostream) + data._pprint_blockdata_components(ostream, sort) else: ostream.write("%s : Active=%s\n" % (data.name, data.active)) ostream = StreamIndenter(ostream, self._PPRINT_INDENT) - data._pprint_blockdata_components(ostream) + data._pprint_blockdata_components(ostream, sort) def _pprint(self): - _attrs = [ - ("Size", len(self)), - ("Index", self._index_set if self.is_indexed() else None), - ('Active', self.active), - ] # HACK: suppress the top-level block header (for historical reasons) if self.parent_block() is None and not self.is_indexed(): - return None, self._data.items(), None, self._pprint_callback + _attrs = None else: - return _attrs, self._data.items(), None, self._pprint_callback + _attrs = [ + ("Size", len(self)), + ("Index", self._index_set if self.is_indexed() else None), + ('Active', self.active), + ] + + return _attrs, self.items, None, self._pprint_callback def display(self, filename=None, ostream=None, prefix=""): """ diff --git a/pyomo/core/base/boolean_var.py b/pyomo/core/base/boolean_var.py index 46536596832..a99f3681b1d 100644 --- a/pyomo/core/base/boolean_var.py +++ b/pyomo/core/base/boolean_var.py @@ -457,7 +457,7 @@ def _pprint(self): ("Size", len(self)), ("Index", self._index_set if self.is_indexed() else None), ], - self._data.items(), + self.items, ("Value", "Fixed", "Stale"), lambda k, v: [v.value, v.fixed, v.stale], ) diff --git a/pyomo/core/base/component.py b/pyomo/core/base/component.py index 8bbdc4d571b..21a4813cb4b 100644 --- a/pyomo/core/base/component.py +++ b/pyomo/core/base/component.py @@ -31,6 +31,7 @@ from pyomo.common.sorting import sorted_robust from pyomo.core.pyomoobject import PyomoObject from pyomo.core.base.component_namer import name_repr, index_repr +from pyomo.core.base.enums import SortComponents from pyomo.core.base.global_set import UnindexedComponent_index from pyomo.core.base.initializer import PartialInitializer @@ -41,6 +42,7 @@ ) _ref_types = {type(None), weakref_ref} +DEFAULT_PPRINT_SORT = SortComponents.ALPHABETICAL | SortComponents.SORTED_INDICES class ModelComponentFactoryClass(Factory): @@ -274,7 +276,7 @@ def __deepcopy_field__(self, value, memo, slot_name): def cname(self, *args, **kwds): return self.getname(*args, **kwds) - def pprint(self, ostream=None, verbose=False, prefix=""): + def pprint(self, ostream=None, verbose=False, prefix="", sort=NOTSET): """Print component information Note that this method is generally only reachable through @@ -292,12 +294,13 @@ def pprint(self, ostream=None, verbose=False, prefix=""): _name = comp.local_name else: # restrict output to only this data object - _data = iter(((self.index(), self),)) + _data = lambda _sort: iter(((self.index(), self),)) _name = "{Member of %s}" % (comp.local_name,) self._pprint_base_impl( ostream, verbose, prefix, + sort, _name, comp.doc, comp.is_constructed(), @@ -348,6 +351,7 @@ def _pprint_base_impl( ostream, verbose, prefix, + sort, _name, _doc, _constructed, @@ -361,6 +365,10 @@ def _pprint_base_impl( if prefix: ostream = StreamIndenter(ostream, prefix) + if sort is NOTSET: + sort = DEFAULT_PPRINT_SORT + sort = SortComponents(sort) + # FIXME: HACK for backwards compatibility with suppressing the # header for the top block if not _attr and self.parent_block() is None: @@ -395,23 +403,37 @@ def _pprint_base_impl( return if type(_fcn) is tuple: + # Exception to the standard formatter case: with two + # callbacks, we will use the first to generate the normal + # table, then call the second callback for each data. + # Currently only used by Complimentarity (which should be + # refactored to remove the need for this edge case) _fcn, _fcn2 = _fcn else: _fcn2 = None + if hasattr(_data, '__call__'): + _data = _data(sort) + if _header is not None: + # This is a standard component, where all the component + # information is printed in a single table if _fcn2 is not None: - _data_dict = dict(_data) - _data = _data_dict.items() + _data = list(_data) tabular_writer(ostream, '', _data, _header, _fcn) if _fcn2 is not None: - for _key in sorted_robust(_data_dict): - _fcn2(ostream, _key, _data_dict[_key]) + for _key, _val in _data: + _fcn2(ostream, sort, _key, _val) elif _fcn is not None: - _data_dict = dict(_data) - for _key in sorted_robust(_data_dict): - _fcn(ostream, _key, _data_dict[_key]) + # This is a non-standard component where we will not + # generate a table at all, and instead defer all formatting + # / printing to the callback. This is primarily used by + # BLocks (and block-like things) + for _key, _val in _data: + _fcn(ostream, sort, _key, _val) elif _data is not None: + # Catch all for everything else: assume that _pprint() + # returned a formatted string. ostream.write(_data) @@ -516,12 +538,13 @@ def valid_model_component(self): """Return True if this can be used as a model component.""" return True - def pprint(self, ostream=None, verbose=False, prefix=""): + def pprint(self, ostream=None, verbose=False, prefix="", sort=NOTSET): """Print component information""" self._pprint_base_impl( ostream, verbose, prefix, + sort, self.local_name, self.doc, self.is_constructed(), diff --git a/pyomo/core/base/connector.py b/pyomo/core/base/connector.py index 26b87569e42..e3ec3a3a4e1 100644 --- a/pyomo/core/base/connector.py +++ b/pyomo/core/base/connector.py @@ -202,7 +202,7 @@ def _initialize_members(self, initSet): for key, val in items.items(): tmp.add(val, key) - def _pprint(self, ostream=None, verbose=False): + def _pprint(self): """Print component information.""" def _line_generator(k, v): @@ -222,7 +222,7 @@ def _line_generator(k, v): ("Size", len(self)), ("Index", self._index_set if self.is_indexed() else None), ], - self._data.items(), + self.items, ("Name", "Size", "Variable"), _line_generator, ) diff --git a/pyomo/core/base/constraint.py b/pyomo/core/base/constraint.py index 970c393425b..8fe9781c500 100644 --- a/pyomo/core/base/constraint.py +++ b/pyomo/core/base/constraint.py @@ -766,7 +766,7 @@ def _pprint(self): ("Index", self._index_set if self.is_indexed() else None), ("Active", self.active), ], - self.items(), + self.items, ("Lower", "Body", "Upper", "Active"), lambda k, v: [ "-Inf" if v.lower is None else v.lower, diff --git a/pyomo/core/base/expression.py b/pyomo/core/base/expression.py index e3766e0ec45..28e51b069ce 100644 --- a/pyomo/core/base/expression.py +++ b/pyomo/core/base/expression.py @@ -303,7 +303,7 @@ def _pprint(self): ('Size', len(self)), ('Index', None if (not self.is_indexed()) else self._index_set), ], - self.items(), + self.items, ("Expression",), lambda k, v: ["Undefined" if v.expr is None else v.expr], ) diff --git a/pyomo/core/base/external.py b/pyomo/core/base/external.py index a968e886219..a9485d10864 100644 --- a/pyomo/core/base/external.py +++ b/pyomo/core/base/external.py @@ -460,7 +460,7 @@ def _pprint(self): ), ), ], - (), + None, None, None, ) @@ -614,7 +614,7 @@ def _pprint(self): ), ), ], - (), + None, None, None, ) diff --git a/pyomo/core/base/indexed_component.py b/pyomo/core/base/indexed_component.py index 8bbcb6fdf55..e97e9755d6f 100644 --- a/pyomo/core/base/indexed_component.py +++ b/pyomo/core/base/indexed_component.py @@ -511,9 +511,15 @@ def keys(self, sort=SortComponents.UNSORTED, ordered=NOTSET): """ % (self.name,) ) + return iter(self._data) + elif SortComponents.SORTED_INDICES in sort: + # We are sorting the indices (and this is a sparse + # IndexedComponent): we might as well just sort the sparse + # _data keys instead of iterating over the whole index. + return iter(sorted_robust(self._data)) else: # - # Test each element of a sparse data with an ordered + # Test each element of a sparse _data with an ordered # index set in order. This is potentially *slow*: if # the component is in fact very sparse, we could be # iterating over a huge (dense) index in order to sort a @@ -556,7 +562,23 @@ def values(self, sort=SortComponents.UNSORTED, ordered=NOTSET): return self._data.values(sort) except TypeError: pass - return map(self.__getitem__, self.keys(sort)) + # We would like to look things up directly in _data (as that is + # fast, since we know that keys() will return valid entries). + # However, some components (notably Param with a default) have + # valid keys that do not have an entry in _data. If we just + # rely on getitem, then we will hit issues for abstract + # components. So we will use a custom getter that tries _data + # first (both for efficiency and to correctly handle + # AbstractScalar components), and then falls back on getitem. + _getdata = self._data.__getitem__ + + def getter(s): + try: + return _getdata(s) + except KeyError: + return self[s] + + return map(getter, self.keys(sort)) def items(self, sort=SortComponents.UNSORTED, ordered=NOTSET): """Return an iterator of (index,data) component data tuples @@ -591,7 +613,23 @@ def items(self, sort=SortComponents.UNSORTED, ordered=NOTSET): return self._data.items(sort) except TypeError: pass - return ((s, self[s]) for s in self.keys(sort)) + # We would like to look things up directly in _data (as that is + # fast, since we know that keys() will return valid entries). + # However, some components (notably Param with a default) have + # valid keys that do not have an entry in _data. If we just + # rely on getitem, then we will hit issues in pprint for + # abstract components. So we will use a custom getter that + # tries _data first (both for efficiency and to correctly handle + # AbstractScalar components), and then falls back on getitem. + _getdata = self._data.__getitem__ + + def getter(s): + try: + return s, _getdata(s) + except KeyError: + return s, self[s] + + return map(getter, self.keys(sort)) @deprecated('The iterkeys method is deprecated. Use dict.keys().', version='6.0') def iterkeys(self): @@ -1135,7 +1173,7 @@ def _pprint(self): ("Size", len(self)), ("Index", self._index_set if self.is_indexed() else None), ], - self._data.items(), + self.items, ("Object",), lambda k, v: [type(v)], ) diff --git a/pyomo/core/base/logical_constraint.py b/pyomo/core/base/logical_constraint.py index fdb9870bc85..066ee19559b 100644 --- a/pyomo/core/base/logical_constraint.py +++ b/pyomo/core/base/logical_constraint.py @@ -309,7 +309,7 @@ def _pprint(self): ("Index", self._index_set if self.is_indexed() else None), ("Active", self.active), ], - self.items(), + self.items, ("Body", "Active"), lambda k, v: [v.body, v.active], ) diff --git a/pyomo/core/base/objective.py b/pyomo/core/base/objective.py index 5123a9207f9..9d80b692e18 100644 --- a/pyomo/core/base/objective.py +++ b/pyomo/core/base/objective.py @@ -393,7 +393,7 @@ def _pprint(self): ("Index", self._index_set if self.is_indexed() else None), ("Active", self.active), ], - self._data.items(), + self.items, ("Active", "Sense", "Expression"), lambda k, v: [v.active, v.sense, v.expr], ) diff --git a/pyomo/core/base/param.py b/pyomo/core/base/param.py index 02ba103cae3..764e37cdb33 100644 --- a/pyomo/core/base/param.py +++ b/pyomo/core/base/param.py @@ -17,7 +17,7 @@ from weakref import ref as weakref_ref from pyomo.common.autoslots import AutoSlots -from pyomo.common.deprecation import deprecation_warning, RenamedClass +from pyomo.common.deprecation import deprecated, deprecation_warning, RenamedClass from pyomo.common.log import is_debug_set from pyomo.common.modeling import NOTSET from pyomo.common.numeric_types import native_types, value as expr_value @@ -26,6 +26,7 @@ from pyomo.core.expr.expr_common import _type_check_exception_arg from pyomo.core.expr.numvalue import NumericValue from pyomo.core.base.component import ComponentData, ModelComponentFactory +from pyomo.core.base.enums import SortComponents from pyomo.core.base.global_set import UnindexedComponent_index from pyomo.core.base.indexed_component import ( IndexedComponent, @@ -424,7 +425,7 @@ def mutable(self): return self._mutable def get_units(self): - """Return the units for this ParamData""" + """Return the units for this Param""" return self._units # @@ -432,29 +433,69 @@ def get_units(self): # only loop over the defined data. # - def sparse_keys(self): + def sparse_keys(self, sort=SortComponents.UNSORTED): """Return a list of keys in the defined parameters""" - return list(self._data.keys()) + try: + # Temporarily remove the default value so that len(self) == + # len(self._dict). This will cause the base class + # implementation of keys() to only return values from + # self._data: + tmp = self._default_val + self._default_val = Param.NoValue + return self.keys(sort) + finally: + self._default_val = tmp - def sparse_values(self): + def sparse_values(self, sort=SortComponents.UNSORTED): """Return a list of the defined param data objects""" - return list(self._data.values()) + # Implementing things this way for consistency with items() (and + # so that any changes in the base class implementation are + # picked up here, too): + try: + tmp = self._default_val + self._default_val = Param.NoValue + return self.values(sort) + finally: + self._default_val = tmp - def sparse_items(self): + def sparse_items(self, sort=SortComponents.UNSORTED): """Return a list (index,data) tuples for defined parameters""" - return list(self._data.items()) + # The base class implements special handling for references. + # Instead of reimplementing that here, we will follow the + # pattern used for sparse_keys (and get len() to "lie") + try: + tmp = self._default_val + self._default_val = Param.NoValue + return self.items(sort) + finally: + self._default_val = tmp + @deprecated( + "The sparse_iterkeys method is deprecated. Use sparse_keys()", + # This should have been deprecated when we dropped Python 2.7 + version='6.10.0.dev0', + ) def sparse_iterkeys(self): """Return an iterator for the keys in the defined parameters""" - return self._data.keys() + return self.sparse_keys() + @deprecated( + "The sparse_itervalues method is deprecated. Use sparse_values()", + # This should have been deprecated when we dropped Python 2.7 + version='6.10.0.dev0', + ) def sparse_itervalues(self): """Return an iterator for the defined param data objects""" - return self._data.values() + return self.sparse_values() + @deprecated( + "The sparse_iteritems method is deprecated. Use sparse_items()", + # This should have been deprecated when we dropped Python 2.7 + version='6.10.0.dev0', + ) def sparse_iteritems(self): """Return an iterator of (index,data) tuples for defined parameters""" - return self._data.items() + return self.sparse_items() def extract_values(self): """ @@ -466,23 +507,20 @@ def extract_values(self): the contents of a parameter. """ if self._mutable: - # - # The parameter is mutable, parameter data are ParamData types. - # Thus, we need to create a temporary dictionary that contains the - # values from the ParamData objects. - # - return {key: param_value() for key, param_value in self.items()} + # The parameter is mutable so parameter data are ParamData + # types. We need to evaluate the ParamData back to POD + # (numeric) data when creating the result. + return {key: param_data() for key, param_data in self.items()} elif not self.is_indexed(): - # - # The parameter is a scalar, so we need to create a temporary - # dictionary using the value for this parameter. - # - return {None: self()} + # The scalar could be defined (in which case items() will + # return the ScalarParam, OR it could be defined by a + # default value (in which case items() will return the + # actual numeric value. to cover both cases we will use + # value(): + return {key: expr_value(param_data) for key, param_data in self.items()} else: - # # The parameter is not mutable, so iteritems() can be # converted into a dictionary containing parameter values. - # return dict(self.items()) def extract_values_sparse(self): @@ -494,28 +532,21 @@ def extract_values_sparse(self): repeated __getitem__ calls are too expensive to extract the contents of a parameter. """ - if self._mutable: - # - # The parameter is mutable, parameter data are ParamData types. - # Thus, we need to create a temporary dictionary that contains the - # values from the ParamData objects. - # - ans = {} - for key, param_value in self.sparse_iteritems(): - ans[key] = param_value() - return ans - elif not self.is_indexed(): - # - # The parameter is a scalar, so we need to create a temporary - # dictionary using the value for this parameter. + if self._mutable or not self.is_indexed(): + # The parameter is mutable so parameter data are ParamData + # types. We need to evaluate the ParamData back to POD + # (numeric) data when creating the result. # - return {None: self()} + # Note that if this is a scalar, sparse_items will return + # the ScalarParam only if it is explicitly defined (in which + # case it will still be evaluatable by calling it). + # ScalarParams whose value comes from the default are not + # returned by sparse_items() + return {key: param_data() for key, param_data in self.sparse_items()} else: - # - # The parameter is not mutable, so sparse_iteritems() can be + # The parameter is not mutable, so sparse_items() can be # converted into a dictionary containing parameter values. - # - return dict(self.sparse_iteritems()) + return dict(self.sparse_items()) def store_values(self, new_values, check=True): """ @@ -933,7 +964,7 @@ def _pprint(self): ] if self._units is not None: headers.append(('Units', str(self._units))) - return (headers, self.sparse_iteritems(), ("Value",), dataGen) + return (headers, self.sparse_items, ("Value",), dataGen) class ScalarParam(ParamData, Param): diff --git a/pyomo/core/base/set.py b/pyomo/core/base/set.py index 8c858f96ba8..3879594a288 100644 --- a/pyomo/core/base/set.py +++ b/pyomo/core/base/set.py @@ -39,6 +39,7 @@ is_constant, ) from pyomo.core.base.disable_methods import disable_methods +from pyomo.core.base.enums import SortComponents from pyomo.core.base.initializer import ( CountedCallInitializer, IndexedCallInitializer, @@ -1608,23 +1609,6 @@ class _FiniteSetData(metaclass=RenamedClass): __renamed__version__ = '6.7.2' -class _ScalarOrderedSetMixin: - # This mixin is required because scalar ordered sets implement - # __getitem__() as an alias of at() - __slots__ = () - - def values(self): - """Return an iterator of the component data objects in the dictionary""" - if list(self.keys()): - yield self - - def items(self): - """Return an iterator of (index,data) tuples from the dictionary""" - _keys = list(self.keys()) - if _keys: - yield _keys[0], self - - class _OrderedSetMixin: __slots__ = () _valid_getitem_keys = {None, (None,), Ellipsis} @@ -2022,6 +2006,29 @@ class _SortedSetData(metaclass=RenamedClass): _SETDATA_API = ('set_value', 'add', 'remove', 'discard', 'clear', 'update', 'pop') +class _ScalarSetMixin: + # This mixin is required because scalar Sets implement __len__(), + # which raises an exception for non-finite sets. Further finite + # scalar sets also implement __getitem__() as an alias of at(), and + # IndexedComponent.items() / IndexedComponent.values() relies on + # __getitem__() + __slots__ = () + + def keys(self, sort=SortComponents.UNSORTED): + # Scalar sets are always defined (we don't support Skip): + return iter(UnindexedComponent_set) + + def values(self, sort=SortComponents.UNSORTED): + """Return an iterator of the component data objects in the dictionary""" + # Scalar sets are always defined (we don't support Skip): + yield self + + def items(self, sort=SortComponents.UNSORTED): + """Return an iterator of (index,data) tuples from the dictionary""" + # Scalar sets are always defined (we don't support Skip): + yield UnindexedComponent_index, self + + @ModelComponentFactory.register("Set data that is used to define a model instance.") class Set(IndexedComponent): """A component used to index other Pyomo components. @@ -2483,7 +2490,7 @@ def _pprint(self): ("Index", self._index_set if self.is_indexed() else None), ("Ordered", _ordered), ], - self._data.items(), + self.items, ("Dimen", "Domain", "Size", "Members"), lambda k, v: [ Set._pprint_dimen(v), @@ -2505,7 +2512,7 @@ def __getitem__(self, index) -> SetData: ... __getitem__ = IndexedComponent.__getitem__ # type: ignore -class FiniteScalarSet(FiniteSetData, Set): +class FiniteScalarSet(_ScalarSetMixin, FiniteSetData, Set): def __init__(self, **kwds): FiniteSetData.__init__(self, component=self) Set.__init__(self, **kwds) @@ -2517,7 +2524,7 @@ class FiniteSimpleSet(metaclass=RenamedClass): __renamed__version__ = '6.0' -class OrderedScalarSet(_ScalarOrderedSetMixin, InsertionOrderSetData, Set): +class OrderedScalarSet(_ScalarSetMixin, InsertionOrderSetData, Set): def __init__(self, **kwds): # In case someone inherits from us, we will provide a rational # default for the "ordered" flag @@ -2532,7 +2539,7 @@ class OrderedSimpleSet(metaclass=RenamedClass): __renamed__version__ = '6.0' -class SortedScalarSet(_ScalarOrderedSetMixin, SortedSetData, Set): +class SortedScalarSet(_ScalarSetMixin, SortedSetData, Set): def __init__(self, **kwds): # In case someone inherits from us, we will provide a rational # default for the "ordered" flag @@ -2652,7 +2659,7 @@ def _pprint(self): """ return ( [("Dimen", self.dimen), ("Size", len(self)), ("Bounds", self.bounds())], - {None: self}.items(), + [(UnindexedComponent_index, self)], ("Ordered", "Members"), lambda k, v: [v.isordered(), str(v._ref)], ) @@ -2695,7 +2702,7 @@ class UnorderedSetOf(metaclass=RenamedClass): __renamed__version__ = '6.2' -class OrderedSetOf(_ScalarOrderedSetMixin, _OrderedSetMixin, FiniteSetOf): +class OrderedSetOf(_OrderedSetMixin, FiniteSetOf): def at(self, index): i = self._to_0_based_index(index) try: @@ -3313,7 +3320,7 @@ def _pprint(self): ("Size", len(self) if self.isfinite() else 'Inf'), ("Bounds", self.bounds()), ], - {None: self}.items(), + [(UnindexedComponent_index, self)], ("Finite", "Members"), lambda k, v: [ v.isfinite(), # isinstance(v, _FiniteSetMixin), @@ -3337,7 +3344,7 @@ class InfiniteSimpleRangeSet(metaclass=RenamedClass): __renamed__version__ = '6.0' -class FiniteScalarRangeSet(_ScalarOrderedSetMixin, FiniteRangeSetData, RangeSet): +class FiniteScalarRangeSet(FiniteRangeSetData, RangeSet): def __init__(self, *args, **kwds): FiniteRangeSetData.__init__(self, component=self) RangeSet.__init__(self, *args, **kwds) @@ -3377,7 +3384,7 @@ class AbstractFiniteSimpleRangeSet(metaclass=RenamedClass): ############################################################################ -class SetOperator(SetData, Set): +class SetOperator(_ScalarSetMixin, SetData, Set): __slots__ = ('_sets',) def __init__(self, *args, **kwds): @@ -3609,7 +3616,7 @@ def __len__(self): return len(set0) + sum(1 for s in set1 if s not in set0) -class SetUnion_OrderedSet(_ScalarOrderedSetMixin, _OrderedSetMixin, SetUnion_FiniteSet): +class SetUnion_OrderedSet(_OrderedSetMixin, SetUnion_FiniteSet): __slots__ = tuple() def at(self, index): @@ -3749,9 +3756,7 @@ def __len__(self): return sum(1 for _ in self) -class SetIntersection_OrderedSet( - _ScalarOrderedSetMixin, _OrderedSetMixin, SetIntersection_FiniteSet -): +class SetIntersection_OrderedSet(_OrderedSetMixin, SetIntersection_FiniteSet): __slots__ = tuple() def at(self, index): @@ -3843,9 +3848,7 @@ def __len__(self): return sum(1 for _ in self) -class SetDifference_OrderedSet( - _ScalarOrderedSetMixin, _OrderedSetMixin, SetDifference_FiniteSet -): +class SetDifference_OrderedSet(_OrderedSetMixin, SetDifference_FiniteSet): __slots__ = tuple() def at(self, index): @@ -3954,7 +3957,7 @@ def __len__(self): class SetSymmetricDifference_OrderedSet( - _ScalarOrderedSetMixin, _OrderedSetMixin, SetSymmetricDifference_FiniteSet + _OrderedSetMixin, SetSymmetricDifference_FiniteSet ): __slots__ = tuple() @@ -4236,9 +4239,7 @@ def __len__(self): return ans -class SetProduct_OrderedSet( - _ScalarOrderedSetMixin, _OrderedSetMixin, SetProduct_FiniteSet -): +class SetProduct_OrderedSet(_OrderedSetMixin, SetProduct_FiniteSet): __slots__ = tuple() def at(self, index): @@ -4287,7 +4288,7 @@ def ord(self, item): ############################################################################ -class _AnySet(SetData, Set): +class _AnySet(_ScalarSetMixin, SetData, Set): def __init__(self, **kwds): SetData.__init__(self, component=self) # There is a chicken-and-egg game here: the SetInitializer uses @@ -4343,7 +4344,7 @@ def get(self, val, default=None): return super(_AnyWithNoneSet, self).get(val, default) -class _EmptySet(_FiniteSetMixin, SetData, Set): +class _EmptySet(_FiniteSetMixin, _ScalarSetMixin, SetData, Set): def __init__(self, **kwds): SetData.__init__(self, component=self) Set.__init__(self, **kwds) diff --git a/pyomo/core/base/sos.py b/pyomo/core/base/sos.py index 46581982468..2a9108f68b5 100644 --- a/pyomo/core/base/sos.py +++ b/pyomo/core/base/sos.py @@ -531,27 +531,21 @@ def add(self, index, variables, weights=None): else: soscondata.set_items(variables, weights) - # NOTE: the prefix option is ignored - def pprint(self, ostream=None, verbose=False, prefix=""): - """TODO""" - if ostream is None: - ostream = sys.stdout - ostream.write(" " + self.local_name + " : ") - if not self.doc is None: - ostream.write(self.doc + '\n') - ostream.write(" ") - ostream.write("\tSize=" + str(len(self._data.keys())) + ' ') - if self.is_indexed(): - ostream.write("\tIndex= " + self._index_set.name + '\n') - else: - ostream.write("\n") - for val in self._data: - if not val is None: - ostream.write("\t" + str(val) + '\n') - ostream.write("\t\tType=" + str(self._data[val].level) + '\n') - ostream.write("\t\tWeight : Variable\n") - for var, weight in self._data[val].get_items(): - ostream.write("\t\t" + str(weight) + ' : ' + var.name + '\n') + def _pprint(self): + """Print component information.""" + headers = [ + ("Size", len(self)), + ("Index", self._index_set if self.is_indexed() else None), + ] + return ( + headers, + self.items, + ("Type", "Weight", "Variable"), + lambda k, v: ( + ("" if i else v.level, w, var) + for i, (var, w) in enumerate(v.get_items()) + ), + ) class ScalarSOSConstraint(SOSConstraint, SOSConstraintData): diff --git a/pyomo/core/base/suffix.py b/pyomo/core/base/suffix.py index 0ce55c67057..43d942863a5 100644 --- a/pyomo/core/base/suffix.py +++ b/pyomo/core/base/suffix.py @@ -10,6 +10,7 @@ # ___________________________________________________________________________ import logging +import operator from pyomo.common.collections import ComponentMap from pyomo.common.config import In @@ -22,6 +23,7 @@ from pyomo.core.base.block import BlockData from pyomo.core.base.component import ActiveComponent, ModelComponentFactory from pyomo.core.base.disable_methods import disable_methods +from pyomo.core.base.enums import SortComponents from pyomo.core.base.initializer import Initializer logger = logging.getLogger('pyomo.core') @@ -386,12 +388,18 @@ def get_direction(self): return self.direction def _pprint(self): + def _data(sort): + data = ((str(k), v) for k, v in self._dict.values()) + if SortComponents.SORTED_INDICES in sort: + data = sorted(data, key=operator.itemgetter(0)) + return data + return ( [ ('Direction', str(self._direction.name)), ('Datatype', getattr(self._datatype, 'name', 'None')), ], - ((str(k), v) for k, v in self._dict.values()), + _data, ("Value",), lambda k, v: [v], ) @@ -402,9 +410,6 @@ def _pprint(self): # complications with __setstate__ # - def pprint(self, *args, **kwds): - return ActiveComponent.pprint(self, *args, **kwds) - def __str__(self): return ActiveComponent.__str__(self) diff --git a/pyomo/core/base/var.py b/pyomo/core/base/var.py index 6b9b5fb4151..0830c10db2d 100644 --- a/pyomo/core/base/var.py +++ b/pyomo/core/base/var.py @@ -844,7 +844,7 @@ def _pprint(self): headers.append(('Units', str(self._units))) return ( headers, - self._data.items(), + self.items, ("Lower", "Value", "Upper", "Fixed", "Stale", "Domain"), lambda k, v: [ value(v.lb), diff --git a/pyomo/core/tests/unit/test_block.py b/pyomo/core/tests/unit/test_block.py index 0a3823d6f01..0c5c439863d 100644 --- a/pyomo/core/tests/unit/test_block.py +++ b/pyomo/core/tests/unit/test_block.py @@ -2713,6 +2713,116 @@ def test_pprint(self): """ self.assertEqual(ref, buf.getvalue()) + def test_pprint_sorting(self): + m = ConcreteModel() + m.I = Set(ordered=False, initialize=[3, 'a', 1]) + m.y = Var(m.I) + m.x = Var([3, 2, 1]) + + OUT = StringIO() + m.pprint(ostream=OUT, sort=False) + self.assertEqual( + """1 Set Declarations + I : Size=1, Index=None, Ordered=False + Key : Dimen : Domain : Size : Members + None : 1 : Any : 3 : {%s, %s, %s} + +2 Var Declarations + y : Size=3, Index=I + Key : Lower : Value : Upper : Fixed : Stale : Domain + %s : None : None : None : False : True : Reals + %s : None : None : None : False : True : Reals + %s : None : None : None : False : True : Reals + x : Size=3, Index={3, 2, 1} + Key : Lower : Value : Upper : Fixed : Stale : Domain + 3 : None : None : None : False : True : Reals + 2 : None : None : None : False : True : Reals + 1 : None : None : None : False : True : Reals + +3 Declarations: I y x +""" + % (tuple(repr(_) for _ in m.I.ordered_iter()) + tuple(m.I)), + OUT.getvalue(), + ) + + OUT = StringIO() + m.pprint(ostream=OUT, sort=SortComponents.ALPHABETICAL) + self.assertEqual( + """1 Set Declarations + I : Size=1, Index=None, Ordered=False + Key : Dimen : Domain : Size : Members + None : 1 : Any : 3 : {%s, %s, %s} + +2 Var Declarations + x : Size=3, Index={3, 2, 1} + Key : Lower : Value : Upper : Fixed : Stale : Domain + 3 : None : None : None : False : True : Reals + 2 : None : None : None : False : True : Reals + 1 : None : None : None : False : True : Reals + y : Size=3, Index=I + Key : Lower : Value : Upper : Fixed : Stale : Domain + %s : None : None : None : False : True : Reals + %s : None : None : None : False : True : Reals + %s : None : None : None : False : True : Reals + +3 Declarations: I y x +""" + % (tuple(repr(_) for _ in m.I.ordered_iter()) + tuple(m.I)), + OUT.getvalue(), + ) + + OUT = StringIO() + m.pprint(ostream=OUT, sort=SortComponents.ORDERED_INDICES) + self.assertEqual( + """1 Set Declarations + I : Size=1, Index=None, Ordered=False + Key : Dimen : Domain : Size : Members + None : 1 : Any : 3 : {%s, %s, %s} + +2 Var Declarations + y : Size=3, Index=I + Key : Lower : Value : Upper : Fixed : Stale : Domain + 1 : None : None : None : False : True : Reals + 3 : None : None : None : False : True : Reals + a : None : None : None : False : True : Reals + x : Size=3, Index={3, 2, 1} + Key : Lower : Value : Upper : Fixed : Stale : Domain + 3 : None : None : None : False : True : Reals + 2 : None : None : None : False : True : Reals + 1 : None : None : None : False : True : Reals + +3 Declarations: I y x +""" + % tuple(repr(_) for _ in m.I.ordered_iter()), + OUT.getvalue(), + ) + + OUT = StringIO() + m.pprint(ostream=OUT, sort=True) + self.assertEqual( + """1 Set Declarations + I : Size=1, Index=None, Ordered=False + Key : Dimen : Domain : Size : Members + None : 1 : Any : 3 : {%s, %s, %s} + +2 Var Declarations + x : Size=3, Index={3, 2, 1} + Key : Lower : Value : Upper : Fixed : Stale : Domain + 1 : None : None : None : False : True : Reals + 2 : None : None : None : False : True : Reals + 3 : None : None : None : False : True : Reals + y : Size=3, Index=I + Key : Lower : Value : Upper : Fixed : Stale : Domain + 1 : None : None : None : False : True : Reals + 3 : None : None : None : False : True : Reals + a : None : None : None : False : True : Reals + +3 Declarations: I y x +""" + % tuple(repr(_) for _ in m.I.ordered_iter()), + OUT.getvalue(), + ) + @unittest.skipIf(not 'glpk' in solvers, "glpk solver is not available") def test_solve1(self): model = Block(concrete=True) diff --git a/pyomo/core/tests/unit/test_param.py b/pyomo/core/tests/unit/test_param.py index b335ce33777..e60372c57e3 100644 --- a/pyomo/core/tests/unit/test_param.py +++ b/pyomo/core/tests/unit/test_param.py @@ -174,7 +174,7 @@ def test_setitem_index_error(self): raise def test_setitem_preexisting(self): - keys = self.instance.A.sparse_keys() + keys = list(self.instance.A.sparse_keys()) if not keys or None in keys: return @@ -356,73 +356,69 @@ def test_items(self): raise def test_iterkeys(self): - test = self.instance.A.iterkeys() + with LoggingIntercept() as LOG: + test = self.instance.A.iterkeys() + self.assertIn("The iterkeys method is deprecated.", LOG.getvalue()) self.assertEqual(sorted(test), sorted(self.instance.A.keys())) def test_itervalues(self): - expectException = False - # len(self.sparse_data) < len(self.data) and \ - # not self.instance.A._default_val is None and \ - # not self.instance.A.mutable - try: - test = self.instance.A.values() - test = zip(self.instance.A.keys(), test) - if self.instance.A._default_val is NoValue: - self.validateDict(self.sparse_data.items(), test) - else: - self.validateDict(self.data.items(), test) - self.assertFalse(expectException) - except ValueError: - if not expectException: - raise + with LoggingIntercept() as LOG: + test = self.instance.A.itervalues() + self.assertIn("The itervalues method is deprecated.", LOG.getvalue()) + self.assertEqual(list(self.instance.A.values()), list(test)) def test_iteritems(self): - expectException = False - # len(self.sparse_data) < len(self.data) and \ - # not self.instance.A._default_val is None and \ - # not self.instance.A.mutable - try: - test = self.instance.A.items() - if self.instance.A._default_val is NoValue: - self.validateDict(self.sparse_data.items(), test) - else: - self.validateDict(self.data.items(), test) - self.assertFalse(expectException) - except ValueError: - if not expectException: - raise + with LoggingIntercept() as LOG: + test = self.instance.A.iteritems() + self.assertIn("The iteritems method is deprecated.", LOG.getvalue()) + self.assertEqual(list(self.instance.A.items()), list(test)) def test_sparse_keys(self): test = self.instance.A.sparse_keys() - self.assertEqual(type(test), list) self.assertEqual(sorted(test), sorted(self.sparse_data.keys())) def test_sparse_values(self): - # self.instance.pprint() test = self.instance.A.sparse_values() - self.assertEqual(type(test), list) - # print test - # print self.sparse_data.items() test = zip(self.instance.A.keys(), test) self.validateDict(self.sparse_data.items(), test) def test_sparse_items(self): test = self.instance.A.sparse_items() - self.assertEqual(type(test), list) self.validateDict(self.sparse_data.items(), test) def test_sparse_iterkeys(self): - test = self.instance.A.sparse_iterkeys() - self.assertEqual(sorted(test), sorted(self.sparse_data.keys())) + with LoggingIntercept() as LOG: + test = self.instance.A.sparse_iterkeys() + self.assertIn("The sparse_iterkeys method is deprecated.", LOG.getvalue()) + self.assertEqual(list(test), list(self.instance.A.sparse_keys())) def test_sparse_itervalues(self): - test = self.instance.A.sparse_itervalues() - test = zip(self.instance.A.keys(), test) - self.validateDict(self.sparse_data.items(), test) + with LoggingIntercept() as LOG: + test = self.instance.A.sparse_itervalues() + self.assertIn("The sparse_itervalues method is deprecated.", LOG.getvalue()) + self.assertEqual(list(test), list(self.instance.A.sparse_values())) def test_sparse_iteritems(self): - test = self.instance.A.sparse_iteritems() - self.validateDict(self.sparse_data.items(), test) + with LoggingIntercept() as LOG: + test = self.instance.A.sparse_iteritems() + self.assertIn("The sparse_iteritems method is deprecated.", LOG.getvalue()) + self.assertEqual(list(test), list(self.instance.A.sparse_items())) + + def test_extract_values(self): + if self.instance.A._default_val is NoValue: + ref = self.sparse_data + else: + ref = self.data + vals = self.instance.A.extract_values() + self.assertEqual(ref, vals) + for k, v in vals.items(): + self.assertIsInstance(v, (float, int)) + + def test_extract_values_sparse(self): + vals = self.instance.A.extract_values_sparse() + self.assertEqual(self.sparse_data, vals) + for k, v in vals.items(): + self.assertIsInstance(v, (float, int)) def test_len(self): # """Check the use of len""" @@ -849,17 +845,42 @@ def setUp(self, **kwds): def test_value_scalar(self): # """Check the value of the parameter""" if self.data.get(None, NoValue) is NoValue: - self.assertRaises(ValueError, value, self.instance.A) - self.assertRaises(TypeError, float, self.instance.A) - self.assertRaises(TypeError, int, self.instance.A) + if self.instance.A.mutable: + msg = "The Param value is currently set to an invalid value." + with self.assertRaisesRegex(ValueError, msg): + value(self.instance.A) + else: + msg = "The Param value is undefined and no default value is specified" + with self.assertRaisesRegex(ValueError, msg): + value(self.instance.A) else: val = self.data[None] tmp = value(self.instance.A) self.assertEqual(type(tmp), type(val)) self.assertEqual(tmp, val) + self.assertIsInstance(val, (int, float)) - self.assertRaises(TypeError, float, self.instance.A) - self.assertRaises(TypeError, int, self.instance.A) + def test_cast_to_number(self): + if self.instance.A.mutable: + msg = r"Implicit conversion of Pyomo numeric value \(A\) to " + with self.assertRaisesRegex(TypeError, msg + 'float'): + float(self.instance.A) + with self.assertRaisesRegex(TypeError, msg + 'int'): + int(self.instance.A) + elif self.data.get(None, NoValue) is NoValue: + msg = "The Param value is undefined and no default value is specified" + with self.assertRaisesRegex(ValueError, msg): + float(self.instance.A) + with self.assertRaisesRegex(ValueError, msg): + int(self.instance.A) + else: + val = self.data[None] + tmp = float(self.instance.A) + self.assertEqual(tmp, val) + self.assertIs(type(tmp), float) + tmp = int(self.instance.A) + self.assertEqual(tmp, int(val)) + self.assertIs(type(tmp), int) def test_call(self): # """Check the use of the __call__ method""" @@ -867,47 +888,48 @@ def test_call(self): self.sparse_data.get(None, 0) is NoValue or self.data.get(None, NoValue) is NoValue ): # not self.sparse_data: - self.assertRaisesRegex( - ValueError, - ".*currently set to an invalid value", - self.instance.A.__call__, - ) + if self.instance.A.mutable: + msg = "The Param value is currently set to an invalid value." + else: + msg = "The Param value is undefined and no default value is specified" + with self.assertRaisesRegex(ValueError, msg): + self.instance.A(), else: self.assertEqual(self.instance.A(), self.data[None]) def test_get_valueattr(self): self.assertEqual(self.instance.A._value, self.sparse_data.get(None, NoValue)) if self.data.get(None, 0) is NoValue: # not self.sparse_data: - try: - value(self.instance.A) - self.fail("Expected value error") - except ValueError: - pass + if self.instance.A.mutable: + msg = "The Param value is currently set to an invalid value." + else: + msg = "The Param value is undefined and no default value is specified" + with self.assertRaisesRegex(ValueError, msg): + self.instance.A.value else: self.assertEqual(self.instance.A.value, self.data[None]) def test_set_valueattr(self): - self.instance.A.value = 4.3 - self.assertEqual(self.instance.A.value, 4.3) - self.assertEqual(self.instance.A(), 4.3) - - def test_get_value(self): - if ( - self.sparse_data.get(None, 0) is NoValue - or self.data.get(None, NoValue) is NoValue - ): # not self.sparse_data: - try: - value(self.instance.A) - self.fail("Expected value error") - except ValueError: - pass + if self.instance.A.mutable: + self.instance.A.value = 4.3 + self.assertEqual(self.instance.A.value, 4.3) + self.assertEqual(self.instance.A(), 4.3) else: - self.assertEqual(self.instance.A.value, self.data[None]) + with self.assertRaisesRegex( + TypeError, "Attempting to set the value of the immutable parameter A" + ): + self.instance.A.value = 4.3 def test_set_value(self): - self.instance.A = 4.3 - self.assertEqual(self.instance.A.value, 4.3) - self.assertEqual(self.instance.A(), 4.3) + if self.instance.A.mutable: + self.instance.A = 4.3 + self.assertEqual(self.instance.A.value, 4.3) + self.assertEqual(self.instance.A(), 4.3) + else: + with self.assertRaisesRegex( + TypeError, "Attempting to set the value of the immutable parameter A" + ): + self.instance.A = 4.3 def test_is_indexed(self): self.assertFalse(self.instance.A.is_indexed()) @@ -916,6 +938,58 @@ def test_dim(self): # """Check the use of dim""" self.assertEqual(self.instance.A.dim(), 0) + def test_extract_values(self): + if self.instance.A._default_val is NoValue: + ref = self.sparse_data + else: + ref = self.data + vals = self.instance.A.extract_values() + self.assertEqual(ref, vals) + for k, v in vals.items(): + self.assertIsInstance(v, (float, int)) + + def test_extract_values_sparse(self): + vals = self.instance.A.extract_values_sparse() + self.assertEqual(self.sparse_data, vals) + for k, v in vals.items(): + self.assertIsInstance(v, (float, int)) + + +class ScalarParam_immutable_noDefault(ScalarTester, unittest.TestCase): + def setUp(self, **kwds): + # + # Sparse single-index Param, no default + # + self.model = AbstractModel() + ScalarTester.setUp(self, mutable=False, **kwds) + + self.sparse_data = {} + self.data = {None: NoValue} + + +class ScalarParam_immutable_init(ScalarTester, unittest.TestCase): + def setUp(self, **kwds): + # + # Sparse single-index Param, no default + # + self.model = AbstractModel() + ScalarTester.setUp(self, mutable=False, initialize=1.3, **kwds) + + self.sparse_data = {None: 1.3} + self.data = {None: 1.3} + + +class ScalarParam_immutable_floatDefault(ScalarTester, unittest.TestCase): + def setUp(self, **kwds): + # + # Sparse single-index Param, no default + # + self.model = AbstractModel() + ScalarTester.setUp(self, mutable=False, default=1.3, **kwds) + + self.sparse_data = {} + self.data = {None: 1.3} + class ScalarParam_mutable_noDefault(ScalarTester, unittest.TestCase): def setUp(self, **kwds): diff --git a/pyomo/gdp/disjunct.py b/pyomo/gdp/disjunct.py index fd2f0c5afd6..d20cbd449fc 100644 --- a/pyomo/gdp/disjunct.py +++ b/pyomo/gdp/disjunct.py @@ -765,7 +765,7 @@ def _pprint(self): ("Index", self._index_set if self.is_indexed() else None), ("Active", self.active), ], - self.items(), + self.items, ("Disjuncts", "Active", "XOR"), lambda k, v: [[x.name for x in v.disjuncts], v.active, v.xor], ) diff --git a/pyomo/mpec/complementarity.py b/pyomo/mpec/complementarity.py index be1779f37e0..c3d0a4b613c 100644 --- a/pyomo/mpec/complementarity.py +++ b/pyomo/mpec/complementarity.py @@ -287,9 +287,9 @@ def _pprint(self): # Book). _transformed = not issubclass(self.ctype, Complementarity) - def _conditional_block_printer(ostream, idx, data): + def _conditional_block_printer(ostream, sort, idx, data): if _transformed or len(data.component_map()): - self._pprint_callback(ostream, idx, data) + self._pprint_callback(ostream, sort, idx, data) return ( [ @@ -297,7 +297,7 @@ def _conditional_block_printer(ostream, idx, data): ("Index", self._index_set if self.is_indexed() else None), ("Active", self.active), ], - self._data.items(), + self.items, ("Arg0", "Arg1", "Active"), (_table_data, _conditional_block_printer), ) diff --git a/pyomo/network/arc.py b/pyomo/network/arc.py index 5bea3f75704..560c59f7c4d 100644 --- a/pyomo/network/arc.py +++ b/pyomo/network/arc.py @@ -368,7 +368,7 @@ def _pprint(self): ("Index", self._index_set if self.is_indexed() else None), ("Active", self.active), ], - self.items(), + self.items, ("Ports", "Directed", "Active"), lambda k, v: [ "(%s, %s)" % v.ports if v.ports is not None else None, diff --git a/pyomo/network/port.py b/pyomo/network/port.py index 882e0bf911b..10dcd7b94e1 100644 --- a/pyomo/network/port.py +++ b/pyomo/network/port.py @@ -415,7 +415,7 @@ def _add_from_container(self, port, items): else: port.add(val) - def _pprint(self, ostream=None, verbose=False): + def _pprint(self): """Print component information.""" def _line_generator(k, v): @@ -433,7 +433,7 @@ def _line_generator(k, v): ("Size", len(self)), ("Index", self._index_set if self.is_indexed() else None), ], - self._data.items(), + self.items, ("Name", "Size", "Variable"), _line_generator, )