Source code for pyomo.core.kernel.tuple_container

#  ___________________________________________________________________________
#
#  Pyomo: Python Optimization Modeling Objects
#  Copyright (c) 2008-2024
#  National Technology and Engineering Solutions of Sandia, LLC
#  Under the terms of Contract DE-NA0003525 with National Technology and
#  Engineering Solutions of Sandia, LLC, the U.S. Government retains certain
#  rights in this software.
#  This software is distributed under the 3-clause BSD License.
#  ___________________________________________________________________________

import collections.abc

from pyomo.core.kernel.homogeneous_container import IHomogeneousContainer


[docs]class TupleContainer(IHomogeneousContainer, collections.abc.Sequence): """ A partial implementation of the IHomogeneousContainer interface that provides tuple-like storage functionality. Complete implementations need to set the _ctype property at the class level and initialize the remaining ICategorizedObject attributes during object creation. If using __slots__, a slot named "_data" must be included. Note that this implementation allows nested storage of other ICategorizedObjectContainer implementations that are defined with the same ctype. """ __slots__ = () _child_storage_delimiter_string = "" _child_storage_entry_string = "[%s]"
[docs] def __init__(self, *args): self._data = [] self._init(args) self._data = tuple(self._data)
def _init(self, args): if len(args) > 0: if len(args) > 1: raise TypeError( "%s expected at most 1 arguments, " "got %s" % (self.__class__.__name__, len(args)) ) for item in args[0]: self._insert(len(self), item) def _fast_insert(self, i, item): item._update_parent_and_storage_key(self, i) self._data.insert(i, item) def _insert(self, i, item): if item.ctype is self.ctype: if item._parent is None: self._fast_insert(i, item) return # see note about allowing objects to live # in more than one container raise ValueError( "Invalid assignment to type %s with index %s. " "A parent container has already been " "assigned to the object being inserted: %s" % (self.__class__.__name__, i, item.parent.name) ) else: raise TypeError( "Invalid assignment to type %s with index %s. " "The object being inserted has the wrong " "category type: %s" % (self.__class__.__name__, i, item.ctype) ) # # Define the ICategorizedObjectContainer abstract methods #
[docs] def child(self, key): """Get the child object associated with a given storage key for this container. Raises: KeyError: if the argument is not a storage key for any children of this container """ try: return self.__getitem__(key) except (IndexError, TypeError): raise KeyError(str(key))
[docs] def children(self): """A generator over the children of this container.""" return self._data.__iter__()
# # Define the Sequence abstract methods # def __getitem__(self, i): return self._data[i] def __len__(self): return self._data.__len__() # # Extend the interface to allow for equality comparison # # We want to avoid generating Pyomo expressions due to # comparison of values. # Convert both objects to a plain tuple of (type(val), # id(val)) tuples and compare that instead.
[docs] def __eq__(self, other): if not isinstance(other, (collections.abc.Set, collections.abc.Sequence)): return False return tuple((type(val), id(val)) for val in self) == tuple( (type(val), id(val)) for val in other )
[docs] def __ne__(self, other): return not (self == other)
# # Override a few default implementations on Sequence # # We want to avoid generating Pyomo expressions due to # comparison of values. def __iter__(self): return self._data.__iter__() def __contains__(self, item): item_id = id(item) return any(item_id == id(_v) for _v in self._data)
[docs] def index(self, item, start=0, stop=None): """S.index(value, [start, [stop]]) -> integer -- return first index of value. Raises ValueError if the value is not present. """ if start is not None and start < 0: start = max(len(self) + start, 0) if stop is not None and stop < 0: stop += len(self) i = start while stop is None or i < stop: try: if self[i] is item: return i except IndexError: break i += 1 raise ValueError
[docs] def count(self, item): 'S.count(value) -> integer -- return number of occurrences of value' item_id = id(item) cnt = sum(1 for _v in self._data if id(_v) == item_id) assert cnt == 1 return cnt