Note
Go to the end to download the full example code.
1c. Simulation of a logit model (traditional and Bayesian)¶
Example of simulation with a logit model
Michel Bierlaire, EPFL Thu Oct 30 2025, 14:03:15
import sys
import pandas as pd
from IPython.core.display_functions import display
See the data processing script: Data preparation for Swissmetro.
from swissmetro_data import (
CAR_AV_SP,
CAR_CO_SCALED,
CAR_TT,
SM_AV,
SM_COST_SCALED,
SM_TT,
TRAIN_AV_SP,
TRAIN_COST_SCALED,
TRAIN_TT,
database,
)
import biogeme.biogeme_logging as blog
from biogeme.bayesian_estimation import BayesianResults
from biogeme.biogeme import BIOGEME
from biogeme.expressions import Beta, Derive
from biogeme.models import logit
logger = blog.get_screen_logger(level=blog.INFO)
Parameters.
asc_car = Beta('asc_car', 0, None, None, 0)
asc_train = Beta('asc_train', 0, None, None, 0)
asc_sm = Beta('asc_sm', 0, None, None, 1)
b_time = Beta('b_time', 0, None, None, 0)
b_cost = Beta('b_cost', 0, None, None, 0)
Definition of the utility functions. As we will calculate the derivative with respect to TRAIN_TT, SM_TT and CAR_TT, they must explicitly appear in the model. If not, the derivative will be zero. Therefore, we do not use the _SCALED version of the attributes. We explicitly include their definition.
v_train = asc_train + b_time * TRAIN_TT / 100 + b_cost * TRAIN_COST_SCALED
v_swissmetro = asc_sm + b_time * SM_TT / 100 + b_cost * SM_COST_SCALED
v_car = asc_car + b_time * CAR_TT / 100 + b_cost * CAR_CO_SCALED
Associate utility functions with the numbering of alternatives.
v = {1: v_train, 2: v_swissmetro, 3: v_car}
Associate the availability conditions with the alternatives.
av = {1: TRAIN_AV_SP, 2: SM_AV, 3: CAR_AV_SP}
Choice probability.
prob_train = logit(v, av, 1)
Elasticity.
time_elasticity_train = Derive(prob_train, 'TRAIN_TT') * TRAIN_TT / prob_train
Quantities to be simulated.
simulate = {
'Prob. train': prob_train,
'train time elasticity': time_elasticity_train,
'Value of time': b_time / b_cost,
}
Create the Biogeme object.
As we simulate the probability for all alternatives, even when one of them is not available, Biogeme may trigger some warnings.
biosim = BIOGEME(database, simulate)
biosim.model_name = 'b01c_logit_simul'
Biogeme parameters read from biogeme.toml.
Retrieve the estimated values of the parameters.
RESULTS_FILE_NAME = 'saved_results/b01a_logit.nc'
try:
estimation_results = BayesianResults.from_netcdf(filename=RESULTS_FILE_NAME)
except FileNotFoundError:
logger.error(
f'File {RESULTS_FILE_NAME} does not exist. Run the estimation script first.'
)
sys.exit()
betas = estimation_results.get_beta_values()
Loaded NetCDF file size: 930.9 MB
load finished in 46 ms
Diagnostics computation took 20.6 seconds (cached).
Simulation using the posterior mean of each parameter
print('Simulation using the posterior mean of each parameter')
results = biosim.simulate(the_beta_values=betas)
display(results)
Simulation using the posterior mean of each parameter
Prob. train train time elasticity Value of time
0 0.167777 -1.192307 1.179714
1 0.184032 -1.075079 1.179714
2 0.142808 -1.425450 1.179714
3 0.161103 -1.105289 1.179714
4 0.139610 -1.430767 1.179714
... ... ... ...
6763 0.172315 -1.143456 1.179714
6764 0.164388 -1.154406 1.179714
6765 0.149214 -1.175370 1.179714
6766 0.134518 -1.417093 1.179714
6767 0.176658 -1.137456 1.179714
[6768 rows x 3 columns]
Bayesian simulation using the posterior draws
print('Bayesian simulation')
bayesian_results = biosim.simulate_bayesian(
bayesian_estimation_results=estimation_results, percentage_of_draws_to_use=3
)
with pd.option_context('display.max_columns', None, 'display.expand_frame_repr', False):
display(bayesian_results)
Bayesian simulation
Bayesian simulation performed with 3% of the draws, that is 240/8000 draws. Adjust the parameter "percentage_of_draws_to_use" if you need a different number of draws.
0%| | 0/240 [00:00<?, ?it/s]
0%| | 1/240 [00:00<01:07, 3.53it/s]
1%| | 2/240 [00:00<01:05, 3.62it/s]
1%|▏ | 3/240 [00:00<01:04, 3.67it/s]
2%|▏ | 4/240 [00:01<01:03, 3.74it/s]
2%|▏ | 5/240 [00:01<01:02, 3.75it/s]
2%|▎ | 6/240 [00:01<01:02, 3.77it/s]
3%|▎ | 7/240 [00:01<01:01, 3.79it/s]
3%|▎ | 8/240 [00:02<01:00, 3.80it/s]
4%|▍ | 9/240 [00:02<01:00, 3.83it/s]
4%|▍ | 10/240 [00:02<01:00, 3.83it/s]
5%|▍ | 11/240 [00:02<01:00, 3.80it/s]
5%|▌ | 12/240 [00:03<00:59, 3.81it/s]
5%|▌ | 13/240 [00:03<00:59, 3.82it/s]
6%|▌ | 14/240 [00:03<00:58, 3.84it/s]
6%|▋ | 15/240 [00:03<00:58, 3.83it/s]
7%|▋ | 16/240 [00:04<00:58, 3.84it/s]
7%|▋ | 17/240 [00:04<00:58, 3.82it/s]
8%|▊ | 18/240 [00:04<00:58, 3.83it/s]
8%|▊ | 19/240 [00:05<00:57, 3.82it/s]
8%|▊ | 20/240 [00:05<00:57, 3.83it/s]
9%|▉ | 21/240 [00:05<00:57, 3.84it/s]
9%|▉ | 22/240 [00:05<00:56, 3.83it/s]
10%|▉ | 23/240 [00:06<00:56, 3.83it/s]
10%|█ | 24/240 [00:06<00:56, 3.85it/s]
10%|█ | 25/240 [00:06<00:56, 3.83it/s]
11%|█ | 26/240 [00:06<00:55, 3.85it/s]
11%|█▏ | 27/240 [00:07<00:55, 3.86it/s]
12%|█▏ | 28/240 [00:07<00:55, 3.85it/s]
12%|█▏ | 29/240 [00:07<00:54, 3.84it/s]
12%|█▎ | 30/240 [00:07<00:54, 3.85it/s]
13%|█▎ | 31/240 [00:08<00:54, 3.85it/s]
13%|█▎ | 32/240 [00:08<00:54, 3.83it/s]
14%|█▍ | 33/240 [00:08<00:54, 3.82it/s]
14%|█▍ | 34/240 [00:08<00:53, 3.82it/s]
15%|█▍ | 35/240 [00:09<00:53, 3.82it/s]
15%|█▌ | 36/240 [00:09<00:53, 3.83it/s]
15%|█▌ | 37/240 [00:09<00:53, 3.82it/s]
16%|█▌ | 38/240 [00:09<00:53, 3.80it/s]
16%|█▋ | 39/240 [00:10<00:53, 3.78it/s]
17%|█▋ | 40/240 [00:10<00:52, 3.78it/s]
17%|█▋ | 41/240 [00:10<00:52, 3.78it/s]
18%|█▊ | 42/240 [00:11<00:52, 3.78it/s]
18%|█▊ | 43/240 [00:11<00:51, 3.81it/s]
18%|█▊ | 44/240 [00:11<00:51, 3.81it/s]
19%|█▉ | 45/240 [00:11<00:51, 3.82it/s]
19%|█▉ | 46/240 [00:12<00:50, 3.82it/s]
20%|█▉ | 47/240 [00:12<00:50, 3.83it/s]
20%|██ | 48/240 [00:12<00:50, 3.83it/s]
20%|██ | 49/240 [00:12<00:49, 3.84it/s]
21%|██ | 50/240 [00:13<00:49, 3.83it/s]
21%|██▏ | 51/240 [00:13<00:49, 3.81it/s]
22%|██▏ | 52/240 [00:13<00:49, 3.83it/s]
22%|██▏ | 53/240 [00:13<00:48, 3.84it/s]
22%|██▎ | 54/240 [00:14<00:48, 3.83it/s]
23%|██▎ | 55/240 [00:14<00:49, 3.74it/s]
23%|██▎ | 56/240 [00:14<00:48, 3.76it/s]
24%|██▍ | 57/240 [00:14<00:48, 3.79it/s]
24%|██▍ | 58/240 [00:15<00:47, 3.80it/s]
25%|██▍ | 59/240 [00:15<00:47, 3.79it/s]
25%|██▌ | 60/240 [00:15<00:47, 3.81it/s]
25%|██▌ | 61/240 [00:16<00:46, 3.84it/s]
26%|██▌ | 62/240 [00:16<00:46, 3.85it/s]
26%|██▋ | 63/240 [00:16<00:45, 3.87it/s]
27%|██▋ | 64/240 [00:16<00:45, 3.85it/s]
27%|██▋ | 65/240 [00:17<00:45, 3.87it/s]
28%|██▊ | 66/240 [00:17<00:45, 3.84it/s]
28%|██▊ | 67/240 [00:17<00:44, 3.86it/s]
28%|██▊ | 68/240 [00:17<00:44, 3.88it/s]
29%|██▉ | 69/240 [00:18<00:44, 3.88it/s]
29%|██▉ | 70/240 [00:18<00:43, 3.87it/s]
30%|██▉ | 71/240 [00:18<00:43, 3.88it/s]
30%|███ | 72/240 [00:18<00:43, 3.86it/s]
30%|███ | 73/240 [00:19<00:43, 3.87it/s]
31%|███ | 74/240 [00:19<00:42, 3.86it/s]
31%|███▏ | 75/240 [00:19<00:44, 3.69it/s]
32%|███▏ | 76/240 [00:19<00:43, 3.75it/s]
32%|███▏ | 77/240 [00:20<00:43, 3.75it/s]
32%|███▎ | 78/240 [00:20<00:42, 3.78it/s]
33%|███▎ | 79/240 [00:20<00:42, 3.78it/s]
33%|███▎ | 80/240 [00:20<00:42, 3.80it/s]
34%|███▍ | 81/240 [00:21<00:41, 3.80it/s]
34%|███▍ | 82/240 [00:21<00:41, 3.83it/s]
35%|███▍ | 83/240 [00:21<00:41, 3.82it/s]
35%|███▌ | 84/240 [00:22<00:40, 3.83it/s]
35%|███▌ | 85/240 [00:22<00:40, 3.84it/s]
36%|███▌ | 86/240 [00:22<00:39, 3.86it/s]
36%|███▋ | 87/240 [00:22<00:39, 3.87it/s]
37%|███▋ | 88/240 [00:23<00:39, 3.86it/s]
37%|███▋ | 89/240 [00:23<00:39, 3.84it/s]
38%|███▊ | 90/240 [00:23<00:39, 3.84it/s]
38%|███▊ | 91/240 [00:23<00:38, 3.84it/s]
38%|███▊ | 92/240 [00:24<00:38, 3.80it/s]
39%|███▉ | 93/240 [00:24<00:38, 3.82it/s]
39%|███▉ | 94/240 [00:24<00:38, 3.82it/s]
40%|███▉ | 95/240 [00:24<00:37, 3.82it/s]
40%|████ | 96/240 [16:05<11:17:46, 282.41s/it]
40%|████ | 97/240 [16:05<7:51:21, 197.77s/it]
41%|████ | 98/240 [16:06<5:27:50, 138.52s/it]
41%|████▏ | 99/240 [16:06<3:48:03, 97.04s/it]
42%|████▏ | 100/240 [16:06<2:38:41, 68.01s/it]
42%|████▏ | 101/240 [16:06<1:50:28, 47.69s/it]
42%|████▎ | 102/240 [16:07<1:16:57, 33.46s/it]
43%|████▎ | 103/240 [16:07<53:39, 23.50s/it]
43%|████▎ | 104/240 [16:07<37:27, 16.53s/it]
44%|████▍ | 105/240 [16:08<26:12, 11.65s/it]
44%|████▍ | 106/240 [16:08<18:22, 8.23s/it]
45%|████▍ | 107/240 [16:08<12:56, 5.84s/it]
45%|████▌ | 108/240 [16:08<09:09, 4.16s/it]
45%|████▌ | 109/240 [16:09<06:31, 2.99s/it]
46%|████▌ | 110/240 [16:09<04:42, 2.17s/it]
46%|████▋ | 111/240 [16:09<03:26, 1.60s/it]
47%|████▋ | 112/240 [16:09<02:33, 1.20s/it]
47%|████▋ | 113/240 [16:10<01:56, 1.09it/s]
48%|████▊ | 114/240 [16:10<01:30, 1.39it/s]
48%|████▊ | 115/240 [16:10<01:12, 1.73it/s]
48%|████▊ | 116/240 [16:10<00:59, 2.08it/s]
49%|████▉ | 117/240 [16:11<00:50, 2.42it/s]
49%|████▉ | 118/240 [16:11<00:44, 2.73it/s]
50%|████▉ | 119/240 [16:11<00:40, 2.99it/s]
50%|█████ | 120/240 [16:11<00:37, 3.23it/s]
50%|█████ | 121/240 [16:12<00:34, 3.42it/s]
51%|█████ | 122/240 [16:12<00:33, 3.57it/s]
51%|█████▏ | 123/240 [16:12<00:32, 3.65it/s]
52%|█████▏ | 124/240 [16:12<00:31, 3.72it/s]
52%|█████▏ | 125/240 [16:13<00:30, 3.76it/s]
52%|█████▎ | 126/240 [16:13<00:29, 3.81it/s]
53%|█████▎ | 127/240 [16:13<00:29, 3.83it/s]
53%|█████▎ | 128/240 [16:13<00:28, 3.87it/s]
54%|█████▍ | 129/240 [16:14<00:28, 3.87it/s]
54%|█████▍ | 130/240 [16:14<00:28, 3.88it/s]
55%|█████▍ | 131/240 [16:14<00:28, 3.88it/s]
55%|█████▌ | 132/240 [16:14<00:27, 3.90it/s]
55%|█████▌ | 133/240 [16:15<00:27, 3.90it/s]
56%|█████▌ | 134/240 [16:15<00:27, 3.90it/s]
56%|█████▋ | 135/240 [16:15<00:26, 3.90it/s]
57%|█████▋ | 136/240 [16:15<00:26, 3.89it/s]
57%|█████▋ | 137/240 [16:16<00:26, 3.89it/s]
57%|█████▊ | 138/240 [16:16<00:26, 3.90it/s]
58%|█████▊ | 139/240 [16:16<00:25, 3.91it/s]
58%|█████▊ | 140/240 [16:16<00:25, 3.94it/s]
59%|█████▉ | 141/240 [16:17<00:25, 3.93it/s]
59%|█████▉ | 142/240 [16:17<00:24, 3.95it/s]
60%|█████▉ | 143/240 [16:17<00:24, 3.90it/s]
60%|██████ | 144/240 [16:18<00:24, 3.92it/s]
60%|██████ | 145/240 [16:18<00:24, 3.94it/s]
61%|██████ | 146/240 [16:18<00:23, 3.94it/s]
61%|██████▏ | 147/240 [16:18<00:23, 3.92it/s]
62%|██████▏ | 148/240 [16:19<00:23, 3.92it/s]
62%|██████▏ | 149/240 [16:19<00:23, 3.92it/s]
62%|██████▎ | 150/240 [16:19<00:22, 3.94it/s]
63%|██████▎ | 151/240 [16:19<00:22, 3.94it/s]
63%|██████▎ | 152/240 [16:20<00:22, 3.95it/s]
64%|██████▍ | 153/240 [16:20<00:22, 3.94it/s]
64%|██████▍ | 154/240 [16:20<00:21, 3.93it/s]
65%|██████▍ | 155/240 [16:20<00:21, 3.93it/s]
65%|██████▌ | 156/240 [16:21<00:21, 3.95it/s]
65%|██████▌ | 157/240 [16:21<00:21, 3.94it/s]
66%|██████▌ | 158/240 [16:21<00:20, 3.94it/s]
66%|██████▋ | 159/240 [16:21<00:20, 3.93it/s]
67%|██████▋ | 160/240 [16:22<00:20, 3.95it/s]
67%|██████▋ | 161/240 [16:22<00:20, 3.93it/s]
68%|██████▊ | 162/240 [16:22<00:19, 3.95it/s]
68%|██████▊ | 163/240 [16:22<00:19, 3.96it/s]
68%|██████▊ | 164/240 [16:23<00:19, 3.97it/s]
69%|██████▉ | 165/240 [16:23<00:18, 3.98it/s]
69%|██████▉ | 166/240 [16:23<00:18, 3.95it/s]
70%|██████▉ | 167/240 [16:23<00:18, 3.97it/s]
70%|███████ | 168/240 [16:24<00:18, 3.96it/s]
70%|███████ | 169/240 [16:24<00:17, 3.96it/s]
71%|███████ | 170/240 [16:24<00:17, 3.95it/s]
71%|███████▏ | 171/240 [16:24<00:17, 3.95it/s]
72%|███████▏ | 172/240 [16:25<00:17, 3.95it/s]
72%|███████▏ | 173/240 [16:25<00:17, 3.94it/s]
72%|███████▎ | 174/240 [16:25<00:17, 3.81it/s]
73%|███████▎ | 175/240 [16:25<00:16, 3.84it/s]
73%|███████▎ | 176/240 [16:26<00:16, 3.87it/s]
74%|███████▍ | 177/240 [16:26<00:16, 3.91it/s]
74%|███████▍ | 178/240 [16:26<00:15, 3.93it/s]
75%|███████▍ | 179/240 [16:26<00:15, 3.92it/s]
75%|███████▌ | 180/240 [16:27<00:15, 3.92it/s]
75%|███████▌ | 181/240 [16:27<00:15, 3.90it/s]
76%|███████▌ | 182/240 [16:27<00:14, 3.89it/s]
76%|███████▋ | 183/240 [16:27<00:14, 3.91it/s]
77%|███████▋ | 184/240 [16:28<00:14, 3.92it/s]
77%|███████▋ | 185/240 [16:28<00:13, 3.94it/s]
78%|███████▊ | 186/240 [16:28<00:13, 3.92it/s]
78%|███████▊ | 187/240 [16:28<00:13, 3.92it/s]
78%|███████▊ | 188/240 [16:29<00:13, 3.94it/s]
79%|███████▉ | 189/240 [16:29<00:12, 3.95it/s]
79%|███████▉ | 190/240 [16:29<00:12, 3.96it/s]
80%|███████▉ | 191/240 [16:29<00:12, 3.92it/s]
80%|████████ | 192/240 [16:30<00:12, 3.93it/s]
80%|████████ | 193/240 [16:30<00:11, 3.95it/s]
81%|████████ | 194/240 [16:30<00:11, 3.94it/s]
81%|████████▏ | 195/240 [16:30<00:11, 3.92it/s]
82%|████████▏ | 196/240 [16:31<00:11, 3.90it/s]
82%|████████▏ | 197/240 [16:31<00:10, 3.93it/s]
82%|████████▎ | 198/240 [16:31<00:10, 3.94it/s]
83%|████████▎ | 199/240 [16:32<00:10, 3.92it/s]
83%|████████▎ | 200/240 [16:32<00:10, 3.91it/s]
84%|████████▍ | 201/240 [16:32<00:09, 3.90it/s]
84%|████████▍ | 202/240 [16:32<00:09, 3.90it/s]
85%|████████▍ | 203/240 [16:33<00:09, 3.91it/s]
85%|████████▌ | 204/240 [16:33<00:09, 3.93it/s]
85%|████████▌ | 205/240 [16:33<00:08, 3.92it/s]
86%|████████▌ | 206/240 [16:33<00:08, 3.89it/s]
86%|████████▋ | 207/240 [16:34<00:08, 3.90it/s]
87%|████████▋ | 208/240 [16:34<00:08, 3.93it/s]
87%|████████▋ | 209/240 [16:34<00:07, 3.91it/s]
88%|████████▊ | 210/240 [16:34<00:07, 3.91it/s]
88%|████████▊ | 211/240 [16:35<00:07, 3.93it/s]
88%|████████▊ | 212/240 [16:35<00:07, 3.93it/s]
89%|████████▉ | 213/240 [16:35<00:06, 3.94it/s]
89%|████████▉ | 214/240 [16:35<00:06, 3.92it/s]
90%|████████▉ | 215/240 [16:36<00:06, 3.93it/s]
90%|█████████ | 216/240 [16:36<00:06, 3.93it/s]
90%|█████████ | 217/240 [16:36<00:05, 3.92it/s]
91%|█████████ | 218/240 [16:36<00:05, 3.91it/s]
91%|█████████▏| 219/240 [16:37<00:05, 3.91it/s]
92%|█████████▏| 220/240 [16:37<00:05, 3.90it/s]
92%|█████████▏| 221/240 [16:37<00:04, 3.81it/s]
92%|█████████▎| 222/240 [16:37<00:04, 3.78it/s]
93%|█████████▎| 223/240 [16:38<00:04, 3.75it/s]
93%|█████████▎| 224/240 [16:38<00:04, 3.73it/s]
94%|█████████▍| 225/240 [16:38<00:04, 3.74it/s]
94%|█████████▍| 226/240 [16:38<00:03, 3.74it/s]
95%|█████████▍| 227/240 [16:39<00:03, 3.71it/s]
95%|█████████▌| 228/240 [16:39<00:03, 3.74it/s]
95%|█████████▌| 229/240 [16:39<00:02, 3.74it/s]
96%|█████████▌| 230/240 [16:40<00:02, 3.77it/s]
96%|█████████▋| 231/240 [16:40<00:02, 3.83it/s]
97%|█████████▋| 232/240 [16:40<00:02, 3.88it/s]
97%|█████████▋| 233/240 [16:40<00:01, 3.92it/s]
98%|█████████▊| 234/240 [16:41<00:01, 3.92it/s]
98%|█████████▊| 235/240 [16:41<00:01, 3.94it/s]
98%|█████████▊| 236/240 [16:41<00:01, 3.92it/s]
99%|█████████▉| 237/240 [16:41<00:00, 3.92it/s]
99%|█████████▉| 238/240 [16:42<00:00, 3.93it/s]
100%|█████████▉| 239/240 [16:42<00:00, 3.95it/s]
100%|██████████| 240/240 [16:42<00:00, 3.94it/s]
100%|██████████| 240/240 [16:42<00:00, 4.18s/it]
Prob. train_mean Prob. train_q025 Prob. train_q975 train time elasticity_mean train time elasticity_q025 train time elasticity_q975 Value of time_mean Value of time_q025 Value of time_q975
__biogeme_internal_obs_id__
0 0.167944 0.157871 0.177540 -1.186147 -1.296221 -1.079916 1.179349 1.05896 1.329006
1 0.184138 0.172726 0.195113 -1.069552 -1.167834 -0.974217 1.179349 1.05896 1.329006
2 0.143071 0.134324 0.151251 -1.418046 -1.552588 -1.288628 1.179349 1.05896 1.329006
3 0.161332 0.151455 0.170765 -1.099549 -1.203943 -1.000240 1.179349 1.05896 1.329006
4 0.139892 0.131175 0.148224 -1.423361 -1.563555 -1.291083 1.179349 1.05896 1.329006
... ... ... ... ... ... ... ... ... ...
6763 0.172492 0.162356 0.181832 -1.137558 -1.244091 -1.033769 1.179349 1.05896 1.329006
6764 0.164581 0.154888 0.173844 -1.148469 -1.257689 -1.043620 1.179349 1.05896 1.329006
6765 0.149449 0.140439 0.157967 -1.169297 -1.280575 -1.062274 1.179349 1.05896 1.329006
6766 0.134817 0.126111 0.142889 -1.409765 -1.549820 -1.277426 1.179349 1.05896 1.329006
6767 0.176818 0.166682 0.186591 -1.131613 -1.238394 -1.029015 1.179349 1.05896 1.329006
[6768 rows x 9 columns]
Total running time of the script: (17 minutes 14.376 seconds)