3.3.1. 問題クラス Problem

問題は Problem というクラスで表現されます.:

problem = Problem(type=min)

問題を定義する際には type キーワードに min あるいは max を指定することができます. これはそれぞれ扱う数理計画問題が最小化問題,最大化問題であることを意味します. この type= を省略した場合,自動的に最小化問題であると見做されます.

問題に対し,+= を行うと目的関数と見做されます.:

x = Variable()
problem = Problem(type=min)
problem += 2*x

カンマで区切って文字列を与えることにより目的関数に名前をつけることもできます.:

problem += 2*x, '目的関数'

問題の目的関数は objective 属性でアクセスすることができます.:

print(problem.objective)

問題に対し,+= 制約式 を行うと制約式の追加と見做されます.:

problem += 2*x >= 0

カンマで区切って文字列を与えることにより制約式に名前をつけることもできます.:

problem += 2*x >= 0, '制約式1'

問題の制約式は 問題[制約式名] でアクセスすることができます.:

print(problem['制約式1'])

目的関数に添字をつける事はできません.例えば,以下の記述は誤りです.:

i = Element(value=[1,2])
x = Variable(index=i)
problem = Problem(type=min)
problem += 2*x[i]

目的関数を複数設定することはできません.例えば,以下の記述は誤りです.:

x = Variable()
problem = Problem(type=min)
problem += 2*x
problem += 3*x + 1

3.3.1.1. solve 関数

求解(最適解計算の実行)を行うには solve メソッドを呼び出します.:

problem.solve()

solve 関数の前に変数や式の値を出力させると,求解前の初期状態の情報が記述されます. 例えば,次のモデルに対する出力は以下のようになります.:

p = Problem(type=min)
i = Element(value=[1, 2, 3])
x = Variable(index=i)
p += Sum(2*x[i])
p += x[i] >= 5
x[i] = 10
print(x.val)  # 10
p.solve(silent=True)
print(x.val)  # 5

出力:

x[1].val=10
x[2].val=10
x[3].val=10
x[1].val=5.000000020802062
x[2].val=5.000000020802062
x[3].val=5.000000020802062

solve 関数は,デフォルトでは標準出力に求解情報を表示し,解ファイル(モデル名.sol)を作成しません. 標準出力による求解情報の表示を抑制するには,問題の宣言時か求解時に silent キーワードを記述します.:

p = Problem(silent=True)
p = Problem()
p.solve(silent=True)

求解時の設定は問題宣言時の設定に優先され,また一時的です.

解ファイルを出力するには solfile キーワードを記述します. 解ファイル,及び実行不可能性要因検出機能については 実行不可能性要因検出機能 をご確認ください.:

p = Problem(solfile=True)
p = Problem()
p.solve(solfile=True)

その他の求解時の制御については 求解オプションコールバック関数 をご確認ください.

3.3.1.2. 最適化計算結果 result

最適化計算の結果は result メンバが保持しています. 一覧は pysimple.problem.Result を確認してください. 以下は最適化計算結果を出力する記述例です.:

x = Variable()
y = Variable()
p = Problem()
p += 2*x + 3*y
p += x + 2*y == 15
p += x >= 0
p += y >= 0
p.solve(silent=True)
print(p.result)
Printf('関数の数         {}', p.result.nfunc)
Printf('内点法の反復回数 {}', p.result.iters)
Printf('関数評価回数     {}', p.result.fevals)
Printf('目的関数値       {}', p.result.optValue)
Printf('収束判定条件     {}', p.result.tolerance)
Printf('最適性条件残差   {}', p.result.residual)
Printf('所要計算時間     {}', p.result.elapseTime)
Printf('終了時ステータス {}', p.result.errorCode)

出力:

errorMessage          : ''
method                : 'higher'
optValue              : 22.50000000376254
errorCode             : 0
nvars                 : 2
nfunc                 : 4
iters                 : 6
elapseTime            : 0.001999974250793457
peakPhysicalMemoryUsed: 44
peakVirtualMemoryUsed : 1518
fevals                : 9
factCount             : 7
tolerance             : 1e-08
residual              : 3.762538162000488e-09
infeasibility         : 3.552713678800501e-15
consInfeasibility     : 0.0
varInfeasibility      : 0.0
hardPenalty           : 0.0
semiHardPenalty       : 0.0
softPenalty           : 0.0
IIS                   : no IIS
関数の数         4
内点法の反復回数 6
関数評価回数     9
目的関数値       22.50000000376254
収束判定条件     1e-08
最適性条件残差   3.762538162000488e-09
所要計算時間     0.001999974250793457
終了時ステータス 0