Last active
March 8, 2018 15:39
-
-
Save snaga/0b2a898cb661e26dc126733ad821022f to your computer and use it in GitHub Desktop.
線形計画をPythonで解いてみる(2)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# 線形計画をPythonで解いてみる(2)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"「入門オペレーションズ・リサーチ」の演習問題を解いてみるシリーズ。\n", | |
"\n", | |
"## 演習問題 p.165\n", | |
"\n", | |
"冷蔵庫を開けたら、豚肉300g、鶏肉500g、キャベツ300g、人参300g、椎茸200gがありました。あなたはこの材料で今日の夕食を作らなければなりません。作れるメニューは以下の通りで、100g作るのに必要な材料が書いてあります。\n", | |
"\n", | |
"| メニュー100gあたりの分量 | 豚肉 (300g) | 鶏肉 (500g) | キャベツ (300g) | 人参 (300g) | 椎茸 (200g) |\n", | |
"|:---|:---|:---|:---|:---|:---|\n", | |
"| 鳥のスープ | | 40g | | 20g | 10g |\n", | |
"| キャベツのスープ | | | 30g | 20g | 20g |\n", | |
"| 鶏肉の炒め物 | | 60g | | 20g | 20g |\n", | |
"| 豚肉の炒め物 | 40g | | 40g | 10g | 10g |\n", | |
"\n", | |
"このメニューで、スープを500g以上、炒め物を500g以上作らなければなりません。どのような線形計画法の問題を作れば、この条件を満たすように、それぞれのメニューを作る量が求められるでしょうか。\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"import pulp\n", | |
"\n", | |
"problem = pulp.LpProblem('夕食計画', pulp.LpMaximize)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"* 鳥のスープの量を x1、キャベツのスープの量を x2 とする。\n", | |
"* 鶏肉の炒め物の量を y1、豚肉の炒め物の量を y2 とする。\n", | |
"\n", | |
"これらはそれぞれ最小値0、最大値500となる。(単位:グラム)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# 鳥のスープの量\n", | |
"x1 = pulp.LpVariable('x1', 0, 500, 'Integer')\n", | |
"# キャベツのスープの量\n", | |
"x2 = pulp.LpVariable('x2', 0, 500, 'Integer')\n", | |
"# 鶏肉の炒め物の量\n", | |
"y1 = pulp.LpVariable('y1', 0, 500, 'Integer')\n", | |
"# 豚肉の炒め物の量\n", | |
"y2 = pulp.LpVariable('y2', 0, 500, 'Integer')" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"* 豚肉、鶏肉、キャベツ、人参、椎茸の使用量を、それぞれ a, b, c, d, e とする。" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"| メニュー100gあたりの分量 | a豚肉 (300g) | b鶏肉 (500g) | cキャベツ (300g) | d人参 (300g) | e椎茸 (200g) |\n", | |
"|:---|:---|:---|:---|:---|:---|\n", | |
"| x1鳥のスープ | | 40g | | 20g | 10g |\n", | |
"| x2キャベツのスープ | | | 30g | 20g | 20g |\n", | |
"| y1鶏肉の炒め物 | | 60g | | 20g | 20g |\n", | |
"| y2豚肉の炒め物 | 40g | | 40g | 10g | 10g |" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# 豚肉の使用量\n", | |
"a = pulp.LpVariable('a', 0, 300, 'Integer')\n", | |
"# 鶏肉の使用量\n", | |
"b = pulp.LpVariable('b', 0, 500, 'Integer')\n", | |
"# キャベツの使用量\n", | |
"c = pulp.LpVariable('c', 0, 300, 'Integer')\n", | |
"# 人参の使用量\n", | |
"d = pulp.LpVariable('d', 0, 300, 'Integer')\n", | |
"# 椎茸の使用量\n", | |
"e = pulp.LpVariable('e', 0, 200, 'Integer')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# 何を最大化(or最小化)するか(目的関数)\n", | |
"# problem += x1 + x2 + y1 + y2\n", | |
"problem += c" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"* スープを500g以上作る\n", | |
"* 炒め物を500g以上作る" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# 調理する量\n", | |
"problem += x1 + x2 >= 500\n", | |
"problem += y1 + y2 >= 500" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"| メニュー100gあたりの分量 | a豚肉 (300g) | b鶏肉 (500g) | cキャベツ (300g) | d人参 (300g) | e椎茸 (200g) |\n", | |
"|:---|:---|:---|:---|:---|:---|\n", | |
"| x1鳥のスープ | | 40g | | 20g | 10g |\n", | |
"| x2キャベツのスープ | | | 30g | 20g | 20g |\n", | |
"| y1鶏肉の炒め物 | | 60g | | 20g | 20g |\n", | |
"| y2豚肉の炒め物 | 40g | | 40g | 10g | 10g |" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"# それぞれの料理に使う食材の量の定義\n", | |
"# 豚肉\n", | |
"problem += 40/100*y2 == a\n", | |
"# 鶏肉\n", | |
"problem += 40/100*x1 + 60/100*y1 == b\n", | |
"# キャベツ\n", | |
"problem += 30/100*x2 + 40/100*y2 == c\n", | |
"# 人参\n", | |
"problem += 20/100*x1 + 20/100*x2 + 20/100*y1 + 10/100*y2 == d\n", | |
"# 椎茸\n", | |
"problem += 10/100*x1 + 20/100*x2 + 20/100*y1 + 10/100*y2 == e\n", | |
"\n", | |
"# それぞれの料理に使える食材の量の上限の制約\n", | |
"# 豚肉\n", | |
"problem += 40/100*y2 <= 300\n", | |
"# 鶏肉\n", | |
"problem += 40/100*x1 + 60/100*y1 <= 500\n", | |
"# キャベツ\n", | |
"problem += 30/100*x2 + 40/100*y2 <= 300\n", | |
"# 人参\n", | |
"problem += 20/100*x1 + 20/100*x2 + 20/100*y1 + 10/100*y2 <= 300\n", | |
"# 椎茸\n", | |
"problem += 10/100*x1 + 20/100*x2 + 20/100*y1 + 10/100*y2 <= 200" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"status = problem.solve()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Optimal\n" | |
] | |
} | |
], | |
"source": [ | |
"print(pulp.LpStatus[status])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"夕食計画:\n", | |
"MAXIMIZE\n", | |
"1*c + 0\n", | |
"SUBJECT TO\n", | |
"_C1: x1 + x2 >= 500\n", | |
"\n", | |
"_C2: y1 + y2 >= 500\n", | |
"\n", | |
"_C3: - a + 0.4 y2 = 0\n", | |
"\n", | |
"_C4: - b + 0.4 x1 + 0.6 y1 = 0\n", | |
"\n", | |
"_C5: - c + 0.3 x2 + 0.4 y2 = 0\n", | |
"\n", | |
"_C6: - d + 0.2 x1 + 0.2 x2 + 0.2 y1 + 0.1 y2 = 0\n", | |
"\n", | |
"_C7: - e + 0.1 x1 + 0.2 x2 + 0.2 y1 + 0.1 y2 = 0\n", | |
"\n", | |
"_C8: 0.4 y2 <= 300\n", | |
"\n", | |
"_C9: 0.4 x1 + 0.6 y1 <= 500\n", | |
"\n", | |
"_C10: 0.3 x2 + 0.4 y2 <= 300\n", | |
"\n", | |
"_C11: 0.2 x1 + 0.2 x2 + 0.2 y1 + 0.1 y2 <= 300\n", | |
"\n", | |
"_C12: 0.1 x1 + 0.2 x2 + 0.2 y1 + 0.1 y2 <= 200\n", | |
"\n", | |
"VARIABLES\n", | |
"0 <= a <= 300 Integer\n", | |
"0 <= b <= 500 Integer\n", | |
"0 <= c <= 300 Integer\n", | |
"0 <= d <= 300 Integer\n", | |
"0 <= e <= 200 Integer\n", | |
"0 <= x1 <= 500 Integer\n", | |
"0 <= x2 <= 500 Integer\n", | |
"0 <= y1 <= 500 Integer\n", | |
"0 <= y2 <= 500 Integer\n", | |
"\n" | |
] | |
} | |
], | |
"source": [ | |
"print(problem)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"scrolled": true | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"x1鳥のスープ: 20\n", | |
"x2キャベツのスープ: 480\n", | |
"y1鶏肉の炒め物: 140\n", | |
"y2豚肉の炒め物: 390\n", | |
"\n", | |
"a豚肉 (300g): 156\n", | |
"b鶏肉 (500g): 92\n", | |
"cキャベツ (300g): 300\n", | |
"d人参 (300g): 167\n", | |
"e椎茸 (200g): 165\n" | |
] | |
} | |
], | |
"source": [ | |
"print(\"x1鳥のスープ: %d\" % x1.value())\n", | |
"print(\"x2キャベツのスープ: %d\" % x2.value())\n", | |
"print(\"y1鶏肉の炒め物: %d\" % y1.value())\n", | |
"print(\"y2豚肉の炒め物: %d\" % y2.value())\n", | |
"print(\"\")\n", | |
"\n", | |
"print(\"a豚肉 (300g): %d\" % a.value())\n", | |
"print(\"b鶏肉 (500g): %d\" % b.value())\n", | |
"print(\"cキャベツ (300g): %d\" % c.value())\n", | |
"print(\"d人参 (300g): %d\" % d.value())\n", | |
"print(\"e椎茸 (200g): %d\" % e.value())" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## ※答え合わせ\n", | |
"\n", | |
"演習の解答に「ここに適当な目的関数を設定すると、線形計画問題になります」とあるけれど、その「目的関数」を知りたいのです。" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"x1 + x2 + y1 + y2 を maximize (最大限の量を作るには)\n", | |
"```\n", | |
"x1鳥のスープ: 500\n", | |
"x2キャベツのスープ: 0\n", | |
"y1鶏肉の炒め物: 500\n", | |
"y2豚肉の炒め物: 500\n", | |
"\n", | |
"a豚肉 (300g): 200\n", | |
"b鶏肉 (500g): 500\n", | |
"cキャベツ (300g): 200\n", | |
"d人参 (300g): 250\n", | |
"e椎茸 (200g): 200\n", | |
"```\n", | |
"\n", | |
"x1 + x2 + y1 + y2 を minimize (最小限の量を作るには)\n", | |
"```\n", | |
"x1鳥のスープ: 500\n", | |
"x2キャベツのスープ: 0\n", | |
"y1鶏肉の炒め物: 500\n", | |
"y2豚肉の炒め物: 0\n", | |
"\n", | |
"a豚肉 (300g): 0\n", | |
"b鶏肉 (500g): 500\n", | |
"cキャベツ (300g): 0\n", | |
"d人参 (300g): 200\n", | |
"e椎茸 (200g): 150\n", | |
"```\n", | |
"\n", | |
"a + b を maximize (肉を食べたい!)\n", | |
"```\n", | |
"x1鳥のスープ: 500\n", | |
"x2キャベツのスープ: 0\n", | |
"y1鶏肉の炒め物: 500\n", | |
"y2豚肉の炒め物: 500\n", | |
"\n", | |
"a豚肉 (300g): 200\n", | |
"b鶏肉 (500g): 500\n", | |
"cキャベツ (300g): 200\n", | |
"d人参 (300g): 250\n", | |
"e椎茸 (200g): 200\n", | |
"```\n", | |
"\n", | |
"a + b を minimize (肉は高い!)\n", | |
"```\n", | |
"x1鳥のスープ: 0\n", | |
"x2キャベツのスープ: 500\n", | |
"y1鶏肉の炒め物: 130\n", | |
"y2豚肉の炒め物: 370\n", | |
"\n", | |
"a豚肉 (300g): 148\n", | |
"b鶏肉 (500g): 78\n", | |
"cキャベツ (300g): 298\n", | |
"d人参 (300g): 163\n", | |
"e椎茸 (200g): 163\n", | |
"```\n", | |
"\n", | |
"c を maximize (安いキャベツを最大限使う!)\n", | |
"```\n", | |
"x1鳥のスープ: 20\n", | |
"x2キャベツのスープ: 480\n", | |
"y1鶏肉の炒め物: 140\n", | |
"y2豚肉の炒め物: 390\n", | |
"\n", | |
"a豚肉 (300g): 156\n", | |
"b鶏肉 (500g): 92\n", | |
"cキャベツ (300g): 300\n", | |
"d人参 (300g): 167\n", | |
"e椎茸 (200g): 165\n", | |
"```\n" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 3", | |
"language": "python", | |
"name": "python3" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.6.3" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment