Variable
Variable
Returned by Model.var. A variable over a set product, or over a subset
of one.
Model.var(name, sets, subset=None, lower=0.0, upper=inf, integer=False)
| Argument | Meaning |
|---|---|
name | the name Solution.primal reads it back by |
sets | the dimensions it is declared over |
subset | the members it has; the full product when omitted |
lower, upper | the bound every one of its columns takes |
integer | whether its columns are integral |
The variable's columns are a virtual coordinate: a member's column is computed from its multi-index by stride arithmetic for a full product, or is its rank among the codes of a subset. Nothing stores a column index. A variable over millions of columns therefore costs only its members.
| Member | Returns |
|---|---|
dims | the names of the sets it is over |
n_columns | the number of columns it occupies |
labels_at(positions) | the labels of the columns at those positions, per set; a position is a column less start |
domain() | the members it has |
terms() | its coefficients over (*dims, COLUMN) |
variable[sets] | a one-term expression referencing it |
import numpy as np
from nimopt import Model, Set
P = Set("P", np.array(["lisbon", "porto"]))
W = Set("W", np.array(["berlin", "paris", "rome"]))
m = Model("transport")
x = m.var("x", (P, W))
open_plant = m.var("open_plant", (P,), lower=0.0, upper=1.0, integer=True)
print(x.dims, x.n_columns)
print(open_plant.n_columns)
print(m.n_columns)
print(m.integrality())
Output
('P', 'W') 6
2
8
[0 0 0 0 0 0 1 1]
Each variable occupies the next range of the single column space of the
model. m.n_columns counts every column declared so far.
A variable over no dimension
The bracket of a variable lists the dimensions it is declared over. A
variable over no dimension takes no bracket and enters a row on its own. It
is one column: a value-at-risk level, a budget slack, or a bound shared by
every row of a family. theta[()] is the same term written out.
A variable over one or more dimensions expresses no term until it is read.
Using one without a bracket raises TypeError and reports the reading it
requires. The same rule applies to a parameter, read as cost[G, T], and as
k over no dimension.
Comparing a variable expresses a row, and == between two variables
expresses a row as well. A list of variables therefore cannot be searched
with in or .index. Both compare their items and raise TypeError
and report the first variable they compare. A dict and a set match on
identity. Store variables in one of them, or search them by name.
import numpy as np
from nimopt import Model, Set, Sum
S = Set("S", np.array(["s1", "s2"]))
m = Model("cvar", sense="min")
theta = m.var("theta", (), lower=-np.inf)
p = m.var("p", (S,))
m.constraint("tail", theta - Sum(S, p[S]) >= 0.0)
m.set_objective(theta)
print(m.n_columns, m.n_rows)
print(m.constraints["tail"].relation)
Output
3 1
theta - Sum(S, p[S]) >= 0
COLUMN and ROW
The dimension names nimopt reserves. COLUMN is "__column__" and ROW
is "__row__". Both are written so that no ordinary set name collides with
them.
A variable's terms are an array over (*dims, COLUMN), and a constraint's
block is one over (ROW, COLUMN). That is the whole correspondence between
a model and its matrix: the column space is a dimension, and the array is the
matrix.
import numpy as np
from nimopt import COLUMN, ROW, Model, Set
P = Set("P", np.array(["lisbon", "porto"]))
W = Set("W", np.array(["berlin", "paris", "rome"]))
m = Model("transport")
x = m.var("x", (P, W))
print(COLUMN, ROW)
print(x.terms().dims)
print(x.domain().dims)
Output
__column__ __row__
('P', 'W', '__column__')
('P', 'W')
A caller writes neither name. Both appear when a nimblend array from
inside a model is inspected.