Skip to content

Commit

Permalink
Change to _GraphManager, separate python Model class
Browse files Browse the repository at this point in the history
  • Loading branch information
wbernoudy committed Nov 20, 2024
1 parent 57aae02 commit 15a5390
Show file tree
Hide file tree
Showing 12 changed files with 512 additions and 454 deletions.
18 changes: 9 additions & 9 deletions dwave/optimization/model.pxd → dwave/optimization/_model.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ from dwave.optimization.libcpp.state cimport State as cppState
__all__ = ["Model"]


cdef class _Model:
cdef class _GraphManager:
cpdef bool is_locked(self) noexcept
cpdef Py_ssize_t num_nodes(self) noexcept

Expand Down Expand Up @@ -59,9 +59,9 @@ cdef class _Model:
cdef object _data_sources


cdef class Model(_Model):
cpdef Py_ssize_t num_constraints(self) noexcept
cpdef Py_ssize_t num_decisions(self) noexcept
cdef class _Model(_GraphManager):
cpdef Py_ssize_t _num_constraints(self) noexcept
cpdef Py_ssize_t _num_decisions(self) noexcept

cdef readonly object objective # todo: cdef ArraySymbol?
"""Objective to be minimized.
Expand Down Expand Up @@ -94,7 +94,7 @@ cdef class States:
cpdef resolve(self)
cpdef Py_ssize_t size(self) except -1

cdef _Model _model(self)
cdef _GraphManager _model(self)

# In order to not create a circular reference, we only hold a weakref
# to the model from the states. This introduces some overhead, but it
Expand All @@ -117,20 +117,20 @@ cdef class States:

cdef class Symbol:
# Inheriting nodes must call this method from their __init__()
cdef void initialize_node(self, _Model model, cppNode* node_ptr) noexcept
cdef void initialize_node(self, _GraphManager model, cppNode* node_ptr) noexcept

cpdef uintptr_t id(self) noexcept

# Exactly deref(self.expired_ptr)
cpdef bool expired(self) noexcept

@staticmethod
cdef Symbol from_ptr(_Model model, cppNode* ptr)
cdef Symbol from_ptr(_GraphManager model, cppNode* ptr)

# Hold on to a reference to the Model, both for access but also, importantly,
# to ensure that the model doesn't get garbage collected unless all of
# the observers have also been garbage collected.
cdef readonly _Model model
cdef readonly _GraphManager model

# Hold Node* pointer. This is redundant as most observers will also hold
# a pointer to their observed node with the correct type. But the cost
Expand All @@ -148,7 +148,7 @@ cdef class Symbol:
# also Symbols (probably a fair assumption)
cdef class ArraySymbol(Symbol):
# Inheriting symbols must call this method from their __init__()
cdef void initialize_arraynode(self, _Model model, cppArrayNode* array_ptr) noexcept
cdef void initialize_arraynode(self, _GraphManager model, cppArrayNode* array_ptr) noexcept

# Hold ArrayNode* pointer. Again this is redundant, because we're also holding
# a pointer to Node* and we can theoretically dynamic cast each time.
Expand Down
48 changes: 8 additions & 40 deletions dwave/optimization/model.pyi → dwave/optimization/_model.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ from dwave.optimization.symbols import *
_ShapeLike: typing.TypeAlias = typing.Union[int, collections.abc.Sequence[int]]


class _Model:
class _GraphManager:
@property
def states(self) -> States: ...

Expand Down Expand Up @@ -71,50 +71,18 @@ class _Model:
def unlock(self): ...


class Model(_Model):
class _Model(_GraphManager):
def __init__(self): ...

@property
def objective(self) -> ArraySymbol: ...
def add_constraint(self, value: ArraySymbol) -> ArraySymbol: ...
def binary(self, shape: typing.Optional[_ShapeLike] = None) -> BinaryVariable: ...
def decision_state_size(self) -> int: ...

def disjoint_bit_sets(
self, primary_set_size: int, num_disjoint_sets: int,
) -> tuple[DisjointBitSets, tuple[DisjointBitSet, ...]]: ...

def disjoint_lists(
self, primary_set_size: int, num_disjoint_lists: int,
) -> tuple[DisjointLists, tuple[DisjointList, ...]]: ...

def feasible(self, index: int = 0) -> bool: ...

def integer(
self,
shape: typing.Optional[_ShapeLike] = None,
lower_bound: typing.Optional[int] = None,
upper_bound: typing.Optional[int] = None,
) -> IntegerVariable: ...

def iter_constraints(self) -> collections.abc.Iterator[ArraySymbol]: ...
def iter_decisions(self) -> collections.abc.Iterator[Symbol]: ...
def list(self, n: int) -> ListVariable: ...
def lock(self) -> contextlib.AbstractContextManager: ...
def minimize(self, value: ArraySymbol): ...
def num_constraints(self) -> int: ...
def num_decisions(self) -> int: ...

# dev note: this is underspecified, but it would be quite complex to fully
# specify the linear/quadratic so let's leave it alone for now.
def quadratic_model(self, x: ArraySymbol, quadratic, linear=None) -> QuadraticModel: ...

def set(
self,
n: int,
min_size: int = 0,
max_size: typing.Optional[int] = None,
) -> SetVariable: ...
def _add_constraint(self, value: ArraySymbol) -> ArraySymbol: ...
def _iter_constraints(self) -> collections.abc.Iterator[ArraySymbol]: ...
def _iter_decisions(self) -> collections.abc.Iterator[Symbol]: ...
def _minimize(self, value: ArraySymbol): ...
def _num_constraints(self) -> int: ...
def _num_decisions(self) -> int: ...


class States:
Expand Down
Loading

0 comments on commit 15a5390

Please sign in to comment.