Source code for passengersim.connection_builder.prebuild

from __future__ import annotations

from typing import TYPE_CHECKING

from passengersim.config.base import filterable_list
from passengersim.config.paths import Path
from passengersim.driver import Simulation

if TYPE_CHECKING:
    from passengersim.config import Config


[docs] def prebuild_connections(cfg: Config, *, inplace: bool = True, **kwargs) -> Config: """ Prebuild connections on this config. Parameters ---------- cfg : Config The config on which to build connections. inplace : bool Whether to modify the config in place or return a modified copy. Default is True. max_legs : int, optional The maximum number of legs to include in any generated path, which should be between 1 and 6. max_legs_if_nonstop_exists : int The maximum number of legs to include in any generated path if a nonstop path exists in that market. The nonstop path can be on any carrier. existing_paths: {"keep", "replace", "required", "none"} What to do with existing paths when generating new ones. The default value is "keep", which means that for any market where paths already exist they will be used, and no new paths will be generated. For markets where no paths exist, new paths will be generated as normal. Alternatively, set this to "none", which has the same behavior as "keep" but will raise an error if the configuration includes any defined paths. Other options are "replace", which will remove all existing paths and then generating new ones for all markets, and "required", which will prevent the generation of any new paths. If set to "required", the connection builder will only serve as a check that all markets have paths, and will raise an error if any market is missing paths. circuity_function : str The function to use when deciding if a path is allowable due to circuity. Circuity is the ratio of the total distance of the path to the direct distance between the origin and destination. The default function disallows paths that are excessively circuitous, with thresholds that vary based on the direct distance. Users can provide their own function with the same signature to implement custom circuity rules. The circuity function is specified by name here and should be a registered circuity function. See `passengersim.connection_builder.circuity` for more details on circuity functions and how to register custom ones. nonstop_leg_path_id_alignment : bool = True Whether to align path IDs with leg IDs for nonstop paths. By default, this is set to True, which means that any nonstop path (corresponds to a single leg) will be assigned the same ID as that leg by the path building algorithm. This can make it easier to identify and analyze nonstop paths in the simulation results. If set to False, nonstop paths will be assigned unique IDs that do not necessarily align with leg IDs. This generally corresponds to the behavior of the previous path building algorithm, and may be desirable in cases where there are existing results to compare against. verbosity : int The level of detail to include in connection builder logging. min_paths_per_market : int The minimum number of paths to generate for each market. This is not a hard minimum, but the connection builder will make an effort to generate at least this many paths for each market, if possible given the other settings. This could be by progressively relaxing circuity rules, maximum connection times, or other tweaks. If the connection builder is unable to generate at least this many paths for a market, it will log a warning. extra_max_connect_time_per_iteration : int Extra time added to all maximum connection times at each iteration. The connection builder iterates when the `min_paths_per_market` value is not met, potentially relaxing circuity rules at each iteration. This setting also allows for the relaxation of maximum connect times, by adding this many minutes to all maximum connection times at each iteration. Returns ------- Config The config with the newly generated paths appended to ``cfg.paths`` and ``cfg.simulation_controls.connection_builder.existing_paths`` set to ``"required"``. When *inplace* is ``True`` this is the same object as *cfg*; when *inplace* is ``False`` it is a deep copy. Raises ------ ValueError If ``existing_paths="none"`` is requested but the config already contains defined paths, or if ``existing_paths="required"`` is requested but any market is missing paths. """ if not inplace: cfg = cfg.model_copy(deep=True) sim_cfg = cfg.model_copy(deep=len(kwargs) > 0) additional_kwds = {} for key, value in kwargs.items(): if hasattr(sim_cfg.simulation_controls.connection_builder, key): setattr(sim_cfg.simulation_controls.connection_builder, key, value) else: additional_kwds[key] = value sim = Simulation(sim_cfg) _num_paths = sim.eng.build_connections( **sim_cfg.simulation_controls.connection_builder.model_dump(), **additional_kwds ) path_defs = [ Path.model_validate( { "path_id": p.path_id, "path_quality_index": p.path_quality_index, "orig": p.orig, "dest": p.dest, "legs": p.leg_ids, } ) for p in sim.eng.paths ] cfg.paths.extend(path_defs) cfg.simulation_controls.connection_builder.existing_paths = "required" cfg.paths = filterable_list(cfg.paths) # ensure paths are filterable return cfg