|
136 | 136 | "\n",
|
137 | 137 | "Consider a salesperson that needs to visit customers at each state capital of the continental US. The salesperson wants to identify the shortest route that goes to all the state capitals.\n",
|
138 | 138 | "\n",
|
139 |
| - "This modeling example requires to import the following libraries.\n", |
140 |
| - "* **math** access to mathematical functions.\n", |
141 |
| - "* **itertools** implements a number of iterator building blocks.\n", |
142 |
| - "* **folium** creates maps.\n", |
143 |
| - "* **gurobipy** calls Gurobi algorithms to solve MIP models.\n" |
| 139 | + "This modeling example requires the following libraries that are not part of the standard Python distribution:\n", |
| 140 | + "* **folium**: to create maps.\n", |
| 141 | + "* **gurobipy**: provides Gurobi algorithms to solve MIP models.\n" |
144 | 142 | ]
|
145 | 143 | },
|
146 | 144 | {
|
|
153 | 151 | },
|
154 | 152 | {
|
155 | 153 | "cell_type": "code",
|
156 |
| - "execution_count": 1, |
| 154 | + "execution_count": null, |
157 | 155 | "metadata": {},
|
158 | 156 | "outputs": [],
|
159 | 157 | "source": [
|
|
174 | 172 | "cell_type": "markdown",
|
175 | 173 | "metadata": {},
|
176 | 174 | "source": [
|
177 |
| - "### Preprocessing\n", |
178 |
| - "The following function calculates the distance of each pair of state capitals combination." |
| 175 | + "### Data computation\n", |
| 176 | + "The following function calculates the distance for each pair of state capitals. Since we are solving the _symmetric_ traveling salesman problem, we use _combinations_ of cities." |
179 | 177 | ]
|
180 | 178 | },
|
181 | 179 | {
|
182 | 180 | "cell_type": "code",
|
183 |
| - "execution_count": 2, |
| 181 | + "execution_count": null, |
184 | 182 | "metadata": {},
|
185 | 183 | "outputs": [],
|
186 | 184 | "source": [
|
187 | 185 | "import math\n",
|
188 |
| - "from itertools import combinations,product\n", |
| 186 | + "from itertools import combinations\n", |
189 | 187 | "\n",
|
190 | 188 | "# Compute pairwise distance matrix\n",
|
191 | 189 | "\n",
|
|
195 | 193 | " diff = (c1[0]-c2[0], c1[1]-c2[1])\n",
|
196 | 194 | " return math.sqrt(diff[0]*diff[0]+diff[1]*diff[1])\n",
|
197 | 195 | "\n",
|
198 |
| - "dist = {(c1, c2): distance(c1, c2) for c1, c2 in product(capitals, capitals) if c1 != c2}" |
| 196 | + "dist = {(c1, c2): distance(c1, c2) for c1, c2 in combinations(capitals, 2)}" |
| 197 | + ] |
| 198 | + }, |
| 199 | + { |
| 200 | + "cell_type": "markdown", |
| 201 | + "metadata": {}, |
| 202 | + "source": [ |
| 203 | + "### Model Code\n", |
| 204 | + "We now write the model for the TSP, by defining decision variables, constraints, and objective function. Because this is the _symmetric_ traveling salesman problem, we can make it more efficient by setting the _object_ x[j,i] to x[i,j], instead of a constraint." |
| 205 | + ] |
| 206 | + }, |
| 207 | + { |
| 208 | + "cell_type": "code", |
| 209 | + "execution_count": null, |
| 210 | + "metadata": {}, |
| 211 | + "outputs": [], |
| 212 | + "source": [ |
| 213 | + "import gurobipy as gp\n", |
| 214 | + "from gurobipy import GRB\n", |
| 215 | + "\n", |
| 216 | + "# tested with Python 3.7 & Gurobi 9.0.0\n", |
| 217 | + "\n", |
| 218 | + "m = gp.Model()\n", |
| 219 | + "\n", |
| 220 | + "# Variables: is city 'i' adjacent to city 'j' on the tour?\n", |
| 221 | + "vars = m.addVars(dist.keys(), obj=dist, vtype=GRB.BINARY, name='x')\n", |
| 222 | + "\n", |
| 223 | + "# Symmetric direction: Copy the object\n", |
| 224 | + "for i, j in vars.keys():\n", |
| 225 | + " vars[j, i] = vars[i, j] # edge in opposite direction\n", |
| 226 | + "\n", |
| 227 | + "# Constraints: two edges incident to each city\n", |
| 228 | + "cons = m.addConstrs(vars.sum(c, '*') == 2 for c in capitals)" |
199 | 229 | ]
|
200 | 230 | },
|
201 | 231 | {
|
|
208 | 238 | },
|
209 | 239 | {
|
210 | 240 | "cell_type": "code",
|
211 |
| - "execution_count": 3, |
| 241 | + "execution_count": null, |
212 | 242 | "metadata": {},
|
213 | 243 | "outputs": [],
|
214 | 244 | "source": [
|
|
225 | 255 | " if len(tour) < len(capitals):\n",
|
226 | 256 | " # add subtour elimination constr. for every pair of cities in subtour\n",
|
227 | 257 | " model.cbLazy(gp.quicksum(model._vars[i, j] for i, j in combinations(tour, 2))\n",
|
228 |
| - " <= len(tour)-1)" |
229 |
| - ] |
230 |
| - }, |
231 |
| - { |
232 |
| - "cell_type": "markdown", |
233 |
| - "metadata": {}, |
234 |
| - "source": [ |
235 |
| - "### Finding Shortest Route\n", |
236 |
| - "The following function determines the shortest route from a given set of edges." |
237 |
| - ] |
238 |
| - }, |
239 |
| - { |
240 |
| - "cell_type": "code", |
241 |
| - "execution_count": 4, |
242 |
| - "metadata": {}, |
243 |
| - "outputs": [], |
244 |
| - "source": [ |
| 258 | + " <= len(tour)-1)\n", |
| 259 | + "\n", |
245 | 260 | "# Given a tuplelist of edges, find the shortest subtour\n",
|
246 | 261 | "\n",
|
247 | 262 | "def subtour(edges):\n",
|
|
265 | 280 | "cell_type": "markdown",
|
266 | 281 | "metadata": {},
|
267 | 282 | "source": [
|
268 |
| - "### Model Deployment\n", |
269 |
| - "We now determine the model for the TSP, by defining decision variables, constraints, and objective function. Next, we start the optimization and Gurobi finds the optimal route for the TSP. " |
| 283 | + "## Solve the model" |
270 | 284 | ]
|
271 | 285 | },
|
272 | 286 | {
|
273 | 287 | "cell_type": "code",
|
274 |
| - "execution_count": 5, |
| 288 | + "execution_count": null, |
275 | 289 | "metadata": {},
|
276 |
| - "outputs": [ |
277 |
| - { |
278 |
| - "name": "stdout", |
279 |
| - "output_type": "stream", |
280 |
| - "text": [ |
281 |
| - "Using license file c:\\gurobi\\gurobi.lic\n", |
282 |
| - "Changed value of parameter lazyConstraints to 1\n", |
283 |
| - " Prev: 0 Min: 0 Max: 1 Default: 0\n", |
284 |
| - "Gurobi Optimizer version 9.1.0 build v9.1.0rc0 (win64)\n", |
285 |
| - "Thread count: 4 physical cores, 8 logical processors, using up to 8 threads\n", |
286 |
| - "Optimize a model with 2304 rows, 2256 columns and 6768 nonzeros\n", |
287 |
| - "Model fingerprint: 0x029d7617\n", |
288 |
| - "Variable types: 0 continuous, 2256 integer (2256 binary)\n", |
289 |
| - "Coefficient statistics:\n", |
290 |
| - " Matrix range [1e+00, 1e+00]\n", |
291 |
| - " Objective range [6e-01, 5e+01]\n", |
292 |
| - " Bounds range [1e+00, 1e+00]\n", |
293 |
| - " RHS range [2e+00, 2e+00]\n", |
294 |
| - "Presolve removed 2256 rows and 1128 columns\n", |
295 |
| - "Presolve time: 0.01s\n", |
296 |
| - "Presolved: 48 rows, 1128 columns, 2256 nonzeros\n", |
297 |
| - "Variable types: 0 continuous, 1128 integer (1128 binary)\n", |
298 |
| - "\n", |
299 |
| - "Root relaxation: objective 3.223715e+02, 72 iterations, 0.00 seconds\n", |
300 |
| - "\n", |
301 |
| - " Nodes | Current Node | Objective Bounds | Work\n", |
302 |
| - " Expl Unexpl | Obj Depth IntInf | Incumbent BestBd Gap | It/Node Time\n", |
303 |
| - "\n", |
304 |
| - " 0 0 322.37153 0 12 - 322.37153 - - 0s\n", |
305 |
| - " 0 0 326.22035 0 18 - 326.22035 - - 0s\n", |
306 |
| - " 0 0 331.56424 0 16 - 331.56424 - - 0s\n", |
307 |
| - " 0 0 333.84959 0 14 - 333.84959 - - 0s\n", |
308 |
| - " 0 0 334.15410 0 33 - 334.15410 - - 0s\n", |
309 |
| - "H 0 0 494.5024872 334.15410 32.4% - 0s\n", |
310 |
| - " 0 2 334.15410 0 33 494.50249 334.15410 32.4% - 0s\n", |
311 |
| - "* 131 58 9 363.5306008 336.61730 7.40% 5.0 0s\n", |
312 |
| - "* 145 64 5 350.8980740 336.61730 4.07% 5.7 0s\n", |
313 |
| - "\n", |
314 |
| - "Cutting planes:\n", |
315 |
| - " Zero half: 8\n", |
316 |
| - " Lazy constraints: 32\n", |
317 |
| - "\n", |
318 |
| - "Explored 223 nodes (1444 simplex iterations) in 0.33 seconds\n", |
319 |
| - "Thread count was 8 (of 8 available processors)\n", |
320 |
| - "\n", |
321 |
| - "Solution count 3: 350.898 363.531 494.502 \n", |
322 |
| - "\n", |
323 |
| - "Optimal solution found (tolerance 1.00e-04)\n", |
324 |
| - "Best objective 3.508980740395e+02, best bound 3.508980740395e+02, gap 0.0000%\n", |
325 |
| - "\n", |
326 |
| - "User-callback calls 634, time in user-callback 0.10 sec\n" |
327 |
| - ] |
328 |
| - } |
329 |
| - ], |
| 290 | + "outputs": [], |
330 | 291 | "source": [
|
331 |
| - "import gurobipy as gp\n", |
332 |
| - "from gurobipy import GRB\n", |
333 |
| - "\n", |
334 |
| - "# tested with Python 3.7 & Gurobi 9.0.0\n", |
335 |
| - "\n", |
336 |
| - "m = gp.Model()\n", |
337 |
| - "\n", |
338 |
| - "# Variables: is city 'i' adjacent to city 'j' on the tour?\n", |
339 |
| - "\n", |
340 |
| - "vars = m.addVars(dist.keys(), obj=dist, vtype=GRB.BINARY, name='e')\n", |
341 |
| - "for i, j in vars.keys():\n", |
342 |
| - " m.addConstr(vars[j, i] == vars[i, j]) # edge in opposite direction\n", |
343 |
| - "\n", |
344 |
| - "# Constraints: two edges incident to each city\n", |
345 |
| - "\n", |
346 |
| - "m.addConstrs(vars.sum(c, '*') == 2 for c in capitals)\n", |
347 |
| - "\n", |
348 |
| - "# Optimize the model\n", |
349 |
| - "\n", |
350 | 292 | "m._vars = vars\n",
|
351 | 293 | "m.Params.lazyConstraints = 1\n",
|
352 |
| - "m.optimize(subtourelim)\n" |
| 294 | + "m.optimize(subtourelim)" |
353 | 295 | ]
|
354 | 296 | },
|
355 | 297 | {
|
|
363 | 305 | },
|
364 | 306 | {
|
365 | 307 | "cell_type": "code",
|
366 |
| - "execution_count": 6, |
| 308 | + "execution_count": null, |
367 | 309 | "metadata": {},
|
368 | 310 | "outputs": [],
|
369 | 311 | "source": [
|
|
385 | 327 | },
|
386 | 328 | {
|
387 | 329 | "cell_type": "code",
|
388 |
| - "execution_count": 7, |
| 330 | + "execution_count": null, |
389 | 331 | "metadata": {},
|
390 |
| - "outputs": [ |
391 |
| - { |
392 |
| - "data": { |
393 |
| - "text/html": [ |
394 |
| - "<div style=\"width:100%;\"><div style=\"position:relative;width:100%;height:0;padding-bottom:60%;\"><iframe src=\"about:blank\" style=\"position:absolute;width:100%;height:100%;left:0;top:0;border:none !important;\" data-html=PCFET0NUWVBFIGh0bWw+CjxoZWFkPiAgICAKICAgIDxtZXRhIGh0dHAtZXF1aXY9ImNvbnRlbnQtdHlwZSIgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVURi04IiAvPgogICAgCiAgICAgICAgPHNjcmlwdD4KICAgICAgICAgICAgTF9OT19UT1VDSCA9IGZhbHNlOwogICAgICAgICAgICBMX0RJU0FCTEVfM0QgPSBmYWxzZTsKICAgICAgICA8L3NjcmlwdD4KICAgIAogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuanMiPjwvc2NyaXB0PgogICAgPHNjcmlwdCBzcmM9Imh0dHBzOi8vY29kZS5qcXVlcnkuY29tL2pxdWVyeS0xLjEyLjQubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9qcy9ib290c3RyYXAubWluLmpzIj48L3NjcmlwdD4KICAgIDxzY3JpcHQgc3JjPSJodHRwczovL2NkbmpzLmNsb3VkZmxhcmUuY29tL2FqYXgvbGlicy9MZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy8yLjAuMi9sZWFmbGV0LmF3ZXNvbWUtbWFya2Vycy5qcyI+PC9zY3JpcHQ+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuLmpzZGVsaXZyLm5ldC9ucG0vbGVhZmxldEAxLjUuMS9kaXN0L2xlYWZsZXQuY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vbWF4Y2RuLmJvb3RzdHJhcGNkbi5jb20vYm9vdHN0cmFwLzMuMi4wL2Nzcy9ib290c3RyYXAubWluLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL21heGNkbi5ib290c3RyYXBjZG4uY29tL2Jvb3RzdHJhcC8zLjIuMC9jc3MvYm9vdHN0cmFwLXRoZW1lLm1pbi5jc3MiLz4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgaHJlZj0iaHR0cHM6Ly9tYXhjZG4uYm9vdHN0cmFwY2RuLmNvbS9mb250LWF3ZXNvbWUvNC42LjMvY3NzL2ZvbnQtYXdlc29tZS5taW4uY3NzIi8+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL0xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLzIuMC4yL2xlYWZsZXQuYXdlc29tZS1tYXJrZXJzLmNzcyIvPgogICAgPGxpbmsgcmVsPSJzdHlsZXNoZWV0IiBocmVmPSJodHRwczovL3Jhd2Nkbi5naXRoYWNrLmNvbS9weXRob24tdmlzdWFsaXphdGlvbi9mb2xpdW0vbWFzdGVyL2ZvbGl1bS90ZW1wbGF0ZXMvbGVhZmxldC5hd2Vzb21lLnJvdGF0ZS5jc3MiLz4KICAgIDxzdHlsZT5odG1sLCBib2R5IHt3aWR0aDogMTAwJTtoZWlnaHQ6IDEwMCU7bWFyZ2luOiAwO3BhZGRpbmc6IDA7fTwvc3R5bGU+CiAgICA8c3R5bGU+I21hcCB7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7Ym90dG9tOjA7cmlnaHQ6MDtsZWZ0OjA7fTwvc3R5bGU+CiAgICAKICAgICAgICAgICAgPG1ldGEgbmFtZT0idmlld3BvcnQiIGNvbnRlbnQ9IndpZHRoPWRldmljZS13aWR0aCwKICAgICAgICAgICAgICAgIGluaXRpYWwtc2NhbGU9MS4wLCBtYXhpbXVtLXNjYWxlPTEuMCwgdXNlci1zY2FsYWJsZT1ubyIgLz4KICAgICAgICAgICAgPHN0eWxlPgogICAgICAgICAgICAgICAgI21hcF8xZGM2NGI0YjJiYWY0NDI2ODE1NjgxZGYwNjk0ZWVmNyB7CiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlOwogICAgICAgICAgICAgICAgICAgIHdpZHRoOiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgaGVpZ2h0OiAxMDAuMCU7CiAgICAgICAgICAgICAgICAgICAgbGVmdDogMC4wJTsKICAgICAgICAgICAgICAgICAgICB0b3A6IDAuMCU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIDwvc3R5bGU+CiAgICAgICAgCjwvaGVhZD4KPGJvZHk+ICAgIAogICAgCiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImZvbGl1bS1tYXAiIGlkPSJtYXBfMWRjNjRiNGIyYmFmNDQyNjgxNTY4MWRmMDY5NGVlZjciID48L2Rpdj4KICAgICAgICAKPC9ib2R5Pgo8c2NyaXB0PiAgICAKICAgIAogICAgICAgICAgICB2YXIgbWFwXzFkYzY0YjRiMmJhZjQ0MjY4MTU2ODFkZjA2OTRlZWY3ID0gTC5tYXAoCiAgICAgICAgICAgICAgICAibWFwXzFkYzY0YjRiMmJhZjQ0MjY4MTU2ODFkZjA2OTRlZWY3IiwKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBjZW50ZXI6IFs0MC4wLCAtOTUuMF0sCiAgICAgICAgICAgICAgICAgICAgY3JzOiBMLkNSUy5FUFNHMzg1NywKICAgICAgICAgICAgICAgICAgICB6b29tOiA0LAogICAgICAgICAgICAgICAgICAgIHpvb21Db250cm9sOiB0cnVlLAogICAgICAgICAgICAgICAgICAgIHByZWZlckNhbnZhczogZmFsc2UsCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICk7CgogICAgICAgICAgICAKCiAgICAgICAgCiAgICAKICAgICAgICAgICAgdmFyIHRpbGVfbGF5ZXJfYzA1MTY4YTYyOThlNGEwZjg5OTkyNmRhN2VhY2ZiOTcgPSBMLnRpbGVMYXllcigKICAgICAgICAgICAgICAgICJodHRwczovL3tzfS50aWxlLm9wZW5zdHJlZXRtYXAub3JnL3t6fS97eH0ve3l9LnBuZyIsCiAgICAgICAgICAgICAgICB7ImF0dHJpYnV0aW9uIjogIkRhdGEgYnkgXHUwMDI2Y29weTsgXHUwMDNjYSBocmVmPVwiaHR0cDovL29wZW5zdHJlZXRtYXAub3JnXCJcdTAwM2VPcGVuU3RyZWV0TWFwXHUwMDNjL2FcdTAwM2UsIHVuZGVyIFx1MDAzY2EgaHJlZj1cImh0dHA6Ly93d3cub3BlbnN0cmVldG1hcC5vcmcvY29weXJpZ2h0XCJcdTAwM2VPRGJMXHUwMDNjL2FcdTAwM2UuIiwgImRldGVjdFJldGluYSI6IGZhbHNlLCAibWF4TmF0aXZlWm9vbSI6IDE4LCAibWF4Wm9vbSI6IDE4LCAibWluWm9vbSI6IDAsICJub1dyYXAiOiBmYWxzZSwgIm9wYWNpdHkiOiAxLCAic3ViZG9tYWlucyI6ICJhYmMiLCAidG1zIjogZmFsc2V9CiAgICAgICAgICAgICkuYWRkVG8obWFwXzFkYzY0YjRiMmJhZjQ0MjY4MTU2ODFkZjA2OTRlZWY3KTsKICAgICAgICAKICAgIAogICAgICAgICAgICB2YXIgcG9seV9saW5lXzUzNDJmZjI5N2ZhMjQ2NzViOWYzOGI0NTU5NDA4ZTI0ID0gTC5wb2x5bGluZSgKICAgICAgICAgICAgICAgIFtbMzIuMzYxNTM4LCAtODYuMjc5MTE4XSwgWzMwLjQ1MTgsIC04NC4yNzI3N10sIFszMy43NiwgLTg0LjM5XSwgWzM0LjAsIC04MS4wMzVdLCBbMzUuNzcxLCAtNzguNjM4XSwgWzM3LjU0LCAtNzcuNDZdLCBbMzguOTcyOTQ1LCAtNzYuNTAxMTU3XSwgWzM5LjE2MTkyMSwgLTc1LjUyNjc1NV0sIFs0MC4yMjE3NDEsIC03NC43NTYxMzhdLCBbNDEuNzY3LCAtNzIuNjc3XSwgWzQxLjgyMzU1LCAtNzEuNDIyMTMyXSwgWzQyLjIzNTIsIC03MS4wMjc1XSwgWzQ0LjMyMzUzNSwgLTY5Ljc2NTI2MV0sIFs0My4yMjAwOTMsIC03MS41NDkxMjddLCBbNDQuMjY2MzksIC03Mi41NzE5NF0sIFs0Mi42NTk4MjksIC03My43ODEzMzldLCBbNDAuMjY5Nzg5LCAtNzYuODc1NjEzXSwgWzM4LjM0OTQ5NywgLTgxLjYzMzI5NF0sIFszOS45NjIyNDUsIC04My4wMDA2NDddLCBbNDIuNzMzNSwgLTg0LjU0NjddLCBbNDMuMDc0NzIyLCAtODkuMzg0NDQ0XSwgWzQ0Ljk1LCAtOTMuMDk0XSwgWzQxLjU5MDkzOSwgLTkzLjYyMDg2Nl0sIFszOS4wNCwgLTk1LjY5XSwgWzQwLjgwOTg2OCwgLTk2LjY3NTM0NV0sIFs0NC4zNjc5NjYsIC0xMDAuMzM2Mzc4XSwgWzQ2LjgxMzM0MywgLTEwMC43NzkwMDRdLCBbNDEuMTQ1NTQ4LCAtMTA0LjgwMjA0Ml0sIFszOS43MzkxNjY3LCAtMTA0Ljk4NDE2N10sIFs0MC43NTQ3LCAtMTExLjg5MjYyMl0sIFs0Ni41OTU4MDUsIC0xMTIuMDI3MDMxXSwgWzQzLjYxMzczOSwgLTExNi4yMzc2NTFdLCBbNDcuMDQyNDE4LCAtMTIyLjg5MzA3N10sIFs0NC45MzExMDksIC0xMjMuMDI5MTU5XSwgWzM4LjU1NTYwNSwgLTEyMS40Njg5MjZdLCBbMzkuMTYwOTQ5LCAtMTE5Ljc1Mzg3N10sIFszMy40NDg0NTcsIC0xMTIuMDczODQ0XSwgWzM1LjY2NzIzMSwgLTEwNS45NjQ1NzVdLCBbMzUuNDgyMzA5LCAtOTcuNTM0OTk0XSwgWzMwLjI2NjY2NywgLTk3Ljc1XSwgWzMwLjQ1ODA5LCAtOTEuMTQwMjI5XSwgWzMyLjMyLCAtOTAuMjA3XSwgWzM0LjczNjAwOSwgLTkyLjMzMTEyMl0sIFszOC41NzI5NTQsIC05Mi4xODkyODNdLCBbMzkuNzgzMjUsIC04OS42NTAzNzNdLCBbMzkuNzkwOTQyLCAtODYuMTQ3Njg1XSwgWzM4LjE5NzI3NCwgLTg0Ljg2MzExXSwgWzM2LjE2NSwgLTg2Ljc4NF0sIFszMi4zNjE1MzgsIC04Ni4yNzkxMThdXSwKICAgICAgICAgICAgICAgIHsiYnViYmxpbmdNb3VzZUV2ZW50cyI6IHRydWUsICJjb2xvciI6ICIjMzM4OGZmIiwgImRhc2hBcnJheSI6IG51bGwsICJkYXNoT2Zmc2V0IjogbnVsbCwgImZpbGwiOiBmYWxzZSwgImZpbGxDb2xvciI6ICIjMzM4OGZmIiwgImZpbGxPcGFjaXR5IjogMC4yLCAiZmlsbFJ1bGUiOiAiZXZlbm9kZCIsICJsaW5lQ2FwIjogInJvdW5kIiwgImxpbmVKb2luIjogInJvdW5kIiwgIm5vQ2xpcCI6IGZhbHNlLCAib3BhY2l0eSI6IDEuMCwgInNtb290aEZhY3RvciI6IDEuMCwgInN0cm9rZSI6IHRydWUsICJ3ZWlnaHQiOiAzfQogICAgICAgICAgICApLmFkZFRvKG1hcF8xZGM2NGI0YjJiYWY0NDI2ODE1NjgxZGYwNjk0ZWVmNyk7CiAgICAgICAgCjwvc2NyaXB0Pg== onload=\"this.contentDocument.open();this.contentDocument.write(atob(this.getAttribute('data-html')));this.contentDocument.close();\" allowfullscreen webkitallowfullscreen mozallowfullscreen></iframe></div></div>" |
395 |
| - ], |
396 |
| - "text/plain": [ |
397 |
| - "<folium.folium.Map at 0x1b8c6c73198>" |
398 |
| - ] |
399 |
| - }, |
400 |
| - "execution_count": 7, |
401 |
| - "metadata": {}, |
402 |
| - "output_type": "execute_result" |
403 |
| - } |
404 |
| - ], |
| 332 | + "outputs": [], |
405 | 333 | "source": [
|
406 | 334 | "# Map the solution\n",
|
407 | 335 | "\n",
|
|
469 | 397 | "name": "python",
|
470 | 398 | "nbconvert_exporter": "python",
|
471 | 399 | "pygments_lexer": "ipython3",
|
472 |
| - "version": "3.7.1" |
| 400 | + "version": "3.8.2" |
473 | 401 | }
|
474 | 402 | },
|
475 | 403 | "nbformat": 4,
|
|
0 commit comments