def _run(self): previous_departure_time = float("inf") n_connections_tot = len(self._all_connections) for i, connection in enumerate(self._all_connections): # basic checking + printing progress: if self._verbose and i % 1000 == 0: print("\r", i, "/", n_connections_tot, " : ", "%.2f" % round(float(i) / n_connections_tot, 3), end='', flush=True) assert (isinstance(connection, Connection)) assert (connection.departure_time <= previous_departure_time) previous_departure_time = connection.departure_time # Get labels from the stop (possibly subject to buffer time) arrival_node_labels = self._get_modified_arrival_node_labels(connection) # This is for the labels staying "in the vehicle" trip_labels = self._get_trip_labels(connection) # Then, compute Pareto-frontier of these alternatives: all_pareto_optimal_labels = merge_pareto_frontiers(arrival_node_labels, trip_labels) # Update labels for this trip if not connection.is_walk: self.__trip_labels[connection.trip_id] = all_pareto_optimal_labels # Update labels for the departure stop profile (later: with the sets of pareto-optimal labels) self._stop_profiles[connection.departure_stop].update(all_pareto_optimal_labels, connection.departure_time) print("finalizing profiles!") self._finalize_profiles()
def test_merge_pareto_frontiers(self): label_a = LabelTimeWithBoardingsCount( departure_time=1, arrival_time_target=2, n_boardings=1, first_leg_is_walk=False) # optimal label_b = LabelTimeWithBoardingsCount( departure_time=1, arrival_time_target=5, n_boardings=0, first_leg_is_walk=False) # d dominates label_c = LabelTimeWithBoardingsCount( departure_time=3, arrival_time_target=4, n_boardings=1, first_leg_is_walk=False) # optimal label_d = LabelTimeWithBoardingsCount( departure_time=4, arrival_time_target=5, n_boardings=0, first_leg_is_walk=False) # optimal front_1 = [label_a, label_b] front_2 = [label_c, label_d] pareto_front = merge_pareto_frontiers(front_1, front_2) self.assertEqual(3, len(pareto_front)) self.assertNotIn(label_b, pareto_front)
def evaluate(self, dep_time, first_leg_can_be_walk=True, connection_arrival_time=None): """ Get the pareto_optimal set of Labels, given a departure time. Parameters ---------- dep_time : float, int time in unix seconds first_leg_can_be_walk : bool, optional whether to allow walking to target to be included into the profile (I.e. whether this function is called when scanning a pseudo-connection: "double" walks are not allowed.) connection_arrival_time: float, int, optional used for computing the walking label if dep_time, i.e., connection.arrival_stop_next_departure_time, is infinity) connection: connection object Returns ------- pareto_optimal_labels : set Set of Labels """ walk_labels = list() # walk label towards target if first_leg_can_be_walk and self._walk_to_target_duration != float( 'inf'): # add walk_label if connection_arrival_time is not None: walk_labels.append( self._get_label_to_target(connection_arrival_time)) else: walk_labels.append(self._get_label_to_target(dep_time)) # if dep time is larger than the largest dep time -> only walk labels are possible if dep_time in self.dep_times_to_index: assert (dep_time != float('inf')) index = self.dep_times_to_index[dep_time] labels = self._label_bags[index] pareto_optimal_labels = merge_pareto_frontiers(labels, walk_labels) else: pareto_optimal_labels = walk_labels if not first_leg_can_be_walk: pareto_optimal_labels = [ label for label in pareto_optimal_labels if not label.first_leg_is_walk ] return pareto_optimal_labels
def update(self, new_labels, departure_time_backup=None): """ Update the profile with the new labels. Each new label should have the same departure_time. Parameters ---------- new_labels: list[LabelTime] Returns ------- added: bool whether new_pareto_tuple was added to the set of pareto-optimal tuples """ if self._closed: raise RuntimeError("Profile is closed, no updates can be made") try: departure_time = next(iter(new_labels)).departure_time except StopIteration: departure_time = departure_time_backup self._check_dep_time_is_valid(departure_time) for new_label in new_labels: assert (new_label.departure_time == departure_time) dep_time_index = self.dep_times_to_index[departure_time] if dep_time_index > 0: # Departure time is modified in order to not pass on labels which are not Pareto-optimal when departure time is ignored. mod_prev_labels = [ label.get_copy_with_specified_departure_time(departure_time) for label in self._label_bags[dep_time_index - 1] ] else: mod_prev_labels = list() mod_prev_labels += self._label_bags[dep_time_index] walk_label = self._get_label_to_target(departure_time) if walk_label: new_labels = new_labels + [walk_label] new_frontier = merge_pareto_frontiers(new_labels, mod_prev_labels) self._label_bags[dep_time_index] = new_frontier return True
def test_merge_pareto_frontiers_empty(self): pareto_front = merge_pareto_frontiers([], []) self.assertEqual(0, len(pareto_front))