JijModeling 2.9.0 リリースノート#

JijModeling 1 のメンテナンス終了告知#

次のマイナーリリースである JijModeling 2.10.0 のリリースと同時に、JijModeling 1 系統のメンテナンスは終了予定です。 JijModeling 2.10.0 のリリースは現時点では 2026 年 10 月半ば以降を予定しています。 これ以後は、JijModeling 1 系に対するセキュリティ対応やバグ修正、新たな Python バージョンへの対応などは行われなくなります。 JijModeling 2 は既に機能・性能両面で JijModeling 1 を上回る状態となっていますので、随時JijModeling 2 移行ガイド を参考に JijModeling 2 への移行をお願い致します。 また、本バージョンから同梱されているコーディングエージェント向けスキル/プラグインとガイドを組み合わせることで、ある程度の移行の手間を省ける場合もございますので、併せてご検討ください。

機能強化#

畳み込みメソッドの LaTeX 出力の改善#

summaxなどの畳み込み演算は、型情報が明確な場合、性格な数値が表示されるように修正しました。 また、axisが指定された場合、内包表記と部分的な畳み込みの組み合わせで表示されるようになりました。

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} \]

定数に対する演算の LaTeX 簡略化#

\(\LaTeX\) 出力で定数式の簡約を行うようになりました。-2*xの単純な係数や、総和でよく見られる - 1などが簡約されるようになり、数式全体の可読性が向上しました。

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} \]

ストリームの論理演算の表記変更#

\(\LaTeX\) 出力で、ストリームの直和・共通部分をとる時の演算子は\(\cup\)\(\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} \]

バグ修正#

バグ修正 1:for 節のループ変数への添え字アクセスで型エラーになる問題の修正#

グラフ G に対する jm.sum(e[1] for e in G) のように、for 節のループ変数への添え字アクセスを行うと、型エラー [E-TE0017] An expression of type ElementOf[stream(..)] cannot be subscripted. が発生する場合があった問題を修正しました。 以下のようなコードは制約検出が有効でも問題なくコンパイルが通るようになりました:

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} \]

また、この例では期待される SOS1 制約が検出されるようになりました。

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)} })])

その他の変更#