diff --git a/tm2py/components/network/highway/highway_assign.py b/tm2py/components/network/highway/highway_assign.py index e2b3909f..ba7f5742 100644 --- a/tm2py/components/network/highway/highway_assign.py +++ b/tm2py/components/network/highway/highway_assign.py @@ -140,13 +140,15 @@ def run(self): else: demand.run() + calculate_reliability = self.config.reliability + for time in self.time_period_names: scenario = self.highway_emmebank.scenario(time) with self._setup(scenario, time): iteration = self.controller.iteration warmstart = self.controller.config.warmstart.warmstart assign_classes = [ - AssignmentClass(c, time, iteration, warmstart) + AssignmentClass(c, time, iteration, calculate_reliability, warmstart) for c in self.config.classes ] if iteration > 0: @@ -156,14 +158,14 @@ def run(self): self._create_skim_matrices(scenario, assign_classes) # calculate highway reliability in global iteration 0 and 1 only # this requires the assignment to be run twice - if iteration <= 1: + if (iteration <= 1) & (calculate_reliability): # set path analysis to False to avoid skimming assign_spec = self._get_assignment_spec( assign_classes, path_analysis=False ) with self.logger.log_start_end( - "Run SOLA assignment with path analyses", level="INFO" + "Run SOLA assignment without path analyses", level="INFO" ): assign = self.controller.emme_manager.tool( "inro.emme.traffic_assignment.sola_traffic_assignment" @@ -202,7 +204,7 @@ def run(self): assign_classes, path_analysis=True ) with self.logger.log_start_end( - "Run SOLA assignment with path analyses and highway reliability", + "Run SOLA assignment with path analyses", level="INFO", ): assign = self.controller.emme_manager.tool( @@ -293,6 +295,14 @@ def _create_skim_matrices( self.logger.debug( f"Create matrix name: {matrix_name}, id: {matrix.id}" ) + # if not skimming reliability, set reliability matrices to 0 + if not self.config.reliability: + if ("rlbty" in matrix_name) | ("autotime" in matrix_name): + data = self._matrix_cache.get_data(matrix_name) + # NOTE: sets values for external zones as well + data = 0 * data + self._matrix_cache.set_data(matrix_name, data) + self._skim_matrices.append(matrix) def _get_assignment_spec( @@ -434,18 +444,22 @@ def _log_debug_report(self, scenario: EmmeScenario, time_period: str): class AssignmentClass: """Highway assignment class, represents data from config and conversion to Emme specs.""" - def __init__(self, class_config, time_period, iteration, warmstart): + def __init__(self, class_config, time_period, iteration, reliability, warmstart): """Constructor of Highway Assignment class. Args: class_config (_type_): _description_ time_period (_type_): _description_ iteration (_type_): _description_ + reliability (bool): include reliability in path analysis or not. + If true, reliability is included in path analysis using link field. + If false, reliability is not included in path analysis, reliability skim is overwritten as 0. warmstart (bool): True if assigning warmstart demand """ self.class_config = class_config self.time_period = time_period self.iteration = iteration + self.skim_reliability = reliability self.warmstart = warmstart self.name = class_config["name"].lower() self.skims = class_config.get("skims", []) @@ -542,7 +556,13 @@ def emme_class_analysis(self) -> List[EmmeHighwayAnalysisSpec]: for skim_type in self.skims: if skim_type == "time": continue - if self.controller.iteration > 1: + # if not skimming reliability in all global iterations + if not self.skim_reliability: + if skim_type in ["rlbty", "autotime"]: + continue + # if skimming reliability + # reliability is only skimmed in global iteration 0 and 1 + if self.iteration > 1: if skim_type == "rlbty": continue if skim_type == "autotime": diff --git a/tm2py/config.py b/tm2py/config.py index fed43e3b..ee9f0273 100644 --- a/tm2py/config.py +++ b/tm2py/config.py @@ -952,6 +952,12 @@ class HighwayConfig(ConfigItem): to the free-flow speed, capacity, and critical speed values interchange_nodes_file: relative path to the interchange nodes file, this is used for calculating highway reliability + reliability: bool to skim highway reliability. Default to true. If true, assignment + will be run twice in global iterations 0 (warmstart) and 1, to calculate reliability, + assignment will be run only once in global iterations 2 and 3, + reliability skim will stay the same as global iteration 1. + If false, reliability will not be calculated nor skimmed in all global + iterations, and the resulting reliability skims will be 0. """ generic_highway_mode_code: str = Field(min_length=1, max_length=1) @@ -967,6 +973,7 @@ class HighwayConfig(ConfigItem): classes: Tuple[HighwayClassConfig, ...] = Field() capclass_lookup: Tuple[HighwayCapClassConfig, ...] = Field() interchange_nodes_file: str = Field() + reliability: bool = Field(default=True) @validator("output_skim_filename_tmpl") def valid_skim_template(value):