# Expression¶

class Base

Abstract class of pyqubo expression.

All basic component class such as Binary, Spin or Add inherits Base.

For example, an expression $$2ab+1$$ (where $$a, b$$ is Binary variable) is represented by the binary tree above.

Note

This class is an abstract class of all component of expressions.

Example:

We write mathematical expressions with objects such as Binary or Spin which inherit Base.

>>> from pyqubo import Binary
>>> a, b = Binary("a"), Binary("b")
>>> 2*a*b + 1
(Binary(a)*Num(2.000000)*Binary(b)+Num(1.000000))

compile(strength=5.0)

Returns the compiled Model.

This method reduces the degree of the expression if the degree is higher than 2, and convert it into Model which has information about QUBO.

Parameters: strength (float) – The strength of the reduction constraint. Insufficient strength can result in the binary quadratic model not having the same minimizations as the polynomial. The model compiled from the Base. Model

Examples:

In this example, there are higher order terms $$abc$$ and $$abd$$. It is decomposed as [[a*b, c], d] hierarchically and converted into QUBO. By calling to_qubo() of the model, we get the QUBO.

>>> from pyqubo import Binary
>>> a, b, c, d = Binary("a"), Binary("b"), Binary("c"), Binary("d")
>>> model = (a*b*c + a*b*d).compile()
>>> pprint(model.to_qubo()) # doctest: +SKIP
({('a', 'a'): 0.0,
('a', 'a*b'): -10.0,
('a', 'b'): 5.0,
('a*b', 'a*b'): 15.0,
('a*b', 'b'): -10.0,
('a*b', 'c'): 1.0,
('a*b', 'd'): 1.0,
('b', 'b'): 0.0,
('c', 'c'): 0,
('d', 'd'): 0},
0.0)


## Binary¶

class Binary(label)

Binary variable i.e. {0, 1}.

Parameters: label (str) – The label of a variable. A variable is identified by this label.

Example:

Example code to create an expression.

>>> from pyqubo import Binary
>>> a, b = Binary('a'), Binary('b')
>>> exp = 2*a*b + 3*a
>>> pprint(exp.compile().to_qubo())   # doctest: +SKIP
({('a', 'a'): 3.0, ('a', 'b'): 2.0, ('b', 'b'): 0}, 0.0)


## Spin¶

class Spin(label)

Spin variable i.e. {-1, 1}.

Parameters: label (str) – The label of a variable. A variable is identified by this label.

Example:

Example code to create an expression.

>>> from pyqubo import Spin
>>> a, b = Spin('a'), Spin('b')
>>> exp = 2*a*b + 3*a
>>> pprint(exp.compile().to_qubo()) # doctest: +SKIP
({('a', 'a'): 2.0, ('a', 'b'): 8.0, ('b', 'b'): -4.0}, -1.0)


## Placeholder¶

class Placeholder(label)

Placeholder expression.

You can specify the value of the Placeholder when creating the QUBO. By using Placeholder, you can change the value without compiling again. This is useful when you need to update the strength of constraint gradually.

Parameters: label (str) – The label of the placeholder.

Example:

The value of the placeholder is specified when you call to_qubo().

>>> from pyqubo import Binary, Placeholder
>>> x, y, a = Binary('x'), Binary('y'), Placeholder('a')
>>> exp = a*x*y + 2.0*x
>>> pprint(exp.compile().to_qubo(feed_dict={'a': 3.0})) # doctest: +SKIP
({('x', 'x'): 2.0, ('x', 'y'): 3.0, ('y', 'y'): 0}, 0.0)
>>> pprint(exp.compile().to_qubo(feed_dict={'a': 5.0})) # doctest: +SKIP
({('x', 'x'): 2.0, ('x', 'y'): 5.0, ('y', 'y'): 0}, 0.0)


## SubH¶

class SubH(hamiltonian, label, as_constraint=False)

SubH expression. The parent class of Constraint. You can specify smaller sub-hamiltonians in your expression.

Parameters: hamiltonian (Base) – The expression you want to specify as a sub-hamiltonian. label (str) – The label of the sub-hamiltonian. Sub-hamiltonians can be identified by their labels. as_constraint (boolean) – Whether or not the sub-hamiltonian should also be treated as a constraint. False by default.

Example:

You can call namespaces to identify the labels defined in a model.

>>> from pyqubo import Spin, SubH
>>> s1, s2, s3 = Spin('s1'), Spin('s2'), Spin('s3')
>>> exp = (SubH(s1 + s2, 'n1'))**2 + (SubH(s1 + s3, 'n2'))**2
>>> model = exp.compile()
>>> model.namespaces  #doctest: +SKIP
({'n1': {'s1', 's2'}, 'n2': {'s1', 's3'}}, {'s1', 's2', 's3'})


## Constraint¶

class Constraint(hamiltonian, label, condition=lambda x: x==0.0)

Constraint expression. You can specify the constraint part in your expression.

Parameters: child (Express) – The expression you want to specify as a constraint. label (str) – The label of the constraint. You can identify constraints by the label. (float => boolean) condition (func) – function to indicate whether the constraint is satisfied or not. Default is lambda x: x == 0.0. function takes float value and returns boolean value. You can define the condition where the constraint is satisfied.

Example:

When the Hamiltonian contains Constraint, you know whether each constraint is satisfied or not by accessing to DecodedSample.

>>> from pyqubo import Binary, Constraint
>>> a, b = Binary('a'), Binary('b')
>>> H = Constraint(a+b-2, "const1") + Constraint(a+b-1, "const2")
>>> model = H.compile()
>>> dec = model.decode_sample({'a': 1, 'b': 0}, vartype='BINARY')
>>> pprint(dec.constraints())
{'const1': (False, -1.0), 'const2': (True, 0.0)}
>>> pprint(dec.constraints(only_broken=True))
{'const1': (False, -1.0)}


class Add(left, right)

Parameters: left (Base) – An expression right (Base) – An expression

Example:

You can add expressions with either the built-in operator or Add.

>>> from pyqubo import Binary, Add
>>> a, b = Binary('a'), Binary('b')
>>> a + b
(Binary(a)+Binary(b))
(Binary(a)+Binary(b))


## Mul¶

class Mul(left, right)

Product of expressions.

Parameters: left (Base) – An expression right (Base) – An expression

Example:

You can multiply expressions with either the built-in operator or Mul.

>>> from pyqubo import Binary, Mul
>>> a, b = Binary('a'), Binary('b')
>>> a * b
Binary(a)*Binary(b)
>>> Mul(a, b)
Binary(a)*Binary(b)


## Num¶

class Num(value)

Expression of number

Parameters: value (float) – the value of the number.

Example:

Example code to create an expression.

>>> from pyqubo import Binary, Num
>>> a = Binary('a')
>>> a + 1
(Binary(a)+Num(1.000000))
>>> a + Num(1)
(Binary(a)+Num(1.000000))


## UserDefinedExpress¶

class UserDefinedExpress

User defined express.

User can define their own expression by inheriting UserDefinedExpress.

Example:

Define the LogicalAnd class by inheriting UserDefinedExpress.

>>> from pyqubo import UserDefinedExpress, Binary
>>> class LogicalAnd(UserDefinedExpress):
...     def __init__(self, bit_a, bit_b):
...         express = bit_a * bit_b
...         super().__init__(express)
>>> a, b = Binary('a'), Binary('b')
>>> logical_and = LogicalAnd(a, b)


## WithPenalty¶

class WithPenalty

You can define the custum penalty class by inheriting WithPenalty. The penalty argument will be added to the generated Hamiltonian. Integer classes with constraints, such as OneHotEncInteger, are defined using this class.

Example:

Define the custom penalty class inheriting WithPenalty. We initialize this class with hamiltonian $$h$$. The constraint term $$(h-1)^2$$ will be added to the generated Hamiltonian.

>>> from pyqubo import WithPenalty
>>> class CustomPenalty(WithPenalty):
...     def __init__(self, hamiltonian, label, strength):
...         penalty = strength * (hamiltonian-1)**2
...         super().__init__(hamiltonian, penalty, label)
>>> a, b = Binary("a"), Binary("b")
>>> p = CustomPenalty(a+b, label="penalty", strength=2.0)
>>> model = (p+1).compile()
>>> qubo, offset = model.to_qubo()