Skip to main content

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)
ArgumentMeaning
namethe name Solution.primal reads it back by
setsthe dimensions it is declared over
subsetthe members it has; the full product when omitted
lower, upperthe bound every one of its columns takes
integerwhether 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.

MemberReturns
dimsthe names of the sets it is over
n_columnsthe 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.