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 pandas as pd
from IPython.core.display_functions import display
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
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,
)
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'
estimation_results = BayesianResults.from_netcdf(filename=RESULTS_FILE_NAME)
betas = estimation_results.get_beta_values()
Loaded NetCDF file size: 855.3 MB
load finished in 4448 ms (4.45 s)
Diagnostics computation took 23.5 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.167825 -1.192850 1.180578
1 0.184090 -1.075555 1.180578
2 0.142838 -1.426131 1.180578
3 0.161141 -1.105807 1.180578
4 0.139629 -1.431470 1.180578
... ... ... ...
6763 0.172357 -1.143983 1.180578
6764 0.164421 -1.154953 1.180578
6765 0.149244 -1.175931 1.180578
6766 0.134531 -1.417798 1.180578
6767 0.176696 -1.137986 1.180578
[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<00:55, 4.30it/s]
1%| | 2/240 [00:00<00:54, 4.34it/s]
1%|▏ | 3/240 [00:00<00:54, 4.38it/s]
2%|▏ | 4/240 [00:00<00:54, 4.37it/s]
2%|▏ | 5/240 [00:01<00:54, 4.35it/s]
2%|▎ | 6/240 [00:01<00:53, 4.36it/s]
3%|▎ | 7/240 [00:01<00:53, 4.37it/s]
3%|▎ | 8/240 [00:01<00:53, 4.38it/s]
4%|▍ | 9/240 [00:02<00:52, 4.36it/s]
4%|▍ | 10/240 [00:02<00:52, 4.38it/s]
5%|▍ | 11/240 [00:02<00:52, 4.36it/s]
5%|▌ | 12/240 [00:02<00:52, 4.34it/s]
5%|▌ | 13/240 [00:02<00:52, 4.35it/s]
6%|▌ | 14/240 [00:03<00:51, 4.35it/s]
6%|▋ | 15/240 [00:03<00:52, 4.32it/s]
7%|▋ | 16/240 [00:03<00:51, 4.34it/s]
7%|▋ | 17/240 [00:03<00:51, 4.37it/s]
8%|▊ | 18/240 [00:04<00:51, 4.34it/s]
8%|▊ | 19/240 [00:04<00:50, 4.37it/s]
8%|▊ | 20/240 [00:04<00:50, 4.39it/s]
9%|▉ | 21/240 [00:04<00:50, 4.37it/s]
9%|▉ | 22/240 [00:05<00:50, 4.31it/s]
10%|▉ | 23/240 [00:05<00:50, 4.29it/s]
10%|█ | 24/240 [00:05<00:50, 4.31it/s]
10%|█ | 25/240 [00:05<00:49, 4.35it/s]
11%|█ | 26/240 [00:05<00:48, 4.37it/s]
11%|█▏ | 27/240 [00:06<00:48, 4.37it/s]
12%|█▏ | 28/240 [00:06<00:48, 4.39it/s]
12%|█▏ | 29/240 [00:06<00:47, 4.40it/s]
12%|█▎ | 30/240 [00:06<00:47, 4.39it/s]
13%|█▎ | 31/240 [00:07<00:47, 4.38it/s]
13%|█▎ | 32/240 [00:07<00:47, 4.39it/s]
14%|█▍ | 33/240 [00:07<00:47, 4.40it/s]
14%|█▍ | 34/240 [00:07<00:46, 4.39it/s]
15%|█▍ | 35/240 [00:08<00:46, 4.39it/s]
15%|█▌ | 36/240 [00:08<00:46, 4.36it/s]
15%|█▌ | 37/240 [00:08<00:46, 4.34it/s]
16%|█▌ | 38/240 [00:08<00:46, 4.35it/s]
16%|█▋ | 39/240 [00:08<00:47, 4.26it/s]
17%|█▋ | 40/240 [00:09<00:47, 4.21it/s]
17%|█▋ | 41/240 [00:09<00:46, 4.26it/s]
18%|█▊ | 42/240 [00:09<00:47, 4.20it/s]
18%|█▊ | 43/240 [00:09<00:47, 4.18it/s]
18%|█▊ | 44/240 [00:10<00:49, 3.99it/s]
19%|█▉ | 45/240 [00:10<00:48, 4.04it/s]
19%|█▉ | 46/240 [00:10<00:46, 4.14it/s]
20%|█▉ | 47/240 [00:10<00:46, 4.19it/s]
20%|██ | 48/240 [00:11<00:45, 4.23it/s]
20%|██ | 49/240 [00:11<00:44, 4.28it/s]
21%|██ | 50/240 [00:11<00:43, 4.34it/s]
21%|██▏ | 51/240 [00:11<00:43, 4.34it/s]
22%|██▏ | 52/240 [00:12<00:43, 4.35it/s]
22%|██▏ | 53/240 [00:12<00:43, 4.34it/s]
22%|██▎ | 54/240 [00:12<00:42, 4.37it/s]
23%|██▎ | 55/240 [00:12<00:42, 4.38it/s]
23%|██▎ | 56/240 [00:12<00:42, 4.38it/s]
24%|██▍ | 57/240 [00:13<00:41, 4.39it/s]
24%|██▍ | 58/240 [00:13<00:41, 4.39it/s]
25%|██▍ | 59/240 [00:13<00:40, 4.42it/s]
25%|██▌ | 60/240 [00:13<00:40, 4.44it/s]
25%|██▌ | 61/240 [00:14<00:40, 4.47it/s]
26%|██▌ | 62/240 [00:14<00:39, 4.46it/s]
26%|██▋ | 63/240 [00:14<00:39, 4.45it/s]
27%|██▋ | 64/240 [00:14<00:39, 4.44it/s]
27%|██▋ | 65/240 [00:14<00:39, 4.43it/s]
28%|██▊ | 66/240 [00:15<00:39, 4.41it/s]
28%|██▊ | 67/240 [00:15<00:39, 4.39it/s]
28%|██▊ | 68/240 [00:15<00:39, 4.40it/s]
29%|██▉ | 69/240 [00:15<00:38, 4.40it/s]
29%|██▉ | 70/240 [00:16<00:38, 4.38it/s]
30%|██▉ | 71/240 [00:16<00:38, 4.35it/s]
30%|███ | 72/240 [00:16<00:38, 4.35it/s]
30%|███ | 73/240 [00:16<00:38, 4.36it/s]
31%|███ | 74/240 [00:17<00:38, 4.36it/s]
31%|███▏ | 75/240 [00:17<00:37, 4.35it/s]
32%|███▏ | 76/240 [00:17<00:37, 4.37it/s]
32%|███▏ | 77/240 [00:17<00:37, 4.38it/s]
32%|███▎ | 78/240 [00:17<00:36, 4.38it/s]
33%|███▎ | 79/240 [00:18<00:36, 4.39it/s]
33%|███▎ | 80/240 [00:18<00:36, 4.38it/s]
34%|███▍ | 81/240 [00:18<00:36, 4.40it/s]
34%|███▍ | 82/240 [00:18<00:35, 4.40it/s]
35%|███▍ | 83/240 [00:19<00:35, 4.40it/s]
35%|███▌ | 84/240 [00:19<00:35, 4.44it/s]
35%|███▌ | 85/240 [00:19<00:35, 4.38it/s]
36%|███▌ | 86/240 [00:19<00:35, 4.36it/s]
36%|███▋ | 87/240 [00:20<00:35, 4.36it/s]
37%|███▋ | 88/240 [00:20<00:34, 4.35it/s]
37%|███▋ | 89/240 [00:20<00:34, 4.32it/s]
38%|███▊ | 90/240 [00:20<00:34, 4.33it/s]
38%|███▊ | 91/240 [00:20<00:34, 4.32it/s]
38%|███▊ | 92/240 [00:21<00:34, 4.34it/s]
39%|███▉ | 93/240 [00:21<00:34, 4.31it/s]
39%|███▉ | 94/240 [00:21<00:33, 4.31it/s]
40%|███▉ | 95/240 [00:21<00:34, 4.22it/s]
40%|████ | 96/240 [00:22<00:38, 3.78it/s]
40%|████ | 97/240 [00:22<00:41, 3.48it/s]
41%|████ | 98/240 [00:22<00:39, 3.63it/s]
41%|████▏ | 99/240 [00:23<00:37, 3.81it/s]
42%|████▏ | 100/240 [00:23<00:35, 3.93it/s]
42%|████▏ | 101/240 [00:23<00:34, 4.05it/s]
42%|████▎ | 102/240 [00:23<00:33, 4.08it/s]
43%|████▎ | 103/240 [00:26<02:14, 1.02it/s]
43%|████▎ | 104/240 [00:26<01:43, 1.32it/s]
44%|████▍ | 105/240 [00:26<01:21, 1.66it/s]
44%|████▍ | 106/240 [00:27<01:06, 2.02it/s]
45%|████▍ | 107/240 [00:27<00:55, 2.39it/s]
45%|████▌ | 108/240 [00:27<00:48, 2.74it/s]
45%|████▌ | 109/240 [00:27<00:42, 3.09it/s]
46%|████▌ | 110/240 [00:28<00:38, 3.36it/s]
46%|████▋ | 111/240 [00:28<00:35, 3.59it/s]
47%|████▋ | 112/240 [00:28<00:33, 3.77it/s]
47%|████▋ | 113/240 [00:28<00:32, 3.95it/s]
48%|████▊ | 114/240 [00:29<00:31, 3.98it/s]
48%|████▊ | 115/240 [00:29<00:30, 4.05it/s]
48%|████▊ | 116/240 [00:29<00:30, 4.06it/s]
49%|████▉ | 117/240 [00:29<00:29, 4.13it/s]
49%|████▉ | 118/240 [00:29<00:29, 4.19it/s]
50%|████▉ | 119/240 [00:30<00:28, 4.19it/s]
50%|█████ | 120/240 [00:30<00:28, 4.24it/s]
50%|█████ | 121/240 [00:30<00:28, 4.24it/s]
51%|█████ | 122/240 [00:30<00:27, 4.26it/s]
51%|█████▏ | 123/240 [00:31<00:27, 4.30it/s]
52%|█████▏ | 124/240 [00:31<00:26, 4.33it/s]
52%|█████▏ | 125/240 [00:31<00:26, 4.37it/s]
52%|█████▎ | 126/240 [00:31<00:26, 4.34it/s]
53%|█████▎ | 127/240 [00:32<00:25, 4.35it/s]
53%|█████▎ | 128/240 [00:32<00:25, 4.31it/s]
54%|█████▍ | 129/240 [00:32<00:25, 4.32it/s]
54%|█████▍ | 130/240 [00:32<00:25, 4.34it/s]
55%|█████▍ | 131/240 [00:32<00:24, 4.36it/s]
55%|█████▌ | 132/240 [00:33<00:24, 4.35it/s]
55%|█████▌ | 133/240 [00:33<00:24, 4.32it/s]
56%|█████▌ | 134/240 [00:33<00:24, 4.32it/s]
56%|█████▋ | 135/240 [00:33<00:24, 4.34it/s]
57%|█████▋ | 136/240 [00:34<00:24, 4.32it/s]
57%|█████▋ | 137/240 [00:34<00:23, 4.34it/s]
57%|█████▊ | 138/240 [00:34<00:23, 4.35it/s]
58%|█████▊ | 139/240 [00:34<00:23, 4.36it/s]
58%|█████▊ | 140/240 [00:35<00:22, 4.38it/s]
59%|█████▉ | 141/240 [00:35<00:22, 4.35it/s]
59%|█████▉ | 142/240 [00:35<00:22, 4.36it/s]
60%|█████▉ | 143/240 [00:35<00:22, 4.35it/s]
60%|██████ | 144/240 [00:35<00:22, 4.25it/s]
60%|██████ | 145/240 [00:36<00:22, 4.16it/s]
61%|██████ | 146/240 [00:36<00:22, 4.14it/s]
61%|██████▏ | 147/240 [00:36<00:22, 4.15it/s]
62%|██████▏ | 148/240 [00:36<00:21, 4.20it/s]
62%|██████▏ | 149/240 [00:37<00:21, 4.22it/s]
62%|██████▎ | 150/240 [00:37<00:21, 4.26it/s]
63%|██████▎ | 151/240 [00:37<00:20, 4.29it/s]
63%|██████▎ | 152/240 [00:37<00:20, 4.30it/s]
64%|██████▍ | 153/240 [00:38<00:20, 4.23it/s]
64%|██████▍ | 154/240 [00:38<00:20, 4.28it/s]
65%|██████▍ | 155/240 [00:38<00:19, 4.29it/s]
65%|██████▌ | 156/240 [00:38<00:19, 4.34it/s]
65%|██████▌ | 157/240 [00:39<00:19, 4.35it/s]
66%|██████▌ | 158/240 [00:39<00:18, 4.34it/s]
66%|██████▋ | 159/240 [00:39<00:18, 4.34it/s]
67%|██████▋ | 160/240 [00:39<00:18, 4.35it/s]
67%|██████▋ | 161/240 [00:39<00:18, 4.39it/s]
68%|██████▊ | 162/240 [00:40<00:17, 4.40it/s]
68%|██████▊ | 163/240 [00:40<00:17, 4.39it/s]
68%|██████▊ | 164/240 [00:40<00:17, 4.40it/s]
69%|██████▉ | 165/240 [00:40<00:17, 4.37it/s]
69%|██████▉ | 166/240 [00:41<00:17, 4.35it/s]
70%|██████▉ | 167/240 [00:41<00:16, 4.34it/s]
70%|███████ | 168/240 [00:41<00:16, 4.37it/s]
70%|███████ | 169/240 [00:41<00:16, 4.40it/s]
71%|███████ | 170/240 [00:42<00:16, 4.35it/s]
71%|███████▏ | 171/240 [00:42<00:15, 4.34it/s]
72%|███████▏ | 172/240 [00:42<00:15, 4.35it/s]
72%|███████▏ | 173/240 [00:42<00:15, 4.36it/s]
72%|███████▎ | 174/240 [00:42<00:15, 4.22it/s]
73%|███████▎ | 175/240 [00:43<00:15, 4.26it/s]
73%|███████▎ | 176/240 [00:43<00:14, 4.29it/s]
74%|███████▍ | 177/240 [00:43<00:14, 4.34it/s]
74%|███████▍ | 178/240 [00:43<00:14, 4.33it/s]
75%|███████▍ | 179/240 [00:44<00:14, 4.30it/s]
75%|███████▌ | 180/240 [00:44<00:13, 4.32it/s]
75%|███████▌ | 181/240 [00:44<00:13, 4.33it/s]
76%|███████▌ | 182/240 [00:44<00:13, 4.35it/s]
76%|███████▋ | 183/240 [00:45<00:13, 4.37it/s]
77%|███████▋ | 184/240 [00:45<00:12, 4.36it/s]
77%|███████▋ | 185/240 [00:45<00:12, 4.37it/s]
78%|███████▊ | 186/240 [00:45<00:12, 4.38it/s]
78%|███████▊ | 187/240 [00:45<00:12, 4.38it/s]
78%|███████▊ | 188/240 [00:46<00:11, 4.36it/s]
79%|███████▉ | 189/240 [00:46<00:11, 4.30it/s]
79%|███████▉ | 190/240 [00:46<00:11, 4.31it/s]
80%|███████▉ | 191/240 [00:46<00:11, 4.34it/s]
80%|████████ | 192/240 [00:47<00:11, 4.34it/s]
80%|████████ | 193/240 [00:47<00:10, 4.33it/s]
81%|████████ | 194/240 [00:47<00:10, 4.34it/s]
81%|████████▏ | 195/240 [00:47<00:10, 4.34it/s]
82%|████████▏ | 196/240 [00:48<00:10, 4.34it/s]
82%|████████▏ | 197/240 [00:48<00:09, 4.30it/s]
82%|████████▎ | 198/240 [00:48<00:09, 4.23it/s]
83%|████████▎ | 199/240 [00:48<00:09, 4.19it/s]
83%|████████▎ | 200/240 [00:48<00:09, 4.21it/s]
84%|████████▍ | 201/240 [00:49<00:09, 4.24it/s]
84%|████████▍ | 202/240 [00:49<00:08, 4.27it/s]
85%|████████▍ | 203/240 [00:49<00:08, 4.28it/s]
85%|████████▌ | 204/240 [00:49<00:08, 4.23it/s]
85%|████████▌ | 205/240 [00:50<00:08, 4.24it/s]
86%|████████▌ | 206/240 [00:50<00:08, 4.23it/s]
86%|████████▋ | 207/240 [00:50<00:07, 4.28it/s]
87%|████████▋ | 208/240 [00:50<00:07, 4.31it/s]
87%|████████▋ | 209/240 [00:51<00:07, 4.31it/s]
88%|████████▊ | 210/240 [00:51<00:06, 4.33it/s]
88%|████████▊ | 211/240 [00:51<00:06, 4.35it/s]
88%|████████▊ | 212/240 [00:51<00:06, 4.37it/s]
89%|████████▉ | 213/240 [00:51<00:06, 4.37it/s]
89%|████████▉ | 214/240 [00:52<00:05, 4.34it/s]
90%|████████▉ | 215/240 [00:55<00:25, 1.04s/it]
90%|█████████ | 216/240 [00:55<00:19, 1.26it/s]
90%|█████████ | 217/240 [00:55<00:14, 1.59it/s]
91%|█████████ | 218/240 [00:55<00:11, 1.96it/s]
91%|█████████▏| 219/240 [00:56<00:08, 2.33it/s]
92%|█████████▏| 220/240 [00:56<00:07, 2.69it/s]
92%|█████████▏| 221/240 [00:56<00:06, 3.04it/s]
92%|█████████▎| 222/240 [00:56<00:05, 3.34it/s]
93%|█████████▎| 223/240 [00:57<00:04, 3.59it/s]
93%|█████████▎| 224/240 [00:57<00:04, 3.75it/s]
94%|█████████▍| 225/240 [00:57<00:03, 3.92it/s]
94%|█████████▍| 226/240 [00:57<00:03, 4.04it/s]
95%|█████████▍| 227/240 [00:57<00:03, 4.11it/s]
95%|█████████▌| 228/240 [00:58<00:02, 4.15it/s]
95%|█████████▌| 229/240 [00:58<00:02, 4.20it/s]
96%|█████████▌| 230/240 [00:58<00:02, 4.22it/s]
96%|█████████▋| 231/240 [00:58<00:02, 4.28it/s]
97%|█████████▋| 232/240 [00:59<00:01, 4.30it/s]
97%|█████████▋| 233/240 [00:59<00:01, 4.33it/s]
98%|█████████▊| 234/240 [00:59<00:01, 4.39it/s]
98%|█████████▊| 235/240 [00:59<00:01, 4.41it/s]
98%|█████████▊| 236/240 [01:00<00:00, 4.37it/s]
99%|█████████▉| 237/240 [01:00<00:00, 4.39it/s]
99%|█████████▉| 238/240 [01:00<00:00, 4.37it/s]
100%|█████████▉| 239/240 [01:00<00:00, 4.34it/s]
100%|██████████| 240/240 [01:00<00:00, 4.35it/s]
100%|██████████| 240/240 [01:00<00:00, 3.94it/s]
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.167515 0.157977 0.178539 -1.189251 -1.286882 -1.088971 1.181914 1.049833 1.313146
1 0.183722 0.172976 0.195906 -1.072349 -1.158776 -0.983756 1.181914 1.049833 1.313146
2 0.142630 0.135141 0.152021 -1.421745 -1.542036 -1.297560 1.181914 1.049833 1.313146
3 0.160822 0.151748 0.171163 -1.102525 -1.196037 -1.006631 1.181914 1.049833 1.313146
4 0.139444 0.131443 0.149657 -1.427078 -1.550104 -1.300481 1.181914 1.049833 1.313146
... ... ... ... ... ... ... ... ... ...
6763 0.172081 0.163140 0.183298 -1.140513 -1.234750 -1.043042 1.181914 1.049833 1.313146
6764 0.164130 0.154941 0.175101 -1.151497 -1.248836 -1.052276 1.181914 1.049833 1.313146
6765 0.149016 0.141000 0.158921 -1.172342 -1.271547 -1.069987 1.181914 1.049833 1.313146
6766 0.134394 0.126414 0.144618 -1.413400 -1.535721 -1.286135 1.181914 1.049833 1.313146
6767 0.176372 0.166627 0.188252 -1.134603 -1.229517 -1.038149 1.181914 1.049833 1.313146
[6768 rows x 9 columns]
Total running time of the script: (1 minutes 41.239 seconds)