jijmodeling

1from ._jijmodeling import *  # type: ignore
class DataType:
INTEGER = DataType.INTEGER
FLOAT = DataType.FLOAT
BINARY = DataType.BINARY
NATURAL = DataType.NATURAL
class Expression:

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.

def shape(self, /):
def len_at(self, /, axis):
def min(self, /, rhs):
def max(self, /, rhs):
def abs(self, /):
def sqrt(self, /):
def sin(self, /):
def cos(self, /):
def tan(self, /):
def asin(self, /):
def acos(self, /):
def atan(self, /):
def sinh(self, /):
def cosh(self, /):
def tanh(self, /):
def asinh(self, /):
def acosh(self, /):
def atanh(self, /):
def exp(self, /):
def ln(self, /):
def log10(self, /):
def log2(self, /):
def ceil(self, /):
def floor(self, /):
def map(self, /, func):
def roll(self, /, shift, *, axis=None):
def filter(self, /, predicate):
def flat_map(self, /, func):
def sum(self, /, axis=None):
def prod(self, /, axis=None):
def diff(self, /, rhs):
def bnot(self, /):
class Placeholder:

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 of Optional[Expression], optional): The (partial) shape of the placeholder if given.
  • dtype (DataType, optional): The data type (DataType.INT or DataType.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 to 0. The ndim must be set to a non-negative value and must concide with the length of shape if both specified. If None is given, you must specify shape explicitly and the length of shape 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 or DataType.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 to name by default.
  • description (str, optional): A description of the placeholder.

Raises

  • TypeError: Raises if set a float value to ndim.
  • OverflowError: Raises if set a negative value to ndim.

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)
def len_at(self, /, index):
def min(self, /, rhs):
def max(self, /, rhs):
def abs(self, /):
def sqrt(self, /):
def sin(self, /):
def cos(self, /):
def tan(self, /):
def asin(self, /):
def acos(self, /):
def atan(self, /):
def sinh(self, /):
def cosh(self, /):
def tanh(self, /):
def asinh(self, /):
def acosh(self, /):
def atanh(self, /):
def exp(self, /):
def ln(self, /):
def log10(self, /):
def log2(self, /):
def ceil(self, /):
def floor(self, /):
def map(self, /, func):
def roll(self, /, shift, *, axis=None):
def filter(self, /, predicate):
def flat_map(self, /, func):
def sum(self, /, axis=None):
def prod(self, /, axis=None):
def diff(self, /, rhs):
def bnot(self, /):
class DecisionVar:

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 Expressions 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]
def min(self, /, rhs):
def max(self, /, rhs):
def abs(self, /):
def sqrt(self, /):
def sin(self, /):
def cos(self, /):
def tan(self, /):
def asin(self, /):
def acos(self, /):
def atan(self, /):
def sinh(self, /):
def cosh(self, /):
def tanh(self, /):
def asinh(self, /):
def acosh(self, /):
def atanh(self, /):
def exp(self, /):
def ln(self, /):
def log10(self, /):
def log2(self, /):
def ceil(self, /):
def floor(self, /):
def map(self, /, func):
def roll(self, /, shift, *, axis=None):
def filter(self, /, predicate):
def flat_map(self, /, func):
def sum(self, /, axis=None):
def prod(self, /, axis=None):
lower_bound
name
upper_bound
description
ndim
kind
shape
class Problem:

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 to ProblemSense.MINIMIZE.
def eval(self, /, instance_data):

A short-hand of Compiler.from_problem(self, data).eval_problem(self).

def Placeholder( self, /, name, *, ndim=None, shape=None, dtype=Ellipsis, jagged=False, latex=None, description=None):
def Integer( self, /, name, *, ndim=None, shape=None, jagged=False, latex=None, description=None):

A shorthand for Problem.Placeholder(dtype=int)

def Float( self, /, name, *, ndim=None, shape=None, jagged=False, latex=None, description=None):

A shorthand for Problem.Placeholder(dtype=float)

def Natural( self, /, name, *, ndim=None, shape=None, jagged=False, latex=None, description=None):

A shorthand for Problem.Placeholder(dtype=DataType.NATURAL)

def Binary( self, /, name, *, ndim=None, shape=None, jagged=False, latex=None, description=None):

A shorthand for Problem.Placeholder(dtype=DataType.BINARY)

def DecisionVar( self, /, name, *, kind, shape=None, lower_bound, upper_bound, latex=None, description=None):

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.
  • lower_bound and upper_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.
  • 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)]
def BinaryVar(self, /, name, *, shape=None, latex=None, description=None):

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.
  • latex (str, optional): A LaTeX-name of the binary variable to be represented in Jupyter notebook.
    • It is set to name by default.
  • 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]
def IntegerVar( self, /, name, *, shape=None, lower_bound, upper_bound, latex=None, description=None):

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.
  • 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.
  • 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]
def SemiIntegerVar( self, /, name, *, shape=None, lower_bound, upper_bound, latex=None, description=None):
def ContinuousVar( self, /, name, *, shape=None, lower_bound, upper_bound, latex=None, description=None):

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.
  • 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.
  • 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)]
def SemiContinuousVar( self, /, name, *, shape=None, lower_bound, upper_bound, latex=None, description=None):
def namespace(self, /):
def Constraint(name, expression, *, description=None):

Constructs Constraint object, __WITHOUT__ registering it to the problem. Use += operator to register the constraint to the problem.

def used_placeholders(self, /):
def get_problem_schema(self, /):

Returns the schema of the problem.

Returns

  • schema: The dictionary containing the schema of the problem.
def generate_random_dataset(seed, default, options):

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 in options.
  • 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:

  1. Direct value of type int or float - it corresponds to a singleton interval $[a, a] = {a}$. In random generation context, this just means a constant fixed value.
  2. Use the functions from jijmodeling.range, jijmodeling.range.size, or jijmodeling.range.value modules.
    • Use functions from jij.modeling.range.size to specify (non-negative) integer intervals, and jij.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]$
  3. Use range builtin function: this is equivalent to jijmodeling.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.
  4. Use a tuple: raw tuple (a, b) is equivalent to jijmodeling.range.closed_open(a, b) if a and b are either int or float.

    • You can also use bound object as a tuple component; in such case, both tuple components must be one of the following:

      1. A string "Unbounded" means $-\infty$ (in the first component) or $\infty$ (the second).
      2. A dictionary {"Included": a} means the endpoint is inclusive.
      3. A dictionary {"Excluded": a} means the endpoint is exclusive.
    • Examples:
      • (1.2, 4) is equivalent to closed_open(1.2, 4),
      • (-1, {"Included": 1}) is equivalent to closed(-1, 1),
      • (-5, {"Excluded": 4}) is equivalent to closed_open(-5, 4) and built in function range(-5, 4),
      • ({"Excluded": 1}, {"Excluded": 2.5}) is equivalent to open(1, 2.5),
      • ({"Included": -1}, "Unbounded") is equivalent to at_least(-1).
      • (5, "Unbounded") is INVALID; 5 must be bound object.
  5. The range object: A dictionary of form {"start": lb, "end": ub}, where both lb and ub 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])}
def generate_random_instance(self, /, _default, _options, _seed, _hints):

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 in options.
  • seed (optional): seed for random number generation.
  • hints (optional): the hints to be detected during compilation see Interpreter.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
def type_of(self, /, name):
def infer(self, /, expr):
class ProblemSense:

An optimization sense

class Constraint:
def is_inequality(self, /):

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()
left
expression
is_equality

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()
right
name
sense
class ConstraintSense:
GREATER_THAN_EQUAL = ConstraintSense.GREATER_THAN_EQUAL
class Namespace:
def from_problem(problem):
def add_placeholder(self, /, placeholder):
def Placeholder( self, /, name, *, ndim=None, shape=None, dtype=Ellipsis, jagged=False, latex=None, description=None):
def add_decision_var(self, /, var):
def type_of(self, /, name):
def infer(self, /, expr):
class Compiler:
def get_constraint_id_by_name(self, /, name):

Obtains a dictionary from subscript to constraint Id.

def eval_function(self, /, expr):
def eval_constraints(self, /, constraint):
def eval_problem(self, /, problem):
def get_decision_variable_by_name(self, /, name, subscript=None):
def from_problem(problem, instance_data):