diff --git a/dwave/optimization/model.pyx b/dwave/optimization/model.pyx index 246257f9..629e9897 100644 --- a/dwave/optimization/model.pyx +++ b/dwave/optimization/model.pyx @@ -40,6 +40,7 @@ import numpy as np from cpython cimport Py_buffer from cython.operator cimport dereference as deref, preincrement as inc from cython.operator cimport typeid +from libc.stdint cimport uintptr_t from libcpp cimport bool from libcpp.utility cimport move from libcpp.vector cimport vector @@ -1193,6 +1194,20 @@ cdef class Symbol: # via their subclasses. raise ValueError("Symbols cannot be constructed directly") + def __repr__(self): + """Return a representation of the symbol. + + The representation refers to the id of the underlying node, rather than + the id of the Python symbol. + """ + cls = type(self) + # We refer to the node_ptr, which is not necessarily the address of the + # C++ node, as it sublasses Node. + # But this is unique to each node, and functions as an id rather than + # as a pointer, so that's OK. + # Otherwise we aim to match Python's default __repr__. + return f"<{cls.__module__}.{cls.__qualname__} at {self.node_ptr:#x}>" + cdef void initialize_node(self, Model model, cppNode* node_ptr) noexcept: self.model = model diff --git a/releasenotes/notes/fix-to_networkx-a78f0f669cc9638c.yaml b/releasenotes/notes/fix-to_networkx-a78f0f669cc9638c.yaml new file mode 100644 index 00000000..63d1e6f7 --- /dev/null +++ b/releasenotes/notes/fix-to_networkx-a78f0f669cc9638c.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + Make ``repr()`` of symbols unique to the underlying node, rather than to the Python symbol. + See `#52 _. diff --git a/tests/test_model.py b/tests/test_model.py index 232cdd4c..bca8dde7 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -424,3 +424,14 @@ def test_abstract(self): from dwave.optimization.model import Symbol with self.assertRaisesRegex(ValueError, "Symbols cannot be constructed directly"): Symbol() + + def test_repr(self): + model = Model() + c0 = model.constant(5) + c1, = model.iter_symbols() + c2 = model.constant(5) + + # the specific form is an implementation detail, but different symbols + # representing the same underlying node should have the same repr + self.assertEqual(repr(c0), repr(c1)) + self.assertNotEqual(repr(c0), repr(c2))