Skip to content

Commit

Permalink
Merge pull request #1298 from JoelPasvolsky/cqm1
Browse files Browse the repository at this point in the history
Update c++ docs
  • Loading branch information
arcondello committed Dec 13, 2022
2 parents 7760d75 + bffc4e1 commit f4ad385
Show file tree
Hide file tree
Showing 13 changed files with 220 additions and 179 deletions.
25 changes: 13 additions & 12 deletions dimod/binary/binary_quadratic_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
# See the License for the specific language governing permissions and
# limitations under the License.

r"""Binary quadratic models (BQMs) are problems of the form:
.. math::
E(\bf{v})
= \sum_{i} a_i v_i
+ \sum_{i<j} b_{i,j} v_i v_j
+ c
\qquad\qquad v_i \in\{-1,+1\} \text{ or } \{0,1\}
where :math:`a_{i}, b_{ij}, c` are real values.
"""

from __future__ import annotations

import collections.abc as abc
Expand Down Expand Up @@ -70,18 +83,6 @@
class BinaryQuadraticModel(QuadraticViewsMixin):
r"""Binary quadratic model.
Binary quadratic models (BQMs) are problems of the form:
.. math::
E(\bf{v})
= \sum_{i=1} a_i v_i
+ \sum_{i<j} b_{i,j} v_i v_j
+ c
\qquad\qquad v_i \in\{-1,+1\} \text{ or } \{0,1\}
where :math:`a_{i}, b_{ij}, c` are real values.
This class encodes Ising and quadratic unconstrained binary optimization
(QUBO) models used by samplers such as the D-Wave system.
Expand Down
116 changes: 29 additions & 87 deletions dimod/constrained/constrained.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,34 @@
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Constrained Quadratic Model class.
r"""Constrained quadratic models are problems of the form:
.. math::
\begin{align}
\text{Minimize an objective:} & \\
& \sum_{i} a_i x_i + \sum_{i \le j} b_{ij} x_i x_j + c, \\
\text{Subject to constraints:} & \\
& \sum_i a_i^{(m)} x_i + \sum_{i \le j} b_{ij}^{(m)} x_i x_j+ c^{(m)} \circ 0,
\quad m=1, \dots, M,
\end{align}
where :math:`\{ x_i\}_{i=1, \dots, N}` can be binary\ [#]_, integer, or continuous
variables, :math:`a_{i}, b_{ij}, c` are real values,
:math:`\circ \in \{ \ge, \le, = \}` and :math:`M` is the total number of constraints.
.. [#]
For binary variables, the range of the quadratic-term summation is
:math:`i < j` because :math:`x^2 = x` for binary values :math:`\{0, 1\}`
and :math:`s^2 = 1` for spin values :math:`\{-1, 1\}`.
Constraints can be categorized as either "hard" or "soft". Any hard constraint
must be satisfied for a solution of the model to qualify as feasible. Soft
constraints may be violated to achieve an overall good solution. By setting
appropriate weights to soft constraints in comparison to the objective
and to other soft constraints, you can express the relative importance of such
constraints.
"""

from __future__ import annotations
Expand Down Expand Up @@ -137,100 +163,16 @@ def __len__(self):
class ConstrainedQuadraticModel(cyConstrainedQuadraticModel):
r"""A constrained quadratic model.
Constrained quadratic models are problems of the form:
.. math::
\begin{align}
\text{Minimize an objective:} & \\
& \sum_{i} a_i x_i + \sum_{i \le j} b_{ij} x_i x_j + c, \\
\text{Subject to constraints:} & \\
& \sum_i a_i^{(m)} x_i + \sum_{i \le j} b_{ij}^{(m)} x_i x_j+ c^{(m)} \circ 0,
\quad m=1, \dots, M,
\end{align}
where :math:`\{ x_i\}_{i=1, \dots, N}` can be binary\ [#]_ or integer
variables, :math:`a_{i}, b_{ij}, c` are real values,
:math:`\circ \in \{ \ge, \le, = \}` and :math:`M` is the total number of constraints.
.. [#]
For binary variables, the range of the quadratic-term summation is
:math:`i < j` because :math:`x^2 = x` for binary values :math:`\{0, 1\}`
and :math:`s^2 = 1` for spin values :math:`\{-1, 1\}`.
Constraints are often categorized as either "hard" or "soft". Any hard constraint
must be satisfied for a solution of the model to qualify as feasible. Soft
constraints may be violated to achieve an overall good solution. By setting
appropriate weights to soft constraints in comparison to the objective
and to other soft constraints, you can express the relative importance of such
constraints.
The objective and constraints are encoded as either :class:`.QuadraticModel`
or :class:`.BinaryQuadraticModel` depending on the variable types used.
Example:
This example solves the simple `bin packing problem <https://w.wiki/3jz4>`_
of packing a set of items of different weights into the smallest
possible number of bins.
`dimod` provides a general :func:`~dimod.generators.random_bin_packing`
function to generate bin packing problems, and this example follows the
same naming conventions.
Consider four objects with weights between 0 and 1, and assume that each
bin has a capacity to hold up to a total weight of 1.
>>> weights = [.9, .7, .2, .1]
>>> capacity = 1
Variable :math:`y_j` indicates that bin :math:`j` is used. Clearly, no
more than four bins are needed.
>>> y = [dimod.Binary(f'y_{j}') for j in range(len(weights))]
Variable :math:`x_{i,j}` indicates that item :math:`i` is put in bin
:math:`j`.
>>> x = [[dimod.Binary(f'x_{i}_{j}') for j in range(len(weights))]
... for i in range(len(weights))]
Create an empty constrained quadratic model ("empty" meaning that no
objective or constraints have set).
objective or constraints are set).
>>> cqm = dimod.ConstrainedQuadraticModel()
The problem is to minimize the number of bins used. Therefore the objective
is to minimize the value of :math:`\sum_j y_j`.
>>> cqm.set_objective(sum(y))
Any feasible solution must meet the constraint that each item can only go
in one bin. You can express this constraint, for a given item :math:`i`,
with :math:`\sum_j x_{i, j} == 1`. Note that the label of each
constraint is returned so that you can access them in the future if
desired.
>>> for i in range(len(weights)):
... cqm.add_constraint(sum(x[i]) == 1, label=f'item_placing_{i}')
'item_placing_0'
'item_placing_1'
'item_placing_2'
'item_placing_3'
Finally, enforce the limits on each bin. You can express this constraint,
for a given bin :math:`j`, with :math:`\sum_i x_{i, j} * w_i <= c` where
:math:`w_i` is the weight of item :math:`i` and :math:`c` is the capacity.
>>> for j in range(len(weights)):
... cqm.add_constraint(
... sum(weights[i] * x[i][j] for i in range(len(weights))) - y[j] * capacity <= 0,
... label=f'capacity_bin_{j}')
'capacity_bin_0'
'capacity_bin_1'
'capacity_bin_2'
'capacity_bin_3'
"""
def __init__(self):
super().__init__()
Expand Down
44 changes: 24 additions & 20 deletions dimod/include/dimod/abc.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,13 @@ class ConstQuadraticIterator {
template <class Bias, class Index>
class QuadraticModelBase {
public:
/// The first template parameter (Bias).
/// The first template parameter (`Bias`).
using bias_type = Bias;

/// The second template parameter (Index).
/// The second template parameter (`Index`).
using index_type = Index;

/// Unsigned integral type that can represent non-negative values.
/// Unsigned integer type that can represent non-negative values.
using size_type = std::size_t;

/// @private <- don't doc
Expand Down Expand Up @@ -176,8 +176,10 @@ class QuadraticModelBase {
/// Add offset.
void add_offset(bias_type bias);

/// Add interaction between variables `v` and `u`.
void add_quadratic(index_type u, index_type v, bias_type bias);

/// Add interactions between row `row` and column `col`.
void add_quadratic(std::initializer_list<index_type> row, std::initializer_list<index_type> col,
std::initializer_list<bias_type> biases);

Expand All @@ -186,7 +188,7 @@ class QuadraticModelBase {
index_type length);

/**
* Add quadratic bias for the given variables at the end of eachother's neighborhoods.
* Add quadratic bias for the given variables at the end of each other's neighborhoods.
*
* # Parameters
* - `u` - a variable.
Expand Down Expand Up @@ -216,14 +218,16 @@ class QuadraticModelBase {
template <class T>
void add_quadratic_from_dense(const T dense[], index_type num_variables);

/// Return an iterator to the beginning of the neighborhood of `v`.
const_neighborhood_iterator cbegin_neighborhood(index_type v) const;

/// Return an iterator to the end of the neighborhood of `v`.
const_neighborhood_iterator cend_neighborhood(index_type v) const;

/// todo
/// Return an iterator to the beginning of the quadratic interactions.
const_quadratic_iterator cbegin_quadratic() const;

/// todo
/// Return an iterator to the end of the quadratic interactions.
const_quadratic_iterator cend_quadratic() const;

/// Remove the offset and all variables and interactions from the model.
Expand All @@ -232,7 +236,7 @@ class QuadraticModelBase {
/**
* Return the energy of the given sample.
*
* The `sample_start` must be random access iterator pointing to the
* The `sample_start` must be a random access iterator pointing to the
* beginning of the sample.
*
* The behavior of this function is undefined when the sample is not
Expand All @@ -250,14 +254,14 @@ class QuadraticModelBase {
template <class T>
void fix_variable(index_type v, T assignment);

/// Check whether u and v have an interaction
/// Check whether `u` and `v` have an interaction.
bool has_interaction(index_type u, index_type v) const;

/// Test whether two quadratic models are equal.
template <class B, class I>
bool is_equal(const QuadraticModelBase<B, I>& other) const;

/// Return True if the model has no quadratic biases.
/// Test whether the model has no quadratic biases.
bool is_linear() const;

/// The linear bias of variable `v`.
Expand Down Expand Up @@ -292,7 +296,7 @@ class QuadraticModelBase {
/// Return the number of interactions in the quadratic model.
size_type num_interactions() const;

/// The number of other variables `v` interacts with.
/// Return the number of other variables that `v` interacts with.
size_type num_interactions(index_type v) const;

/// Return the number of variables in the quadratic model.
Expand All @@ -302,24 +306,24 @@ class QuadraticModelBase {
bias_type offset() const;

/**
* Return the quadratic bias associated with `u`, `v`.
* Return the quadratic bias associated with `u` and `v`.
*
* If `u` and `v` do not have a quadratic bias, returns 0.
*
* Note that this function does not return a reference, this is because
* Note that this function does not return a reference because
* each quadratic bias is stored twice.
*
*/
bias_type quadratic(index_type u, index_type v) const;

/**
* Return the quadratic bias associated with `u`, `v`.
* Return the quadratic bias associated with `u` and `v`.
*
* Note that this function does not return a reference, this is because
* Note that this function does not return a reference because
* each quadratic bias is stored twice.
*
* Raises an `out_of_range` error if either `u` or `v` are not variables or
* if they do not have an interaction then the function throws an exception.
* Raises an `out_of_range` error if either `u` or `v` are not variables;
* if they do not have an interaction, the function throws an exception.
*/
bias_type quadratic_at(index_type u, index_type v) const;

Expand All @@ -334,7 +338,7 @@ class QuadraticModelBase {
*/
virtual void remove_variable(index_type v);

/// Multiply all biases 'scalar'
/// Multiply all biases by the value of `scalar`.
void scale(bias_type scalar);

/// Set the linear bias of variable `v`.
Expand All @@ -346,7 +350,7 @@ class QuadraticModelBase {
/// Set the offset.
void set_offset(bias_type offset);

/// Set the quadratic bias for the given variables.
/// Set the quadratic bias between variables `u` and `v`.
void set_quadratic(index_type u, index_type v, bias_type bias);

void substitute_variable(index_type v, bias_type multiplier, bias_type offset);
Expand All @@ -371,7 +375,7 @@ class QuadraticModelBase {
/// Increase the size of the model by `n`. Returns the index of the first variable added.
index_type add_variables(index_type n);

/// Return an empty neighborhood - useful when we don't have an adj
/// Return an empty neighborhood; useful when a variable does not have an adjacency.
static const std::vector<OneVarTerm<bias_type, index_type>>& empty_neighborhood() {
static std::vector<OneVarTerm<bias_type, index_type>> empty;
return empty;
Expand All @@ -381,7 +385,7 @@ class QuadraticModelBase {
void resize(index_type n);

/// Protected version of vartype() that allows subclasses to distinguish
/// between the vartype_ called by mixin functions and the public API one.
/// between the `vartype_` called by mixin functions and the public API one.
/// By default they are the same.
virtual Vartype vartype_(index_type v) const { return vartype(v); }

Expand Down
Loading

0 comments on commit f4ad385

Please sign in to comment.