jijmodeling
1from ._jijmodeling import * # type: ignore
Any expression in Python.
NOTE: to allow custom [FromPyObject
] and #[pyclass]
, we MUST NOT impl [Clone
] trait directly on this type;
see PyO3/pyo3#4337
for the discussion.
Instead, we use a custom [PyExpression::clone
] and [PyExpression::clone_from
] methods for cloning.
A spec of a placeholder value.
The Placeholder class represents a spec Placeholder, which is maintained in namespace (i.e. Problem). It is a symbol to be replaced by a numerical value when you evaluate an optimization problem before solving it.
Expressions on Placeholder automatically turns into an Expression
object.
Attributes
name
(str
): A name of the placeholder.ndim
(int
): The number of dimensions of the placeholder.shape
(list
ofOptional[Expression]
, optional): The (partial) shape of the placeholder if given.dtype
(DataType
, optional): The data type (DataType.INT
orDataType.FLOAT
) of the placeholder.jagged
(boolean
, defaut:False
):True
if the placeholder will be treated as a jagged array in random data generation. Ignored for scalars.description
(str
, optional): A description of the placeholder.
Args
name
(str
): A name of the placeholder.ndim
(Optional[int]
): The number of dimensions of the placeholder. Defaults to0
. Thendim
must be set to a non-negative value and must concide with the length ofshape
if both specified. IfNone
is given, you must specifyshape
explicitly and the length ofshape
will be used.shape
(list[Optional[Expression]]
, optional): The (partial) shape of the placeholder. Used for random data generation.dtype
(DataType
, optional): The data type (DataType.INT
orDataType.FLOAT
) of the placeholder. Used for random data generation.jagged
(boolean
, defaut:False
):True
if the placeholder will be treated as a jagged array in random data generation. Ignored for scalars.latex
(str
, optional): A LaTeX-name of the placeholder to be represented in Jupyter notebook. It is set toname
by default.description
(str
, optional): A description of the placeholder.
Raises
TypeError
: Raises if set a float value tondim
.OverflowError
: Raises if set a negative value tondim
.
Examples
Create a scalar (or ndim
is 0
) placeholder whose name is "a".
>>> import jijmodeling as jm
>>> a = jm.Placeholder("a")
Create a 2-dimensional placeholder whose name is "m".
>>> import jijmodeling as jm
>>> problem = jm.Problem("example")
>>> m = problem.Placeholder("m", ndim=2)
Create a 1-dimensional placeholder with the index of 123
.
>>> import jijmodeling as jm
>>> problem = jm.Problem("example")
>>> a = problem.Placeholder("a", ndim=2)
>>> a[123]
a[123]
>>> problem.get_placeholde("a")
Placeholder(name='a', ndim=2, shape=None, dtype=typing.float, jagged=False)
A class representing a decision variable in a mathematical model.
As the decision variables must belong to some namespace, you CANNOT construct it directly.
Instead, you should use Problem.DecisionVar
, Problem.BinaryVar
,
Problem.IntegerVar
, Problem.ContinuousVar
,Problem.SemiIntegerVar
,
or Problem.SemiContinuousVar
.
The DecisonVar
class is used to create a continuous variable.
The lower and upper bounds of the variable can be any scalar or tensor with the same shape as the variable expression which DOES NOT contain any decision variable.
The DecisionVar
class itself represents a definition of a decision variable,
but you can use ordinary operations on Expression
s to create expressions that contain decision variables.
Attributes
name
(str
): A name of the continuous variable.kind
(DecisionVarKind
): The kind of the decision variable, which can be one of the following:BINARY
: A binary variable.INTEGER
: An integer variable.CONTINUOUS
: A continuous variable.SEMI_INTEGER
: A semi-integer variable.SEMI_CONTINUOUS
: A semi-continuous variable.
shape
(tuple
): A tuple with the size of each dimension of the integer variable. Empty if the variable is not multi-dimensional.lower_bound
: The lower bound of the variable.upper_bound
: The upper bound of the variable.description
(str
): A description of the continuous variable.
Examples
Create a scalar continuous variable whose name is "z" and domain is [-1, 1]
.
>>> import jijmodeling as jm
>>> problem = jm.Problem("example")
>>> z = problem.DecisionVar(
>>> "z",
>>> kind=jm.DecisionVarKind.CONTINUOUS,
>>> lower_bound=-1, upper_bound=1
>>> )
or equivalently:
>>> import jijmodeling as jm
>>> problem = jm.Problem("example")
>>> z = problem.ContinuousVar("z", lower_bound=-1, upper_bound=1)
Create a 2-dimensional integer variable...
- whose name is "x".
- whose domain is [0, 2].
- where each dimension has length 2 (making this a 2x2 matrix).
>>> import jijmodeling as jm
>>> problem = jm.Problem("example")
>>> x = problem.IntegerVar("x", shape=[2, 2], lower_bound=0, upper_bound=2)
Create a 1-dimensional continuous variable, and construct an expression accessing the 123rd component of it..
>>> import jijmodeling as jm
>>> problem = jm.Problem("example")
>>> x = problem.ContinuousVar("x", shape=[124], lower_bound=0, upper_bound=2)
>>> x[123]
x[123]
A class for creating an optimization problem
The Problem class is used to create an optimization problem.
Attributes
name
(str
): A name of the optimization problem.sense
: Sense of the optimization problem.objective
: The objective function of the optimization problem.constraints
(dict
): A dictionary that stores constraints.- A key is the name of a constraint and the value is the constraint object.
custom_penalty_terms
(dict
): A dictionary that stores custom penalty terms.- A key is the name of a custom penalty and the value is the custom penalty object.
Args
name
(str
): A name of the optimization problem.sense
(optional): Sense of the optimization problem. Defaults toProblemSense.MINIMIZE
.
A short-hand of Compiler.from_problem(self, data).eval_problem(self)
.
A shorthand for Problem.Placeholder(dtype=int)
A shorthand for Problem.Placeholder(dtype=float)
A shorthand for Problem.Placeholder(dtype=DataType.NATURAL)
A shorthand for Problem.Placeholder(dtype=DataType.BINARY)
A function to create a decision variable and register to the problem namespace. See DecisionVar
for more details.
Args
name
(str
): A name of the binary variable.kind
(DecisionVarKind
): A kind of the decision variable.shape
(list | tuple
): A sequence with the size of each dimension of the binary variable. Defaults to an empty tuple (a scalar value).- Each item in
shape
must be a valid expression evaluating to a non-negative scalar.
- Each item in
lower_bound
andupper_bound
(jijmodeling.Expression
): A lower and upper bounds of the binary variable.kind
(DecisionVarKind
): A kind of the decision variable.latex
(str
, optional): A LaTeX-name of the binary variable to be represented in Jupyter notebook.- It is set to
name
by default.
- It is set to
description
(str
, optional): A description of the binary variable.
Examples
Create a scalar binary variable whose name is "z".
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> z = problem.DecisionVar("z", kind=jm.DecisionVarKind.BINARY, lower_bound=0, upper_bound=1)
Create a 2-dimensional binary variable whose name is "x" and has a 2x2 shape.
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> x = problem.BinaryVar("x", shape=[2, 2])
Create a 1-dimensional binary variable with the index of 123
.
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> x = jm.BinaryVar("x", shape=[124])
>>> x[123]
BinaryVar(name='x', shape=[NumberLit(value=124)])[NumberLit(value=123)]
A function to create a binary decision variable and register to the problem namespace. See DecisionVar
for more details.
Args
name
(str
): A name of the binary variable.shape
(list | tuple
): A sequence with the size of each dimension of the binary variable. Defaults to an empty tuple (a scalar value).- Each item in
shape
must be a valid expression evaluating to a non-negative scalar.
- Each item in
latex
(str
, optional): A LaTeX-name of the binary variable to be represented in Jupyter notebook.- It is set to
name
by default.
- It is set to
description
(str
, optional): A description of the binary variable.
Examples
Create a scalar binary variable whose name is "z".
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> z = problem.BinaryVar("z")
Create a 2-dimensional binary variable whose name is "x" and has a 2x2 shape.
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> x = problem.BinaryVar("x", shape=[2, 2])
Create a 1-dimensional binary variable with the index of 123
.
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> x = problemm.BinaryVar("x", shape=[124])
>>> x[123]
x[123]
A function to create a decision variable and register to the problem namespace. See DecisionVar
for more details.
Args
name
(`str): A name of the integer variable.shape
(list | tuple
): A sequence with the size of each dimension of the integer variable. Defaults to an empty tuple (a scalar value).- Each item in
shape
must be a valid expression evaluating to a non-negative scalar.
- Each item in
lower_bound
: The lower bound of the variable.upper_bound
: The upper bound of the variable.latex
(str
, optional): A LaTeX-name of the integer variable to be represented in Jupyter notebook.- It is set to
name
by default.
- It is set to
description
(str
, optional): A description of the integer variable.
Raises
ModelingError
: Raises if a bound is a Placeholder
or Subscript
object whose ndim
is neither 0
nor the same value as ndim
of the integer variable.
Examples
Create a scalar integer variable whose name is "z" and domain is [-1, 1]
.
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> z = problem.IntegerVar("z", lower_bound=-1, upper_bound=1)
Create a 2-dimensional integer variable...
- whose name is "x".
- whose domain is [0, 2].
- where each dimension has length 2 (making this a 2x2 matrix).
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> x = problem.IntegerVar("x", shape=[2, 2], lower_bound=0, upper_bound=2)
Create a 1-dimensional integer variable with the index of 123
.
>>> import jijmodeling as jm
>>> problem = jm.Problem("my_problem")
>>> x = problem.IntegerVar("x", shape=[124], lower_bound=0, upper_bound=2)
>>> x[123]
x[123]
A function to create a decision variable and register to the problem namespace. See DecisionVar
for more details.
Args
name
(str
): A name of the continuous variable.shape
(list | tuple
): A sequence with the size of each dimension of the continuous variable. Defaults to an empty tuple (a scalar value).- Each item in
shape
must be a valid expression evaluating to a non-negative scalar.
- Each item in
lower_bound
: The lower bound of the variable.upper_bound
: The upper bound of the variable.latex
(str
, optional): A LaTeX-name of the continuous variable to be represented in Jupyter notebook.- It is set to
name
by default.
- It is set to
description
(str
, optional): A description of the continuous variable.
Raises
ModelingError
: Raises if a bound is a Placeholder
or Subscript
object whose ndim
is neither 0
nor the same value as ndim
of the continuous variable.
Examples
Create a scalar continuous variable whose name is "z" and domain is [-1, 1]
.
>>> import jijmodeling as jm
>>> z = jm.ContinuousVar("z", lower_bound=-1, upper_bound=1)
Create a 2-dimensional continuous variable...
- whose name is "x".
- whose domain is [0, 2].
- where each dimension has length 2 (making this a 2x2 matrix).
>>> import jijmodeling as jm
>>> x = jm.ContinuousVar("x", shape=[2, 2], lower_bound=0, upper_bound=2)
Create a 1-dimensional continuous variable with the index of 123
.
>>> import jijmodeling as jm
>>> x = jm.ContinuousVar("x", shape=[124], lower_bound=0, upper_bound=2)
>>> x[123]
ContinuousVar(name='x', shape=[NumberLit(value=124)], lower_bound=NumberLit(value=0), upper_bound=NumberLit(value=2))[NumberLit(value=123)]
Constructs Constraint
object, __WITHOUT__ registering it to the problem.
Use +=
operator to register the constraint to the problem.
Returns the schema of the problem.
Returns
schema
: The dictionary containing the schema of the problem.
Generates a dictionary of random InstanceDataValue
for a given problem.
To generate ommx.v1.Instance
object directly, use InstanceDataValue.generate_random_instance
instead.
Args
options
(optional): a dictionary of range parameters for each separate placeholders. The key must be the name of the placeholder and the value must be range parameter (as described in "Range Parameters and Range Syntax" below).default
(optional): default range parameters for placeholders which is not specified inoptions
.seed
(optional): seed for random number generation.
Returns
dict
: The dictionary from the name of placeholders to the generated InstanceDataValue
objects. To be fed to Interpreter.eval_problem
.
Range Parameters and Range Syntax
A range parameter is a dictionary consisting of the following fields:
size
(optional): interval of natural numbers for the size of each array dimension (default:range(1, 6)
)value
(optional): interval of real numbers for the value of each array element (default:range(-1.0, 1.0)
- a uniform distribution on a closed interval $[-1.0, 1.0]$).
Example range parameter config:
{"size": range(2, 10), "value": jm.range.value.closed(100.0, 200.0)}
Intervals are expressed as a range object. Currently, the following syntax is supported for range objects:
- Direct value of type
int
orfloat
- it corresponds to a singleton interval $[a, a] = {a}$. In random generation context, this just means a constant fixed value. - Use the functions from
jijmodeling.range
,jijmodeling.range.size
, orjijmodeling.range.value
modules.- Use functions from
jij.modeling.range.size
to specify (non-negative) integer intervals, andjij.modeling.range.value
for real intervals.jij.modeling.range
dynamically determines the type of the range based on the input. - These three modules provides the following combinators (see the module documents for more details.):
closed(a, b)
: a closed interval $[a, b]$open(a, b)
: an open interval $(a, b)$closed_open(a, b)
: an upper half-open interval $[a, b)$open_closed(a, b)
: a lower half-open interval $(a, b]$greater_than(a)
: an open interval $(a, \infty)$at_least(a)
: a closed interval $[a, \infty)$less_than(a)
: an open interval $(-\infty, a)$at_most(a)
: a closed interval $(-\infty, a]$
- Use functions from
- Use
range
builtin function: this is equivalent tojijmodeling.range.value.closed_open(a, b)
.- Any python range object with
step = 1
can be used as a size range; otherwise it results in runtime error.
- Any python range object with
Use a tuple: raw tuple
(a, b)
is equivalent tojijmodeling.range.closed_open(a, b)
ifa
andb
are eitherint
orfloat
.You can also use bound object as a tuple component; in such case, both tuple components must be one of the following:
- A string
"Unbounded"
means $-\infty$ (in the first component) or $\infty$ (the second). - A dictionary
{"Included": a}
means the endpoint is inclusive. - A dictionary
{"Excluded": a}
means the endpoint is exclusive.
- A string
- Examples:
(1.2, 4)
is equivalent toclosed_open(1.2, 4)
,(-1, {"Included": 1})
is equivalent toclosed(-1, 1)
,(-5, {"Excluded": 4})
is equivalent toclosed_open(-5, 4)
and built in functionrange(-5, 4)
,({"Excluded": 1}, {"Excluded": 2.5})
is equivalent toopen(1, 2.5)
,({"Included": -1}, "Unbounded")
is equivalent toat_least(-1)
.(5, "Unbounded")
is INVALID;5
must be bound object.
- The range object: A dictionary of form
{"start": lb, "end": ub}
, where bothlb
andub
are the bound object described as above.
Examples
>>> import jijmodeling as jm
>>> import builtins
>>> N = jm.Placeholder("N", dtype=jm.DataType.INTEGER)
>>> c = jm.Placeholder("c", dtype=jm.DataType.FLOAT, shape=(N,))
>>> x = jm.BinaryVar("x", shape=(N,))
>>> i = jm.Element("i", belong_to=N)
>>> problem = jm.Problem("problem")
>>> problem += jm.sum(i, c[i] * x[i])
>>> inputs = problem.generate_random_dataset(
... options={
... 'N': {"value": builtins.range(10, 20)},
... 'c': {"value": jm.range.value.closed(-1.0, 1.0)}
... # You can also specify "size" for the range of jagged array dimension size.
... },
... seed=123 # omittable
... )
>>> assert set(inputs.keys()) == {"N", "c"}
>>> inputs
{'N': 11.0, 'c': array([ 0.93914459, -0.06511935, -0.7460324 , -0.32443706, 0.99981451,
-0.24407535, 0.31329469, 0.52206453, -0.1291936 , 0.30443087,
0.53125838])}
Generates random ommx.v1.Instance
for a given problem.
See also InstanceDataValue.generate_random_dataset
.
Args
options
(optional): a dictionary of range parameters for each separate placeholders. The key must be the name of the placeholder and the value must be range parameter (as described in "Range Parameters and Range Syntax" section in~jijmodeling.Problem.generate_random_dataset()
).default
(optional): default range parameters for placeholders which is not specified inoptions
.seed
(optional): seed for random number generation.hints
(optional): the hints to be detected during compilation seeInterpreter.eval_problem
for more details.
Returns
instance
: The OMMX v1 instance object.
Examples
>>> import jijmodeling as jm
>>> import builtins
>>> import ommx.v1
>>> N = jm.Placeholder("N", dtype=jm.DataType.INTEGER)
>>> c = jm.Placeholder("c", dtype=jm.DataType.FLOAT, shape=(N,))
>>> x = jm.BinaryVar("x", shape=(N,))
>>> i = jm.Element("i", belong_to=N)
>>> problem = jm.Problem("problem")
>>> problem += jm.sum(i, c[i] * x[i])
>>> instance = problem.generate_random_instance(
... options={
... 'N': {"value": builtins.range(10, 20)},
... 'c': {"value": jm.range.value.closed(-1.0, 1.0)}
... },
... seed=123
... )
>>> assert type(instance) is ommx.v1.Instance
An optimization sense
Returns true if the constraint is an inequality constraint.
Returns
bool
: True if the constraint is an inequality constraint. Otherwise, False.
Examples
>>> import jijmodeling as jm
>>> N = jm.Placeholder("N")
>>> i = jm.Element("i", belong_to=N)
>>> x = jm.BinaryVar("x", shape=(N,))
>>> constraint = jm.Constraint("constraint", jm.sum(i, x[i]) <= 1)
>>> assert constraint.is_inequality()
Returns true if the constraint is an equality constraint.
Returns
bool
: True if the constraint is an equality constraint. Otherwise, False.
Examples
>>> import jijmodeling as jm
>>> N = jm.Placeholder("N")
>>> i = jm.Element("i", belong_to=N)
>>> x = jm.BinaryVar("x", shape=(N,))
>>> constraint = jm.Constraint("constraint", jm.sum(i, x[i]) == 1)
>>> assert constraint.is_equality()