JijModeling 2.2.0 Release Notes#

Feature Enhancements#

Fix dictionary sum and convolution behavior#

Formerly, summation or folding on dictionaries were intended to be performed via items(), values(), and keys(), and direct folding was not planned to be supported. However, up to the previous version, dictionary folding was mistakenly available, and it operated over the set of keys in the same way as Python dictionaries. From the standpoint of consistency with how Placeholder and DecisionVar multi-dimensional arrays, it is more natural for dictionaries to be folded over the set of values rather than keys. Given these, we have formalized this behavior as the official specification and re-implemented it accordingly.

Below is an example of the fix.

import jijmodeling as jm
import ommx.v1

problem = jm.Problem("My Problem")
I = problem.CategoryLabel("I")
x = problem.BinaryVar("x", dict_keys=I)

problem += x.sum()  # Now behaves like the old x.values().sum()

problem
\[\begin{array}{rl} \text{Problem}\colon &\text{My Problem}\\\displaystyle \min &\displaystyle \sum _{\vec{\imath }}{{{\left(x\right)}}_{\vec{\imath }}}\\&\\\text{where}&\\&\text{Decision Variables:}\\&\qquad \begin{alignedat}{2}x&\in \mathop{\mathrm{TotalDict}}\left[\mathrm{I};\left\{0, 1\right\}\right]&\quad &\text{a dictionary of }\text{binary}\text{ variables with key }I\\\end{alignedat}\\&\\&\text{Category Labels:}\\&\qquad \begin{array}{rl} I&\text{Category Label}\end{array} \end{array} \]

Improve display of decision variable bounds#

The bounds of decision variables are now displayed more clearly in \(\LaTeX\) output.

problem = jm.Problem("problem")
N = problem.Natural("N")
M = problem.Natural("M")
d = problem.Float("d", shape=(M,))
L = problem.Float("L", shape=(N, M))
x = problem.ContinuousVar(
    "s", shape=(N, M), lower_bound=L, upper_bound=lambda i, j: d[j]
)
problem += x.sum()

problem
\[\begin{array}{rl} \text{Problem}\colon &\text{problem}\\\displaystyle \min &\displaystyle \sum _{\vec{\imath }}{{{\left(s\right)}}_{\vec{\imath }}}\\&\\\text{where}&\\&\text{Decision Variables:}\\&\qquad \begin{alignedat}{2}s&\in \mathop{\mathrm{Array}}\left[N\times M;\mathbb{R}\right]\;\left({L}_{i,j}\leq {s}_{i,j}\leq {d}_{j}\right)&\quad &2\text{-dim continuous variable}\\\end{alignedat}\\&\\&\text{Placeholders:}\\&\qquad \begin{alignedat}{2}d&\in \mathop{\mathrm{Array}}\left[M;\mathbb{R}\right]&\quad &1\text{-dimensional array of placeholders with elements in }\mathbb{R}\\L&\in \mathop{\mathrm{Array}}\left[N\times M;\mathbb{R}\right]&\quad &2\text{-dimensional array of placeholders with elements in }\mathbb{R}\\M&\in \mathbb{N}&\quad &\text{A scalar placeholder in }\mathbb{N}\\N&\in \mathbb{N}&\quad &\text{A scalar placeholder in }\mathbb{N}\\\end{alignedat}\end{array} \]

Add a feature to fix decision variable values#

We added a feature to (partially) fix decision variable values in Problem.eval and Compiler.from_problem. You can pass a dictionary to the optional keyword argument fixed_variables, where the keys are variable names and the values are either fixed values or a dictionary mapping indices to fixed values. The substituted value will be stored in fixed_value attribute in the corresponding ommx decision variable(s).

problem = jm.Problem("My Problem")
N = problem.Length("N")
x = problem.ContinuousVar("x", shape=(N, N), lower_bound=-10, upper_bound=10)
y = problem.IntegerVar("y", lower_bound=0, upper_bound=10)
problem += x.sum() + y

compiler = jm.Compiler.from_problem(
    problem,
    {"N": 2},
    fixed_variables={
        "x": {(0, 1): 1, (1, 1): 5},
        "y": 3,  # You may also write {(): 3}
    },
)
instance = compiler.eval_problem(problem)

instance.objective
Function(x0 + x2 + 9)
x00 = compiler.get_decision_variable_by_name("x", (0, 0))
x10 = compiler.get_decision_variable_by_name("x", (1, 0))
assert instance.objective.almost_equal(ommx.v1.Function(x00 + x10 + 9))

Bugfixes#

Fix issue where constraint detection could not handle indexed constraints correctly#

In previous releases, when generating instances of optimization problems with indexed constraints, an unexpected error occurred if constraint detection was enabled (default state). This issue has been fixed.

Flatten nested subscripts in LaTeX output#

Nested subscripts like x[i][j] nodes now render as \({x}_{i,j}\) instead of the \({{x}_{i}}_{j}\) in LaTeX output.

import jijmodeling as jm

problem = jm.Problem("My Problem")
x = problem.BinaryVar("x", shape=(2, 2))
x[0][1]
\[{x}_{0,1}\]

Improve errors for invalid decision variable definitions#

Previously, when bounds were specified incorrectly for decision variables, the compiler raised an unrecoverable exception that could not be caught with try-except. With this fix, a ValueError is raised instead, and the error message is more informative.