Skip to content

Instantly share code, notes, and snippets.

@yogabonito
Created July 7, 2017 13:51
Show Gist options
  • Save yogabonito/7fc6247444641eea20fa1487a6794d70 to your computer and use it in GitHub Desktop.
Save yogabonito/7fc6247444641eea20fa1487a6794d70 to your computer and use it in GitHub Desktop.
Regionalization with PuLP: exact optimization model called "Order" in Duque et al. (2011)
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import libpysal as ps"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Making the lattice"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We are generating a 3x3 lattice: "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"lat_w = ps.weights.util.lat2W(nrows=3, ncols=3, rook=True, id_type=\"int\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{0: [3, 1],\n",
" 1: [0, 4, 2],\n",
" 2: [1, 5],\n",
" 3: [0, 6, 4],\n",
" 4: [1, 3, 7, 5],\n",
" 5: [2, 4, 8],\n",
" 6: [3, 7],\n",
" 7: [4, 6, 8],\n",
" 8: [5, 7]}"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"neighbor_dict = lat_w.neighbors\n",
"neighbor_dict"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Defining the data (_hardcoded_)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"{0: 726.7,\n",
" 1: 623.6,\n",
" 2: 487.3,\n",
" 3: 200.4,\n",
" 4: 245.0,\n",
" 5: 481.0,\n",
" 6: 170.9,\n",
" 7: 225.9,\n",
" 8: 226.9}"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"value_list = [726.7, 623.6, 487.3, 200.4, 245.0, 481.0, 170.9, 225.9, 226.9]\n",
"value_dict = {area: value for area, value in zip(neighbor_dict.keys(), value_list)}\n",
"value_dict"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Defining the optimization model from Duque et al. (2011): \"The p-Regions Problem\""
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from pulp import LpProblem, LpMinimize, LpVariable, \\\n",
" LpInteger, lpSum, GLPK, LpStatus, \\\n",
" value"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"prob = LpProblem(\"Tree\", LpMinimize)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Parameters"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"n = len(value_dict)\n",
"p = 2 # TODO: turn this into a part of the API\n",
"I = list(value_dict.keys())\n",
"II = [(i, j) for i in I \n",
" for j in I]\n",
"II_upper_triangle = [(i, j) for i, j in II if i < j]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"K = range(p) # index for regions"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"O = range(n - p) # index for orders"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def dissim_measure(v1, v2):\n",
" \"\"\"\\\n",
" Returns the dissimilarity between the values v1 and\n",
" v2.\n",
" \"\"\"\n",
" return abs(v1 - v2)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"d = {(i, j): dissim_measure(value_dict[i], value_dict[j])\n",
" for i, j in II_upper_triangle}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Decision variables"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"t = LpVariable.dicts(\n",
" \"t\",\n",
" ((i, j) for i, j in II_upper_triangle),\n",
" lowBound=0, upBound=1, cat=LpInteger)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"x = LpVariable.dicts(\n",
" \"x\",\n",
" ((i, k, o) for i in I for k in K for o in O),\n",
" lowBound=0, upBound=1, cat=LpInteger)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Objective function"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# (13) in Duque et al. (2011): \"The p-Regions Problem\"\n",
"prob += lpSum(d[i, j] * t[i, j] for i, j in II_upper_triangle)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Constraints"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# (14) in Duque et al. (2011): \"The p-Regions Problem\"\n",
"for k in K:\n",
" prob += sum(x[i, k, 0] for i in I) == 1"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# (15) in Duque et al. (2011): \"The p-Regions Problem\"\n",
"for i in I:\n",
" prob += sum(x[i, k, o] for k in K for o in O) == 1"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"# (16) in Duque et al. (2011): \"The p-Regions Problem\"\n",
"for i in I:\n",
" for k in K:\n",
" for o in range(1, len(O)):\n",
" prob += x[i, k, o] <= \\\n",
" sum(x[j, k, o-1] for j in neighbor_dict[i])"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"# (17) in Duque et al. (2011): \"The p-Regions Problem\"\n",
"for i, j in II_upper_triangle:\n",
" for k in K:\n",
" summ = sum(x[i, k, o] + x[j, k, o] for o in O) - 1\n",
" prob += t[i, j] >= summ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Solve the optimization problem"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/plain": [
"1"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prob.solve(GLPK(msg=0))"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'Optimal'"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"LpStatus[prob.status]"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [],
"source": [
"#for v in prob.variables():\n",
"# print(v.name, \"=\", v.varValue)"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"area 0 is in region 0\n",
"area 1 is in region 0\n",
"area 2 is in region 0\n",
"area 3 is in region 1\n",
"area 4 is in region 1\n",
"area 5 is in region 0\n",
"area 6 is in region 1\n",
"area 7 is in region 1\n",
"area 8 is in region 1\n"
]
}
],
"source": [
"for i in I:\n",
" for k in K:\n",
" for o in O:\n",
" if x[i, k, o].varValue == 1:\n",
" print(\"area\", i, \"is in region\", k)"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1222.8"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"value(prob.objective)"
]
},
{
"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.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment