Skip to main content

For agents

The whole manual is at /llms-full.txt; the index is at /llms.txt.

The mental model​

A variable is a dimension. m.var("x", (P, W)) occupies a block of the model's single column space. A member's column is computed from its multi-index and is not stored. A variable over millions of columns costs its members, not its columns.

An expression is symbolic. cost[P, W] * x[P, W] contains references, not arrays. Writing it allocates nothing. It becomes matrix entries when a constraint is materialised.

A constraint is an array. It is a nimblend array over its free sets crossed with the column space. There is no assembly step: the array is the matrix.

A definition is a model without its data. Definition provides the vocabulary a model is written in, set, param, var, constraint and set_objective, over symbols declared with no members and no values. explain() reports what it declares. build(data) binds a copy and returns a Model. One definition builds a model for each dataset it is given.

A built model is inspected through three methods. explain() reports what it built. row(name, **coords) computes one row: the entries assemble writes for it, and no other row. absent(name) reports which coordinates were dropped from a constraint and by which rule.

A session keeps the solver open. model.session() assembles once and keeps the solver's model. diagnose() queries the solved instance for the conflicting rows of an infeasible model, or for the ray of an unbounded one. available() lists the installed adapters. capabilities(name) reports what one adapter supports and which capabilities it rejects together. A model with integer columns has no duals: a mixed-integer model's duals are not its relaxation's.

nimblend is the layer below. Its vocabulary is dimensions, labels, entries and alignment, and it contains no optimization term. Import from nimblend itself, never from nimblend.sparse or another submodule, and never read an array's .index or .data or a domain's .codes. Each of the three has a reader above it: coordinates(), values(), positions_of_coordinates() and as_coord(). Do not build an index matrix either: a domain returns the array over its own members through array(values) and identity(into, coord, start).

The public surface​

FromNames
nimoptCOLUMN, ROW, Absence, Alias, Assembled, Coefficient, Constraint, Definition, Diagnosis, Explanation, Expression, Model, Option, Param, Piecewise, Relation, Row, Session, Set, Solution, Sum, Term, Variable, available, capabilities, dumps, load, loads, options, product, save, subset, subset_of
nimblendArray, DenseArray, Domain, EntryBuffer, SparseArray, combined_dims, from_long, from_dense, is_canonical, sum_arrays, StoredCoord, ProductCoord, SubsetCoord

A coefficient composes. A coefficient is a parameter read at its sets or an arithmetic combination of such readings: price[G, T] / eta[G, T] is a coefficient written before any data exists, read at its sets like a parameter, and evaluated once when the matrix is built. +, -, *, / and a power by a number combine coefficients. An expression also contains a constant: x + 1 <= 5 produces the row x <= 4.

What goes wrong​

A chained comparison. 0 <= expr <= 10 raises TypeError. Python evaluates it as two comparisons joined by and and keeps only the second. A relation has no truth value, and the chained form raises instead of dropping the first bound. Write each bound as its own constraint.

A sum over a lag. Sum(T - 1, ...) raises: a sum runs over a set's members. Put the lag on the variable reference, x[T - 1].

The built-in sum over a set's members. sum(x[S, t] for t in members) returns the correct expression at a cost: it produces one term per member, where Sum(T, x[S, T]) produces one term and reduces a dimension. The terms concatenate pairwise and each materialises its own block. Building a model that way runs 24 times slower at 25 members and 275 times slower at 400, and the factor grows with the member count. Use the built-in sum for a short list of distinct expressions and Sum for a set's members.

A right-hand side over the wrong dimensions. A constraint's right-hand side is a parameter over exactly its free dimensions. The error message gives both.

Reading values from a model that did not solve. objective and primal raise where feasible is False. They raise at status unbounded and unbounded_or_infeasible whatever feasible reports. bound and gap are None at those two statuses. dual raises where status is not "optimal". A solve stopped at a limit reports feasible True where the solver found a point, with bound and gap beside it. Read status first.

A domain over a definition's sets. product((B, T)) needs each set's coordinate, and a declared set has none. In a definition, give where=, over= and subset= as a tuple of its sets or as one of its parameters, whose coefficients are the coordinates.

A row that is not there. row() raises for a coordinate at which the constraint has no row. absent() reports which rule dropped it: a coefficient absent inside a sum removes a term and keeps the row; a term absent along a free dimension removes the row.

Reading a MILP's duals. A model with integer columns has no duals. dual() raises; it does not return the relaxation's duals. Read primal.

A conflict HiGHS cannot prove. HiGHS computes its conflict over the linear relaxation. A model infeasible only through its integrality produces no conflict, and diagnose() raises. The Gurobi conflict covers the integrality.

Two operands that share no dimension. Every binary operator combines two dimensioned operands only where they share a dimension. The rule applies to a coefficient multiplied by a variable and to two coefficients alike. Frames sharing no dimension raise ValueError; their combination would be an outer product. A number has no dimension and scales every entry.

A division by zero. A divisor that is zero raises ZeroDivisionError with the coordinate, for a Python number, a NumPy scalar and a coefficient with a zero at one coordinate alike. Handle the divisor before it is passed to an expression.

A derived coefficient read at the wrong sets. A combination is read at its sets as a parameter is, and the reading is checked against the dimensions it has. unit_cost[T, G] raises where it is written and reports ('G', 'T').

Bypassing the nimblend interface. A test fails on an import from a nimblend submodule. It also fails on a read of an array's .index or .data or a domain's .codes, and on a module of the package that assembles an index matrix of its own.

Every error, and where it is shown​

The prose above covers the common mistakes. The table lists every error the documentation demonstrates. Each row is executed to produce the message beside it.

RaisesMessageShown at
ValueErrorthe upper bound 'cap' has no value at member ('b',) of variable 'x'; give the bound a value at every member of the variable/guides/bounds-from-parameters
ValueErrorvariable 'x' is declared over ('G',) and is not over ['W']; its upper bound 'cap' is declared over ('W',)/guides/bounds-from-parameters
TypeErrora coefficient is a parameter; build one with Param.from_dense or Param.from_long and read it at its sets. A product of two expressions is not linear./guides/coefficient-arithmetic
ValueErrorcoefficient (fuel_price / efficiency) is declared over ('G', 'T'); got ('T', 'G')/guides/coefficient-arithmetic
ZeroDivisionErrordivisor holed is zero at 1 coordinate(s), first at {'G': 'base', 'T': 1}; remove the zeros or divide by another parameter/guides/coefficient-arithmetic
ValueErrorframes ('G',) and ('T',) share no dimension; pass operands that share a dimension/guides/coefficient-arithmetic
ValueErrorconstraint 'capacity' has free dimensions ('P',); its condition is over ('W',)/guides/conditions
ValueErrorconstraint 'capacity' is given over= and where= together; pass one of them/guides/conditions
ValueErrorvariable 'x' is read at member 't9' of dimension 'T'; read it at a member that set contains/guides/fixed-members
ValueErrora lag is a whole number of members; got 1.7/guides/lags
ValueErrora sum is over the members of ['T'] and takes the set, not a lag of it; write the lag at the variable's reference/guides/lags /reference/expression
ValueErrorparameter 'rate' is read at a lag ['T']; write the lag at the variable's reference/guides/lags
ValueErrorpiecewise 'fuel' has points that are not convex, required by sign '>=' at {'G': 'a'}; use method 'incremental'/guides/piecewise
ValueError'max(gen[G, T]) <= 10': the syntax supports one call; write Sum/guides/saving-and-loading
ValueErrormember '2030-01-01T00:30' does not convert exactly to datetime64[h] at dimension 'T' of variable 'gen'; write a member in the unit of that dimension/guides/saving-and-loading
ValueErrorcapital does not fall from base to what follows it; pass a capital cost that falls across the merit order/models/expansion
ValueErrorabsence is 'unknown' and the array has no value at 3 of 4 coordinates; pass fill= to to_dense()/nimblend/arrays
ValueErrorframes ('P',) and ('Q',) share no dimension; pass operands that share a dimension/nimblend/arrays
ValueErrorlabel columns have lengths {'t': 2} and the value column has length 1; pass columns of equal length/nimblend/arrays
ValueError3 member(s) numbered from 4 end at position 6, and dimension 'k' has extent 6; pass a smaller start or a larger coord/nimblend/domains
ValueErrora domain of 3 member(s) requires values of shape (3,); got shape (2,)/nimblend/domains
ValueErrorconstraint 'supply' has free dimensions ('P',); its right-hand side 'demand' is over ('W',)/reference/constraint /tutorial/constraints
ValueErrordata does not cover ['S']; add an entry for each/reference/definition
ValueErrorparameter 'S' is already declared as a set; declare another name/reference/definition
TypeErrora relation already has one bound; compare the expression again in its own constraint/reference/expression
TypeErrora relation has no truth value; write each bound in its own constraint/reference/expression /tutorial/constraints
TypeErroran LP has no row for a strict inequality; write <= or >=, and reduce with Sum in place of min or max/reference/expression
TypeErroran expression has no absolute value: expressions are linear; bound the expression with two rows, or reduce it with Sum over its sets/reference/expression
TypeErroran expression is reduced over the sets it is summed across; specify them with Sum(I, J, expression)/reference/expression
TypeErrorcannot divide by an expression: expressions are linear; declare the reciprocal as a coefficient the variable multiplies/reference/expression
TypeErrorcannot raise an expression to a power: expressions are linear; raise a coefficient to the power and multiply it by a variable/reference/expression
ValueErrorterm 'x' already sums over ['T']; sum over each dimension once/reference/expression
ValueErrorconstraint 'cap' gives where= a domain with no name; declare its members as a parameter and refer to that parameter/reference/files
ValueErrorparameter 'c' is given columns ['value', 'S']; a table lists the dimensions then value: ['S', 'value']/reference/files
ValueErrorvariable 'x' contains the unknown key 'bound'; write only 'sets', 'subset', 'lower', 'upper', 'integer'/reference/files
ValueErrorconstraint 'cap' has no row at {'P': 'p3'}; read absent('cap') for the rule that dropped it/reference/inspection
ValueErrorparameter 'cost': label columns have lengths {'P': 1, 'W': 2} and the value column has length 2; pass columns of equal length/reference/param
TypeErrorparameter 'price' is over ('G',) and expresses no coefficient until it is read; read it at its sets as price[G]/reference/param
ValueErrorstatus is 'infeasible' and the solver reports no feasible point; read status before reading values/reference/solution /tutorial/solving
ValueErrormodel 'm' has integer columns and 'highs' reports no duals for it; read primal values only/reference/solvers
TypeErrorparameter 'supply' is over ('P',) and expresses no coefficient until it is read; read it at its sets as supply[P]/tutorial/constraints
ValueErrorabsence is 'unknown' and the array has no value at 1 of 6 coordinates; pass fill= to to_dense()/tutorial/reading-the-answer
ValueErrorparameter 'cost' is over sets of shape (2, 3); got values of shape (2, 2)/tutorial/sets-and-parameters