{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# PuLPを使ってみる"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"特に実装すべきアルゴリズムはなかったが、せっかくなのでpythonで線形計画問題を解くためのパッケージ(?)である**PuLP**を使って実際に線形計画問題を解く方法を調べてみた。\n",
"\n",
"[参考にしたサイト](http://qiita.com/Tsutomu-KKE@github/items/070ca9cb37c6b2b492f0)\n",
"\n",
"インストール方法は、\n",
"```\n",
"sudo pip install pulp\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"from pulp import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"$$\\max 100x + 100y$$\n",
"\n",
"$$ s.t. \\\\ x + 2y \\leq 16 $$\n",
"\n",
"$$ x + y \\leq 18 $$"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"4.0 6.0\n"
]
}
],
"source": [
"m = LpProblem(sense=LpMaximize) # 数理モデル\n",
"x = LpVariable('x', lowBound=0) # 変数\n",
"y = LpVariable('y', lowBound=0)\n",
"m += 100 * x + 100 * y # 目的関数\n",
"m += x + 2 * y <= 16 #制約1\n",
"m += 3 * x + y <= 18 # 制約2\n",
"m.solve() # ソルバー実行\n",
"print(value(x), value(y))"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"100*x + 100*y\n"
]
}
],
"source": [
"print(m.objective)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1000.0\n"
]
}
],
"source": [
"print(value(m.objective))"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"status = m.solve()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Optimal\n"
]
}
],
"source": [
"print (LpStatus[status])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# PuLP with pandas"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"輸送最適化問題を解く(参考サイトに問題の詳細あり)"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np, pandas as pd\n",
"from itertools import product\n",
"from pulp import *\n",
"\n",
"np.random.seed(1)\n",
"nw, nf = 3, 4\n",
"pr = list(product(range(nw),range(nf)))\n",
"supply = np.random.randint(30, 50, nw)\n",
"demand = np.random.randint(20, 40, nf)\n",
"cost = np.random.randint(10, 20, (nw,nf))"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"{(0, 0): 28.0,\n",
" (0, 1): 7.0,\n",
" (1, 2): 31.0,\n",
" (1, 3): 5.0,\n",
" (2, 1): 22.0,\n",
" (2, 3): 20.0}"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# pandasを使わずにモデリングすると\n",
"\n",
"m1 = LpProblem() # minimizing\n",
"v1 = {(i,j):LpVariable('v%d_%d'%(i,j), lowBound=0) for i,j in pr}\n",
"m1 += lpSum(cost[i][j] * v1[i,j] for i,j in pr) # objective function\n",
"for i in range(nw):\n",
" m1 += lpSum(v1[i,j] for j in range(nf)) <= supply[i]\n",
"for j in range(nf):\n",
" m1 += lpSum(v1[i,j] for i in range(nw)) >= demand[j]\n",
"m1.solve()\n",
"{k:value(x) for k,x in v1.items() if value(x) > 0}"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"{(0, 0): v0_0,\n",
" (0, 1): v0_1,\n",
" (0, 2): v0_2,\n",
" (0, 3): v0_3,\n",
" (1, 0): v1_0,\n",
" (1, 1): v1_1,\n",
" (1, 2): v1_2,\n",
" (1, 3): v1_3,\n",
" (2, 0): v2_0,\n",
" (2, 1): v2_1,\n",
" (2, 2): v2_2,\n",
" (2, 3): v2_3}"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v1"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"v1_1"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v1[1,1]"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"dict_items([((0, 1), v0_1), ((1, 2), v1_2), ((0, 0), v0_0), ((1, 1), v1_1), ((2, 1), v2_1), ((0, 2), v0_2), ((2, 0), v2_0), ((1, 3), v1_3), ((2, 3), v2_3), ((2, 2), v2_2), ((1, 0), v1_0), ((0, 3), v0_3)])"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"v1.items()"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.0"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"value(v1[1,1])"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"
\n",
" \n",
" \n",
" | \n",
" warehouse | \n",
" factory | \n",
" cost | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 0 | \n",
" 0 | \n",
" 10 | \n",
"
\n",
" \n",
" | 1 | \n",
" 0 | \n",
" 1 | \n",
" 10 | \n",
"
\n",
" \n",
" | 2 | \n",
" 0 | \n",
" 2 | \n",
" 11 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" warehouse factory cost\n",
"0 0 0 10\n",
"1 0 1 10\n",
"2 0 2 11"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# pandasを使ってモデリング\n",
"a = pd.DataFrame([(i,j) for i, j in pr], columns=['warehouse', 'factory'])\n",
"a['cost'] = cost.flatten()\n",
"a[:3]"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"
\n",
" \n",
" \n",
" | \n",
" warehouse | \n",
" factory | \n",
" cost | \n",
" Var | \n",
" Val | \n",
"
\n",
" \n",
" \n",
" \n",
" | 0 | \n",
" 0 | \n",
" 0 | \n",
" 10 | \n",
" v0 | \n",
" 28.0 | \n",
"
\n",
" \n",
" | 1 | \n",
" 0 | \n",
" 1 | \n",
" 10 | \n",
" v1 | \n",
" 7.0 | \n",
"
\n",
" \n",
" | 6 | \n",
" 1 | \n",
" 2 | \n",
" 12 | \n",
" v6 | \n",
" 31.0 | \n",
"
\n",
" \n",
" | 7 | \n",
" 1 | \n",
" 3 | \n",
" 14 | \n",
" v7 | \n",
" 5.0 | \n",
"
\n",
" \n",
" | 9 | \n",
" 2 | \n",
" 1 | \n",
" 12 | \n",
" v9 | \n",
" 22.0 | \n",
"
\n",
" \n",
" | 11 | \n",
" 2 | \n",
" 3 | \n",
" 12 | \n",
" v11 | \n",
" 20.0 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" warehouse factory cost Var Val\n",
"0 0 0 10 v0 28.0\n",
"1 0 1 10 v1 7.0\n",
"6 1 2 12 v6 31.0\n",
"7 1 3 14 v7 5.0\n",
"9 2 1 12 v9 22.0\n",
"11 2 3 12 v11 20.0"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"m2 = LpProblem()\n",
"a['Var'] = [LpVariable('v%d'%i, lowBound=0) for i in a.index]\n",
"m2 += lpDot(a.cost, a.Var)\n",
"for k, v in a.groupby('warehouse'):\n",
" m2 += lpSum(v.Var) <= supply[k]\n",
"for k, v in a.groupby('factory'):\n",
" m2 += lpSum(v.Var) >= demand[k]\n",
"m2.solve()\n",
"a['Val'] = a.Var.apply(value)\n",
"a[a.Val > 0]"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0\n",
"1\n",
"2\n",
"3\n",
"4\n",
"5\n",
"6\n",
"7\n",
"8\n",
"9\n",
"10\n",
"11\n"
]
}
],
"source": [
"for i in a.index:\n",
" print (i)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0\n",
"0 v0\n",
"1 v1\n",
"2 v2\n",
"3 v3\n",
"Name: Var, dtype: object\n",
"1\n",
"4 v4\n",
"5 v5\n",
"6 v6\n",
"7 v7\n",
"Name: Var, dtype: object\n",
"2\n",
"8 v8\n",
"9 v9\n",
"10 v10\n",
"11 v11\n",
"Name: Var, dtype: object\n"
]
}
],
"source": [
"for k, v in a.groupby('warehouse'):\n",
" print (k)\n",
" print (v.Var)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python [conda root]",
"language": "python",
"name": "conda-root-py"
},
"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.5.2"
},
"toc": {
"nav_menu": {
"height": "48px",
"width": "252px"
},
"navigate_menu": true,
"number_sections": true,
"sideBar": true,
"threshold": 4,
"toc_cell": false,
"toc_section_display": "block",
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 1
}