metrosim/docs/architecture/simulator/pre-day_model.rst

454 lines
15 KiB
ReStructuredText

Pre-Day Model
=============
As its name suggests, the pre-day model runs before any agent start his / her trips.
In the pre-day model, the agents are planning their trips for the next day, given the expected network conditions.
Any decision taken in the pre-day model is susceptible to be changed during the day (see :doc:`within-day_model`).
.. uml:: pre-day_model_component.puml
:caption: Pre-Day Model Component Diagram
:width: 100 %
:align: center
Route Choice
-------------------
The route choice function runs independently for each trip of each agent.
The function evaluates all the attractive routes of the agent for this trip.
The agent is planning to take the route with the best utility.
The planned departure time is the best departure time for the chosen route.
.. note::
Before evaluating all the routes, the function sort the routes by decreasing utility (using utility guesses).
Then, the routes are evaluated in this order so that the best route is likely to be found early, and other routes can be skipped if the function knows that the utility will not be larger.
The utility guesses can be free-flow utilities (computed by the initializer) or the utilities computed during the previous iteration.
Route Evaluation
----------------
To evaluate the utility and departure time of a given route of an agent, the route choice function calls the route evaluation function.
This function runs differently for continuous-time or discrete-time routes.
Continuous-Time Routes
^^^^^^^^^^^^^^^^^^^^^^
Continuous-time routes are composed of constant or continuous trip segments (see :doc:`/architecture/overview/routes`).
For constant segments, MetroSim knows the segment travel-time, which is constant for the whole simulation period.
For continuous segments, MetroSim knows the segment travel-time for evenly spaced departure times.
.. warning::
TODO: Add a reference to technical parameters page, where the argument used for the evenly spaced time intervals is defined.
When evaluating a continuous-time route of an agent, MetroSim first constructs a list of departure-times for which it will compute the expected travel utility (see TODO).
Then, MetroSim retrieves the travel time for the first segment of the route, for each departure time in this list
For all following segments (if any), MetroSim retrieves the travel time for this segment, for each departure time in the list, *accounting for the travel time of the previous segments*.
The following table represents this process.
The first column is the departure-time list of the agent.
The second column is the travel time for the first segment, for each departure time from column 1.
The third column is the departure time for the second segment (i.e., the sum of columns 1 and 2).
The fourth column is the travel time for the second segment, for each departure time from column 3.
The last column is the total travel time (i.e., the sum of columns 2 and 4).
========= ==================== ====================== ==================== ===================
Dep. time Travel time (seg. 1) Dep. time (for seg. 2) Travel time (seg. 2) Travel time (total)
========= ==================== ====================== ==================== ===================
7:00 0:20 7:20 0:10 0:30
7:30 0:21 7:51 0:13 0:34
7:45 0:23 8:08 0:14 0:37
7:50 0:25 8:15 0:14 0:39
7:55 0:25 8:20 0:13 0:38
8:00 0:27 8:27 0:13 0:40
8:05 0:27 8:32 0:13 0:40
8:10 0:26 8:36 0:12 0:38
8:15 0:25 8:40 0:12 0:37
8:30 0:22 8:52 0:11 0:33
9:00 0:20 9:20 0:10 0:30
========= ==================== ====================== ==================== ===================
.. warning::
TODO: Find a smart way to get time intervals for an agent (with a higher density closer to a guessed departure time). Explain it in the docs and add a reference here.
.. note::
With continuous segments, MetroSim can try to retrieve travel time at a departure time for which travel time is not recorded.
In this case, MetroSim approximates the travel time (see TODO).
Once MetroSim has computed total travel time for all departure times in the list, it can compute total utility using the following formula::
total_utility = travel_utility(travel_time) + schedule_utility(departure_time, travel_time)
The computation of travel utility is specific to the mode of transportation of the route.
Then, the function approximates the maximum of the total utility over the departure-time period.
It returns the approximate maximum total utility and the corresponding departure time.
.. note::
If a route combines multiple modes of transportation, then the travel utility and travel time of each part of the route are computed independently.
Total travel utility and total travel time of the route are simply the sum of the partial travel utilities and travel times.
.. warning::
TODO: Discuss how stochasticity is implemented.
Discrete-Time Routes
^^^^^^^^^^^^^^^^^^^^
For discrete-time routes, the function finds the departure time with the highest utility.
To do so, it evaluates all departure times one by one.
When calling the function to compute the utility of the route, the current best utility found for the trip (for any route) is passed as an argument so that the function called can stop prematurely if the utility can not be larger than the best utility.
Also, the departure times are evaluated in order such that best departure times are likely to be evaluated early.
Here is a pseudocode of the function ``get_route_utility(route, utility_ub)``::
dep_times = route.get_sorted_dep_times()
for dep_time in dep_times:
u = route.get_exp_utility(dep_time, agent, best_utility)
if u > best_utility:
best_utility = u
best_route = route
best_dep_time = dep_time
Departure-Time Choice in Metropolis 1
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This section describes how departure-time choice is implemented in Metropolis 1 (for car commutes).
Recall that Metropolis 1 works with the :math:`\alpha-\beta-\gamma` model, where :math:`t^*` is either the desired arrival time or desired departure time (we assume below that it represents a desired arrival time).
Metropolis knows the travel times :math:`\{{tt}_1, \dots, {tt}_{10}\}` between origin and destination for 10 evenly spaced values of departure time :math:`\{{td}_1, \dots, {td}_{10}\}`.
The associated arrival times are computed as :math:`\{{ta}_1, \dots, {ta}_{10}\} = \{{td}_1+{tt}_1, \dots, {td}_{10}+{tt}_{10}\}`.
Metropolis also approximates the travel time such that arrival time is :math:`t^*` using a linear approximation:
.. math::
\hat{tt} = {tt}_{i-1} + (t^* - {ta}_{i-1}) \cdot \frac{{tt}_i - {tt}_{i-1}}{{ta}_{i} - {ta}_{i-1}},
where :math:`i` is such that :math:`{ta}_{i-1} < t^* < {ta}_i`.
The departure time which is such that the agent is expecting to arrive just on time is thus :math:`\hat{td} = t^*-\hat{tt}`.
The values :math:`\hat{td}`, :math:`\hat{tt}` and :math:`t^*` are added to the previous lists, which now contains 11 values.
.. plot:: plots/metro1_tt.py
Travel times as a function of arrival times
Then, Metropolis computes the exponential of the travel cost for each departure time, using the following formula:
.. math::
\exp(-c_i/\mu_{\text{dep}}) = \exp\left( -\frac{\alpha \cdot {tt}_i + {sc}_i}{\mu_{\text{dep}}} \right),
where
.. math::
{sc}_i = \beta \left[t^*-{ta}_i\right]^+ + \gamma \left[{ta}_i-t^*\right]^+.
.. plot:: plots/metro1_c.py
Travel costs as a function of arrival times
.. plot:: plots/metro1_expc.py
Exponential of travel costs as a function of arrival times
Metropolis also computes the following values.
The marginal travel time (using linear approximation):
.. math::
\delta_i = \frac{\text{d} {tt}_i}{\text{d} {ta}_i} = \frac{{tt}_{i+1} - {tt}_i}{{ta}_{i+1} - {ta}_i}.
The marginal cost of arriving one minute later:
.. math::
b_i = \frac{\text{d} c_i}{\text{d} {ta}_i} = \alpha \cdot \delta_i - \beta \cdot \mathbf{1}_{\{{ta}_i<t^*\}} + \gamma \cdot \mathbf{1}_{\{{ta}_i \geq t^*\}}.
This value:
.. math::
a_i = c_i + b_i \cdot {ta}_i = \alpha ({tt}_i - {ta}_i \cdot \delta_i) + \beta \cdot t^* \cdot \mathbf{1}_{\{{ta}_i < t^*\}} - \gamma \cdot t^* \cdot \mathbf{1}_{\{{ta}_i \geq t^*\}}.
The individual chooses an arrival time.
His / her departure time is deduced using the expected travel time for the chosen arrival time.
The departure time is chosen in three steps:
#. The individual chooses an interval :math:`[{ta}_i, {ta}_{i+1})`.
#. The individual chooses an arrival time :math:`{ta}^* \in [{ta}_i, {ta}_{i+1})`.
#. The chosen departure time is deduced from :math:`{ta}^*`.
Step 1
""""""
For the first step, the probability to choose interval :math:`[{ta}_i, {ta}_{i+1})` is
.. math::
P_i = \frac{ g_i }{ \sum_i g_i },
where
.. math::
:label: approx1
g_i = \max\left( \frac{\exp(-c_i/\mu_{\text{dep}}) - \exp(-c_{i+1}/\mu_{\text{dep}})}{b_i}, 0 \right),
if :math:`b_i>0`, and
.. math::
:label: approx2
g_i = \frac{\exp(-c_i/\mu_{\text{dep}}) \cdot ( {ta}_{i+1} - {ta}_i )}{\mu_{\text{dep}}},
otherwise.
.. note::
Metropolis approximates the integral
.. math::
\int_{{ta}_i}^{{ta}_{i+1}} \exp(-c({ta}) / \mu_{\text{dep}}) \text{d}{ta}.
Assume that :math:`c({ta})` is piece-wise linear, i.e.,
.. math::
\frac{ \partial c }{ \partial {ta} }({ta}) = b_i, \quad \forall {ta} \in [{ta}_i, {ta}_{i+1}), \quad \forall i \in \{1, \dots, 11\}.
Then,
.. math::
\int_{{ta}_i}^{{ta}_{i+1}} \exp(-c({ta}) / \mu_{\text{dep}}) \text{d}{ta}
=
-\mu_{\text{dep}} \left[ \frac{ \exp\big( -c(ta) / \mu_{\text{dep}} \big) }{ b_i } \right]^{{ta}_{i+1}}_{{ta}_i},
and thus
.. math::
\int_{{ta}_i}^{{ta}_{i+1}} \exp(-c({ta}) / \mu_{\text{dep}}) \text{d}{ta}
=
\mu_{\text{dep}}\frac{\exp(-c_i/\mu_{\text{dep}}) - \exp(-c_{i+1}/\mu_{\text{dep}})}{b_i},
hence equation :eq:`approx1`, where the factor :math:`\mu_{\text{dep}}` is discarded as it impacts similarly :math:`g_i` for all values of :math:`i`.
The :math:`\max` function ensures that :math:`g_i` is positive.
When :math:`b_i=0`, then the integral
.. math::
\int_{{ta}_i}^{{ta}_{i+1}} \exp(-c({ta}) / \mu_{\text{dep}}) \text{d}{ta}.
corresponds to the area of a rectangle of height :math:`\exp(-c_i/\mu_{\text{dep}})` and of width :math:`{ta}_{i+1} - {ta}_{i}`, hence equation :eq:`approx2`, where the multiplicative factor :math:`1/\mu_{\text{dep}}` is added to be consistent with the previous equation.
.. warning::
Would it be better to approximate :math:`b_i` with
.. math::
\frac{{c}_{i+1} - {c}_i}{{ta}_{i+1} - {ta}_i}.
instead of
.. math::
\alpha \cdot \delta_i - \beta \cdot \mathbf{1}_{\{{td}_i<t^*\}} + \gamma \cdot \mathbf{1}_{\{{td}_i \geq t^*\}}.
Each individual has a value :math:`\epsilon \in [0, 1]` for his / her departure-time choice.
Let
.. math::
F_i = \sum_{j<i} P_i.
Metropolis finds the value :math:`i^*` such that
.. math::
F_{i^*} \leq \epsilon < F_{i^*+1}.
The departure time chosen by the individual will be in the interval :math:`[{ta}_{i^*}, {ta}_{i^*+1})`.
.. plot:: plots/metro1_cumprobs.py
Cumulative probabilities and interval choice
Step 2
""""""
Then, Metropolis computes an exact arrival time :math:`{ta}^*`, according to the following rules.
Let
.. math::
A = \exp(-c_{i^*} / \mu_{\text{dep}}) - b_{i^*} \left(\epsilon-F_{i^*}\right) \sum_i g_i,
and
.. math::
B = 1 - 2 \cdot b_{i^*} \cdot \left( \epsilon - F_{i^*} \right) \cdot \sum_i g_i / \exp(-c_{i^*} / \mu_{\text{dep}}).
**Case 1:**
.. math::
{ta}^* = \frac{ - \mu_{\text{dep}} \cdot \log(A) - a_{i^*} }{ b_{i^*} }.
**Case 2:**
.. math::
{ta}^* = {ta}_{i^*} + \frac{ \mu_{\text{dep}} }{ b_{i^*} } \left( 1 + \sqrt{B} \right).
**Case 3:**
.. math::
{ta}^* = {ta}_{i^*} + (\epsilon - F_{i^*}) \sum_i g_i / \exp(-c_{i^*} / \mu_{\text{dep}}).
**Case 4:**
.. math::
{ta}^* = {ta}_{i^*} + ({ta}_{i^*+1} - {ta}_{i^*})\frac{(\epsilon-F_{i^*})}{P_{i^*}}.
**Case 5:**
.. math::
{ta}^* = {ta}_{i^*}.
**Case 6:**
.. math::
{ta}^* = {ta}_{i^*+1}.
::
ta_star = -1
if |b_i| > 0:
if A > 0:
# Case 1.
ta_star = ...
if (ta_star < ta_prev or ta_star > ta_next) and B > 0:
# Case 2.
ta_star = ...
else:
# Case 3.
ta_star = ...
if ta_star < ta_prev or ta_star > ta_next:
# Case 4.
ta_star = ...
if ta_star < ta_prev:
# Case 5.
ta_star = ...
else if ta_star > ta_next:
# Case 6.
ta_star = ...
.. note::
Let
.. math::
q = \frac{\epsilon - F_{i^*}}{P_{i^*}}.
We want to find :math:`{ta}^*` such that
.. math::
q = \frac{
\int_{{ta}_{i^*}}^{{ta}^*} \exp(-c(t) / \mu_{\text{dep}}) \text{d}t
}{
\int_{{ta}_{i^*}}^{{ta}_{i^*+1}} \exp(-c(t) / \mu_{\text{dep}}) / \text{d}t
}.
This expression simplifies to
.. math::
c({ta}^*) = -\mu_{\text{dep}} \log \left\{ \exp(-c_{i^*}/\mu_{\text{dep}}) - q \big[ \exp(-c_{i^*}/\mu_{\text{dep}}) - \exp(-c_{i^*+1}/\mu_{\text{dep}}) \big] \right\}.
If we set :math:`{ta}^* = p {ta}_{i^*} + (1-p) {ta}_{i^*+1}`, then we have :math:`c({ta}^*) = p c_{i^*} + (1-p) c_{i^*+1}`, and thus
.. math::
p = \frac{
-c_{i^*+1} - \mu_{\text{dep}} \log(A')
}{
c_{i^*} - c_{i^*+1}
},
where
.. math::
A' = \exp(-c_{i^*}/\mu_{\text{dep}}) - q \big[ \exp(-c_{i^*}/\mu_{\text{dep}}) - \exp(-c_{i^*+1}/\mu_{\text{dep}}) \big].
Observe that
.. math::
\exp(-c_{i^*}/\mu_{\text{dep}}) - \exp(-c_{i^*+1}/\mu_{\text{dep}}) \approx b_i g_i \approx b_i P_i \sum g_i,
and thus, we have :math:`A=A'`.
Then,
.. math::
{ta}^* = \frac{
-c_{i^*+1} - \mu_{\text{dep}} \log(A)
}{
c_{i^*} - c_{i^*+1}
}
(t_{i^*} - t_{i^*+1})
- t_{i^*+1},
which can be approximated with
.. math::
{ta}^* = \frac{ - \mu_{\text{dep}} \log(A) }{ b_{i^*} } - \frac{c_{i^*+1}}{ b_{i^*} } - {ta}_{i^*+1}.
Finally, using the approximation
.. math::
- \frac{c_{i^*+1}}{ b_{i^*} } - {ta}_{i^*+1}
\approx
- \frac{c_{i^*}}{ b_{i^*} } - {ta}_{i^*}
=
- \frac{a_{i^*}}{b_{i^*}},
we get
.. math::
{ta}^* = \frac{ - \mu_{\text{dep}} \log(A) - a_{i^*} }{ b_{i^*} },
which corresponds to **Case 1**.