Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c6389b8
Return HashKey fro HashDispatcher (and not id())
jsiirola Feb 8, 2026
6e10267
Improve tuple handling in hash dispatcher: only generate HashKeys whe…
jsiirola Feb 8, 2026
ad99ee0
Minor cleanup
jsiirola Feb 8, 2026
6f793d9
Make HashDispatcher callable (support use in place of id())
jsiirola Feb 8, 2026
6ba2426
Minor ComponentMap performance improvements
jsiirola Feb 10, 2026
59f7ba2
Support deriving from ComponentMap/ComponentSet
jsiirola Feb 10, 2026
fe4d4da
Standardize str() and KeyError for COmponentMap/Set
jsiirola Feb 10, 2026
c2238d3
Add ObjectIdMap/ObjectIdSet
jsiirola Feb 10, 2026
e60cabb
Minor code cleanup/fixes
jsiirola Feb 10, 2026
e3c8cbd
NFC: update comments/docstrings
jsiirola Feb 10, 2026
9b3e036
Support cleaner fallback to ComponentMap when first positional argume…
jsiirola Feb 10, 2026
bfd5092
Add / update tests
jsiirola Feb 10, 2026
4cc18e8
Merge branch 'main' into component-map-hashing
jsiirola Feb 10, 2026
a865f03
NFC: apply black
jsiirola Feb 10, 2026
c8823a7
Avoid resolving expressions created during ComponentMap comparisons
jsiirola Feb 10, 2026
dcee582
Generate more human-readable str(ComponentMap)/str(COmponentSet)
jsiirola Feb 10, 2026
156557a
ComponetMap keys/values/items should return views
jsiirola Feb 10, 2026
5458af6
Merge branch 'main' into component-map-hashing
jsiirola Feb 10, 2026
bd7835e
Merge branch 'main' into component-map-hashing
jsiirola Jun 2, 2026
ad1fa4f
Improve/test HashKey repr/str
jsiirola Jun 2, 2026
facfa68
NFC: update docs
jsiirola Jun 2, 2026
7560771
Make update() API consistent with dict/set
jsiirola Jun 2, 2026
1a4fecc
Fix typo
jsiirola Jun 2, 2026
5c1dd71
We don't need a full HashKey class; just a flag to add in a native tuple
jsiirola Jun 2, 2026
484b6f7
Support ComponentMap as the substitution map for ExpressionReplacemen…
jsiirola Jun 2, 2026
11cc469
Don't look up ComponentMap values by key id()
jsiirola Jun 2, 2026
7ee41f0
Track updated exception message
jsiirola Jun 2, 2026
c455f6b
Catch that comparing numpy types can produce numpy bools
jsiirola Jun 2, 2026
9365fff
Guard against object collection under ExpressionReplacementVisitor
jsiirola Jun 2, 2026
295d8b6
Update to track simplification of string representations
jsiirola Jun 2, 2026
a6ac21f
Expose ObjectIdMap / ObjectIdSet through pyomo.common.collections
jsiirola Jun 2, 2026
5ebac4b
Update test for pypy
jsiirola Jun 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pyomo/common/collections/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
from collections.abc import Mapping, MutableMapping, MutableSet, Sequence, Set

from .bunch import Bunch
from .component_map import ComponentMap, DefaultComponentMap
from .component_set import ComponentSet
from .component_map import ComponentMap, DefaultComponentMap, ObjectIdMap
from .component_set import ComponentSet, ObjectIdSet
from .orderedset import OrderedSet
36 changes: 34 additions & 2 deletions pyomo/common/collections/_hasher.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
from collections import defaultdict


class _HashKey:
"""Utility class to support hashing by object id()

This class should never be instantiated, and should never be
accessed referenced by user code. Instead this provides a simple
:class:`type` that we can use as an internal flag to differentiate
between an :class:`int` key and the result from :func:`id()`.

"""

pass


class HashDispatcher(defaultdict):
"""Dispatch table for generating "universal" hashing of all Python objects.

Expand All @@ -25,11 +38,18 @@ class HashDispatcher(defaultdict):
appropriate hashing strategy to each element within the tuple.
"""

__slots__ = ()

def __init__(self, *args, **kwargs):
super().__init__(lambda: self._missing_impl, *args, **kwargs)
self[tuple] = self._tuple

def _missing_impl(self, val):
# Inherit the hasher from a base class, if found
for _type in val.__class__.__mro__[1:]:
if _type in self:
self[val.__class__] = ans = self[_type]
return ans(val)
try:
hash(val)
self[val.__class__] = self._hashable
Expand All @@ -43,10 +63,18 @@ def _hashable(val):

@staticmethod
def _unhashable(val):
return id(val)
return _HashKey, id(val)

def _tuple(self, val):
return tuple(self[i.__class__](i) for i in val)
try:
# if *this tuple* is hashable, then use it as the key
hash(val)
return val
except:
# duplicate the tuple, recursively processing all fields.
# The use of val.__class__ ensures that derived things (like
# namedtuples) have their class preserved.
return val.__class__(self[i.__class__](i) for i in val)

def hashable(self, obj, hashable=None):
if isinstance(obj, type):
Expand All @@ -60,6 +88,10 @@ def hashable(self, obj, hashable=None):
return fcn is self._hashable
self[cls] = self._hashable if hashable else self._unhashable

def __call__(self, obj):
# Make the dispatcher callable so that it can be used in place of id()
return self[obj.__class__](obj)


#: The global 'hasher' instance for managing "universal" hashing.
#:
Expand Down
Loading
Loading