Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e28116b
Update README.md
tina-seb Jul 22, 2020
a5d36f6
Create FoodBankRouteDeliveryOptimization.py
tina-seb Jul 22, 2020
b4590fd
Create FoodBankClientDeliveryData.txt
tina-seb Jul 23, 2020
8d94719
Create FoodBankHouseLookup.txt
tina-seb Jul 23, 2020
0b58dc4
Create Food_Bank_Delivery.route.txt
tina-seb Jul 23, 2020
646f8cc
Initial explanation, credits and license.
eduardsmetanin Jul 23, 2020
95839f6
Refactored a bit and removed license.
eduardsmetanin Jul 23, 2020
50ce4d7
Create Code
sgangoly Jul 23, 2020
4729035
Add files via upload
sgangoly Jul 23, 2020
d21274b
Notebook with food bank delivery scheduling solution for CDL Hackatho…
tina-seb Jul 23, 2020
d214bf6
Notebook with solution for foodbank delivery scheduling using DWave Q…
tina-seb Jul 23, 2020
1c3fccb
Delete CDL_Hackathon_2020_JediMasters.ipynb
tina-seb Jul 23, 2020
a1f54c5
Add files via upload
desiEunice Jul 23, 2020
15ed5cd
Update README.md
tina-seb Jul 23, 2020
8e99721
Update README.md
tina-seb Jul 23, 2020
2460965
Update README.md
tina-seb Jul 23, 2020
1de434c
Update README.md
tina-seb Jul 23, 2020
b87e6de
Update README.md
tina-seb Jul 23, 2020
7e15eec
Create TravellingSalesman.md
tina-seb Jul 23, 2020
8a3c0e9
Update TravellingSalesman.md
tina-seb Jul 23, 2020
083f75b
Update README.md
tina-seb Jul 23, 2020
93c8919
Update README.md
tina-seb Jul 23, 2020
688acef
Create README.md
tina-seb Jul 23, 2020
43de402
Rename JediMasters/CDL_Hackathon_2020_FoodBankDeliveryScheduling.ipyn…
tina-seb Jul 23, 2020
b736785
Update README.md
tina-seb Jul 23, 2020
ab07ea7
Rename JediMasters/FoodBankClientDeliveryData.txt to JediMasters/DWav…
tina-seb Jul 23, 2020
1a12311
Rename JediMasters/FoodBankHouseLookup.txt to JediMasters/DWave Chall…
tina-seb Jul 23, 2020
82b2c6e
Rename JediMasters/FoodBankRouteDeliveryOptimization.py to JediMaster…
tina-seb Jul 23, 2020
5d816ff
Rename JediMasters/Food_Bank_Delivery.route.txt to JediMasters/DWave …
tina-seb Jul 23, 2020
7b835d7
Rename JediMasters/TravellingSalesman.md to JediMasters/DWave Challen…
tina-seb Jul 23, 2020
968e542
Update README.md
tina-seb Jul 23, 2020
5069773
Delete FoodBankDelivery Presentation .pdf
desiEunice Jul 23, 2020
91975ac
Add files via upload
desiEunice Jul 23, 2020
acd1291
Renamed md file.
eduardsmetanin Jul 23, 2020
e1cda0a
Merge branch 'master' of github.com:tina-seb/Hackathon2019
eduardsmetanin Jul 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,377 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "CDL_Hackathon_2020-JediMasters.ipynb",
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyOVkbtDsT8ddCrTD9WjVH0E",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/tina-seb/Hackathon2020/blob/master/JediMasters/CDL_Hackathon_2020_FoodBankDeliveryScheduling.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "7-W1uufjf2Yp",
"colab_type": "text"
},
"source": [
"# **Food Bank Delivery Route Scheduler**"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "ye5iy8A7Z-Pa",
"colab_type": "text"
},
"source": [
"**Problem** : Food banks use volunteers on a daily basis to deliver food and groceries to the homebound. Currently they depend on manual scheduling and/or classical software to schedule routes for a variable number of volunteers, which may change during the day.\n",
"\n",
"**Challenges** : The route maps need to be generated quickly if a volunteer drops off, and also need to be the most cost-efficient and fastest route possible.\n",
"\n",
"**Proposed Solution** : We implement a variation of the Multiple Travelling Salesman algorithm using DWave Leap Hybrid Solver and QBSolve to generate the most efficient routes for a variable number of volunteers, by minimizing the cost as energy and total mileage.\n",
"\n",
"**Constraints** : \n",
"1) All volunteeers must start and end at the same food bank location.\n",
"2) Each volunteer should only visit one home for delivery.\n",
"3) If a volunteer does not show up or cancels, another volunteer should be able to pick up his or her route as an extension, without having to reschedule every other route.\n",
"4) The cost of each individual route as well as the cost of the entire schedule should be minimized."
]
},
{
"cell_type": "code",
"metadata": {
"id": "LWSG8rcob1ug",
"colab_type": "code",
"colab": {}
},
"source": [
"from dwave_qbsolv import QBSolv\n",
"from dwave.system import LeapHybridSampler\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import re"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "cRJL6Pohc8_r",
"colab_type": "text"
},
"source": [
"The number of houses with homebound clients served by a food bank changes every day. This is currently defined as a variable and can be changed into an input variable. The home addresses and the distance information of each address needs to be provided as input files to the algorithm."
]
},
{
"cell_type": "code",
"metadata": {
"id": "nGR7Wx-jcm-6",
"colab_type": "code",
"colab": {}
},
"source": [
"# Number of houses in our food delivery problem\n",
"Total_Number_Houses = 48\n",
"Number_Volunteers = 8\n",
"Number_Routes = (int)(Total_Number_Houses/Number_Volunteers)\n",
"\n",
"# Tunable parameters. \n",
"A = 8500\n",
"B = 1\n",
"chainstrength = 4500\n",
"numruns = 100"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "rAiho6obdpHA",
"colab_type": "text"
},
"source": [
"We initialize and construct a distance matrix where the row and column represent a house address and each entry is a distance in metres."
]
},
{
"cell_type": "code",
"metadata": {
"id": "Iol81rlvd2Wf",
"colab_type": "code",
"colab": {}
},
"source": [
"## Constructing the distance matrix\n",
"D = [[0 for z in range(Total_Number_Houses)] for y in range(Total_Number_Houses)]\n",
"\n",
"# Input file containing inter-house distances for all counties\n",
"fn = \"FoodBankClientDeliveryData.txt\"\n",
"\n",
"# check that the user has provided input file\n",
"try:\n",
" with open(fn, \"r\") as myfile:\n",
" distance_text = myfile.readlines()\n",
" myfile.close()\n",
"except IOError:\n",
" print(\"Input inter-house distance file missing\")\n",
" exit(1)\n",
"\n",
"# Extract the distances from the input file. \n",
"for i in distance_text:\n",
" if re.search(\"^between\", i):\n",
" m = re.search(\"^between_(\\d+)_(\\d+) = (\\d+)\", i)\n",
" housea = int(m.group(1))\n",
" houseb = int(m.group(2))\n",
" D[housea][houseb] = D[houseb][housea] = int(m.group(3))\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "VKVAwVx3d8X9",
"colab_type": "text"
},
"source": [
"We then construct a QUBO (Quadratic Unconstrained Binary Optimization) to feed into the various DWave samplers. We define the objective and constraints based on our preidentified requirements here."
]
},
{
"cell_type": "code",
"metadata": {
"id": "3etPBbyEeoi-",
"colab_type": "code",
"colab": {}
},
"source": [
"\n",
"# Function to compute index in QUBO for variable \n",
"def return_QUBO_Index(a, b):\n",
" return (a)*Total_Number_Houses+(b)\n",
"\n",
"## Creating the QUBO\n",
"# Start with an empty QUBO\n",
"Q = {}\n",
"for i in range(Total_Number_Houses*Total_Number_Houses):\n",
" for j in range(Total_Number_Houses*Total_Number_Houses):\n",
" Q.update({(i,j): 0})\n",
"\n",
"# Constraint that each row has exactly one 1, constant = N*A\n",
"for v in range(Total_Number_Houses):\n",
" for j in range(Total_Number_Houses):\n",
" Q[(return_QUBO_Index(v,j), return_QUBO_Index(v,j))] += -1*A\n",
" for k in range(j+1, Total_Number_Houses):\n",
" Q[(return_QUBO_Index(v,j), return_QUBO_Index(v,k))] += 2*A\n",
" Q[(return_QUBO_Index(v,k), return_QUBO_Index(v,j))] += 2*A\n",
"\n",
"# Constraint that each col has exactly one 1\n",
"for j in range(Total_Number_Houses):\n",
" for v in range(Total_Number_Houses):\n",
" Q[(return_QUBO_Index(v,j), return_QUBO_Index(v,j))] += -1*A\n",
" for w in range(v+1,Total_Number_Houses):\n",
" Q[(return_QUBO_Index(v,j), return_QUBO_Index(w,j))] += 2*A\n",
" Q[(return_QUBO_Index(w,j), return_QUBO_Index(v,j))] += 2*A\n",
"\n",
"# Objective that minimizes distance\n",
"for u in range(Total_Number_Houses):\n",
" for v in range(Total_Number_Houses):\n",
" if u!=v:\n",
" for j in range(Total_Number_Houses):\n",
" Q[(return_QUBO_Index(u,j), return_QUBO_Index(v,(j+1)%Total_Number_Houses))] += B*D[u][v]\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "O2t7kZISevtf",
"colab_type": "text"
},
"source": [
"We have two approaches below : A classical solver approach using QBSolv and a Quantum solver approach using Leap Hybrid Sampler. No significant timing differences were found between the two solutions."
]
},
{
"cell_type": "code",
"metadata": {
"id": "WWSWT04AfRZO",
"colab_type": "code",
"colab": {}
},
"source": [
"# Run the QUBO using qbsolv (classically solving)\n",
"#resp = QBSolv().sample_qubo(Q)\n",
"\n",
"# Use LeapHybridSampler() for faster QPU access\n",
"sampler = LeapHybridSampler()\n",
"resp = sampler.sample_qubo(Q)\n",
"\n",
"# First solution is the lowest energy solution found\n",
"sample = next(iter(resp))"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "SGFuyufYfTrS",
"colab_type": "text"
},
"source": [
"Display the results obtained as a schedule of route maps for the required number of routes."
]
},
{
"cell_type": "code",
"metadata": {
"id": "Q0CaOlx0Z2D7",
"colab_type": "code",
"colab": {}
},
"source": [
"# Display energy for best solution found\n",
"print('Energy: ', next(iter(resp.data())).energy)\n",
"\n",
"# Print route for solution found\n",
"route = [-1]*Total_Number_Houses\n",
"for node in sample:\n",
" if sample[node]>0:\n",
" j = node%Total_Number_Houses\n",
" v = (node-j)/Total_Number_Houses\n",
" route[j] = int(v)\n",
"\n",
"# Compute and display total mileage\n",
"mileage = 0\n",
"for i in range(Total_Number_Houses):\n",
" mileage+=D[route[i]][route[(i+1)%Total_Number_Houses]]\n",
"\n",
"print('Mileage: ', mileage)\n",
"\n",
"# Print route:\n",
"\n",
"houses = [',']*Total_Number_Houses\n",
"cities = [',']*Total_Number_Houses\n",
"\n",
"with open('FoodBankHouseLookup.txt', \"r\") as myfile:\n",
" address_text = myfile.readlines()\n",
" myfile.close()\n",
"\n",
"for i in address_text:\n",
" index, city, house = i.split(',')\n",
" cities[int(index)] = city.rstrip()\n",
" houses[int(index)] = house.rstrip()\n",
"\n",
"output = open('Food_Bank_Delivery.route.offline', 'w')\n",
"\n",
"r_no = 1\n",
"for i in range(Total_Number_Houses):\n",
" if(i % Number_Routes == 0):\n",
" output.write('\\n' + 'Route ' + str(r_no) + '\\n')\n",
" r_no = r_no + 1\n",
" output.write(houses[route[i]] + ',' + cities[route[i]] + '\\n')\n",
"\n"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "gB9pntwGfqFD",
"colab_type": "text"
},
"source": [
"The route schedule output is as follows :\n",
"\n",
"\n",
"Route 1\n",
"9980 Brookside Dr.,Columbus OH\n",
"417 Theatre Lane,Columbus OH\n",
"26 Walnut Drive,Columbus OH\n",
"7085 Myers St.,Columbus OH\n",
"821 Garfield Rd.,Columbus OH\n",
"7297 North Park Road,Columbus OH\n",
"\n",
"Route 2\n",
"16 Park Ave.,Columbus OH\n",
"51 Lexington Dr.,Columbus OH\n",
"31 York Drive,Columbus OH\n",
"349 W. Rockaway Drive,Columbus OH\n",
"19 Center Street,Columbus OH\n",
"7750 John Drive,Columbus OH\n",
"\n",
"Route 3\n",
"11 High Noon St.,Columbus OH\n",
"69 Buckingham St.,Columbus OH\n",
"8891 Vine Street,Columbus OH\n",
"977 Elizabeth Lane,Columbus OH\n",
"78 High Point St.,Columbus OH\n",
"44 NW. San Pablo St.,Columbus OH\n",
"\n",
"Route 4\n",
"82 Paris Hill St.,Columbus OH\n",
"23 S. Woodside Road,Columbus OH\n",
"7655 Catherine Road,Columbus OH\n",
"70 Coffee Ave.,Columbus OH\n",
"7152 Augusta St.,Columbus OH\n",
"5 South Greystone Street,Columbus OH\n",
"\n",
"Route 5\n",
"192 West Albany St.,Columbus OH\n",
"7 Marvon Road,Columbus OH\n",
"92 South Country Club Rd.,Columbus OH\n",
"98 Galvin Street,Columbus OH\n",
"3 Hillcrest Court,Columbus OH\n",
"9070 Ramblewood Ave.,Columbus OH\n",
"\n",
"Route 6\n",
"8043 N. Glen Ridge Dr.,Columbus OH\n",
"7678 Clinton Road,Columbus OH\n",
"685 Oakland Court,Columbus OH\n",
"737 Pacific Street,Columbus OH\n",
"32 Southampton Street,Columbus OH\n",
"9697 Bowman Drive,Columbus OH\n",
"\n",
"Route 7\n",
"9304 Brickyard St.,Columbus OH\n",
"8858 Canal Lane,Columbus OH\n",
"8 Old Jackson Avenue,Columbus OH\n",
"51 Columbia Street,Columbus OH\n",
"1961 Cleveland Ave,Columbus OH\n",
"7798 Brown Drive,Columbus OH\n",
"\n",
"Route 8\n",
"3432 Main St,Columbus OH\n",
"23 Oak Meadow Drive,Columbus OH\n",
"287 Military Dr.,Columbus OH\n",
"1944 Frank Dr,Columbus OH\n",
"64 Illinois Lane,Columbus OH\n",
"953 South Fieldstone Drive,Columbus OH\n"
]
}
]
}
Loading