Skip to main content

Files

dumps, load, loads, save​

FunctionDoes
dumps(what, inline=False, instructions=False, version=4)returns the text of a definition's file, or of a model's file; a model's data is included with inline=True alone; a definition with inline=True raises ValueError
load(path, data=None)reads a file; returns a Definition, or a Model where the file contains data or data= gives it
loads(text, data=None)the same over text; a sidecar name in text raises ValueError. Text has no directory
save(what, path, inline=False, instructions=False, version=4)writes a definition's file, or a model's with an .npz beside it, or one file with an inline block when inline=True; instructions=True writes the comment block that describes the format at the top of the file; version is 4 or 3

data= is the mapping build takes or the path of an .npz. A file that contains data and a data= together raises ValueError.

dumps returns the text save writes, without a sidecar line. Only save writes a sidecar and the line that identifies it.

version=4 writes each piecewise declaration under piecewise, and omits the sets, parameters, variables and constraints it generated. version=3 writes a model's generated declarations as ordinary declarations, and omits the piecewise declarations and any parameter only they read. A model loaded from that file contains the same rows and no piecewise declaration. A definition with a piecewise declaration raises ValueError at version 3. Any other version raises ValueError.

With instructions=True, every writer puts a fixed comment block at the top of the text. The block describes the format: the keys and their order, the defaults, the rules that determine which rows a constraint has, and the expression syntax. The text is the same in every file and describes the format, not the model. A reader with one file interprets it without this package. The block is a YAML comment: a file with it and a file without it load to the same model.

The file​

KeyContains
version4, or 3 where the caller asks for it; files of version 2 and 3 also load; any other value raises ValueError and reports the versions this reader accepts
name, sensethe model's
setsa list of names
aliaseseach alias to its base set; absent where the model declares none
parameterseach name to its dimensions
variableseach name to sets, and to subset, lower, upper, integer where they differ from no subset, 0, infinity and false
constraintseach name to relation, and to where or over where given
piecewiseeach name to x, x_points, y, y_points, sign, method, and to active, relaxed and where where given; version 4 only; absent where the model declares none
objectivethe objective expression; absent where the model declares none
dataan inline mapping, or the name of an .npz beside the file

subset, where and over take a parameter's name, meaning the coordinates it contains, or a list of set names, meaning their full product. A symbol's name is a Python identifier other than Sum. A dimension listed in parameters, in a variable's sets, or in a list of set names is a set or an alias. An alias is declared after its base set.

The expressions are written as they are typed in Python and are read back through the same operators. The file is a fixed point: reading it and writing it again gives the same text.

from nimopt import Definition, Sum, dumps, loads

d = Definition("d")
S = d.set("S")
c = d.param("c", (S,))
x = d.var("x", (S,), integer=True)
d.constraint("cap", 2 * c[S] * x[S] - 1 <= 5)
text = dumps(d)
print(text)
print(dumps(loads(text)) == text)
Output
version: 4
name: d
sense: min
sets: [S]
parameters:
c: [S]
variables:
x:
sets: [S]
integer: true
constraints:
cap:
relation: (c[S] * 2) * x[S] - 1 <= 5

True

A key the format does not define raises ValueError, at the top level and inside an entry.

from nimopt import loads

loads(
"version: 3\nname: d\nsense: min\nsets: [S]\n"
"variables:\n x: {sets: [S], bound: 1}\n"
)
Raises ValueError
ValueError: variable 'x' contains the unknown key 'bound'; write only 'sets', 'subset', 'lower', 'upper', 'integer'

Data​

The data in a file is the mapping build takes, in three shapes.

ShapeInlineIn the .npz
a set's membersa lista one-dimensional label array
a set of datetime64 or timedelta64 membersdtype and membersa one-dimensional label array
a dense parameternested lists in row-major orderits grid
a long parametercolumns, the dimensions then value, and rowsa structured array with one field per dimension and value

A parameter is written dense where its array covers its full product and long otherwise. The .npz is read with allow_pickle=False. An array of object dtype raises ValueError at save and reports the symbol: the container would pickle it, and the reader rejects a pickled array.

from nimopt import loads

loads(
"version: 3\nname: d\nsense: min\nsets: [S]\nparameters:\n c: [S]\n"
"data:\n S: [a]\n c:\n columns: [value, S]\n rows:\n - [1.0, a]\n"
)
Raises ValueError
ValueError: parameter 'c' is given columns ['value', 'S']; a table lists the dimensions then value: ['S', 'value']

Datetime members​

A set whose members are datetime64 or timedelta64 is written inline as a mapping of dtype and members, instead of a list.

data:
T:
dtype: datetime64[s]
members: ['2030-01-01T00:00:00', '2030-01-01T01:00:00']

A datetime64 member is written as its ISO 8601 string. A timedelta64 member is written as its integer count of the unit in the dtype. A label column of a long table is written in the same text and takes no marker: the column belongs to a set, and the reader converts it to that set's dtype. The .npz stores the dtype of every array and uses no separate form.

A member fixed in a relation is written as text. A datetime64 member is its quoted ISO 8601 string, such as x['2030-01-01T00:00:00']. A timedelta64 member is a quoted count and numpy unit code, such as x['3 h'].

Every member is converted to the dtype of its set. A string is parsed as ISO 8601. A datetime.datetime, a datetime.date and a datetime64 of another unit are converted. An integer against a timedelta64 set is a count of that set's own unit. A conversion that is not exact raises ValueError: '2030-01-01T00:30' against a set in hours raises instead of truncating to the hour.

A member specifies no time zone. datetime64 represents no offset, and a conversion to UTC would move the member. A string with an offset or a trailing Z raises ValueError, and a datetime.datetime with a tzinfo raises the same error. Write the naive form, '2030-01-01T00:00:00'.

A member outside the range its dtype represents raises ValueError and reports the first and the last member of that range. A NaT member raises ValueError.

What raises before anything is written​

WrittenReason
a model whose subset, where or over is a domain with no namedeclare the members as a parameter
two parameter objects or two set objects sharing a name in one modelthe file keys a symbol by name
a symbol whose name is not an identifier, or is Sumthe expression syntax cannot address it
an array of object dtypethe container would pickle it
import numpy as np
from nimopt import Model, Set, dumps, subset

P = Set("P", np.array(["a", "b"]))
m = Model("m")
x = m.var("x", (P,))
m.constraint("cap", x[P] <= 1.0, where=subset((P,), {"P": np.array(["a"])}))
dumps(m)
Raises ValueError
ValueError: constraint 'cap' gives where= a domain with no name; declare its members as a parameter and refer to that parameter