-
Notifications
You must be signed in to change notification settings - Fork 230
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
2,474 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
__author__ = 'vberaudi' |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,295 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# Campsite" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Selecting the ideal camping site requires careful consideration of many factors such as the proximity to water, availability of firewood, and protection from the elements. Your potential camping sites are shown in the corresponding map. The map consists of 64 sites each with varying characteristics including water, wood, swamp, and mosquitoes.\n", | ||
"\n", | ||
"The quality of a site is determined by a points system. A site that contains water receives +3 points and a site that is near water receives +1 point. A site that contains wood receives +2 points and a site that is near wood receives +1 point. A site that contains swamp is -2 points and a site that is near swamp is -1 point. A site that contains mosquitoes receives -3 points and a site that is near mosquitoes is -2 points. “Near” is defined as adjacent sites including diagonals.\n", | ||
"\n", | ||
"For example, site B5 is worth 1 point (based on +3 on water, +1 near wood, -2 near mosquitoes, -1 near swamp). Note that you only count points once for each type of characteristic.\n", | ||
"\n", | ||
"\n", | ||
"Question: Where is the best campsite?\n", | ||
"\n", | ||
"### References\n", | ||
"\n", | ||
" * The PuzzlOr - Campsite (http://puzzlor.com/2015-06_Campsite.html) .\n" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"<center>\n", | ||
"<img src=\"http://puzzlor.com/images/CampSitePicture.png\"> \n", | ||
"</center>" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"!pip install docplex==0.0.24" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"First things first, we specialize a namedtuple class to model 2D points:" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from collections import namedtuple\n", | ||
"\n", | ||
"class Point(namedtuple(\"TPoint\", [\"x\", \"y\"])):\n", | ||
" def __str__(self):\n", | ||
" return \"P<%g,%g>\" % (self.x, self.y)\n", | ||
" def coords(self):\n", | ||
" return (self.x, self.y)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Now we define the site of water, wood, swamp and mosquitoes present on our map " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"water = [Point(x=1,y=3),Point(x=2,y=5),Point(x=3,y=5),Point(x=4,y=2),Point(x=4,y=4),Point(x=4,y=8),Point(x=5,y=2),Point(x=5,y=3),Point(x=6,y=2),Point(x=7,y=3),Point(x=7,y=5)]\n", | ||
"wood = [Point(x=1,y=7),Point(x=3,y=4),Point(x=5,y=5),Point(x=7,y=3),Point(x=8,y=3),Point(x=8,y=4),Point(x=8,y=8)]\n", | ||
"swamp = [Point(x=1,y=5),Point(x=1,y=6),Point(x=2,y=1),Point(x=3,y=5),Point(x=4,y=2),Point(x=4,y=7),Point(x=6,y=2),Point(x=7,y=4),Point(x=7,y=8),Point(x=8,y=3)]\n", | ||
"mosquitoes = [Point(x=1,y=3),Point(x=1,y=6),Point(x=2,y=2),Point(x=3,y=5),Point(x=3,y=8),Point(x=7,y=1),Point(x=7,y=3),Point(x=8,y=6)]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Now lets define a fonction that calculate the distance between two points" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"import math\n", | ||
"\n", | ||
"def euclidean_distance(p1, p2):\n", | ||
" dx = p1.x - p2.x\n", | ||
" dy = p1.y - p2.y\n", | ||
" return (dx * dx + dy * dy)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Let's define a fonction that give us the nearest site to our point" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"def nearest_site(p1):\n", | ||
" result = {}\n", | ||
" for i in [water, wood, swamp, mosquitoes]:\n", | ||
" if i == water: vardi = 'water'\n", | ||
" if i == wood: vardi = 'wood'\n", | ||
" if i == swamp: vardi = 'swamp'\n", | ||
" if i == mosquitoes: vardi = 'mosquitoes'\n", | ||
" for j in range(len(i)):\n", | ||
" if j == 0: result[vardi] = i[j] \n", | ||
" else:\n", | ||
" if euclidean_distance(i[j], p1)< euclidean_distance(result[vardi], p1):\n", | ||
" result[vardi] = i[j]\n", | ||
"\n", | ||
" return result" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Let's now define the number of point on a defined site" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"def how_many_point(p1):\n", | ||
" point=0\n", | ||
" neighborhood = nearest_site(p1)\n", | ||
" for i in ['water', 'wood', 'swamp', 'mosquitoes']:\n", | ||
" if euclidean_distance(p1,neighborhood[i])==0:\n", | ||
" if i == 'water': point= point+ 3\n", | ||
" if i == 'wood': point= point+2\n", | ||
" if i == 'swamp':point= point-2\n", | ||
" if i == 'mosquitoes': point= point-3\n", | ||
" elif euclidean_distance(p1,neighborhood[i])<=2:\n", | ||
" if i == 'water': point= point+1\n", | ||
" if i == 'wood': point= point+1\n", | ||
" if i == 'swamp': point= point-1\n", | ||
" if i == 'mosquitoes': point= point-2\n", | ||
" return point" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Lets map our point on every site on a matrix " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"points = [Point(x,y) for (x,y) in [(i,j) for i in range(1,8) for j in range(1,8)]]\n", | ||
"def generate_matrix(point):\n", | ||
" matrix = {p: how_many_point(p) for p in point}\n", | ||
" return matrix\n", | ||
"matrix = generate_matrix(points)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from docplex.mp.environment import Environment\n", | ||
"env = Environment()\n", | ||
"env.print_information()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Let's now build the model that will choose the best site " | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from docplex.mp.context import DOcloudContext\n", | ||
"context = DOcloudContext(url=\"PUT_YOUR_DOCLOUD_URL_HERE\", \n", | ||
" api_key=\"PUT_YOUR_DOCLOUD_KEY_HERE\")\n", | ||
"#context.verbose = True" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false, | ||
"scrolled": true | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"from docplex.mp.model import Model\n", | ||
"\n", | ||
"mdl = Model(\"best_campsite\", docloud_context=context)\n", | ||
"\n", | ||
"cord_vars = mdl.binary_var_dict(points, name=\"cord\")\n", | ||
"\n", | ||
"mdl.add_constraint(mdl.sum(cord_vars[h] for h in points) == 1)\n", | ||
"\n", | ||
"mdl.maximize(mdl.sum(cord_vars[h] * matrix[h] for h in points))\n", | ||
"\n", | ||
"ok = mdl.solve()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": null, | ||
"metadata": { | ||
"collapsed": false | ||
}, | ||
"outputs": [], | ||
"source": [ | ||
"if not ok:\n", | ||
" print(\"Campsite model fails\")\n", | ||
"else:\n", | ||
" total_points = mdl.objective_value\n", | ||
" best_site = [h for h in points if float(cord_vars[h]) ==1]\n", | ||
" print(\"the best site is {} and its score is {}\" .format(best_site,total_points))" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 2", | ||
"language": "python", | ||
"name": "python2" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 2 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython2", | ||
"version": "2.7.6" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 0 | ||
} |
Oops, something went wrong.