Quick Reference: Operations and Functions for Integer Variables and Constraints
pyqbpp.Expr is a unified type for plain expressions, integer variables, and constraint expressions. The same type is used for all three; only the extra metadata differs.
An Expr has three “faces”:
- Plain expression (polynomial): e.g.
x + 2*y*z - Integer variable: created via
qbpp.var("x", between=(0, 10)) - Constraint expression: created via
qbpp.constrain(e, equal=5)etc.
Core principles
- All
pyqbpp.Exproperations / functions work on every Expr, regardless of face.- Face-specific accessors (
min_val,body, …) abort at runtime when called on a mismatching Expr.- Mutating methods (
+=,-=,*=,/=,//=,sqr(),replace()) turn the internal state into a plain expression: metadata is discarded.- Exception:
simplify*()preserves face identity.- Use
e.is_varint()/e.is_exprexpr()for runtime face checks.
1. Integer variables
The integer variables on this page are the ones expanded into binary variables. Native integer variables (IntVar), which keep the integer value as is, are a distinct type from Expr; their reference is in Variables and Expressions. Both kinds can appear in the body of a cons() constraint.
Construction
| Syntax | Result |
|---|---|
qbpp.var("x", between=(l, u)) | Expr (integer variable in [l, u]) |
qbpp.var("x", shape=N, between=(l, u)) | array of integer-variable Expr elements |
qbpp.var("x", shape=(s1, s2, ...), between=(l, u)) | multi-dim integer-variable array |
qbpp.var("x", shape=N, equal=0) | placeholder integer-variable array (assign each element later) |
Operations / functions
| Category | Example | Result | Notes |
|---|---|---|---|
| Unary | -vi | Expr | |
| Arithmetic (RHS Expr-like) | vi + 1, vi * 2, vi - x | Expr | |
| Arithmetic (RHS integer variable) | vi1 + vi2, vi1 * vi2 | Expr | |
| Constraint (equality) | qbpp.constrain(vi, equal=5) | Expr (constraint) | constraint creation |
| Constraint (range) | qbpp.constrain(vi, between=(l, u)) | Expr (constraint) | range constraint |
| Global functions | qbpp.sqr(vi), qbpp.simplify(vi), qbpp.simplify_as_binary(vi) | Expr | |
| Integer-specific metadata | vi.min_val, vi.max_val | various | read-only |
| Integer-specific structure | vi.var_count, vi.coeff(i), vi.get_var(i), vi[i] | various | read-only |
| Array properties | vi.vars, vi.coeffs | list | read-only |
| Expr access | str(vi) | str | |
| Compound assignment | vi += 1, vi -= 1, vi *= 2, vi //= 2, vi /= 2 | (vi becomes a plain expression) | integer-specific accessors no longer available |
| Square | vi.sqr() | (vi becomes a plain expression) | |
| Replace | vi.replace(ml) | (vi becomes a plain expression) | |
| In-place simplify | vi.simplify(), vi.simplify_as_binary(), vi.simplify_as_spin() | Expr | only the held expression is rewritten; integer-variable metadata is preserved |
| Assignment | vi = other | (rebinding) | normal Python assignment |
Note: After calling a mutator like
vi += 1, the Python type is stillExprbut the internal state is a plain expression. Calling integer-specific accessors (vi.min_val, etc.) afterward raises a runtime error.
2. Constraint expressions
Construction
| Syntax | Result | Meaning (penalty / body) |
|---|---|---|
qbpp.constrain(f, equal=n) | Expr (constraint) | penalty = sqr(f - n), body = f |
qbpp.constrain(f, between=(l, u)) | Expr (constraint) | penalty = between, body = f |
qbpp.constrain(f, between=(l, None)) | Expr (constraint) | f >= l (no upper bound) |
qbpp.constrain(f, between=(None, u)) | Expr (constraint) | f <= u (no lower bound) |
f is a non-integer expression (Var, Term, Expr, integer-variable Expr); n, l, u are integers.
Operations / functions
| Category | Example | Result | Notes |
|---|---|---|---|
| Unary | -ee | Expr | negates penalty |
| Arithmetic (RHS Expr-like) | ee + 1, ee * 2, ee + x | Expr | |
| Arithmetic (RHS constraint) | ee1 + ee2 | Expr | penalty + penalty |
| Global functions | qbpp.sqr(ee), qbpp.simplify_as_binary(ee), qbpp.replace(ee, ml) | Expr | applied to penalty |
| Properties | ee.body, str(ee) | Expr / str | clones |
| Evaluation by Sol | sol(ee) (evaluate penalty), sol(ee.body) (evaluate body) | int | for constraint verification |
| Compound assignment | ee += 1, ee -= 1, ee *= 2, ee //= 2, ee /= 2 | (ee becomes a plain expression) | body no longer reachable |
| Square | ee.sqr() | (ee becomes a plain expression) | |
| Replace | ee.replace(ml) | (ee becomes a plain expression) | |
| In-place simplify | ee.simplify(), ee.simplify_as_binary(), ee.simplify_as_spin() | Expr | applies the rule to both penalty and body, stays a constraint |
| Assignment | ee = other | (rebinding) | normal Python assignment |
Note: After
ee += 1etc., only the penalty is updated and the body becomes inaccessible. In contrast,ee.simplify*()applies the same rule to both penalty and body, keeping the constraint in a consistent state.
3. Native constraints (cons)
Creating a constraint with qbpp.cons() produces an expression with a declared native constraint. Declared constraints are treated specially as constraints, and the bundled solvers search efficiently for solutions that satisfy them. See Native Constraints for details.
Construction
| Syntax | Meaning |
|---|---|
qbpp.cons(f, equal=n) | equality constraint f == n |
qbpp.cons(f, equal=[a, b, ...]) | discrete allowed-value set (f must be one of a, b, …) |
qbpp.cons(f, between=(l, u)) | range constraint (either bound may be None) |
qbpp.cons(constraint_expr) | declares a constraint expression built with == as a native constraint |
qbpp.cons(array comparison) | one constraint per element |
P * qbpp.cons(...) | assigns weight P (positive integer) |
obj + qbpp.cons(...) + qbpp.cons(...) | combines freely with the objective and other constraints via + |
Operations / functions
For an expression f containing declared constraints:
| Example | Result | Description |
|---|---|---|
f.is_declared_cons() | bool | whether f contains declared constraints |
sol(f) | int | matches the Energy reported by the solvers (objective + penalties) |
f.cons(sol) | int | number of constraints violated by sol (0 means all satisfied) |
f.cons() | str | the declared constraint list as a string (show with print(f.cons())) |
f.violations(sol) | list | reports value, bounds, violation, and weight of each constraint |
f.is_feasible(sol) | bool | whether all constraints are satisfied |
f.simplify_as_binary() | Expr | simplifies both objective and constraints, declarations preserved |
qbpp.replace(f, ml) | Expr | variable substitution, declarations preserved |
qbpp.expand_cons(f) / f.expand_cons() | Expr | expands into the classic penalty form (declarations removed) |
sqr(), expression multiplication, scalar factor ≤ 0, subtracting a constraint, reduce(), etc. | — | operations that would break the declarations are explicit runtime errors |
4. Global functions: return a new Expr
The principal global functions that accept integer variables / constraint expressions. All return a new pyqbpp.Expr and never modify their argument:
| Function | Result | Description |
|---|---|---|
qbpp.sqr(x) | Expr | x * x |
qbpp.simplify(x) | Expr | merge like terms |
qbpp.simplify_as_binary(x) | Expr | binary (0/1) simplification |
qbpp.simplify_as_spin(x) | Expr | spin (±1) simplification |
qbpp.replace(x, ml) | Expr | variable substitution |
qbpp.constrain(f, equal=n) | Expr (constraint) | equality constraint |
qbpp.constrain(f, between=(l, u)) | Expr (constraint) | range constraint |
qbpp.cons(...) | Expr (declared constraint) | declares a native constraint |
qbpp.expand_cons(f) | Expr | expands declared constraints into penalty form |
The argument x may be Var, Term, or Expr of any face (internally treated as Expr).
5. Array variants
Arrays of integer variables / constraint expressions follow the same rules:
- Arithmetic treats each element as
Expr-> result is anExprarray - In-place mutators (
+=,*=, etc.) are allowed; per element, the same decay rule above applies (the element becomes a plain expression).
# Integer-variable array
x = qbpp.var("x", shape=3, between=(0, 7)) # Array of integer-variable Expr
sum_expr = qbpp.sum(x) # Expr
f = qbpp.sqr(sum_expr - 5) # Expr
# Constraint-expression array (per-element constraints)
m = qbpp.var("m", shape=(3, 4)) # 2D Var array
rows = qbpp.vector_sum(m, axis=0) # sum of each row (Expr array)
onehot = qbpp.constrain(rows, equal=1) # Array of constraint Expr
penalty = qbpp.sum(onehot) # Expr (sum of all penalties)
Per-element body access: arr[i].body.
6. Differences from C++
Both C++ and Python allow += etc. on these forms, but the semantics differ slightly:
- C++: the same object’s internal state changes to a plain expression. Face-specific accessors raise a runtime error afterward.
- Python: the same object is rewritten in place; Python object identity is preserved, but face-specific accessors raise a runtime error too.
See also
- Integer Variables and Solving Simultaneous Equations — examples using
qbpp.var(..., between=...)andqbpp.constrain(...) - Comparison Constraints —
qbpp.constrain(f, equal=n)constraint creation - Native Constraints —
qbpp.cons()usage and per-solver semantics - Replace —
qbpp.replace(...)usage