Nonlinear Models#

This page describes the dwave-optimization package’s nonlinear model: classes, attributes, and methods.

For an introduction to formulating problems as nonlinear models, see the Model Construction section. The Traveling Salesperson: Simple Nonlinear Model demonstrates a simple use of the Leap hybrid nonlinear solver on a problem formulated as a nonlinear model; for a more-advanced end-to-end example, see the Vehicle Routing: Using a Nonlinear Model section.

Nonlinear models are especially suited for use with decision variables that represent a common logic, such as subsets of choices or permutations of ordering. For example, in a traveling salesperson problem permutations of the variables representing cities can signify the order of the route being optimized and in a knapsack problem the variables representing items can be divided into subsets of packed and not packed.

Model Class#

class Model[source]#

Nonlinear model.

The nonlinear model represents a general optimization problem with an objective function and/or constraints over variables of various types.

The Model class can contain this model and its methods provide convenient utilities for working with representations of a problem.

Examples

This example creates a model for a flow-shop-scheduling problem with two jobs on three machines.

>>> from dwave.optimization.generators import flow_shop_scheduling
...
>>> processing_times = [[10, 5, 7], [20, 10, 15]]
>>> model = flow_shop_scheduling(processing_times=processing_times)
add_constraint(value)[source]#

Add a constraint to the model.

For a solution to the model to be feasible, the constraint must be satisfied.

Parameters:

value – Value that must evaluate to True for the state of the model to be feasible.

Returns:

The symbol associated with the constraint.

Examples

This example adds a single constraint to a model.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer()
>>> c = model.constant(5)
>>> constraint_sym = model.add_constraint(i <= c)

The returned constraint symbol (a LessEqual for this example) can be assigned, and evaluated for, a model state:

>>> with model.lock():
...     model.states.resize(1)
...     i.set_state(0, 1) # Feasible state
...     print(constraint_sym.state(0))
1.0
>>> with model.lock():
...     i.set_state(0, 6) # Infeasible state
...     print(constraint_sym.state(0))
0.0
binary(shape: None | _ShapeLike = None, lower_bound: None | np.typing.ArrayLike = None, upper_bound: None | np.typing.ArrayLike = None, sum_subject_to: None | list[tuple[str, float]] = None, axes_sums_subject_to: None | list[tuple[int, str | list[str], float | list[float]]] = None) BinaryVariable[source]#

Add a binary decision variable to the model.

A binary symbol is an array of True/False values assigned as a solution to the problem being modeled.

Parameters:
  • shape (optional) – Shape of the binary array to create, formatted as an integer or a tuple of integers. If None, creates a zero-dimensional (scalar) binary variable.

  • lower_bound (optional) – Lower bound(s) for the symbol. Can be scalar (one bound for all variables) or an array (one bound for each variable). Non-Boolean values are rounded up to the domain [0,1]. If None, the default value of 0 is used.

  • upper_bound (optional) – Upper bound(s) for the symbol. Can be scalar (one bound for all variables) or an array (one bound for each variable). Non-Boolean values are rounded down to the domain [0,1]. If None, the default value of 1 is used.

  • sum_subject_to (optional) – Constraint on the sum of the values in the array. Must be an array of tuples where each tuple has the form: (operator, bound). - operator (str): The constraint operator (“<=”, “==”, or “>=”). - bound (float): The constraint bound. If provided, the sum of values within the array must satisfy the corresponding operator–bound pair. Note 1: At most one sum constraint may be provided. Note 2: If provided, axes_sums_subject_to must None.

  • axes_sums_subject_to (optional) – Constraint on the sum of the values in each slice along a fixed axis in the array. Must be an array of tuples where each tuple has the form: (axis, operator(s), bound(s)). - axis (int): The axis that the constraint is applied to. - operator(s) (str | array[str]): The constraint operator(s) (“<=”, “==”, or “>=”). A single operator applies to all slice along the axis; an array specifies one operator per slice. - bound(s) (float | array[float]): The constraint bound. A single value applies to all slices; an array specifies one bound per slice. If provided, the sum of values within each slice along the specified axis must satisfy the corresponding operator–bound pair. Note 1: At most one sum constraint may be provided. Note 2: If provided, sum_subject_to must None.

Returns:

A binary symbol at the root of the directed acyclic graph for the model.

Examples

This example adds a \(20 \times 30\)-sized binary variable to a model.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> x = model.binary((20, 30))
>>> x.shape()
(20, 30)

This example adds a \(2\)-sized binary symbol with a scalar lower bound and index-wise upper bounds to a model.

>>> from dwave.optimization.model import Model
>>> import numpy as np
>>> model = Model()
>>> b = model.binary(2, lower_bound=-1.1, upper_bound=[1.1, 0.9])
>>> b.upper_bound()
array([1., 0.])

This example adds a \((2x3)\)-sized binary symbol with index-wise lower bounds and a sum constraint along axis 1. Let x_i (int i : 0 <= i <= 2) denote the sum of the values within slice i along axis 1. For each state defined for this symbol: (x_0 <= 0), (x_1 == 2), and (x_2 >= 1).

>>> from dwave.optimization.model import Model
>>> import numpy as np
>>> model = Model()
>>> b = model.binary([2, 3], lower_bound=[[0, 1, 1], [0, 1, 0]],
... axes_sums_subject_to=[(1, ["<=", "==", ">="], [0, 2, 1])])
>>> np.all(b.sum_constraints() == [(1, ["<=", "==", ">="], [0, 2, 1])])
True

This example adds a \(6\)-sized binary symbol such that the sum of the values within the array is equal to 2.

>>> from dwave.optimization.model import Model
>>> import numpy as np
>>> model = Model()
>>> b = model.binary(6, sum_subject_to=[("==", 2)])
>>> np.all(b.sum_constraints() == [(["=="], [2])])
True

Changed in version 0.6.7: Beginning in version 0.6.7, user-defined index-wise bounds are supported.

Changed in version 0.6.13: Beginning in version 0.6.13, user-defined sum constraints are supported.

constant(array_like: numpy.typing.ArrayLike) Constant[source]#

Add a constant to the model.

A constant symbol is an array of floats used in the model’s formulation.

To prevent redundancy, constants are cached. Repeated calls to constant() with the same array_like argument return the first Constant instance. You can clear cache by calling the clear_cache() method.

Parameters:

array_like – An array-like representing a constant. Can be a scalar or a NumPy array. If the numpy.dtype of the array is numpy.double, the array is not copied.

Returns:

A constant symbol at the root of the directed acyclic graph for the model.

Examples

This example creates a \(1 \times 4\)-sized constant symbol with the specified values.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> time_limits = model.constant([10, 15, 5, 8.5])

See also

Constant: Generated symbol

binary(), input(), integer()

iter_symbols()

Changed in version 0.6.4: Beginning in version 0.6.4, constants are cached. Also known as memoization.

decision_state_size()[source]#

Estimate the size, in bytes, of a model’s decision states.

For more details, see the state_size() method. This method differs by counting the states of only the decision variables.

Returns:

Estimated state size of the model’s decision variables.

Return type:

int

Examples

This example estimates the size of a model’s decision state. In this example a single value is added to a \(5\times4\) array. The output of the addition is also a \(5\times4\) array. Each element of each array requires \(8\) bytes to represent in memory. The total state size is \((5*4 + 1 + 5*4) * 8 = 328\) bytes, but the decision state size is only \(5*4*8 = 160\).

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer((5, 4))    # 5x4 array of integers
>>> c = model.constant(1)        # one scalar value, not a decision
>>> y = i + c                    # 5x4 array of values, not a decision
>>> model.state_size()           # (5*4 + 1 + 5*4) * 8 bytes
328
>>> model.decision_state_size()  # 5*4*8 bytes
160

See also

Symbol.state_size() Estimates the size of a symbol’s state

ArraySymbol.state_size() Estimates the size of an array symbol’s state

Model.state_size() Estimates the size of all of a model’s states

disjoint_bit_sets(primary_set_size: int, num_disjoint_sets: int) tuple[DisjointBitSets, tuple[DisjointBitSet, ...]][source]#

Add a disjoint-sets decision variable to the model.

A disjoint-sets symbol divides a set of elements into ordered partitions of bit sets, with ones signifying elements in the set, where the placement of these ones is assigned as a solution to the problem being modeled.

The elements are values of range(primary_set_size). Each of the num_disjoint_sets ordered partitions is a bit set (array) of length primary_set_size with ones at the indices of elements currently in the set, and zeros elsewhere. The set is disjoint in that for every index \(i\) between zero and primary_set_size, there is a single partition assigned a value of one at that position.

Also creates from the symbol num_disjoint_sets successors that output the disjoint sets as arrays.

Parameters:
  • primary_set_size – Number of elements in the primary set that are partitioned into disjoint sets. Must be non-negative.

  • num_disjoint_sets – Number of disjoint sets. Must be positive.

Returns:

A tuple where the first element is a disjoint-sets symbol at the root of the directed acyclic graph for the model and the second is a set of num_disjoint_sets successors.

Examples

This example creates a symbol of five elements that is divided into two sets, which could be part a bin_packing() problem of packing five items into two bins with an interest in the number of items packed in the first bin (three in the example solution shown here).

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> bins_set, bins_subsets = model.disjoint_bit_sets(5, 2)
>>> in_bin0 = bins_subsets[0].sum()
>>> with model.lock():
...     model.states.resize(1)
...     bins_set.set_state(0, [[0, 1, 1, 1, 0], [1, 0, 0, 0, 1]]) # Example solution
...     print(in_bin0.state(0))
3.0
Image of the model constructed in this example

Fig. 254 Visualization of the model as a directed acyclic graph. See the to_networkx() function for information on visualizing models.#

disjoint_lists(primary_set_size: int, num_disjoint_lists: int) tuple[DisjointLists, tuple[DisjointList, ...]][source]#

Add a disjoint-lists decision variable to the model.

Deprecated since version 0.6.7: The return behavior of this method will be changed in dwave.optimization 0.8.0. Use disjoint_lists_symbol().

A disjoint-lists symbol divides a set of the elements of range(primary_set_size) into num_disjoint_lists ordered partitions, with the division being assigned as a solution to the problem being modeled.

Also creates from the symbol num_disjoint_lists successors that output the disjoint lists as arrays.

Parameters:
  • primary_set_size – Number of elements in the primary set to be partitioned into disjoint lists. Must be non-negative.

  • num_disjoint_lists – Number of disjoint lists. Must be positive.

Returns:

A tuple where the first element is the disjoint-lists symbol at the root of the directed acyclic graph for the model and the second is a list of num_disjoint_lists successors.

Examples

This example creates a symbol of 10 elements that is divided into 4 lists.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> destinations, routes = model.disjoint_lists(10, 4)
disjoint_lists_symbol(primary_set_size: int, num_disjoint_lists: int) DisjointLists[source]#

Create a disjoint-lists symbol as a decision variable.

A disjoint-lists symbol divides a set of the elements of range(primary_set_size) into num_disjoint_lists ordered partitions, where the division is assigned as a solution to the problem being modeled.

Also creates from the symbol num_disjoint_lists successors that output the disjoint lists as arrays.

Parameters:
  • primary_set_size – Number of elements in the primary set to be partitioned into disjoint lists. Must be non-negative.

  • num_disjoint_lists – Number of disjoint lists. Must be positive.

Returns:

A disjoint-lists symbol at the root of the directed acyclic graph for the model.

Examples

This example creates a symbol of 10 elements that is divided into 4 lists.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> disjoint_lists = model.disjoint_lists_symbol(10, 4)
>>> disjoint_lists.primary_set_size()
10
>>> disjoint_lists.num_disjoint_lists()
4
>>> with model.lock():
...    model.states.resize(1)
...    disjoint_lists.set_state(0, [[0, 1, 2], [3, 5, 6], [4], [7, 8, 9]])
...    for i, disjoint_list in enumerate(disjoint_lists):
...        print(f"Element {i}: {disjoint_list.state(0)}")
Element 0: [0. 1. 2.]
Element 1: [3. 5. 6.]
Element 2: [4.]
Element 3: [7. 8. 9.]
Image of the model constructed in this example

Fig. 255 Visualization of the model as a directed acyclic graph. See the to_networkx() function for information on visualizing models.#

feasible(index: int = 0) bool[source]#

Check the feasibility of a state.

Parameters:

index – Index of the state to check for feasibility.

Returns:

Feasibility of the state.

Examples

This example demonstrates checking the feasibility of a simple model with feasible and infeasible states.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> b = model.binary()
>>> _ = model.add_constraint(b)
>>> model.states.resize(2)
>>> b.set_state(0, 1) # Feasible
>>> b.set_state(1, 0) # Infeasible
>>> with model.lock():
...     model.feasible(0)
True
>>> with model.lock():
...     model.feasible(1)
False
classmethod from_file(file, *, check_header=True, substitute=None, lock=False)[source]#

Construct a model from the given file.

Parameters:
  • file – File pointer to a readable, seekable file-like object encoding a model. Strings are interpreted as a file name. Files are not rewound to the beginning.

  • substitute – A mapping of symbol substitutions to make when loading the file. The keys are strings giving the node class name to be substituted. The values are callables to create a different node. The callable should have the same signature as the substituted symbol’s constructor.

  • lock – Whether to return a locked model. Only locked models will include any saved intermediate states.

Returns:

A model.

Examples

This example serializes a model to a buffered I/O object, then creates a new model from that object.

>>> from dwave.optimization.generators import flow_shop_scheduling
...
>>> processing_times = [[10, 5, 7], [20, 10, 15]]
>>> model = flow_shop_scheduling(processing_times=processing_times)
>>> my_file = model.to_file()
...
>>> from dwave.optimization import Model
>>> new_model = Model.from_file(my_file)

See also

into_file(), to_file()

from_file() Restores states from a file

Changed in version 0.6.0: Add the substitute and lock keyword-only arguments.

input(shape: tuple[int, ...] = (), lower_bound: None | float = -inf, upper_bound: None | float = inf, integral: None | bool = None) Input[source]#

Add an input symbol as a placeholder for a decision variable.

An input symbol functions similarly to a decision variable, in that it takes no predecessors, but its state is always set manually (and not updated if the model is submitted for solution to a solver). Used as a placeholder for input to a model.

The shape of the output array is fixed at initialization and cannot be changed.

The provided bounds and integrality are used to validate the state when set manually; for example, supplied values cannot violate the lower bound.

Parameters:
  • shape – Shape of the output array, formatted as an integer or a tuple of integers. If None, creates a zero-dimensional (scalar) input.

  • lower_bound – Lower bound on any possible output of the node.

  • upper_bound – Upper bound on any possible output of the node.

  • integral – Whether the output of the node should always be integral.

Returns:

An input symbol at the root of the directed acyclic graph for the model.

Examples

This example creates an integer decision symbol and an input symbol it uses to multiply the sums of the integer symbol’s rows.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer(shape=(2, 3), lower_bound=-5, upper_bound=5)
>>> x = model.input(shape=(2, 1), lower_bound=-2, upper_bound=2, integral=True)
>>> y = x*i.sum(axis=1)
>>> with model.lock():
...    model.states.resize(1)
...    i.set_state(0, [[1, 2, 3], [1, 1, 2]])
...    x.set_state(0, [[1], [-1]])
...    print(y.state(0))
[[ 6.  4.]
 [-6. -4.]]

See also

Input: Generated symbol

constant()

Added in version 0.6.2.

integer(shape: None | _ShapeLike = None, lower_bound: None | numpy.typing.ArrayLike = None, upper_bound: None | numpy.typing.ArrayLike = None, sum_subject_to: None | list[tuple[str, float]] = None, axes_sums_subject_to: None | list[tuple[int, str | list[str], float | list[float]]] = None) IntegerVariable[source]#

Add an integer decision variable to the model.

An integer symbol is an array of integer values assigned as a solution to the problem being modeled.

Parameters:
  • shape (optional) – Shape of the integer array to create, formatted as an integer or a tuple of integers. If None, creates a zero-dimensional (scalar) variable.

  • lower_bound (optional) – Lower bound(s) for the symbol. Can be scalar (one bound for all variables) or an array (one bound for each variable). Non-integer values are rounded up. If None, the default value, zero, is used.

  • upper_bound (optional) – Upper bound(s) for the symbol. Can be scalar (one bound for all variables) or an array (one bound for each variable). Non-integer values are down up. If None, the default value is used.

  • sum_subject_to (optional) – Constraint on the sum of the values in the array. Must be an array of tuples where each tuple has the form: (operator, bound). - operator (str): The constraint operator (“<=”, “==”, or “>=”). - bound (float): The constraint bound. If provided, the sum of values within the array must satisfy the corresponding operator–bound pair. Note 1: At most one sum constraint may be provided. Note 2: If provided, axes_sums_subject_to must None.

  • axes_sums_subject_to (optional) – Constraint on the sum of the values in each slice along a fixed axis in the array. Must be an array of tuples where each tuple has the form: (axis, operator(s), bound(s)). - axis (int): The axis that the constraint is applied to. - operator(s) (str | array[str]): The constraint operator(s) (“<=”, “==”, or “>=”). A single operator applies to all slice along the axis; an array specifies one operator per slice. - bound(s) (float | array[float]): The constraint bound. A single value applies to all slices; an array specifies one bound per slice. If provided, the sum of values within each slice along the specified axis must satisfy the corresponding operator–bound pair. Note 1: At most one sum constraint may be provided. Note 2: If provided, sum_subject_to must None.

Returns:

An integer symbol at the root of the directed acyclic graph for the model.

Examples

This example adds a \(5\)-sized integer decision variable with scalar bounds to a model, and takes the logarithm of its elements.

>>> from dwave.optimization.model import Model
>>> from dwave.optimization.mathematical import log
...
>>> model = Model()
>>> i = model.integer(5, lower_bound=1, upper_bound=10)
>>> i.shape()
(5,)
>>> a = log(i)
>>> with model.lock():
...    model.states.resize(1)
...    i.set_state(0, [[1, 2, 3, 1, 2]])
...    print(a.state(0)[0])
0.0

This example adds a \(2\)-sized integer symbol with a scalar lower bound and index-wise upper bounds to a model.

>>> from dwave.optimization.model import Model
>>> import numpy as np
>>> model = Model()
>>> i = model.integer(2, lower_bound=-1.1, upper_bound=[1.1, 2.9])
>>> np.all([-1, -1] == i.lower_bound())
True
>>> np.all([1, 2] == i.upper_bound())
True

This example adds a \((2x3)\)-sized integer symbol with general lower and upper bounds and a sum constraint along axis 1. Let x_i (int i : 0 <= i <= 2) denote the sum of the values within slice i along axis 1. For each state defined for this symbol: (x_0 <= 2), (x_1 <= 4), and (x_2 <= 5).

>>> from dwave.optimization.model import Model
>>> import numpy as np
>>> model = Model()
>>> i = model.integer([2, 3], lower_bound=1, upper_bound=3,
... axes_sums_subject_to=[(1, "<=", [2, 4, 5])])
>>> np.all(i.sum_constraints() == [(1, ["<="], [2, 4, 5])])
True

This example adds a \(6\)-sized integer symbol such that the sum of the values within the array is less than or equal to 20.

>>> from dwave.optimization.model import Model
>>> import numpy as np
>>> model = Model()
>>> i = model.integer(6, sum_subject_to=[("<=", 20)])
>>> np.all(i.sum_constraints() == [(["<="], [20])])
True

Changed in version 0.6.7: Beginning in version 0.6.7, user-defined index-wise bounds are supported.

Changed in version 0.6.13: Beginning in version 0.6.13, user-defined sum constraints are supported.

into_file(file, *, max_num_states=0, only_decision=False, version=None)[source]#

Serialize the model into an existing file.

Parameters:
  • file – File pointer to an existing writeable, seekable file-like object encoding a model. Strings are interpreted as a file name.

  • max_num_states – Maximum number of states to serialize along with the model. The number of states serialized is the minimum between size() and the specified max_num_states value.

  • only_decision – If True, only decision variables are serialized. If False, all symbols are serialized.

  • version – A 2-tuple indicating which serialization version to use.

See also

from_file(), to_file()

into_file() Saves states to an existing file

Format Specification (Version 1.0):

This format is inspired by the NPY format

The first 4 bytes are a magic string: exactly “DWNL”.

The next 1 byte is an unsigned byte: the major version of the file format.

The next 1 byte is an unsigned byte: the minor version of the file format.

The next 4 bytes form a little-endian unsigned int, the length of the header data HEADER_LEN.

The next HEADER_LEN bytes form the header data. This is a json-serialized dictionary. The dictionary contains the following key/values: decision_state_size, num_nodes, num_states, and state_size. It is terminated by a newline character and padded with spaces to make the entire length of the entire header divisible by 64.

Following the header, the remaining data is encoded as a zip file. All arrays are saved using the NumPy serialization format, see numpy.save().

The information in the header is also saved in a json-formatted file info.json.

The serialization version is saved in a file version.txt.

Each node is listed by type in a file nodetypes.txt.

The adjacency of the nodes is saved in an adjacency format file, adj.adjlist. E.g., a graph with edges a->b, a->c, b->d would be saved as

a b c
b d
c
d

The id of the object is stored in objective.json, and the list of constraint symbols are stored by id in constraints.json.

Finally each symbol has symbol-specific storage in a directory.

nodes/
    <symbol id>/
        <symbol-specific storage>
    ...

The states, if also saved, are saved according to States.into_file().

Format Specification (Version 0.1):

Prior to version 1.0, states were saved differently.

Changed in version 0.5.2: Added the version keyword-only argument.

Changed in version 0.6.0: Added support for serialization format version 1.0.

is_locked()[source]#

Lock status of the model.

No new symbols can be added to a locked model.

Returns:

True if the model is locked.

Return type:

bool

Examples

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> model.is_locked()
False

See also

lock(), unlock()

iter_constraints()[source]#

Iterate over all constraints in the model.

Yields:

Symbols associated with the constraints.

Examples

This example adds a single constraint to a model and iterates over it.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer()
>>> c = model.constant(5)
>>> _ = model.add_constraint(i <= c)
>>> constraint = next(model.iter_constraints())
>>> print(type(constraint))
<class 'dwave.optimization.symbols.binaryop.LessEqual'>
iter_decisions()[source]#

Iterate over all decision variables in the model.

Yields:

Decision variables; for example, an IntegerVariable symbol.

Examples

This example adds a single decision symbol to a model and iterates over it.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer()
>>> c = model.constant(5)
>>> _ = model.add_constraint(i <= c)
>>> decisions = next(model.iter_decisions())
iter_inputs()[source]#

Iterate over all inputs in the model.

Yields:

Input symbols.

Examples

This example iterates over a model’s inputs.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i0, i1 = model.input(), model.input()
>>> c = model.constant(7)
>>> inputs = list(model.iter_inputs())
>>> len(inputs)
2

Added in version 0.6.2.

iter_symbols()[source]#

Iterate over all symbols in the model.

Yields:

Symbol – Symbols of the model.

Examples

This example iterates over a model’s symbols.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer(1, lower_bound=10)
>>> c = model.constant([[2, 3], [5, 6]])
>>> symbol_1, symbol_2 = model.iter_symbols()
list(n: int, min_size: None | int = None, max_size: None | int = None) ListVariable[source]#

Add a list decision variable to the model.

A list symbol is a list containing a permutation of the values in \([0, n-1]\), where the permutation is assigned as a solution to the problem being modeled.

Parameters:
  • n – Range of values in the permutations list (zero to \(n - 1\)).

  • min_size – Minimum list size. Defaults to max_size.

  • max_size – Maximum list size. Defaults to n.

Returns:

A list symbol at the root of the directed acyclic graph for the model.

Examples

This example creates a list symbol of 200 elements.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> routes = model.list(200)

This example creates a list symbol with at least 2 elements and at most 4 elements with values between 0 to 99. It sets two states of the decision variable with different lengths.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> routes = model.list(99, min_size=2, max_size=4)
>>> with model.lock():
...    model.states.resize(2)
...    routes.set_state(0, [10, 2, 44])
...    routes.set_state(1, [67, 1])

Changed in version 0.6.12: Beginning in version 0.6.12, sub-lists are supported.

lock() AbstractContextManager[source]#

Lock the model.

No new symbols can be added to a locked model. Unlocked models do not allow access to methods such as state() and topological_index() for successor (non-decision) variables.

Returns:

A context manager. If the context is subsequently exited, the unlock() method is called.

Examples

This example checks the status of a model after locking it and subsequently unlocking it.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer(20, upper_bound=100)
>>> cntx = model.lock()
>>> model.is_locked()
True
>>> model.unlock()
>>> model.is_locked()
False

This example locks a model temporarily with a context manager.

>>> model = Model()
>>> with model.lock():
...     # no nodes can be added within the context
...     print(model.is_locked())
True
>>> model.is_locked()
False

See also

is_locked(), unlock()

minimize(value: ArraySymbol)[source]#

Set the objective value to minimize.

Optimization problems have an objective and/or constraints. The objective expresses one or more aspects of the problem that should be minimized (equivalent to maximization when multiplied by a minus sign). For example, an optimized itinerary might minimize the value of distance traveled or cost of transportation or travel time.

Parameters:

value – Value of the cost function to minimize.

Examples

This example minimizes a simple polynomial, \(y = i^2 - 4i\), within bounds.

>>> from dwave.optimization import Model
>>> model = Model()
>>> i = model.integer(lower_bound=-5, upper_bound=5)
>>> c = model.constant(4)
>>> y = i*i - c*i
>>> model.minimize(y)
num_constraints()[source]#

Return the number of constraints in the model.

Returns:

Number of constraints.

Return type:

int

Examples

This example checks the number of constraints in the model after adding a couple of constraints.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer()
>>> c = model.constant([5, -14])
>>> _ = model.add_constraint(i <= c[0])
>>> _ = model.add_constraint(c[1] <= i)
>>> model.num_constraints()
2
num_decisions()[source]#

Return the number of decision variables in the model.

An array-of-integers symbol, for example, counts as a single decision symbol.

Returns:

Number of independent decision symbols.

Return type:

int

Examples

This example checks the number of decisions in a model after adding a single (size 20) decision symbol.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> c = model.constant([1, 5, 8.4])
>>> i = model.integer(20, upper_bound=100)
>>> model.num_decisions()
1
num_edges()[source]#

Return the number of edges in the model’s graph.

Returns:

Number of edges in the directed acyclic graph for the model.

Return type:

int

Examples

This example minimizes the sum of a single constant symbol and a single decision symbol, then checks the number of edges in the model.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> c = model.constant(5)
>>> i = model.integer()
>>> model.minimize(c + i)
>>> model.num_edges()
2
num_inputs()[source]#

Return the number of input symbols in the model.

Returns:

Number of Input symbols in the model.

Return type:

int

Examples

This example adds two inputs and a constant to a model and checks the number of inputs.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i0, i1 = model.input(), model.input()
>>> c = model.constant(7)
>>> model.num_inputs()
2

Added in version 0.6.2.

num_nodes()[source]#

Return the number of nodes in the model’s graph.

Returns:

Number of nodes in the directed acyclic graph for the model.

Return type:

int

Examples

This example adds a single (size 20) decision symbol and a single (size 3) constant symbol, and checks the number of nodes in the model.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> c = model.constant([1, 5, 8.4])
>>> i = model.integer(20, upper_bound=100)
>>> model.num_nodes()
2
num_symbols()[source]#

Return the number of symbols in the model.

Equivalent to the number of nodes in the directed acyclic graph for the model.

Returns:

Number of symbols in the model.

Return type:

int

Examples

This example adds a single (size 20) decision symbol and a single (size 3) constant symbol, and checks the number of symbols in the model.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> c = model.constant([1, 5, 8.4])
>>> i = model.integer(20, upper_bound=100)
>>> model.num_symbols()
2
property objective: None | ArraySymbol[source]#

Objective to be minimized.

Created when you use the minimize() method and associated with the ArraySymbol being minimized; as such, supports such methods as state(), reshape(), max(), etc.

Examples

This example prints the value of the objective of a model representing the simple polynomial, \(y = i^2 - 4i\), for a state with value \(i=2.0\).

>>> from dwave.optimization import Model
...
>>> model = Model()
>>> i = model.integer(lower_bound=-5, upper_bound=5)
>>> c = model.constant(4)
>>> y = i**2 - c*i
>>> model.minimize(y)
>>> with model.lock():
...     model.states.resize(1)
...     i.set_state(0, 2.0)
...     print(f"Objective = {model.objective.state(0)}")
Objective = -4.0

See also

ArraySymbol: Symbol created by the minimize() method

minimize(), state()

quadratic_model(x: ArraySymbol, quadratic, linear=None) QuadraticModel[source]#

Add a quadratic model to the model.

Creates a quadratic model from a predecessor ArraySymbol and a quadratic model, such as a QUBO.

Parameters:
  • x – Predecessor array symbol.

  • quadratic – Quadratic values for the quadratic model. Can also include linear values as self loops (e.g., (3, 3): 2.5).

  • linear – Linear values for the quadratic model.

Returns:

A successor symbol that outputs the values of a quadratic model on its predecessor symbol’s state.

Examples

This example creates a binary quadratic model (BQM).

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> x = model.binary(3)
>>> Q = {(0, 0): 0, (0, 1): 1, (0, 2): 2, (1, 1): 1, (1, 2): 3, (2, 2): 2}
>>> qm = model.quadratic_model(x, Q)

This example creates a quadratic example and prints a state.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer(3, lower_bound=-5, upper_bound=10)
>>> quad = {(0, 1): 1, (0, 2): 2, (1, 2): 3}
>>> lin = {0: 0.5, 1: 1.2, 2: 2.0}
>>> qm = model.quadratic_model(i, quadratic=quad, linear=lin)
...
>>> with model.lock():
...    model.states.resize(1)
...    i.set_state(0, [1, 3, 0])
...    print(qm.state(0).round())
7.0

See also

QuadraticModel: Generated symbol

remove_unused_symbols()[source]#

Remove unused symbols from the model.

A symbol is considered unused if all of the following are true :

  • It is not a decision.

  • It is not an ancestor of the objective.

  • It is not an ancestor of a constraint.

  • It has no ArraySymbol object(s) referring to it.

See examples below.

Returns:

Number of symbols removed.

Return type:

int

Examples

This example creates a mix of unused and used symbols, and then removes the unused symbols.

>>> from dwave.optimization import Model
>>> model = Model()
>>> x = model.binary(5)
>>> x.sum()  # create a symbol that will never be used
<dwave.optimization...Sum at ...>
>>> model.minimize(x.prod())
>>> model.num_symbols()
3
>>> model.remove_unused_symbols()
1
>>> model.num_symbols()
2

This example creates a mix of unused and used symbols; however, unlike in the previous example, the unused symbol is assigned to a name in the namespace, preventing from being removed.

>>> from dwave.optimization import Model
>>> model = Model()
>>> x = model.binary(5)
>>> y = x.sum()  # create a symbol and assign it a name
>>> model.minimize(x.prod())
>>> model.num_symbols()
3
>>> model.remove_unused_symbols()
0
>>> model.num_symbols()
3
set(n: int, min_size: int = 0, max_size: None | int = None) SetVariable[source]#

Add a set decision variable to the model.

A set symbol is an unordered collection of values in \([0, n-1]\), with the values assigned as a solution to the problem being modeled.

Parameters:
  • n – Range of values (zero to \(n-1)\) for the set.

  • min_size – Minimum set size. Defaults to 0.

  • max_size – Maximum set size. Defaults to n.

Returns:

A set symbol at the root of the directed acyclic graph for the model.

Examples

This example creates a set symbol of up to four elements with values between 0 to 99, and sets a set of three elements as a state of the decision variable.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> destinations = model.set(100, max_size=4)
...
>>> with model.lock():
...    model.states.resize(1)
...    destinations.set_state(0, [0, 22, 58])
state_size()[source]#

Return an estimate of the size, in bytes, of a model’s state.

For a model encoding several array operations, the state of each array must be held in memory. This method returns an estimate of the total memory needed to hold a state for every symbol in the model.

The number of bytes returned by this method is only an estimate. Some symbols hold additional information that is not accounted for.

Returns:

Size of the state for the model.

Return type:

int

Examples

This example estimates the size of a model’s state. In this example a single value is added to a \(5\times4\) array. The output of the addition is also a \(5\times4\) array. Each element of each array requires \(8\) bytes to represent in memory. Therefore the total state size is \((5*4 + 1 + 5*4) * 8 = 328\) bytes.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer((5, 4))  # 5x4 array of integers
>>> c = model.constant(1)      # one scalar value
>>> y = i + c                  # 5x4 array of values
>>> model.state_size()         # (5*4 + 1 + 5*4) * 8 bytes
328

See also

Symbol.state_size() Estimates the size of a symbol’s state

ArraySymbol.state_size() Estimates the size of an array symbol’s state

Model.decision_state_size() Estimates the size of a model’s decision states

Stride Solver Properties Properties of the Leap service’s quantum-classical hybrid nonlinear solver, including limits on the maximum state size of a model.

states: States[source]#

States of the model.

The States class represents assignments of values to a symbol.

Examples

This example resizes the States class of a simple model to enable the setting of a binary variable. It then clears the set state and the allocated memory.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> x = model.binary((2, 2))
>>> model.states.resize(1)
>>> with model.lock():
...     x.set_state(0, [[0, 0], [1, 0]])
>>> model.states.clear()
>>> model.states.size()
0

See also

States methods to read, save, and manipulate the states of a model.

to_file(**kwargs) BinaryIO[source]#

Serialize the model to a new file-like object.

Examples

This example serializes a model to a buffered I/O object.

>>> from dwave.optimization.generators import flow_shop_scheduling
...
>>> processing_times = [[10, 5, 7], [20, 10, 15]]
>>> model = flow_shop_scheduling(processing_times=processing_times)
...
>>> my_file = model.to_file()

The temporary file created above can be saved to disk, for example, using Python’s shutil module.

import shutil

my_file.seek(0)  # Move cursor to start
with open("my_file.bin", "wb") as f:
    shutil.copyfileobj(my_file, f)

See also

into_file(), from_file()

to_file() Saves states to a file

to_networkx() object[source]#

Convert the model to a NetworkX graph.

Returns:

A NetworkX graph.

Examples

This example converts a model to a graph.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> one = model.constant(1)
>>> two = model.constant(2)
>>> i = model.integer()
>>> model.minimize(two * i - one)
>>> G = model.to_networkx()

One advantage of converting to NetworkX is the wide availability of drawing tools. See NetworkX’s drawing documentation.

This example uses DAGVIZ to draw the NetworkX graph created in the example above.

>>> import dagviz
>>> r = dagviz.render_svg(G)
>>> with open("model.svg", "w") as f:
...     f.write(r)

This creates the following image:

Image of NetworkX Directed Graph
unlock()[source]#

Release a lock and decrement the lock count.

Symbols can be added to unlocked models only. Unlocked models do not allow access to methods such as state() and topological_index() for successor (non-decision) variables.

Examples

This example checks the status of a model.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer(20, upper_bound=100)
>>> model.is_locked()
False

See also

is_locked(), lock()

Expressions#

expression(function: Callable, **kwargs) Expression[source]#
expression(**kwargs) Callable

Transform a function into an Expression.

Such expressions are used as input by some symbols.

Parameters:

function – Callable function that is executed once to generate the Expression.

Examples

>>> from dwave.optimization import expression
>>> @expression
... def func(a, b, c):
...     return (a + b) * c
>>> @expression(a=dict(lower_bound=0), b=dict(upper_bound=1))
... def func(a, b, c):
...     return (a + b) * c

See also

Expression

Added in version 0.6.4.

class Expression[source]#

An expression that can be used as an input to other symbols.

Instantiated through the expression() function.

Examples

This example creates expression \(v_0 + 2*(v_1 + 1)\) and uses it for an AccumulateZip symbol that calculates the cumulative value of sequential elements of an IntegerVariable symbol, \(v_1\), where \(v_0\) is the result from the previous elements.

For example, for input \(v_1 = [1, 1, 0, 1]\) and an initial value, \(v_0[0]\) of 2, the first element of the AccumulateZip symbol is \(2 + 2*(1 + 1) = 6\), the 2nd is therefore \(6 + 2*(1 + 1) = 10\), the 3rd is \(10 + 2*(0 + 1) = 12\), etc.

>>> from dwave.optimization import expression, Model
>>> from dwave.optimization.symbols import AccumulateZip
...
>>> model = Model()
>>> i1 = model.integer(4, lower_bound=0, upper_bound=10)
...
>>> @expression(v1=dict(lower_bound=-10, upper_bound=20))
... def func(v0, v1):
...     return 2*(v1 + 1) + v0
...
>>> j = AccumulateZip(func, (i1, ), initial=2)
...
>>> with model.lock():
...     model.states.resize(1)
...     i1.set_state(0,[1, 1, 0, 1])
...     print(j.state(0))
[ 6. 10. 12. 16.]

See also

expression()

Added in version 0.6.4.

States Class#

class States#

States of a model.

States represent assignments of values to the symbols of a model. For example, an IntegerVariable symbol of size \(1 \times 5\) might have state [3, 8, 0, 12, 8], representing one assignment of values to the symbol. When the symbol is a decision variable in the model, the state might be (part of) a solution to the modeled problem.

You can set the states of a model’s symbols for the purpose of testing your model or providing an initial state for a solver; a model submitted to a solver can have its states updated by returned solutions.

Examples

This example creates a model that includes the polynomial \(k = i^2 + j^2 + 1\) on integer variables and manipulates its states to test that it behaves as expected.

>>> from dwave.optimization import Model
...
>>> model = Model()
>>> i = model.integer(5, lower_bound=-10, upper_bound=10) # Array of 5 int elements
>>> j = model.integer(lower_bound=-4, upper_bound=6)      # scalar integer
>>> k = i**2 + j**2 + 1

At this point the size of the size of the newly created model’s state is zero: to set states on its symbols, resize it to the number of wanted states using the resize() method.

>>> model.states.size()
0
>>> model.states.resize(2)

Lock the model to enable access to the states of successor symbols (non-decision variables) such as \(k\).

>>> with model.lock():
...     i.set_state(0, [-10, -5, 0, 5, 10])
...     j.set_state(0, 0)
...     print(k.state(0))
...     i.set_state(1, [-10, -5, 0, 5, 10])
...     j.set_state(1, 2)
...     print(k.state(1))
[101.  26.   1.  26. 101.]
[105.  30.   5.  30. 105.]

You can clear the states you set.

>>> model.states.clear()
>>> model.states.size()
0

See also

states

clear()#

Clear any saved states.

Clears any memory allocated to the states.

Examples

This example clears a state set on an integer decision symbol.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer(2)
>>> model.states.resize(3)
>>> i.set_state(0, [3, 5])
>>> print(i.state(0))
[3. 5.]
>>> model.states.clear()
>>> model.states.size()
0

See also

resize(), size()

from_file(file, *, replace=True, check_header=True)#

Construct states from the given file.

Parameters:
  • file – File pointer to a readable, seekable file-like object encoding the states. Strings are interpreted as a file name.

  • replace (bool) – Currently only the default is supported.

  • check_header (bool) – Currently unsupported.

Returns:

States as assigned in the file.

Examples

This example creates a simple model, sets two states, and then saves those states to a buffered I/O object. It clears and then restores the states from file.

>>> from dwave.optimization import Model
>>> model = Model()
>>> i = model.integer(5, lower_bound=-10, upper_bound=10)
>>> j = i**2 + 1
...
>>> with model.lock():
...     model.states.resize(2)
...     i.set_state(0, [-10, -5, 0, 5, 10])
...     i.set_state(1, [-8, -3, 1, 4, 9])
...     my_file = model.states.to_file()        # Save the states
...
>>> model.states.clear()                        # Clear the states
>>> model.states.size()
0
>>> model.states.from_file(my_file)             # Restore the states
>>> with model.lock():
...     print(j.state(0))
...     print(j.state(1))
[101.  26.   1.  26. 101.]
[65. 10.  2. 17. 82.]

See also

into_file(), to_file()

from_file() Restores a model from a file

from_future(future, result_hook)#

Populate the states from the result of a future computation.

A Future object is returned by the solver to which you submit your problem model. This enables asynchronous problem submission.

This method is intended for use by developers of the Ocean SDK.

Parameters:
  • future – A future object such as a Future object.

  • result_hook – Method executed to retrieve the Future.

See also

from_file(), resolve()

from_file() Restores a model from a file

initialize()#

Initialize any uninitialized states.

This method is intended for use by developers of the Ocean SDK.

See also

clear(), resize()

into_file(file, *, version=None)#

Serialize the states into an existing file.

Parameters:
  • file – File pointer to an existing writeable, seekable file-like object encoding a model. Strings are interpreted as a file name.

  • version – A 2-tuple indicating which serialization version to use; for example, (1, 0) represents version 1.0. By default, uses the latest version.

Examples

This example creates a simple model, sets two states, and then saves those states to a buffered I/O object. It then changes a state and saves into the previously created file.

>>> from dwave.optimization import Model
>>> model = Model()
>>> i = model.integer(5, lower_bound=-10, upper_bound=10)
>>> j = i**2 + 1
...
>>> with model.lock():
...     model.states.resize(2)
...     i.set_state(0, [-10, -5, 0, 5, 10])
...     i.set_state(1, [-8, -3, 1, 4, 9])
...     my_file = model.states.to_file()        # Save the states
>>> my_file.seek(0)
0
>>> with model.lock():                          # Change a state
...     model.states.resize(2)
...     i.set_state(0, [-10, -5, 0, 5, 10])
...     i.set_state(1, [-10, -4, 2, 6, 10])
...     model.states.into_file(my_file)         # Save into file

See also

from_file(), to_file()

into_file() Saves a model into an existing file

Format Specification (Version 1.0):

The first section of the file is the header, as described in Model.into_file().

Following the header, the remaining data is encoded as a zip file. All arrays are saved using the NumPy serialization format, see numpy.save().

The information in the header is also saved in a json-formatted file info.json.

The serialization version is saved in a file version.txt.

The states have the following structure.

Symbols with a state that’s uniquely determined by their predecessor’s states and Constant symbols do not have their states serialized.

For symbols with a fixed shape and which have all states initialized, the states are stored as a (num_states, *symbol.shape()) array.

nodes/
    <symbol id>/
        states.npy
    ...

For symbols without a fixed shape, or for which not all states are initialized, the states are each saved in a separate array.

nodes/
    <node id>/
        states/
            <state index>/
                array.npy
            ...
    ...

This format allows the states and the model to be saved in the same file, sharing the header.

Format Specification (Version 0.1):

Saved as a Model encoding only the decision symbols.

Changed in version 0.5.2: Added the version keyword-only argument.

Changed in version 0.6.0: Added support for serialization format version 1.0.

resize(n)#

Resize the number of states.

To set the states of a model’s symbols, for the purpose of testing your model or providing an initial state for a solver, you must first set the size of the model’s states. A newly created model has a state size of zero.

Resizing to 0 is not guaranteed to clear the memory allocated to states.

Parameters:

n (int) – Required number of states. If smaller than the current size(), states are reduced to the first n states by removing those beyond. If greater than the current size(), new uninitialized states are added as needed to reach a size of n.

Examples

This example adds three uninitialized states to a model.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> i = model.integer(2)
>>> model.states.resize(3)

See also

clear(), size()

resolve()#

Block until states are retrieved from any pending future computations.

A Future object is returned by the solver to which you submit your problem model. This enables asynchronous problem submission.

This method is intended for use by developers of the Ocean SDK.

See also

from_future()

size()#

Number of model states.

Examples

This example adds three uninitialized states to a model and verifies the number of model states.

>>> from dwave.optimization.model import Model
>>> model = Model()
>>> model.states.resize(3)
>>> model.states.size()
3

See also

resize()

to_file(**kwargs)#

Serialize the states to a new file-like object.

Examples

This example creates a simple model, sets two states, and then saves those states to a buffered I/O object.

>>> from dwave.optimization import Model
>>> model = Model()
>>> i = model.integer(5, lower_bound=-10, upper_bound=10)
>>> j = i**2 + 1
...
>>> with model.lock():
...     model.states.resize(2)
...     i.set_state(0, [-10, -5, 0, 5, 10])
...     i.set_state(1, [-8, -3, 1, 4, 9])
...     my_file = model.states.to_file()        # Save the states

The temporary file created above can be saved to disk, for example, using Python’s shutil module.

import shutil

my_file.seek(0)  # Move cursor to start
with open("my_file.bin", "wb") as f:
    shutil.copyfileobj(my_file, f)

See also

from_file(), into_file()

to_file() Saves a model into a file

Functions#

constant.clear_cache()#

Clear the cache for constant symbols.

To prevent redundancy, constants are cached: Repeated calls to the constant() method with the same argument, return the first Constant instance. After clearing the cache, subsequent such calls create new symbols.

Examples

>>> from dwave.optimization import Model
...
>>> model = Model()
>>> a = model.constant(4)
>>> b = model.constant(4)
>>> model.constant.clear_cache()
>>> c = model.constant(4)
>>> b is a
True
>>> c is a
False

See also

constant()

locked(model: _Graph)[source]#

Context manager that holds a locked model and unlocks it upon exiting.

Instantiated through the lock() method.

Examples

This example creates a model, locks it, sets a state for a decision variable, and prints a successor symbol.

>>> from dwave.optimization import Model
...
>>> model = Model()
>>> i = model.integer(lower_bound=-5, upper_bound=5)
>>> j = i**2
>>> with model.lock():
...     model.states.resize(1)
...     i.set_state(0, 2)
...     print(j.state(0))
4.0