Skip to main content

JijModelingでの定式化

この記事ではJijModelingでの定式化のTipsを紹介します。

変数のdimとshapeについて

JijModelingでPlaceholder, Binaryを利用する際にdimまたはshapeという引数を使用しますが、これらの使い方について説明します。

dimは変数が持つことができる添字の数を表します。例えば 

d = jm.Placeholder("d", dim=2)

と書くとdという名前の2次元配列のPlaceholderを生成できます。このdは2つまで添字を持つことができます。そのため以下のような振る舞いをします。

# 2つまで添字を持つことができるので以下の記述は可能です.
d["i"]
d["i", "j"]

# しかしdim=2なので, 3つの添字を入れようとするとエラーになります.
d["i", "j", "k"]

shapeは変数の大きさを直接指定することができます。

n = jm.Placeholder("n")
d = jm.Placeholder("d", shape=(n, 5))

このdはさきほどdim=2と指定した時と同じように2次元配列ですが、大きさが決まっています。
dim=2はshapeが未定だが添字の数は決まっているということを意味するので、実は

d = jm.Placeholder("d", dim=2)
d = jm.Placeholder("d", shape=(None, None))

はどちらも同じ意味を持ちます。

shape と dimの使い分け

ではshapedimはどのように使い分けるのが良いでしょうか。

二つの例を見てみましょう。

import jijmodeling as jm

n = jm.Placeholder("n")
d = jm.Placeholder("d", shape=(n, ))
import jijmodeling as jm
d = jm.Placeholder("d", dim=1)
n = d.shape[0]

この例は同じ実装に見えますが、前者は数式を評価する際にデータとしてndの両方が必要となります。 しかし後者はdのみをデータとして与えればよく、ndの大きさから推定されます。

!!! note 先程 dimshapeNoneにした時と同じ意味を持つと説明しましたが、.shapeインターフェースでshapeの値を取り出す際にNoneの場合は自動的にdの大きさに対応するPlaceholderが出力されます。
つまりn = d.shape[0]nは実際のdに代入されるデータの大きさと紐づいています。

ここで紹介した例の前者だとndの両方のデータを入れる必要があり、この関係に矛盾が合った場合、数式の評価時(コンパイルのときなど)にしか間違いに気づけず、思わぬところでエラーが発生します。
そのため後者のようにdimを使った実装の方がより安全です。

次にshapeを使った方が良い例を見てみましょう。 2つのPlaceholderを作ることを考えます。

import jijmodeling as jm

d = jm.Placeholder("d", dim=1)
C = jm.Placeholder("C", dim=1)
import jijmodeling as jm
d = jm.Placeholder("d", dim=1)
n = d.shape[0]
C = jm.Placeholder("C", shape=(n, ))

これら二つも同じように見えますが、前者は変数dCの長さに関係はありません。 しかし後者はddimで1次元配列であることを表していますが、nとしてdの長さを取得し、Cnつまりdと同じ長さであることを表しています。

このように各変数間の大きさに依存関係がある場合はshapeを使って陽に依存関係がわかるようにすることをおすすめします。