Skip to content

Commit

Permalink
2022-04-25 distace matrix concepts
Browse files Browse the repository at this point in the history
  • Loading branch information
nikzadr committed Apr 25, 2022
1 parent 656ac29 commit d7265c3
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 2 deletions.
158 changes: 156 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
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.
}

```
94 changes: 94 additions & 0 deletions run.ipynb
Original file line number Diff line number Diff line change
@@ -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<module>\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
}

0 comments on commit d7265c3

Please sign in to comment.