From d7265c3f2c84a8c76c780ce8adcef28844ae4dd5 Mon Sep 17 00:00:00 2001 From: nikzadr <80527642+nikzadr@users.noreply.github.com> Date: Mon, 25 Apr 2022 16:08:44 +0200 Subject: [PATCH] 2022-04-25 distace matrix concepts --- README.md | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++- run.ipynb | 94 ++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+), 2 deletions(-) create mode 100644 run.ipynb diff --git a/README.md b/README.md index b968485..0ffcc90 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,164 @@ states are defined as followed: 1 = new contract 2 = end contract 3 = exact same container 4 = switch container - 5 = filling up + 5 = filling ` up 6 = dangerous waste The depot is always situated in Kampenhout and the closest suitable wpf is used. For each element on the diagonal, the service time of client i is shown (matrix[i,i] = service time for i). -Service time = time spend at the costumer. \ No newline at end of file +Service time = time spend at the costumer. + + + + +after depot: do whatever you want. + +at wpf: we unload without taking the containr off, no need to calculate additional 12 min. + +if you can go direct, don't think about depot in the distance matrix! + +## possible courses of actions and their total service time +### STARTING FROM END OF ACTIONTYPE 1,3 +- 1-1: + - $$1-1 : idj = t_{id} + 6 + t_{dj} + 12 + EXTRA$$ +- 1-2 + - $$1-2 : ij = t_{ij} + 12 + EXTRA$$ +- 1-3 + - $$1-3: ijwj = t_{ij} + 12 + t_{jw} + 20 + t_{wj} + 12 + EXTRA$$ +- 1-4 + - $$1-4 : idj = t_{id} + 6 + t_{dj} + 25 + EXTRA$$ +- 1-5 + - $$1-5 : idj = t_{id} + 6 + t_{dj} + 30 + EXTRA$$ +- 1-d + - $$1-d : id = t_{id}$$ +- 3: same as 1 : both start unloaded (empty) + +### STARTING FROM END OF ACTIONTYPE 2,4,5 +- 2-1 + - $$2-1 \& RS : iwj = t_{iw} + 20 + t_{wj} + 12 + EXTRA$$ + - $$2-1 \& WS : iwdj = t_{iw} + 20 + t_{wd} + 2*6 + t_{dj} + 12 + EXTRA$$ +- 2-2 + - $$2-2 : iwdj = t_{iw} + 20 + t_{wd} + 6 + t_{dj} + 12 + EXTRA$$ +- 2-3: + - $$2-3 : iwdjwj: t_{iw} + 20 + t_{wd} + 6 + t_{dj} + 12 + t_{jw} + 20 + t_{wj} + 12 + EXTRA$$ +- 2-4: + - $$2-4 \& RS : iwj = t_{iw} + 20 + t_{wj} + 25 + EXTRA$$ + - $$2-4 \& WS : iwdj = t_{iw} + 20 + t_{wd} + 2*6 + t_{dj} + 25 + EXTRA$$ +- 2-5: very similar to 2-4 + - $$2-5 \& RS : iwj = t_{iw} + 20 + t_{wj} + 30 + EXTRA$$ + - $$2-5 \& WS : iwdj = t_{iw} + 20 + t_{wd} + 2*6 + t_{dj} + 30 + EXTRA$$ +- 2-d: + - $$2-d : iwd = t_{iw} + 20 + t_{wd} + 6$$ +- 4: same as 2 : both start loaded & full +- 5: same as 2 : both start loaded & full + +### STARTING FROM DEPOT +- $$d-1 : dj = 6 + t_{dj} + 12 + EXTRA$$ +- $$d-2 : dj = t_{dj} + 12 + EXTRA$$ +- $$d-3 : djwj = t_{dj} + 12 + t_{jw} + 20 + t_{wj} + 12 + EXTRA$$ +- $$d-4 : dj = 6 + t_{dj} + 25 + EXTRA$$ +- $$d-5 : dj = 6 + t_{dj} + 30 + EXTRA$$ + +We have only 10 first-level pairs. As we care about the following pair: +$[endState_i,actionType_{j}]$ + +Then we consider size for 3 of them (when you start loaded & full): **13 in total** + +Lastly, dangerous waste or other conditions, can be considered for the wpf. They don't have a nest of their own. + +**ASSMPTION: trucks always start/end the day empty. all containers should be placed in depot not on trucks** + +## how to enumerate the matrix +for each course of action, several routes might be available. we store them, and choose the "shortest path". + +These possiblites are "per available customer_j". So, 1-5 means if you finish at actionType 1 (state Empty), there is only 1 route per customer of actionType 5 (your next step). + +1-1: 1 +1-2: 1 +1-3: #wpfs available +1-4: 1 +1-5: 1 + +2-1RS: #w available +2-1WS: #w available +2-2: #w +2-3: #w@i * #w@j +2-4RS: #w +2-4WS: #w +2-5RS: #w +2-5WS: #w + +then for all clients, we consider the values above. + + + +### Now how to define number of wpfs available? (#w)? +if i = dangerous : only antwerp (w=1) +if i = construction : all (w=4) +if i = rest : mechelen,brugge,gent (w=3) + +### some toy examples: +we are done with first customer, and want to calculate service time for another one. +bookstore20 to fish20: +3-4 = 1-4: +only one value + + +[construction 18, lab 15] + + +[lab 10, end 12] + + +## HOW TO DEAL with end of tour? +if there are no feasible customers in the distance matrix, go back to depot and end your tour. feasiblity can be time cosntraint, fuel, work, etc. + +## HOW TO STRUCTURE THE CODE? +```python +getNodes(database) { + # here we save each node in JSON or sth, where we can access its attributes. + # these nodes (clients / depot) will be used in later functions. + + node = { + 'ID', ..., #0 is depot, minus values for wpfs; the rest are clients. + 'coordinates', [x,y], # getX and getY: this can be taken from googlemaps API + 'actionType',1 to 5, # 1: new cont. 2: end cont. 3: exact same 4: swap 5: fill ; is 0 for non-clients + 'containerSize',..., # whateever integer value ; is 0 for non-clients + 'wasteType', ..., #1:general 2: paper 3:const 4:dangerous ; is 0 for non-clients + 'wasteTypesHandled',... , # 0 for non-wpfs; an array of wastetypes handled for wpfs. e.g. antwerp is dangerous only [4] + 'opening',..., #starting time window + 'closing ',..., #closing time window + 'extraHandling',..., #0 if none; int if needed (e.g. 15) + ... + } +} +# I THINK THE CODE ABOVE IS ALREADY IMPLEMENTED VIA PANDAS, THIS IS JUST TO GIVE AN IDEA + +getShortestServiceTime(node_i,node_j) { + # for depot + # consider depot as customer with ID = 0 + # first check ID=0, to see if it's depot + # here we consider services times starting from/end at depot: d-x, or x-d + + + # for all nodes (clients) + # we get the following attributes from the client_i and client_j : ID + # first check ID!=0, to make sure it's not depot + # if not depot: get following attricuts containerSize, Location, actionType, wasteType + ... + # now we implement the conditions here, so that we can finally return a "serviceTime" + # the idea is to use these attributes to implement the formulas + # e.g. dangerous waste can be just an if statement inside one of the courses of action. + + + # at the end we select the shortest service time (path) from i to j, and return it; + # the output will be added to our pre-procssed distance matrix. +} + +createDistanceMatrix { + # here we iterate over all i and j, and fill in the shortest service time value inside it. + # the values, are already taking into consideration all possible intermediate steps, and the shortest one is already selected. +} + +``` \ No newline at end of file diff --git a/run.ipynb b/run.ipynb new file mode 100644 index 0000000..b45fcfe --- /dev/null +++ b/run.ipynb @@ -0,0 +1,94 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run the script, to define all necessary functions." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "%run distanceMatrix.py" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## TODO\n", + "- structure the logic in a different way:\n", + " - currently there's a lot of overlap\n", + " - " + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[ 0. 68. 86. 89. 68. 64. 119.]\n", + " [107. 0. 83. 133. 56. 112. 107.]\n", + " [117. 83. 0. 142. 66. 121. 117.]\n", + " [ 89. 93. 112. 0. 94. 24. 144.]\n", + " [ 19. 49. 68. 74. 0. 50. 100.]\n", + " [132. 98. 107. 157. 81. 0. 131.]\n", + " [157. 99. 133. 183. 104. 162. 0.]]\n" + ] + }, + { + "ename": "PermissionError", + "evalue": "[Errno 13] Permission denied: 'distanceMatrix.csv'", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mPermissionError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m~\\AppData\\Local\\Temp/ipykernel_14856/1685011400.py\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mmatrix\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mcreateDistanceMatrix\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'clientsTest.csv'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'belgian-cities-geocoded.csv'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'WPF.csv'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mpd\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mDataFrame\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mmatrix\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mto_csv\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'distanceMatrix.csv'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;32m~\\anaconda3\\envs\\ip1\\lib\\site-packages\\pandas\\core\\generic.py\u001b[0m in \u001b[0;36mto_csv\u001b[1;34m(self, path_or_buf, sep, na_rep, float_format, columns, header, index, index_label, mode, encoding, compression, quoting, quotechar, line_terminator, chunksize, date_format, doublequote, escapechar, decimal, errors, storage_options)\u001b[0m\n\u001b[0;32m 3464\u001b[0m )\n\u001b[0;32m 3465\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m-> 3466\u001b[1;33m return DataFrameRenderer(formatter).to_csv(\n\u001b[0m\u001b[0;32m 3467\u001b[0m \u001b[0mpath_or_buf\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3468\u001b[0m \u001b[0mline_terminator\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mline_terminator\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\anaconda3\\envs\\ip1\\lib\\site-packages\\pandas\\io\\formats\\format.py\u001b[0m in \u001b[0;36mto_csv\u001b[1;34m(self, path_or_buf, encoding, sep, columns, index_label, mode, compression, quoting, quotechar, line_terminator, chunksize, date_format, doublequote, escapechar, errors, storage_options)\u001b[0m\n\u001b[0;32m 1103\u001b[0m \u001b[0mformatter\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfmt\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1104\u001b[0m )\n\u001b[1;32m-> 1105\u001b[1;33m \u001b[0mcsv_formatter\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msave\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 1106\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 1107\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mcreated_buffer\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\anaconda3\\envs\\ip1\\lib\\site-packages\\pandas\\io\\formats\\csvs.py\u001b[0m in \u001b[0;36msave\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 235\u001b[0m \"\"\"\n\u001b[0;32m 236\u001b[0m \u001b[1;31m# apply compression and byte/text conversion\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 237\u001b[1;33m with get_handle(\n\u001b[0m\u001b[0;32m 238\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfilepath_or_buffer\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 239\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmode\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;32m~\\anaconda3\\envs\\ip1\\lib\\site-packages\\pandas\\io\\common.py\u001b[0m in \u001b[0;36mget_handle\u001b[1;34m(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)\u001b[0m\n\u001b[0;32m 700\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mioargs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mencoding\u001b[0m \u001b[1;32mand\u001b[0m \u001b[1;34m\"b\"\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mioargs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmode\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 701\u001b[0m \u001b[1;31m# Encoding\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 702\u001b[1;33m handle = open(\n\u001b[0m\u001b[0;32m 703\u001b[0m \u001b[0mhandle\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 704\u001b[0m \u001b[0mioargs\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mmode\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", + "\u001b[1;31mPermissionError\u001b[0m: [Errno 13] Permission denied: 'distanceMatrix.csv'" + ] + } + ], + "source": [ + "matrix = createDistanceMatrix('clientsTest.csv', 'belgian-cities-geocoded.csv', 'WPF.csv')\n", + "pd.DataFrame(matrix).to_csv('distanceMatrix.csv')" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "1ebd53531a265123f8d6b96a0394cf5c6958acea593669dc45d7411847354196" + }, + "kernelspec": { + "display_name": "Python 3.9.7 ('ip1')", + "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.9.7" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +}