JijModeling 2.9.0 Release Notes#

JijModeling 1 End of Maintenance Notice#

Maintenance for JijModeling 1.x is scheduled to end with the next minor release, JijModeling 2.10.0. JijModeling 2.10.0 is currently planned for release in mid-October 2026 or later. After that, JijModeling 1.x will no longer receive security updates, bug fixes, or support for new Python versions. JijModeling 2 already surpasses JijModeling 1 in both features and performance, so we encourage you to migrate to JijModeling 2 following the guidance in JijModeling 2 Migration Guide. The skills/plugins for coding agents bundled starting with this release may also help reduce migration effort when used alongside the guide. Please consider using them as well.

Feature Enhancements#

Improved LaTeX output for folding methods#

Methods like sum or max will now use type information when available to expand the notation. And when axis is specified, they now render as comprehensions with partial convolution:

import jijmodeling as jm

problem = jm.Problem("myproblem")
N = problem.Natural("N")
a = problem.Integer("a", shape=(N, N))
A = problem.NamedExpr("A", a.sum())
B = problem.NamedExpr("B", a.sum(axis=1))

problem
\[\begin{array}{rl} \text{Problem}\colon &\text{myproblem}\\\displaystyle \min &\displaystyle 0\\&\\\text{where}&\\&\\&\text{Placeholders:}\\&\qquad \begin{alignedat}{2}{a}_{i,j}&\in \mathbb{Z}&\qquad &\text{a }2\text{-dim array of placeholders with elements in }\mathbb{Z}\\&\forall i\in \left\{0,\ldots ,N-1\right\},\;\forall j\in \left\{0,\ldots ,N-1\right\}&&\\&&&\\N&\in \mathbb{N}&\qquad &\text{a scalar placeholder in }\mathbb{N}\\\end{alignedat}\\&\\&\text{Named Expressions:}\\&\qquad \begin{alignedat}{2}A&=\sum _{i=0}^{N-1}{\sum _{j=0}^{N-1}{{a}_{i,j}}}&\quad &\in \mathbb{Z}\\&&&\\B&={\left( \sum _{j=0}^{N-1}{{a}_{i,j}}\right) }_{i\in \left\{0,\ldots ,N-1\right\}}&\quad &\in \mathop{\mathrm{Array}}\left[N;\mathbb{Z}\right]\\\end{alignedat}\end{array} \]

Simplify operations on constants in LaTeX output#

Basic operations involving constants will now be simplified when displaying \(\LaTeX\). This generally makes equations easier to read, particularly summations which often involved - 1s for the termination, and basic coefficients like -2 * x.

problem = jm.Problem("TestProblem")
V = problem.Natural("V")
problem += jm.map(lambda x: x + 3 - 2, V - 1).sum() 
problem += - 2 * V + - 2 - 1
problem += 2 * (3 * V)
problem += 2 * (V * 3)
problem
\[\begin{array}{rl} \text{Problem}\colon &\text{TestProblem}\\\displaystyle \min &\displaystyle \sum _{x=0}^{V-2}{\left(x+1\right)}-2V-3+2\cdot 3V+2\cdot V\cdot 3\\&\\\text{where}&\\&\\&\text{Placeholders:}\\&\qquad \begin{alignedat}{2}V&\in \mathbb{N}&\qquad &\text{a scalar placeholder in }\mathbb{N}\\\end{alignedat}\end{array} \]

Change display of logical operators on streams#

When displaying \(\LaTeX\), the operators for stream unions and intersections now display as \(\cup\) and \(\cap\).

@jm.Problem.define("Stream Union Example")
def problem(problem: jm.DecoratedProblem):
    N = problem.Natural()
    x = problem.BinaryVar(shape=N)
    target_a = problem.Natural(less_than=N, ndim=1)
    target_b = problem.Natural(less_than=N, ndim=1)

    problem += jm.sum(x[i] for i in jm.stream(target_a) | jm.stream(target_b))
    
problem
\[\begin{array}{rl} \text{Problem}\colon &\text{Stream Union Example}\\\displaystyle \min &\displaystyle \sum _{i\in target\_{}a\cup target\_{}b}{{x}_{i}}\\&\\\text{where}&\\&\text{Decision Variables:}\\&\qquad \begin{alignedat}{2}{x}_{i}&\in \left\{0,1\right\}&\qquad &\text{a }1\text{-dim array of }\text{binary}\text{ decision variables}\\&\forall i\in \left\{0,\ldots ,N-1\right\}&&\\\end{alignedat}\\&\\&\text{Placeholders:}\\&\qquad \begin{alignedat}{2}N&\in \mathbb{N}&\qquad &\text{a scalar placeholder in }\mathbb{N}\\&&&\\{target\_{}a}_{i}&\in N&\qquad &\text{a }1\text{-dim array of placeholders with elements in }N\\&\forall i\in \left\{0,\ldots ,\mathop{\mathtt{len\_{}at}}\left(target\_{}a,0\right)-1\right\}&&\\&&&\\{target\_{}b}_{i}&\in N&\qquad &\text{a }1\text{-dim array of placeholders with elements in }N\\&\forall i\in \left\{0,\ldots ,\mathop{\mathtt{len\_{}at}}\left(target\_{}b,0\right)-1\right\}&&\\\end{alignedat}\end{array} \]

Bugfixes#

Bugfix 1: Fix type errors when subscripting loop variables in for-clauses#

Fixed a type-checking issue where subscripting a loop variable in for-clauses, such as jm.sum (e[1] for e in G) where G is a graph, could raise [E-TE0017] An expression of type ElementOf[stream(..)] cannot be subscripted. The following code now compiles successfully with constraint detection enabled:

import jijmodeling as jm


@jm.Problem.define("Erroring Problem")
def problem(problem: jm.DecoratedProblem):
    N = problem.Natural()
    x = problem.BinaryVar("x", shape=(N,))
    G = problem.Graph(dtype=N)

    problem += problem.Constraint(
        "even-sources",
        (jm.sum(x[e[1]] for e in G if e[0] % 2 == 0) <= 1),
    )


display(problem)
instance = problem.eval({"N": 3, "G": [(0, 0), (0, 1), (1, 2)]})
\[\begin{array}{rl} \text{Problem}\colon &\text{Erroring Problem}\\\displaystyle \min &\displaystyle 0\\&\\\text{s.t.}&\\&\begin{aligned} \text{even-sources}&\quad \displaystyle \sum _{\substack{e\in G\\{e}_{0}\bmod 2=0}}{{x}_{{e}_{1}}}\leq 1\end{aligned} \\&\\\text{where}&\\&\text{Decision Variables:}\\&\qquad \begin{alignedat}{2}{x}_{i}&\in \left\{0,1\right\}&\qquad &\text{a }1\text{-dim array of }\text{binary}\text{ decision variables}\\&\forall i\in \left\{0,\ldots ,N-1\right\}&&\\\end{alignedat}\\&\\&\text{Placeholders:}\\&\qquad \begin{alignedat}{2}{G}_{i}&\in N\times N&\qquad &\text{a }1\text{-dim array of placeholders with elements in }N\times N\\&\forall i\in \left\{0,\ldots ,\mathop{\mathtt{len\_{}at}}\left(G,0\right)-1\right\}&&\\&&&\\N&\in \mathbb{N}&\qquad &\text{a scalar placeholder in }\mathbb{N}\\\end{alignedat}\end{array} \]

The expected SOS1 constraint is now detected in this example as well.

instance.constraint_hints
ConstraintHints(one_hot_constraints=[], sos1_constraints=[Sos1(Sos1 { binary_constraint_id: ConstraintID(0), big_m_constraint_ids: {}, variables: {VariableID(0), VariableID(1)} })])

Other Changes#