Swiss Federal Railways (SBB) · Rail operator · SIMBA MOBi modeling team
A City-Scale Activity Scheduler That Reproduces the Swiss Microcensus on an Open-Source Stack
A continuous-time MILP framework built with SBB at EPFL, calibrated on 10,110 real microcensus schedules and run end-to-end on a 46,970-schedule synthetic Lausanne population — without a single rule-based patch
Travel-demand forecasting depends on simulating what real people actually do during the day, when they work, when they shop, when they have lunch, not just how many cars are on the road. Most operational models cheat on the temporal layer with rule-based heuristics, and lose all the realism the moment something disruptive happens.
We worked with SBB and EPFL to build a proper optimization model for the time dimension. A mixed-integer program decides each person's full daily schedule jointly, calibrated on real Swiss microcensus data. The result is a city-scale simulation whose activity profiles match the empirical observations without any heuristic patching.
The challenge
Traditional activity-based travel models simulate decisions sequentially, what to do, then when, then where, then how, which makes them blind to trade-offs. Two activities competing for the same hour? Forty thousand people trying to commute and shop at the same time? Sequential models guess; they don't optimize.
SBB needed a framework realistic enough to feed traffic assignment in MATSim, fast enough to simulate full daily schedules for an entire city, and flexible enough to absorb major behavioral shifts like the rise in working from home.
Our approach
We turned the temporal layer into a real optimization problem: each person's start times, durations, and activity sequence are decided jointly by a mixed-integer linear program with utility parameters estimated from data. Non-temporal choices (where, what, how) stay in SBB's existing discrete-choice models, feeding the optimizer as fixed inputs.
We deployed it on the open-source SCIP solver via OR-Tools so the operational pipeline doesn't need a commercial license, and validated against the Swiss microcensus on the full-time-worker subpopulation of Lausanne.
The outcome
Deliverable: a calibrated, validated activity-based scheduling framework that resolves time conflicts in daily schedules through a utility-maximising MILP, built on the open-source SCIP / OR-Tools stack (zero commercial-solver license cost). Published at STRC 2021 in co-authorship with SBB and EPFL, as part of the Innosuisse-funded SBB × EPFL travel-demand modelling collaboration (Project 2155006680).
On a 46,970-schedule synthetic Lausanne population, the simulated activity profiles reproduce every empirical signature of the Swiss microcensus, morning work peak, lunch dip, evening leisure window, multi-tour structure, without a single rule-based patch. The framework calibrates 64 behavioral parameters on 10,110 real microcensus schedules and reaches ρ̄² = 0.165.
Technical deep dive
The model behind the result.
The model
Each individual i has a fixed set of activities A_i to perform within a 24-hour budget ξ. The MILP picks the start time x_a, duration τ_a, travel time tt_a to the next activity, and a binary sequence indicator z_{ab} (= 1 if a is immediately followed by b). The objective is the total schedule utility, a sum of penalties for deviating from desired start times and durations, plus a travel-time disutility.
Schedule utility. Secondary activities are penalized individually; primary and home activities share a duration budget across the day.
Piecewise-linear timing penalty around the desired start time x_a*. Asymmetric, being early can hurt more or less than being late.
Mirror penalty around the desired duration τ_a*. Estimated from microcensus data via maximum likelihood.
Big-M sequence consistency. When z_{ab} = 1, this collapses to the equality x_b = x_a + τ_a + tt_a; otherwise the bounds are inactive.
Time budget fills the 24-hour day exactly. Each activity (except dawn/dusk endpoints) has exactly one predecessor and one successor.
The flexibility parameters β^early, β^late, β^short, β^long are unknown per activity type. We estimate them by maximum likelihood: for every observed schedule in the microcensus, we build a competitive choice set, score every alternative with the utility above, and fit the parameters that make the observed schedule most likely under a logit choice model. The parameters then drop into the same MILP at simulation time.
Benchmark
Estimated flexibility parameters for selected activity clusters (significant at the 5% level).
| Activity / cluster | β^early | β^late | β^short | β^long |
|---|---|---|---|---|
| work : morning start | −0.615 | −0.436 | - | - |
| work : afternoon start | −0.406 | 0 | - | - |
| work : daily duration budget | - | - | −0.022 | 0 |
| leisure : lunch (sub-tour) | −1.610 | −0.821 | −7.550 | −1.360 |
| leisure : evening secondary tour | −0.076 | 0 | −3.060 | −0.692 |
| shopping : in a secondary tour | −0.239 | −0.486 | −5.910 | −0.721 |
| home : after work | −0.073 | −0.596 | - | - |
| home : daily duration budget | - | - | 0 | −0.354 |
Negative numbers are penalties (loss of utility per hour of deviation). Lunch is the most rigid activity, both for being off-time and for missing the desired duration. Morning work has a stiff start time; afternoon work is much more flexible. The home-late penalty (β^late = −0.596) captures the well-documented preference to be home by early evening. Sample size 10,110 cleaned full-time-worker schedules, ρ̄² = 0.165, log-likelihood improved from −57,295.58 to −47,847.37 over 64 parameters.
From the record



Techniques
- Continuous-time activity-based scheduling
- Mixed-integer linear programming via OR-Tools / SCIP
- Maximum-likelihood estimation of utility parameters
- Choice-set generation (likely + random alternatives)
- Coupling MILP optimization with sequential discrete-choice models
Stack
- Python
- OR-Tools
- SCIP
- Biogeme
- Ray (parallel execution)
- MATSim integration
A problem like this?