def test_copy_two_dimensions(self): target = np.zeros(50).reshape(10, 5) source = np.random.rand(50).reshape(10, 5) copy_two_dimensions(target, source, 1) self.assertEqual(target.sum(), source.sum(), 'Copying one dimension returned different values') if target.sum() == 0: self.fail( 'Target and source are the other way around for copying one dimension' )
def execute(self): for c in self.traffic_classes: c.graph.set_graph(self.time_field) logger.info("{} Assignment STATS".format(self.algorithm)) logger.info("Iteration, RelativeGap, stepsize") for self.iter in range(1, self.max_iter + 1): if pyqt: self.equilibration.emit(['rgap', self.rgap]) self.equilibration.emit(['iterations', self.iter]) flows = [] aon_flows = [] for c in self.traffic_classes: aon = allOrNothing(c.matrix, c.graph, c._aon_results) if pyqt: aon.assignment.connect(self.signal_handler) aon.execute() c._aon_results.total_flows() aon_flows.append(c._aon_results.total_link_loads * c.pce) self.aon_total_flow = np.sum(aon_flows, axis=0) if self.iter == 1: for c in self.traffic_classes: copy_two_dimensions(c.results.link_loads, c._aon_results.link_loads, self.cores) c.results.total_flows() copy_one_dimension(c.results.total_link_loads, c._aon_results.total_link_loads, self.cores) if c.results.num_skims > 0: copy_three_dimensions(c.results.skims.matrix_view, c._aon_results.skims.matrix_view, self.cores) flows.append(c.results.total_link_loads * c.pce) else: self.__calculate_step_direction() self.calculate_stepsize() for c in self.traffic_classes: stp_dir = self.step_direction[c.mode] cls_res = c.results linear_combination(cls_res.link_loads, stp_dir.link_loads, cls_res.link_loads, self.stepsize, self.cores) if cls_res.num_skims > 0: linear_combination_skims(cls_res.skims.matrix_view, stp_dir.skims.matrix_view, cls_res.skims.matrix_view, self.stepsize, self.cores) cls_res.total_flows() flows.append(cls_res.total_link_loads * c.pce) self.fw_total_flow = np.sum(flows, axis=0) # Check convergence # This needs ot be done with the current costs, and not the future ones if self.iter > 1: if self.check_convergence(): if self.steps_below >= self.steps_below_needed_to_terminate: break else: self.steps_below += 1 self.vdf.apply_vdf(self.congested_time, self.fw_total_flow, self.capacity, self.free_flow_tt, *self.vdf_parameters) for c in self.traffic_classes: c.graph.cost = self.congested_time if self.time_field in c.graph.skim_fields: idx = c.graph.skim_fields.index(self.time_field) c.graph.skims[:, idx] = self.congested_time[:] c._aon_results.reset() logger.info("{},{},{}".format(self.iter, self.rgap, self.stepsize)) if self.rgap > self.rgap_target: logger.error("Desired RGap of {} was NOT reached".format( self.rgap_target)) logger.info( f"{self.algorithm} Assignment finished. {self.iter} iterations and {self.rgap} final gap" ) if pyqt: self.equilibration.emit(['rgap', self.rgap]) self.equilibration.emit(['iterations', self.iter]) self.equilibration.emit(['finished_threaded_procedure'])
def __calculate_step_direction(self): """Calculates step direction depending on the method""" sd_flows = [] # 2nd iteration is a fw step. if the previous step replaced the aggregated # solution so far, we need to start anew. if ((self.iter == 2) or (self.stepsize == 1.0) or (self.do_fw_step) or (self.algorithm == "frank-wolfe") or (self.algorithm == "msa")): # logger.info("FW step") self.do_fw_step = False self.do_conjugate_step = True self.conjugate_stepsize = 0.0 for c in self.traffic_classes: aon_res = c._aon_results stp_dir_res = self.step_direction[c.mode] copy_two_dimensions(stp_dir_res.link_loads, aon_res.link_loads, self.cores) if c.results.num_skims > 0: copy_three_dimensions(stp_dir_res.skims.matrix_view, aon_res.skims.matrix_view, self.cores) aon_res.total_flows() sd_flows.append(aon_res.total_link_loads * c.pce) # 3rd iteration is cfw. also, if we had to reset direction search we need a cfw step before bfw elif (self.iter == 3) or (self.do_conjugate_step) or (self.algorithm == "cfw"): self.do_conjugate_step = False self.calculate_conjugate_stepsize() # logger.info("CFW step, conjugate stepsize = {}".format(self.conjugate_stepsize)) for c in self.traffic_classes: stp_dr = self.step_direction[c.mode] pre_previous = self.pre_previous_step_direction[c.mode] copy_two_dimensions(pre_previous.link_loads, stp_dr.link_loads, self.cores) if c.results.num_skims > 0: copy_three_dimensions(pre_previous.skims.matrix_view, stp_dr.skims.matrix_view, self.cores) linear_combination(stp_dr.link_loads, stp_dr.link_loads, c._aon_results.link_loads, self.conjugate_stepsize, self.cores) if c.results.num_skims > 0: linear_combination_skims(stp_dr.skims.matrix_view, stp_dr.skims.matrix_view, c._aon_results.skims.matrix_view, self.conjugate_stepsize, self.cores) sd_flows.append(np.sum(stp_dr.link_loads, axis=1) * c.pce) # biconjugate else: self.calculate_biconjugate_direction() # deep copy because we overwrite step_direction but need it on next iteration for c in self.traffic_classes: ppst = self.pre_previous_step_direction[ c.mode] # type: AssignmentResults prev_stp_dir = self.previous_step_direction[ c.mode] # type: AssignmentResults stp_dir = self.step_direction[ c.mode] # type: AssignmentResults copy_two_dimensions(ppst.link_loads, stp_dir.link_loads, self.cores) if c.results.num_skims > 0: copy_three_dimensions(ppst.skims.matrix_view, stp_dir.skims.matrix_view, self.cores) triple_linear_combination(stp_dir.link_loads, c._aon_results.link_loads, stp_dir.link_loads, prev_stp_dir.link_loads, self.betas, self.cores) if c.results.num_skims > 0: triple_linear_combination_skims( stp_dir.skims.matrix_view, c._aon_results.skims.matrix_view, stp_dir.skims.matrix_view, prev_stp_dir.skims.matrix_view, self.betas, self.cores) sd_flows.append(np.sum(stp_dir.link_loads, axis=1) * c.pce) copy_two_dimensions(prev_stp_dir.link_loads, ppst.link_loads, self.cores) if c.results.num_skims > 0: copy_three_dimensions(prev_stp_dir.skims.matrix_view, ppst.skims.matrix_view, self.cores) self.step_direction_flow = np.sum(sd_flows, axis=0)
def execute(self): for c in self.traffic_classes: c.graph.set_graph(self.time_field) logger.info(f"{self.algorithm} Assignment STATS") logger.info("Iteration, RelativeGap, stepsize") for self.iter in range(1, self.max_iter + 1): self.iteration_issue = [] if pyqt: self.equilibration.emit(["rgap", self.rgap]) self.equilibration.emit(["iterations", self.iter]) aon_flows = [] for c in self.traffic_classes: aon = allOrNothing(c.matrix, c.graph, c._aon_results) if pyqt: aon.assignment.connect(self.signal_handler) aon.execute() aon_flows.append(c._aon_results.total_link_loads * c.pce) self.aon_total_flow = np.sum(aon_flows, axis=0) flows = [] if self.iter == 1: for c in self.traffic_classes: copy_two_dimensions(c.results.link_loads, c._aon_results.link_loads, self.cores) copy_one_dimension(c.results.total_link_loads, c._aon_results.total_link_loads, self.cores) if c.results.num_skims > 0: copy_three_dimensions(c.results.skims.matrix_view, c._aon_results.skims.matrix_view, self.cores) flows.append(c.results.total_link_loads * c.pce) else: self.__calculate_step_direction() self.calculate_stepsize() for c in self.traffic_classes: stp_dir = self.step_direction[c.mode] cls_res = c.results linear_combination(cls_res.link_loads, stp_dir.link_loads, cls_res.link_loads, self.stepsize, self.cores) if cls_res.num_skims > 0: linear_combination_skims( cls_res.skims.matrix_view, stp_dir.skims.matrix_view, cls_res.skims.matrix_view, self.stepsize, self.cores, ) cls_res.total_flows() flows.append(cls_res.total_link_loads * c.pce) self.fw_total_flow = np.sum(flows, axis=0) # Check convergence # This needs to be done with the current costs, and not the future ones converged = False if self.iter > 1: converged = self.check_convergence() self.convergence_report["iteration"].append(self.iter) self.convergence_report["rgap"].append(self.rgap) self.convergence_report["warnings"].append("; ".join( self.iteration_issue)) self.convergence_report["alpha"].append(self.stepsize) if self.algorithm == "bfw": self.convergence_report["beta0"].append(self.betas[0]) self.convergence_report["beta1"].append(self.betas[1]) self.convergence_report["beta2"].append(self.betas[2]) logger.info(f"{self.iter},{self.rgap},{self.stepsize}") if converged: if self.steps_below >= self.steps_below_needed_to_terminate: break else: self.steps_below += 1 self.vdf.apply_vdf( self.congested_time, self.fw_total_flow, self.capacity, self.free_flow_tt, *self.vdf_parameters, self.cores, ) for c in self.traffic_classes: aggregate_link_costs(self.congested_time, c.graph.compact_cost, c.results.crosswalk) if self.time_field in c.graph.skim_fields: idx = c.graph.skim_fields.index(self.time_field) c.graph.skims[:, idx] = self.congested_time[:] c._aon_results.reset() if self.rgap > self.rgap_target: logger.error(f"Desired RGap of {self.rgap_target} was NOT reached") logger.info( f"{self.algorithm} Assignment finished. {self.iter} iterations and {self.rgap} final gap" ) if pyqt: self.equilibration.emit(["rgap", self.rgap]) self.equilibration.emit(["iterations", self.iter]) self.equilibration.emit(["finished_threaded_procedure"])
def execute(self): # We build the fixed cost field for c in self.traffic_classes: if c.fixed_cost_field: # divide fixed cost by volume-dependent prefactor (vot) such that we don't have to do it for # each occurence in the objective funtion. TODO: Need to think about cost skims here, we do # not want this there I think c.fixed_cost[c.graph.graph.__supernet_id__] = ( c.graph.graph[c.fixed_cost_field].values[:] * c.fc_multiplier / c.vot) c.fixed_cost[np.isnan(c.fixed_cost)] = 0 # TODO: Review how to eliminate this. It looks unnecessary # Just need to create some arrays for cost for c in self.traffic_classes: c.graph.set_graph(self.time_field) logger.info(f"{self.algorithm} Assignment STATS") logger.info("Iteration, RelativeGap, stepsize") for self.iter in range(1, self.max_iter + 1): self.iteration_issue = [] if pyqt: self.equilibration.emit(["rgap", self.rgap]) self.equilibration.emit(["iterations", self.iter]) aon_flows = [] self.__maybe_create_path_file_directories() for c in self.traffic_classes: # type: TrafficClass # cost = c.fixed_cost / c.vot + self.congested_time # now only once cost = c.fixed_cost + self.congested_time aggregate_link_costs(cost, c.graph.compact_cost, c.results.crosswalk) aon = allOrNothing(c.matrix, c.graph, c._aon_results) if pyqt: aon.assignment.connect(self.signal_handler) aon.execute() c._aon_results.link_loads *= c.pce c._aon_results.total_flows() aon_flows.append(c._aon_results.total_link_loads) self.aon_total_flow = np.sum(aon_flows, axis=0) flows = [] if self.iter == 1: for c in self.traffic_classes: copy_two_dimensions(c.results.link_loads, c._aon_results.link_loads, self.cores) c.results.total_flows() if c.results.num_skims > 0: copy_three_dimensions(c.results.skims.matrix_view, c._aon_results.skims.matrix_view, self.cores) flows.append(c.results.total_link_loads) if self.algorithm == "all-or-nothing": break else: self.__calculate_step_direction() self.calculate_stepsize() for c in self.traffic_classes: stp_dir = self.step_direction[c.__id__] cls_res = c.results linear_combination(cls_res.link_loads, stp_dir.link_loads, cls_res.link_loads, self.stepsize, self.cores) if cls_res.num_skims > 0: linear_combination_skims( cls_res.skims.matrix_view, stp_dir.skims.matrix_view, cls_res.skims.matrix_view, self.stepsize, self.cores, ) cls_res.total_flows() flows.append(cls_res.total_link_loads) self.fw_total_flow = np.sum(flows, axis=0) # Check convergence # This needs to be done with the current costs, and not the future ones converged = self.check_convergence() if self.iter > 1 else False self.vdf.apply_vdf( self.congested_time, self.fw_total_flow, self.capacity, self.free_flow_tt, *self.vdf_parameters, self.cores, ) self.convergence_report["iteration"].append(self.iter) self.convergence_report["rgap"].append(self.rgap) self.convergence_report["warnings"].append("; ".join( self.iteration_issue)) self.convergence_report["alpha"].append(self.stepsize) if self.algorithm in ["cfw", "bfw"]: self.convergence_report["beta0"].append(self.betas[0]) self.convergence_report["beta1"].append(self.betas[1]) self.convergence_report["beta2"].append(self.betas[2]) for c in self.traffic_classes: c._aon_results.reset() if self.time_field not in c.graph.skim_fields: continue idx = c.graph.skim_fields.index(self.time_field) c.graph.skims[:, idx] = self.congested_time[:] logger.info(f"{self.iter},{self.rgap},{self.stepsize}") if converged: self.steps_below += 1 if self.steps_below >= self.steps_below_needed_to_terminate: break else: self.steps_below = 0 for c in self.traffic_classes: c.results.link_loads /= c.pce c.results.total_flows() # TODO (Jan 18/4/21): Do we want to blob store path files (by iteration, class, origin, destination) in sqlite? # or do we just use one big hdf5 file? if (self.rgap > self.rgap_target) and (self.algorithm != "all-or-nothing"): logger.error(f"Desired RGap of {self.rgap_target} was NOT reached") logger.info( f"{self.algorithm} Assignment finished. {self.iter} iterations and {self.rgap} final gap" ) if pyqt: self.equilibration.emit(["rgap", self.rgap]) self.equilibration.emit(["iterations", self.iter]) self.equilibration.emit(["finished_threaded_procedure"])
def execute(self): for c in self.traffic_classes: c.graph.set_graph(self.time_field) logger.info("{} Assignment STATS".format(self.algorithm)) logger.info("Iteration, RelativeGap, stepsize") for self.iter in range(1, self.max_iter + 1): flows = [] aon_flows = [] for c in self.traffic_classes: aon = allOrNothing(c.matrix, c.graph, c._aon_results) aon.execute() c._aon_results.total_flows() aon_flows.append(c._aon_results.total_link_loads * c.pce) self.aon_total_flow = np.sum(aon_flows, axis=0) if self.iter == 1: for c in self.traffic_classes: copy_two_dimensions(c.results.link_loads, c._aon_results.link_loads, self.cores) c.results.total_flows() copy_one_dimension(c.results.total_link_loads, c._aon_results.total_link_loads, self.cores) if c.results.num_skims > 0: copy_three_dimensions(c.results.skims.matrix_view, c._aon_results.skims.matrix_view, self.cores) flows.append(c.results.total_link_loads * c.pce) else: self.__calculate_step_direction() self.calculate_stepsize() for c in self.traffic_classes: stp_dir = self.step_direction[c.mode] cls_res = c.results linear_combination(cls_res.link_loads, stp_dir.link_loads, cls_res.link_loads, self.stepsize, self.cores) # TODO: We need to compute the step direction for skims as well. # It is probably a matter of transforming the step_direction values from numpy arrays to # full AssignmentResults() ones, and cleaning the stuff we don't need if cls_res.num_skims > 0: linear_combination_skims(cls_res.skims.matrix_view, stp_dir.skims.matrix_view, cls_res.skims.matrix_view, self.stepsize, self.cores) cls_res.total_flows() flows.append(cls_res.total_link_loads * c.pce) self.fw_total_flow = np.sum(flows, axis=0) # Check convergence # This needs ot be done with the current costs, and not the future ones if self.iter > 1: if self.check_convergence(): if self.steps_below >= self.steps_below_needed_to_terminate: break else: self.steps_below += 1 self.vdf.apply_vdf( self.congested_time, self.fw_total_flow, self.capacity, self.free_flow_tt, *self.vdf_parameters ) for c in self.traffic_classes: c.graph.cost = self.congested_time c._aon_results.reset() logger.info("{},{},{}".format(self.iter, self.rgap, self.stepsize)) if self.rgap > self.rgap_target: logger.error("Desired RGap of {} was NOT reached".format(self.rgap_target)) logger.info( "{} Assignment finished. {} iterations and {} final gap".format(self.algorithm, self.iter, self.rgap) )