Merge branch 'tactical-forecasting' into main
Some checks failed
CI / fast (without R) (push) Has been cancelled
CI / slow (with R) (push) Has been cancelled

This commit is contained in:
Alexander Hess 2021-03-01 14:13:21 +01:00
commit f5ced933d6
Signed by: alexander
GPG key ID: 344EA5AB10D868E0
9 changed files with 3965 additions and 12 deletions

View file

@ -16,19 +16,39 @@ that iteratively build on each other.
### Data Cleaning
The UDP provided its raw data as a PostgreSQL dump.
This [notebook](https://nbviewer.jupyter.org/github/webartifex/urban-meal-delivery/blob/develop/research/clean_data.ipynb)
This [notebook](https://nbviewer.jupyter.org/github/webartifex/urban-meal-delivery/blob/main/research/01_clean_data.ipynb)
cleans the data extensively
and maps them onto the [ORM models](https://github.com/webartifex/urban-meal-delivery/tree/develop/src/urban_meal_delivery/db)
and maps them onto the [ORM models](https://github.com/webartifex/urban-meal-delivery/tree/main/src/urban_meal_delivery/db)
defined in the `urban-meal-delivery` package
that is developed in the [src/](https://github.com/webartifex/urban-meal-delivery/tree/develop/src) folder
that is developed in the [src/](https://github.com/webartifex/urban-meal-delivery/tree/main/src) folder
and contains all source code to drive the analyses.
Due to a non-disclosure agreement with the UDP,
neither the raw nor the cleaned data are published as of now.
However, previews of the data can be seen throughout the [research/](https://github.com/webartifex/urban-meal-delivery/tree/develop/research) folder.
However, previews of the data can be seen throughout the [research/](https://github.com/webartifex/urban-meal-delivery/tree/main/research) folder.
### Real-time Demand Forecasting
### Tactical Demand Forecasting
Before any optimizations of the UDP's operations are done,
a **demand forecasting** system for *tactical* purposes is implemented.
To achieve that, the cities first undergo a **gridification** step
where each *pickup* location is assigned into a pixel on a "checker board"-like grid.
The main part of the source code that implements that is in this [file](https://github.com/webartifex/urban-meal-delivery/blob/main/src/urban_meal_delivery/db/grids.py#L60).
Visualizations of the various grids can be found in the [visualizations/](https://github.com/webartifex/urban-meal-delivery/tree/main/research/visualizations) folder
and in this [notebook](https://nbviewer.jupyter.org/github/webartifex/urban-meal-delivery/blob/main/research/03_grid_visualizations.ipynb).
Then, demand is aggregated on a per-pixel level
and different kinds of order time series are generated.
The latter are the input to different kinds of forecasting `*Model`s.
They all have in common that they predict demand into the *short-term* future (e.g., one hour)
and are thus used for tactical purposes, in particular predictive routing (cf., next section).
The details of how this works can be found in the first academic paper
published in the context of this research project
and titled "*Real-time Demand Forecasting for an Urban Delivery Platform*"
(cf., the [repository](https://github.com/webartifex/urban-meal-delivery-demand-forecasting) with the LaTeX files).
All demand forecasting related code is in the [forecasts/](https://github.com/webartifex/urban-meal-delivery/tree/main/src/urban_meal_delivery/forecasts) sub-package.
### Predictive Routing
@ -51,11 +71,11 @@ and
`poetry install --extras research`
The `--extras` option is necessary as the non-develop dependencies
are structured in the [pyproject.toml](https://github.com/webartifex/urban-meal-delivery/blob/develop/pyproject.toml) file
are structured in the [pyproject.toml](https://github.com/webartifex/urban-meal-delivery/blob/main/pyproject.toml) file
into dependencies related to only the `urban-meal-delivery` source code package
and dependencies used to run the [Jupyter](https://jupyter.org/) environment
with the analyses.
Contributions are welcome.
Use the [issues](https://github.com/webartifex/urban-meal-delivery/issues) tab.
The project is licensed under the [MIT license](https://github.com/webartifex/urban-meal-delivery/blob/develop/LICENSE.txt).
The project is licensed under the [MIT license](https://github.com/webartifex/urban-meal-delivery/blob/main/LICENSE.txt).

View file

@ -19,7 +19,7 @@
"- numeric columns are checked for plausibility\n",
"- foreign key relationships are strictly enforced\n",
"\n",
"The structure of the data can be viewed at the [ORM layer](https://github.com/webartifex/urban-meal-delivery/tree/develop/src/urban_meal_delivery/db) in the package."
"The structure of the data can be viewed at the [ORM layer](https://github.com/webartifex/urban-meal-delivery/tree/main/src/urban_meal_delivery/db) in the package."
]
},
{

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -49,9 +49,9 @@ class Config:
TIME_STEPS = [60]
# Training horizons (in full weeks) used to train the forecasting models.
# For now, we only use 8 weeks as that was the best performing in
# For now, we only use 7 and 8 weeks as that was the best performing in
# a previous study (note:4f79e8fa).
TRAIN_HORIZONS = [8]
TRAIN_HORIZONS = [7, 8]
# The demand forecasting methods used in the simulations.
FORECASTING_METHODS = ['hets', 'rtarima']

View file

@ -105,7 +105,12 @@ def tactical_heuristic( # noqa:C901,WPS213,WPS216,WPS231
# Continue with forecasting on the day the last prediction was made ...
last_predict_at = ( # noqa:ECE001
db.session.query(func.max(db.Forecast.start_at))
.join(db.Pixel, db.Forecast.pixel_id == db.Pixel.id)
.join(db.Grid, db.Pixel.grid_id == db.Grid.id)
.filter(db.Forecast.pixel == pixel)
.filter(db.Grid.side_length == side_length)
.filter(db.Forecast.time_step == time_step)
.filter(db.Forecast.train_horizon == train_horizon)
.first()
)[0]
# ... or start `train_horizon` weeks after the first `Order`

View file

@ -542,9 +542,9 @@ class OrderHistory:
pixel_id=pixel_id, predict_day=predict_day, train_horizon=train_horizon,
)
# For now, we only make forecasts with 8 weeks
# For now, we only make forecasts with 7 and 8 weeks
# as the training horizon (note:4f79e8fa).
if train_horizon == 8:
if train_horizon == 7 or train_horizon == 8:
if add >= 25: # = "high demand"
return models.HorizontalETSModel(order_history=self)
elif add >= 10: # = "medium demand"