TOML configuration examples¶
All scripts in MultiModX are configured using TOML configuration files.
The data available on Zenodo (see Input Files) contains some examples, here a description of the different elements of the configuration files is provided for:
- Strategic pipeline
- Policy package definition
- Heuristics computation
- Pre-tactical pipeline
- For Performance Indicators, the information is directly in the description of the scripts.
1. Strategic Pipeline¶
Strategic pipeline TOML description (strategic_pipeline.toml)
########################################################################################
# Example of toml config file used to define experiment to run with strategic pipeline #
########################################################################################
# python strategic_pipeline.py -tf ../toml_examples/strategic_pipeline.toml -ni 50 -np 100 -mc 2 -hpc -pc 10
# -eo _sp -lf ./strategic_pipeline.log -v -ppv 0
# ni number of itineraries
# np number of paths
# mc max number of connections
# pc number of process
# eo ending to add
# ppv processed version
# For each category an explanation is given followed by an example
# Input files format documented in files documentation
# General path information to experiments to run
[general]
experiment_path = "../../data/CS11/v=0.25/" # path to the experiment
output_folder = "output/processed_cs11" # path to the output folder where resulst will be stored.
# This folder will be inside the experiment_path
# Can provide policy packages to apply. See policy_package.toml example
[policy_package]
policy_package = 'policies/PP00.toml'
# Demand is provided as a list of demands with the logit model to use for each demand
# it can be one or several demand, but all as list [[]]
[[demand]]
# Path to demand file (csv)
demand = "demand/demand_1arch_regions.csv"
# Within this demand the information on the logit to use (sensitivities)
[demand.sensitivities_logit]
logit_id = "international" # id of logit model. Can be anything, but distinct to others. Used as key internally.
# if another demand uses same logit_id then this one will be replaced by the last
# definition.
sensitivities = "../../../libs/logit_model/international_spain_1_archetype/v=0.1" # By default this is a path within
# experiment_path with the sensitivity
# files for the logit model
# (archetype_#.pickle). However,
# the repository provides three calibrated
# sensitivies already. These are located
# within libs/logit_model folder:
# - intra_spain_6_archetypes/v=0.5 --> Sensitivities of 6
# archetypes used in
# MultiModX deliverables
# for intra-Spain mobility
# - intra_spain_1_archetype/v=0.1 --> Sensitivitis of 1 single
# archetype for all the
# intra-Spain mobility
# demand
# - international_spain_1_archetype/v=0.1 --> Sensitivities of 1
# single archetype for
# international demand
# starting-ending in Spain
compress_archetypes = true # This is an optional parameter. If not provided it will be considered as false.
# If true, then all the demand per (date, origin, destination) is aggregated and
# grouped into a single archetype (archetype_0). This allows to 'compress' demand which
# originally could have been defined as a collection of archetypes.
n_archetypes = 1 # This is an optional parameter (see example below where not provided).
# If not provided number of archetypes directly taken from the sensitiviy files names
[[demand]]
# Example of another demand
demand = "demand/demand_ES_MD_intra_v0.4.csv"
[demand.sensitivities_logit]
# In this sensitivities_logit example the n_archetypes are not provided. They'll be automatically taken from
# the sensitivity_logit archetype_#.pickle files names
logit_id = "spanish"
sensitivities = "logit/sensitivities_v0.5" # Here a different logit model sensitivities located in a folder
# called logit/sensitivities_v0.5 within the experiment_path is
# used. See sensitivities defined in the previous example
# (international), for information on the sensitivities already
# available within the libs/logit_model folder.
# This section defines the mobility network (there is only one composed of several layers), which is composed of:
# - n air networks (based on flight schedules)
# - m rail networks (based on rail timetables)
# - p processing times (processing time (e.g. k2g, k2p, g2k, mct) for pax in infrastructure nodes)
# - q transition layers between mobility networks
# - r regions access with access and egress times to infrastructure nodes
[network_definition]
# List of air networks (usually one but could be several)
[[network_definition.air_network]]
flight_schedules = "flights_schedules/flight_schedules_oag_es_v0.3.csv" # Path to flight schedules (csv)
alliances = "flights_schedules/air_alliances_v0.1.csv" # Path to file defining alliances to enable
# connections (csv)
airports_static = "infrastructure/airports_info/airports_coordinates_v1.1.csv" # Path to file with airports
# coordinates (csv)
mct_air = "infrastructure/mct/mct_air_v0.2.csv" # Path to file with MCT between flight at airports (csv)
mct_default = 30 # Default MCT in minutes to be used if airport/connection not in mct_air
n_seats_default = 180 # Default number of seats to be used if seats not provided in flight_schedules
# List of all rail networks (usually one but could be several) (Current version only allows one throught
# adding more layers is in future features to be developed (see preprocess_input in strategic_evaluator.py
# but still need to be defined as [[]]).
[[network_definition.rail_network]]
gtfs = "gtfs_es_UIC_v2.3" # Path to folder with GTFS rail timetable insde (GTFS formats)
date_rail = "20230920" # Date to use to filter GTFS
date_to_set_rail = "20190906" # Date from flights to make rail and flights 'compatible'.
# The train timetable will be 'shifted' to this date so that trains and flights
# operate on the same day enabling multimodal connections.
rail_stations_considered = "infrastructure/rail_info/rail_stations_considered_GTFS_2022v0.1.csv" # Path to file
# with id of
# rail stations
# to be used
# from the
# GTFS to
# reduce the
# services
# considered
mct_rail = "infrastructure/mct/mct_rail_v0.1.csv" # Minimum connecting time between trains at rail stations
mct_default = 15 # Default minimum connecting time between trains if rail station not in mct_rail
create_rail_layer_from = 'services' # If pre_processed_version > 0, then instead of using GTFS the train
# timetables can be taken from the processed folder (output_folder)
# and using as input directly the rail_timetable_proc_#.csv as input
# this allows to providde timetables already prepared/processed.
# If pre_processed_version=0 (first time), then the
# rail_timetable_proc_0.csv will be created from the GTFS regardless of this
# parameter
country = "LE" # Country of the rail timetable. Future work to identify this directly. Needed to estimate things
# like emissions which are country dependent for rail (see compute_cost_emissions_rail in
# strategic_evaluator.py
n_seats_default = 295 # Number of seats to be used for all trains. Note in this version there's no other option
# to specify the seats in the trains
# List of processing times defined. It can be a list if the processing times are defined in different folders/files
[[network_definition.processing_time]]
airport_processes = "infrastructure/pax_processes/airport_processes_v0.1.csv" # Path to csv file with airport
# processing time (k2g, g2k)
iata_icao_static = "infrastructure/airports_info/IATA_ICAO_Airport_codes_v1.3.csv" # Path to csv file with
# convertion ICAO/IATA codes
rail_stations_processes = "infrastructure/pax_processes/rail_stations_processes_v0.1.csv" # Path to csv file
# with rail station
# processing time
# (k2p, p2k)
default_process_time_k2g = 90 # Default k2g in minutes if none provided in airport_processes for the airport
default_process_time_g2k = 30 # Default g2k in minutes if none provided in airport_processes for the airport
default_process_time_k2p = 15 # Default k2p in minutes if none provided in the rail_station_processes
default_process_time_p2k = 10 # Default p2k in minutes if none provided in the rail_station_processes
# List of multimodal transition times between layers.
# Note that this is not necessarily multimodal, it could allow transfer between nodes in the same layer, e.g.
# between two rail stations (or airports) within the same city.
[[network_definition.multimodal]]
air_rail_transitions = "infrastructure/infrastructure_transitions/infrastructure_transitions_v0.1.csv" # Path to
# file
# List of regions access files enabling the transition between regions (as defined in the demand) and the
# infrastructure nodes (airports or rail stations). Note that the initial point in the demand could be an airport
# or a rail station; in that case, this would not be needed.
[[network_definition.regions_access]]
regions_access = "infrastructure/regions_access/regions_access_v0.5.csv" # Path to csv file with access and
# egress time between regions and
# infrastructure nodes
iata_icao_static = "infrastructure/airports_info/IATA_ICAO_Airport_codes_v1.3.csv" # Path to csv file with
# convertion ICAO/IATA codes
# Other paramters to control how the computation of paths, itinearies, passenger assigment is performed by the
# strategic_evaluator
[other_param]
# You can provide heuristics precomputed. These heuristics are for air and rail time between distances and are
# used by the A* algorithm when looking for possible itineraries and paths. If not provided then the A* won't use
# the heuristic and perform like a uniform cost search (UCS). The scrip compute_air_rail_heuristics.py can be used
# to generate these heuristcis
[other_param.heuristics_precomputed]
heuristics_precomputed_air = "heuristics/air_time_heuristics_v0.1.csv" # within experiment_path
heuristics_precomputed_rail = "heuristics/rail_time_heuristics_v0.1.csv" # within experiment_path
# Can define, or not kpis_to_use for the clustering of itineraries.
# Then, thresholds can be provided. if category doesn't exit (e.g. no rail, or no some kpi for some category),
# the values from 'all' will be taken (if given) if nothing is provided, the threshold will be computed as the
# std of the kpi for the category being clustered
[other_param.kpi_cluster_itineraries]
kpis_to_use = ['total_travel_time', 'total_cost', 'total_emissions', 'total_waiting_time', 'nservices']
[other_param.kpi_cluster_itineraries.thresholds.all]
total_cost = 30
total_travel_time = 50
total_emissions = 15
total_waiting_time = 30
nservices = 0
[other_param.kpi_cluster_itineraries.thresholds.air]
total_emissions = 20
# These are thresholds whe comparing different clusters to decide if a cluster Pareto dominates another, it will
# need to be 'better' on all these categories by at least these thresholds
[other_param.thresholds_pareto_dominance]
total_travel_time = 15
total_cost = 10
total_emissions = 5
total_waiting_time = 30
# Parameters for the passenger assigner
[other_param.pax_assigner]
fillers_in_not_used_flights = 1 # For flights in the schedule but without any pax from the pax itineraries flow
# to fill them with fillers. Otherwise, these flights will be empty.
train_seats_per_segment = 'segment' # How to consider capacity in the trains:
# - 'segment' each train segment is treated independently (A-B, A-C, B-D,
# etc), as in real trains.
# - 'combined', but then if a pax uses x_1_2 and another x_3_5 the seats
# are "shared" for the whole train 1_5...
type_of_optimisation = 'lexicographic' # Type of optimisation lexicographic (can select solver)
# or max_assinged_only (will be with Gurobi)
# Parameters for pax assigner if max_assiged_only is used as type_of_optimisation
[other_param.pax_assigner.max_assinged_only]
problem_file = 'problem' # Save the Gurobi LP problem in a file (name of the file)
compute_leg2_plus_first = 1 # Either 1 or 0 to select if doing 2+ legs assigment first
# Parameters for pax assigner if lexicographic is used as type_of_optimisation
[other_param.pax_assigner.lexicographic]
solver = 'gurobi' # Could be any solver installed in your computer (e.g. gurobi or scip). This will be
# given to SolverFactory from pyomo.
nprocs = 23 # Number of processes to be used for parallel computing
# List of objectives to be used and if they are minimization of maximization and in order for lexicographic.
# Possible objectives are:
# - total_pax_connecting --> put as many pax with connections as possible
# - total_pax --> put as many pax in general as possible
# - minimize_load_factor_diff --> minimise load factor difference between flights
# - minimize_underutilization --> penalise underutilisation of services
# - total_pax_combined_utilisation --> combined objective of maximise pax while minimise load factors
# imbalance
objectives = [['total_pax_connecting','maximize'],
['total_pax', 'maximize']]
#['total_pax_combined_utilisation', 'maximize']]
# Thresholds to be used for lexigraphic optimisation --> how much degrade a given objective to improve
# the next one. Defined per objective.
[other_param.pax_assigner.lexicographic.thresholds]
[other_param.pax_assigner.lexicographic.thresholds.total_pax_connecting]
type = 'relative'
value = 0.05
# Define target load factors for services
[other_param.pax_assigner.target_load_factor]
# This first one to be used as default, then can be defined for flgihts and rail below (or not)
type = 'triangular' # triangular | fix. If something else then flights will be at full capacity
param = [0.75,0.95,1] # Parameters for triangular or fixed value
[other_param.pax_assigner.target_load_factor.flight]
type = 'triangular' # triangular | fix. If something else then flights will be at full capacity
param = [0.75,0.95,1]
[other_param.pax_assigner.target_load_factor.rail]
type = 'fix' # triangular | fix. If something else then flights will be at full capacity
param = 1
# Define target minimum load factors for services (as target). These will be used to generate filler pax if
# needed.
[other_param.pax_assigner.minimum_load_factor]
type = 'triangular' # triangular | fix. If something else then flights will be at full capacity
param = [0.35,0.8,0.8]
[other_param.pax_assigner.minimum_load_factor.flight]
type = 'triangular' # triangular | fix. If something else then flights will be at full capacity
param = [0.35,0.8,0.8]
[other_param.pax_assigner.minimum_load_factor.rail]
type = 'triangular' # triangular | fix. If something else then flights will be at full capacity
param = [0.35,0.8,0.8]
# Parameteres needed to generate tactical_input (Mercury input)
[other_param.tactical_input]
# Information on aircraft data needed to generate Mercury schedules on aircraft (IATA/ICAO codes, MTOW, WTC).
[other_param.tactical_input.aircraft]
ac_type_icao_iata_conversion = "ac_airline_info/ac_type_icao_iata_v0.1.csv"
ac_mtow = "ac_airline_info/mtow_v0.1.csv"
ac_wtc = "ac_airline_info/wtc_v0.1.csv"
# Information on airlines (airlines types and IATA/ICAO codes to generate schedules
[other_param.tactical_input.airlines]
airline_ao_type = "ac_airline_info/airline_icao_ao_type_v1.1.csv"
airline_iata_icao = "ac_airline_info/iata_icao_airlines_codes_v1.1.csv"
2. Policy Package¶
Policy package TOML description (policy_package.toml)
# TOML defining policy package
# Only sections which are to be applied need to be defined. For example, if there is no flight ban, then that
# section should just be removed.
# Flight ban policy definition
# The strategic evaluator will ban/remove the flights which fall within this definition
[flight_ban]
ban_type = 'time' #time or distance
ban_length = 180 #number in minutes or km
distance_rail_serves_airport = 30 # km to consider that if a rail station is closer than that then it's same as
# airport (if nothing provided 30 used)
# Emission taxes policies applied to cost of tickets, i.e., extra cost to flights/rail based on CO2
[tax_charges]
[tax_charges.air]
co2_cost = 0.15 #carbon price EU Emissions Trading System forecast #0.05 #eur per kg -- atmosfair.de
[tax_charges.rail]
co2_cost = 0
# Integrated ticketing policy which adds/reduces time between modes (as MCT).
[integrated_ticketing]
air_air_processing_extra = 0 # Extra time to go between two airports
rail_rail_processing_extra = 0 # Extra time to go between two rail stations
air_rail_processing_extra = 0 # Extra time to go from airport to rail station --> without integrated ticketing
# MCT increased by 15 minutes
rail_air_processing_extra = 0 # Extra time to go from rail station to airport --> without integrated ticketing
# MCT increased by 30 minutes
3. Heuristics Computation¶
Heuristics computation TOML description (heuristics_computation.toml)
# TOML file to configure how to compute the heuristics for the strategic_pipeline with
# script/strategic/compute_air_rail_heuristics.py
# Input files format documented in files documentation
# Parameters for air_heuristic
[air_heuristic]
network_path = "data/es_full_AW/" # Path to network data from air_heuristic computation / schedules
flight_schedules = "flight_schedules_oag_es.csv" # csv with flight schedules to consider
airports_static = "infrastructure/airports_info/aiports_coordinates_v1.1.csv" # csv with airport static information
dist_range = '[(0, 150, None), (150, 2000, 100), (2000, 99999, 500)]' # How to group flights for sampling in
# heuristic (min_dist, max_dist, step)
# Parameters for rail_heuristic
[rail_heuristic]
gtfs_path = "data/es_full_AW/gtfs_es_20220708" # Path to GTFS file
# Rail stations considered either as rail_stations_considered or rail_stations_considered_nuts
# Depending on format input file
#rail_stations_considered = 'data/example_strategic/es/rail_stations_considered.csv'
rail_stations_considered_nuts = 'output/data_analysis/nuts3_ES_filtered.csv'
country = 'ES' # Country of rail to add to rail_stop_id, can be none, i.e. not provide value
date = '20220923' # Date to filter rail
interval_range = 50 # Interval for sampling of heuristic
# Output folder to save results (and plots)
[output]
output_folder = "data/es_full_AW/processed/heuristics_computed/"
4. Pretactical Pipeline¶
Pretactical pipeline TOML description (pretactical_pipeline.toml)
##########################################################################################
# Example of toml config file used to define experiment to run with pretactical pipeline #
##########################################################################################
# For each category an explanation is given followed by an example
# Input files format documented in files documentation
# python ./replanning_passengers_script.py -tf ../data/CS10/v=0.16/replanned_disruptions/DP200/replanning_05.toml -ni 50 -np 100
# -mc 1 -hpc -ppv 0 -pc 23 -eo _output_04
[general]
# General has information on where the experiment is (including the replanning)
experiment_path = "../../data/CS10/v=0.16/" # path to the experiment
replanned_input_folder = "replanned_disruptions/DP200/PP00.DM00.PA05" # path to where the replanning will be
# computed
replanned_actions_folder = "replanned_actions" # Folder inside replanned_input_folder which contains the replanning
# actions. These could be
# - flight_added_schedules_proc_#.csv --> New flights
# - flight_cancelled_#.csv --> Flights to be removed
# - flight_replanned_#.csv --> Flights to be replanned (i.e., new
# schedules, so usually delayed)
# - rail_cancelled_#.csv --> Rail services to be removed
# - rail_timetable_added_all_gtfs_#.csv --> Rail services to be added
# - rail_timetable_replanned_all_gtfs_#.csv --> Rail services to be
# replanned (i.e, usualy delayed)
[planned_network_info]
# Info on where the original planned network is located (i.e., outoput from Strategic Evaluator)
# The files of the planned network are looked for inside, the subfolders defined here, for example:
# path_planned_pax_assigned = Path(toml_config['general']['experiment_path']) /
# toml_config['planned_network_info']['planned_network'] /
# toml_config['planned_network_info']['path_results'] /
# ('pax_assigned_to_itineraries_options_' +
# str(toml_config['planned_network_info']['precomputed']) + '.csv')
planned_network = 'output/processed_cs10.pp00.nd00.so00.00' # Path to original network within experiment_path
path_results = 'paths_itineraries' # Folder inside planned_network where paths_itineraries of oringal network
# are located
path_processed = 'processed' # Folder inside planned_network where the planned network is located
precomputed = 0 # # within processed for the netwokr
[network_definition]
# Info on where the parameters defining the network parameters (inside experiment path)
# See definition in strategic_pipeline.toml file
[[network_definition.air_network]]
airports_static = "infrastructure/airports_info/airports_coordinates_v1.1.csv"
mct_air = "infrastructure/mct/mct_air_v0.2.csv"
mct_default = 30
[[network_definition.rail_network]]
gtfs = "gtfs_es_UIC_v2.3"
date_to_set_rail = "20190906" # Date from flights to make rail and flights 'compatible'
rail_stations_considered = "infrastructure/rail_info/rail_stations_considered_GTFS_2022v0.1.csv"
mct_rail = "infrastructure/mct/mct_rail_v0.1.csv"
mct_default = 15
create_rail_layer_from = 'gtfs' #gtfs / services
[[network_definition.processing_time]]
airport_processes = "infrastructure/pax_processes/airport_processes_v0.1.csv"
iata_icao_static = "infrastructure/airports_info/IATA_ICAO_Airport_codes_v1.3.csv"
rail_stations_processes = "infrastructure/pax_processes/rail_stations_processes_v0.1.csv"
default_process_time_k2g = 90
default_process_time_g2k = 30
default_process_time_k2p = 15
default_process_time_p2k = 10
[[network_definition.multimodal]]
air_rail_transitions = "infrastructure/infrastructure_transitions/infrastructure_transitions_v0.1.csv"
[[network_definition.regions_access]]
regions_access = "infrastructure/regions_access/regions_access_v0.4.csv"
iata_icao_static = "infrastructure/airports_info/IATA_ICAO_Airport_codes_v1.3.csv"
[replanning_considerations]
# This is important for the replanning of operations, it defines how the replanning can be done.
# Therefore, it sets up the flexibility for considering alternatives as valid or not and how to
# assign passengers to those alternatives considering the available seats.
[replanning_considerations.constraints]
# This section defines the constraints that need to be satisfied to consider that an alternative is valid,
# i.e., it defines the flexibility available when finding alternatives for otherwise stranded passengers.
respect_alliances_pax_it_new_it = false # true/false -- respect (or not) new itineraries same alliances as
# in the originally planned pax itineraries
new_itineraries_respect_alliances = true # true/false -- allow new itineraries to use services that among them
# might not be in the same alliance (e.g. RYR-BA)
respect_path = false # keep only the same paths from planned (i.e., same infrastructure nodes (airports and
# rail stations))
respect_modes = false # keep same mode as planned
initial_node_same = false # keep initial node the same (same airport or rail station)
final_node_same = false # keep the final node the same (same airport or rail station)
departure_before_pax_it = true # allow departure (from home (consiering d2i)) before initial pax planned
[replanning_considerations.optimisation]
# This defines the optimisation that is used to assign passengers to the possible alternatives that they could use.
# Note that some sort of optimisation is needed as there are constraints (seats available).
# A lexicographic optimisation is performed.
solver = 'gurobi' # Which solver to use (pyomo is used as library (SolverFactory(solver)))
nprocs = 23 # For parallel computing
# List of objectives to consider in the assigment, they are in the order that they will be optimised.
objectives = [['total_pax', 'maximize'], # Total number of passengers (i.e., minimise stranded pax)
['arrival_door_difference', 'minimize'], # Arrive as close as possible to whenever it was
# originally planned considering i2d phase.
['same_path', 'maximize'], # Try to keep the same path
['same_starting_node', 'maximize'], # Try to start in the same infrastructure node
['same_arrival_node', 'maximize']] # Try to keep the sam arrival node
# Thesholds for the lexicographic optimisation (i.e., by how much allow one objective to be degradated to
# optimise the ones below)
[replanning_considerations.optimisation.thresholds]
[replanning_considerations.optimisation.thresholds.total_pax]
type = 'relative'
value = 0.10
[replanning_considerations.optimisation.thresholds.arrival_door_difference]
type = 'relative'
value = 0.05
[replanning_considerations.optimisation.thresholds.starting_node_different]
type = 'relative'
value = 0.05
[replanning_considerations.optimisation.thresholds.arrival_node_different]
type = 'relative'
value = 0.05
[other_param]
# Other parameters
[other_param.heuristics_precomputed]
# Heuristics for tha path finding algorithm (A*) same as for the Strategic Pipeline
heuristics_precomputed_air = "heuristics/air_time_heuristics_v0.1.csv" # within experiment_path
heuristics_precomputed_rail = "heuristics/rail_time_heuristics_v0.1.csv" # within experiment_path
[other_param.tactical_input]
# Parameters to generate the tactical input at the end of the Pretactical pipeline so that results can be
# used as input for the Tactical Evaluator (if desired)
[other_param.tactical_input.aircraft]
ac_type_icao_iata_conversion = "ac_airline_info/ac_type_icao_iata_v0.1.csv"
ac_mtow = "ac_airline_info/mtow_v0.1.csv"
ac_wtc = "ac_airline_info/wtc_v0.1.csv"
[other_param.tactical_input.airlines]
airline_ao_type = "ac_airline_info/airline_icao_ao_type_v1.1.csv"
airline_iata_icao = "ac_airline_info/iata_icao_airlines_codes_v1.1.csv"