Skip to content

Instantly share code, notes, and snippets.

@snaga
Last active March 8, 2018 15:39
Show Gist options
  • Save snaga/0b2a898cb661e26dc126733ad821022f to your computer and use it in GitHub Desktop.
Save snaga/0b2a898cb661e26dc126733ad821022f to your computer and use it in GitHub Desktop.
線形計画をPythonで解いてみる(2)
Display the source blob
Display the rendered blob
Raw
{
"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