配合問題をPulPとPySIMPLEとGurobiで解く

CBC

https://github.com/coin-or/CbcCBCソルバをPythonで利用するにはPuLPを使用する。

PuLPとは

PuLPはPythonで書かれたLPモデラー。
PuLPはMPSまたはLPファイルを生成し、
GLPK, COIN-OR CLP/CBC, CPLEX, GUROBI, MOSEK, XPRESS, CHOCO, MIPCL, SCIPを呼び出して線形問題を解くことができる。

インストール

$ pip install pulp

対応Pythonバージョン

  • Python 2.7
  • Python >= 3.4.

使用例

新しい変数を作成するには、LpVariable()を使用します。

0 <= x <= 3:

x = LpVariable("x", 0, 3)

0 <= y <= 1:

y = LpVariable("y", 0, 1)

LpProblem() を使って、新しい問題を作成します。myProblem “を作成。

prob = LpProblem("myProblem", LpMinimize)

変数を組み合わせて式や制約を作り、問題に追加する。

prob += x + y <= 2

式(制約ではない)を追加すると、それが目的関数になる。

prob += -4*x + y

解く。

status = prob.solve()

ソリューションのステータスを表示。

LpStatus[status]

変数の値を取得するには、value()を使用。

value(x)

配合問題による例

import pulp

# 関数の最小化を目的として設定する
problem = pulp.LpProblem("配合問題", pulp.LpMinimize)

# 変数の設定 (変数名、最小値、最大値、型)
# 9種類の合金の割合
x1 = pulp.LpVariable('X1', 0, 1, 'Continuous')
x2 = pulp.LpVariable('X2', 0, 1, 'Continuous')
x3 = pulp.LpVariable('X3', 0, 1, 'Continuous')
x4 = pulp.LpVariable('X4', 0, 1, 'Continuous')
x5 = pulp.LpVariable('X5', 0, 1, 'Continuous')
x6 = pulp.LpVariable('X6', 0, 1, 'Continuous')
x7 = pulp.LpVariable('X7', 0, 1, 'Continuous')
x8 = pulp.LpVariable('X8', 0, 1, 'Continuous')
x9 = pulp.LpVariable('X9', 0, 1, 'Continuous')

# 目的関数(最小にしたいコストを定義)
problem += 7.3*x1 + 6.9*x2 + 7.3*x3 + 7.5*x4 + 7.6*x5 + 6.0*x6 + 5.8*x7 + 4.3*x8 + 4.1*x9

# 制約の設定
# 合計で1(100%)とする
problem += x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 == 1

# 鉛の混合比
problem += 20*x1 + 50*x2 + 30*x3 +30*x4 + 30*x5 + 60*x6 + 40*x7 + 10*x8 + 10*x9 == 30
# 亜鉛の混合比
problem += 30*x1 + 40*x2 + 20*x3 +40*x4 + 30*x5 + 30*x6 + 50*x7 + 30*x8 + 10*x9 == 30
# スズの混合比
problem += 50*x1 + 10*x2 + 50*x3 +30*x4 + 40*x5 + 10*x6 + 10*x7 + 60*x8 + 80*x9 == 40

# 問題定義の確認
print(problem)

# 実行
result = problem.solve()

# 結果の確認
print("X1:" ,pulp.value(x1))
print("X2:" ,pulp.value(x2))
print("X3:" ,pulp.value(x3))
print("X4:" ,pulp.value(x4))
print("X5:" ,pulp.value(x5))
print("X6:" ,pulp.value(x6))
print("X7:" ,pulp.value(x7))
print("X8:" ,pulp.value(x8))
print("X9:" ,pulp.value(x9))
print("Cost:" ,pulp.value(problem.objective))

Numerical optimizer

http://www.msi.co.jp/nuopt/
Numerical OptimizerソルバをPythonで利用するにはSIMPLEを使用する。

SIMPLEとは

PySIMPLEは Numerical Optimizerの Python インタフェース。
PySIMPLE ではこのうち線形計画問題、
目的関数と制約式がすべて線形である問題に対して Numerical Optimizer への接続インターフェースを提供

インストール

$ pip install pysimple

対応Pythonバージョン

  • Python3.6
  • Python3.7
  • Python3.8

配合問題による例

from pysimple import *

problem = Problem(name='配合問題', type=min)

# 変数
x1 = Variable(index=1, lb=0, name='混合比率')
x2 = Variable(index=2, lb=0, name='混合比率')
x3 = Variable(index=3, lb=0, name='混合比率')
x4 = Variable(index=4, lb=0, name='混合比率')
x5 = Variable(index=5, lb=0, name='混合比率')
x6 = Variable(index=6, lb=0, name='混合比率')
x7 = Variable(index=7, lb=0, name='混合比率')
x8 = Variable(index=8, lb=0, name='混合比率')
x9 = Variable(index=9, lb=0, name='混合比率')

# 目的関数
problem += 7.3*x1 + 6.9*x2 + 7.3*x3 + 7.5*x4 + 7.6*x5 + 6.0*x6 + 5.8*x7 + 4.3*x8 + 4.1*x9

# 鉛の混合比
problem += 20*x1 + 50*x2 + 30*x3 +30*x4 + 30*x5 + 60*x6 + 40*x7 + 10*x8 + 10*x9 == 30
# 亜鉛の混合比
problem += 30*x1 + 40*x2 + 20*x3 +40*x4 + 30*x5 + 30*x6 + 50*x7 + 30*x8 + 10*x9 == 30
# スズの混合比
problem += 50*x1 + 10*x2 + 50*x3 +30*x4 + 40*x5 + 10*x6 + 10*x7 + 60*x8 + 80*x9 == 40

# 実行
problem.solve()

# 出力
print()
print("Cost:", problem.result.optValue())

Gurobi

https://www.engineering-eye.com/GUROBI/index.html
Gurobi OptimizerソルバをPythonで利用するにはgurobipyを使用する。

インストール

$ pip install gurobipy

配合問題による例

from gurobipy import *

m = Model()

X1 = m.addVar()
X2 = m.addVar()
X3 = m.addVar()
X4 = m.addVar()
X5 = m.addVar()
X6 = m.addVar()
X7 = m.addVar()
X8 = m.addVar()
X9 = m.addVar()

# 目的関数(最小にしたいコストを定義)
# 制約の設定

m.setObjective(
    7.3*X1 + 6.9*X2 + 7.3*X3 + 7.5*X4 + 7.6*X5 + 6.0*X6 + 5.8*X7 + 4.3*X8 + 4.1*X9,
    GRB.MINIMIZE
)

# 合計で1(100%)とする
m.addConstr(X1 + X2 + X3 + X4 + X5 + X6 + X7 + X8 + X9 == 1)

# 鉛の混合比
m.addConstr(20*X1 + 50*X2 + 30*X3 +30*X4 + 30*X5 + 60*X6 + 40*X7 + 10*X8 + 10*X9 == 30)
# 亜鉛の混合比
m.addConstr(30*X1 + 40*X2 + 20*X3 +40*X4 + 30*X5 + 30*X6 + 50*X7 + 30*X8 + 10*X9 == 30)
# スズの混合比
m.addConstr(50*X1 + 10*X2 + 50*X3 +30*X4 + 40*X5 + 10*X6 + 10*X7 + 60*X8 + 80*X9 == 40)

# 問題定義の確認
print(m)

# 実行
m.optimize()

print("X1:" ,X1.x)
print("X2:" ,X2.x)
print("X3:" ,X3.x)
print("X4:" ,X4.x)
print("X5:" ,X5.x)
print("X6:" ,X6.x)
print("X7:" ,X7.x)
print("X8:" ,X8.x)
print("X9:" ,X9.x)
print("Cost:" ,m.objVal)

ディープテックのマガジンはこちら『DeepMagazine』

https://deep-recommend.com/magazine