上限を1増やすと利益はいくら増えるか
感度分析とは、制約の上限や利益が変わったとき、最適な答えがどう変わるかを調べることです。とくに双対価格は、上限を1だけ増やしたときに増える利益で、「小麦粉をあと1kg買う価値」を教えてくれます。
仕入れや増員を決めるときの、値段の目安になります。
このレッスンのゴール
メモ
制約の上限が変わったとき、最大の利益がいくら変わるかを、双対価格で言うことができる。
キーワード
| ことば | いみ | れい |
|---|---|---|
| 感度分析 | 条件が変わったとき、答えがどう動くかを調べること | |
| 双対価格 | 上限を1増やしたときに増える最大の目的の値 | 小麦粉1kgで125円 |
| 使い切る | 制約が上限ちょうどまで使われていること | |
| 余裕がある | 上限まで使われず、余りが出ていること | |
| 有効な制約 | 使い切っていて、答えを決めている制約 |
学生が入力するセルは、このプレビューでは空白です。
上限を1増やして、解き直す
一番かんたんな感度分析は、上限を1だけ変えて、もう一度解くことです。小麦粉を8kgから9kgにして、最大の利益を比べます。
増えた分が、小麦粉の双対価格です。オーブンも、180分を181分にして同じように調べます。
1つだけ上限を変えた結果
| 小麦粉 | オーブン | 最大の利益 | 前との差 |
|---|---|---|---|
| 8kg | 180分 | 1450円 | 基準 |
| 9kg | 180分 | 1575円 | +125円 |
| 8kg | 181分 | 1452.5円 | +2.5円 |
学生が入力するセルは、このプレビューでは空白です。
小麦粉を9kgにして解く
docker exec jupyter python3 -c "from scipy.optimize import linprog; r = linprog([-200, -300], A_ub=[[1, 2], [30, 20]], b_ub=[9, 180]); print(round(-r.fun, 2))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
オーブンを181分にして解く
docker exec jupyter python3 -c "from scipy.optimize import linprog; r = linprog([-200, -300], A_ub=[[1, 2], [30, 20]], b_ub=[8, 181]); print(round(-r.fun, 2))"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
双対価格は、解くと同時に出る
上限を変えて何度も解かなくても、linprog は双対価格を一緒に返します。r.ineqlin.marginals に、制約ごとの値が入っています。
linprog は小さくする向きなので、符号が逆(マイナス)で出ます。abs で正にして読みます。
双対価格を直接読む
docker exec jupyter python3 -c "from scipy.optimize import linprog; r = linprog([-200, -300], A_ub=[[1, 2], [30, 20]], b_ub=[8, 180]); print([round(abs(m), 2) for m in r.ineqlin.marginals])"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
余裕のある制約の双対価格は0
オーブンを300分に増やすと、食パンを8本焼けますが、小麦粉8kgが先になくなります。オーブンは240分しか使わず、60分余ります。
余っている資源は、増やしても利益が増えません。だから、余裕のある制約の双対価格は0です。
オーブンが300分のとき
| 制約 | 使った量 | 上限 | 双対価格 |
|---|---|---|---|
| 小麦粉 | 8kg | 8kg | 200円 |
| オーブン | 240分 | 300分 | 0円 |
学生が入力するセルは、このプレビューでは空白です。
余裕のある制約を確かめる
docker exec jupyter python3 -c "from scipy.optimize import linprog; r = linprog([-200, -300], A_ub=[[1, 2], [30, 20]], b_ub=[8, 300]); print(round(-r.fun, 2), r.x, [round(abs(m), 2) for m in r.ineqlin.marginals])"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
多くの人は、双対価格の125円が、いくら増やしても続くと考えます。実際は、小さな変化のあいだだけ成り立ちます。小麦粉を20kgにすると、増えた12kgで利益は1250円しか増えず、125円 × 12 の1500円にはなりません。
何度も解いて差を見る
# 小麦粉の上限を変えて、最大の利益を求めます。
def best(flour, oven):
best_value = 0
points = [[0, 0], [flour, 0], [0, flour / 2], [oven / 30, 0], [0, oven / 20]]
x = (oven / 10 - flour) / 2
points.append([x, (flour - x) / 2])
for p in points:
if p[0] >= 0 and p[1] >= 0 and p[0] + 2 * p[1] <= flour + 0.000001 and 30 * p[0] + 20 * p[1] <= oven + 0.000001:
best_value = max(best_value, 200 * p[0] + 300 * p[1])
return best_value
print(best(8, 180), best(9, 180))
# 9 を 10 に変えると、利益はいくら増えるでしょう。
さらに挑戦: 仕入れを決める
小麦粉を1kg追加で仕入れると、300円かかるとします。双対価格が125円なら、買うと損をします。
60円なら買うと得です。小麦粉の値段が、何円のときに買うのをやめるかを、ノートに書いてください。