def test_walk_duration(self): node_profile = NodeProfileSimple(walk_to_target_duration=27) self.assertEqual(27, node_profile.get_walk_to_target_duration()) pt1 = LabelTimeSimple(departure_time=5, arrival_time_target=35) self.assertFalse(node_profile.update_pareto_optimal_tuples(pt1)) pt2 = LabelTimeSimple(departure_time=10, arrival_time_target=35) self.assertTrue(node_profile.update_pareto_optimal_tuples(pt2))
def test_pareto_optimality2(self): node_profile = NodeProfileSimple() pt2 = LabelTimeSimple(departure_time=10, arrival_time_target=35) self.assertTrue(node_profile.update_pareto_optimal_tuples(pt2)) pt1 = LabelTimeSimple(departure_time=5, arrival_time_target=35) self.assertFalse(node_profile.update_pareto_optimal_tuples(pt1)) self.assertEquals(len(node_profile.get_final_optimal_labels()), 1)
def test_trip_duration_statistics_simple(self): pairs = [ LabelTimeSimple(1.0, 2.0), LabelTimeSimple(2.0, 4.0), LabelTimeSimple(4.0, 5.0) ] profile = NodeProfileSimple() for pair in pairs: profile.update_pareto_optimal_tuples(pair) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 100) self.assertAlmostEqual(2, analyzer.max_trip_duration()) self.assertAlmostEqual(1, analyzer.min_trip_duration()) self.assertAlmostEqual(4 / 3.0, analyzer.mean_trip_duration()) self.assertAlmostEqual(1, analyzer.median_trip_duration())
def test_earliest_arrival_time(self): node_profile = NodeProfileSimple() self.assertEquals( float("inf"), node_profile.evaluate_earliest_arrival_time_at_target(0, 0)) node_profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=1, arrival_time_target=1)) self.assertEquals( 1, node_profile.evaluate_earliest_arrival_time_at_target(0, 0)) node_profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=3, arrival_time_target=4)) self.assertEquals( 4, node_profile.evaluate_earliest_arrival_time_at_target(2, 0))
def test_temporal_distance_statistics_with_walk(self): pt1 = LabelTimeSimple(departure_time=1, arrival_time_target=2) pt2 = LabelTimeSimple( departure_time=4, arrival_time_target=5) # not taken into account by the analyzer profile = NodeProfileSimple(1.5) assert isinstance(pt1, LabelTimeSimple), type(pt1) profile.update_pareto_optimal_tuples(pt1) profile.update_pareto_optimal_tuples(pt2) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 3) self.assertAlmostEqual( 1.5, analyzer.max_temporal_distance()) # 1 -wait-> 2 -travel->4 self.assertAlmostEqual(1, analyzer.min_temporal_distance()) self.assertAlmostEqual((2.5 * 1.5 + 0.5 * 1.25) / 3., analyzer.mean_temporal_distance()) self.assertAlmostEqual(1.5, analyzer.median_temporal_distance())
def test_last_leg_is_walk(self): event_list_raw_data = [(0, 1, 0, 10, "trip_1", 1)] transit_connections = list( map(lambda el: Connection(*el), event_list_raw_data)) walk_network = networkx.Graph() walk_network.add_edge(1, 2, d_walk=20) walk_speed = 1 source_stop = 0 target_stop = 2 transfer_margin = 0 start_time = 0 end_time = 50 pareto_tuples = list() pareto_tuples.append( LabelTimeSimple(departure_time=0, arrival_time_target=30)) csa_profile = ConnectionScanProfiler(transit_connections, target_stop, start_time, end_time, transfer_margin, walk_network, walk_speed) csa_profile.run() found_tuples = csa_profile.stop_profiles[ source_stop].get_final_optimal_labels() self._assert_pareto_labels_equal(found_tuples, pareto_tuples)
def test_simple(self): event_list_raw_data = [ (2, 4, 40, 50, "trip_5", 1), ] transit_connections = list( map(lambda el: Connection(*el), event_list_raw_data)) walk_network = networkx.Graph() walk_network.add_edge(1, 2, d_walk=20) walk_network.add_edge(3, 4, d_walk=15) walk_speed = 1 source_stop = 1 target_stop = 4 transfer_margin = 0 start_time = 0 end_time = 50 pareto_tuples = list() pareto_tuples.append( LabelTimeSimple(departure_time=20, arrival_time_target=50)) csa_profile = ConnectionScanProfiler(transit_connections, target_stop, start_time, end_time, transfer_margin, walk_network, walk_speed) csa_profile.run() source_stop_profile = csa_profile.stop_profiles[source_stop] source_stop_pareto_tuples = source_stop_profile.get_final_optimal_labels( ) self._assert_pareto_labels_equal(pareto_tuples, source_stop_pareto_tuples)
def get_time_profile_analyzer(self, max_n_boardings=None): """ Parameters ---------- max_n_boardings: int The maximum number of boardings allowed for the labels used to construct the "temporal distance profile" Returns ------- analyzer: NodeProfileAnalyzerTime """ if max_n_boardings is None: max_n_boardings = self.max_trip_n_boardings() # compute only if not yet computed if not max_n_boardings in self._n_boardings_to_simple_time_analyzers: if max_n_boardings == 0: valids = [] else: candidate_labels = [ LabelTimeSimple(label.departure_time, label.arrival_time_target) for label in self._node_profile_final_labels if ((self.start_time_dep <= label.departure_time) and label.n_boardings <= max_n_boardings) ] valids = compute_pareto_front(candidate_labels) valids.sort(key=lambda label: -label.departure_time) profile = NodeProfileSimple(self._walk_to_target_duration) for valid in valids: profile.update_pareto_optimal_tuples(valid) npat = NodeProfileAnalyzerTime.from_profile( profile, self.start_time_dep, self.end_time_dep) self._n_boardings_to_simple_time_analyzers[max_n_boardings] = npat return self._n_boardings_to_simple_time_analyzers[max_n_boardings]
def test_temporal_distance_statistics(self): pairs = [ LabelTimeSimple(1, 2), LabelTimeSimple(2, 4), LabelTimeSimple(4, 5) ] profile = NodeProfileSimple() for pair in pairs: profile.update_pareto_optimal_tuples(pair) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 3) self.assertAlmostEqual( 4 - 1, analyzer.max_temporal_distance()) # 1 -wait-> 2 -travel->4 self.assertAlmostEqual(1, analyzer.min_temporal_distance()) self.assertAlmostEqual((1.5 * 1 + 2.5 * 1 + 2.5 * 1) / 3., analyzer.mean_temporal_distance()) self.assertAlmostEqual(2.25, analyzer.median_temporal_distance())
def test_identity_profile(self): identity_profile = NodeProfileSimple(0) self.assertFalse( identity_profile.update_pareto_optimal_tuples( LabelTimeSimple(10, 10))) self.assertEqual( 10, identity_profile.evaluate_earliest_arrival_time_at_target(10, 0))
def plot_plain_profile(): profile = NodeProfileSimple(walk_to_target_duration=10 * 60) for label in labels_t_dep_dur_b: profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=label[0] * 60, arrival_time_target=(label[0] + label[1]) * 60)) analyzer = NodeProfileAnalyzerTime(profile, 0 * 60, 20 * 60) fig = plt.figure(figsize=(5.5, 3.5)) ax1 = plt.subplot(gs[:, :4]) analyzer.plot_temporal_distance_profile(format_string="%M", plot_journeys=True, lw=3, ax=ax1, plot_tdist_stats=True, alpha=0.15, plot_trip_stats=False, duration_divider=60.0) ax2 = plt.subplot(gs[:, 4:]) # ax2 = plt.subplot2grid(subplot_grid, (0, 4), colspan=2, rowspan=1) fig = analyzer.plot_temporal_distance_pdf_horizontal(use_minutes=True, ax=ax2, legend_font_size=9) ax2.set_ylabel("") ax2.set_yticks([]) ax1.set_ylim(0, 11.5) ax2.set_ylim(0, 11.5) ax2.set_xlim(0, 0.3) ax2.set_yticklabels(["" for _ in ax2.get_yticks()]) ax2.set_xticks([0.1, 0.2, 0.3]) ax1.set_xlabel("Departure time $t_{\\text{dep}}$ (min)") ax1.set_ylabel("Temporal distance $\\tau$ (min)") handles, labels = ax1.get_legend_handles_labels() ax1.legend(handles, labels, loc="best", fancybox=True, ncol=2, shadow=False, prop={'size': 9}) for _ax, letter in zip([ax1, ax2], "AB"): _ax.text(0.04, 0.98, "\\textbf{" + letter + "}", horizontalalignment="left", verticalalignment="top", transform=_ax.transAxes, fontsize=15, color="black") fig.savefig(settings.FIGS_DIRECTORY + "schematic_temporal_distance.pdf")
def test_pareto_optimality(self): node_profile = NodeProfileSimple() pair1 = LabelTimeSimple(departure_time=1, arrival_time_target=2) self.assertTrue(node_profile.update_pareto_optimal_tuples(pair1)) pair2 = LabelTimeSimple(departure_time=2, arrival_time_target=3) self.assertTrue(node_profile.update_pareto_optimal_tuples(pair2)) self.assertEquals(2, len(node_profile._labels)) pair3 = LabelTimeSimple(departure_time=1, arrival_time_target=1) self.assertTrue(node_profile.update_pareto_optimal_tuples(pair3)) self.assertEquals(2, len(node_profile._labels), msg=str(node_profile.get_final_optimal_labels())) pair4 = LabelTimeSimple(departure_time=1, arrival_time_target=2) self.assertFalse(node_profile.update_pareto_optimal_tuples(pair4))
def _scan_footpaths_to_departure_stop(self, connection_dep_stop, connection_dep_time, arrival_time_target): """ A helper method for scanning the footpaths. Updates self._stop_profiles accordingly""" for _, neighbor, data in self._walk_network.edges_iter( nbunch=[connection_dep_stop], data=True): d_walk = data['d_walk'] neighbor_dep_time = connection_dep_time - d_walk / self._walk_speed pt = LabelTimeSimple(departure_time=neighbor_dep_time, arrival_time_target=arrival_time_target) self._stop_profiles[neighbor].update_pareto_optimal_tuples(pt)
def _run(self): # if source node in s1: previous_departure_time = float("inf") connections = self._connections # list[Connection] n_connections = len(connections) for i, connection in enumerate(connections): # basic checking + printing progress: if self._verbose and i % 1000 == 0: print(i, "/", n_connections) assert (isinstance(connection, Connection)) assert (connection.departure_time <= previous_departure_time) previous_departure_time = connection.departure_time # get all different "accessible" / arrival times (Pareto-optimal sets) arrival_profile = self._stop_profiles[ connection.arrival_stop] # NodeProfileSimple # Three possibilities: # 1. earliest arrival time (Profiles) via transfer earliest_arrival_time_via_transfer = arrival_profile.evaluate_earliest_arrival_time_at_target( connection.arrival_time, self._transfer_margin) # 2. earliest arrival time within same trip (equals float('inf') if not reachable) earliest_arrival_time_via_same_trip = self.__trip_min_arrival_time[ connection.trip_id] # then, take the minimum (or the Pareto-optimal set) of these three alternatives. min_arrival_time = min(earliest_arrival_time_via_same_trip, earliest_arrival_time_via_transfer) # If there are no 'labels' to progress, nothing needs to be done. if min_arrival_time == float("inf"): continue # Update information for the trip if earliest_arrival_time_via_same_trip > min_arrival_time: self.__trip_min_arrival_time[ connection.trip_id] = earliest_arrival_time_via_transfer # Compute the new "best" pareto_tuple possible (later: merge the sets of pareto-optimal labels) pareto_tuple = LabelTimeSimple(connection.departure_time, min_arrival_time) # update departure stop profile (later: with the sets of pareto-optimal labels) dep_stop_profile = self._stop_profiles[connection.departure_stop] updated_dep_stop = dep_stop_profile.update_pareto_optimal_tuples( pareto_tuple) # if the departure stop is updated, one also needs to scan the footpaths from the departure stop if updated_dep_stop: self._scan_footpaths_to_departure_stop( connection.departure_stop, connection.departure_time, min_arrival_time)
def test_basics(self): csa_profile = ConnectionScanProfiler(self.transit_connections, self.target_stop, self.start_time, self.end_time, self.transfer_margin, self.walk_network, self.walk_speed) csa_profile.run() stop_3_pareto_tuples = csa_profile.stop_profiles[ 3].get_final_optimal_labels() self.assertEqual(len(stop_3_pareto_tuples), 1) self.assertIn(LabelTimeSimple(32, 35), stop_3_pareto_tuples) stop_2_pareto_tuples = csa_profile.stop_profiles[ 2].get_final_optimal_labels() self.assertEqual(len(stop_2_pareto_tuples), 2) self.assertIn(LabelTimeSimple(40, 50), stop_2_pareto_tuples) self.assertIn(LabelTimeSimple(25, 35), stop_2_pareto_tuples) source_stop_profile = csa_profile.stop_profiles[self.source_stop] source_stop_pareto_optimal_tuples = source_stop_profile.get_final_optimal_labels( ) pareto_tuples = list() pareto_tuples.append( LabelTimeSimple(departure_time=10, arrival_time_target=35)) pareto_tuples.append( LabelTimeSimple(departure_time=20, arrival_time_target=50)) pareto_tuples.append( LabelTimeSimple(departure_time=32, arrival_time_target=55)) self._assert_pareto_labels_equal(pareto_tuples, source_stop_pareto_optimal_tuples)
def test_temporal_distances_no_transit_trips_within_range(self): pairs = [ LabelTimeSimple(departure_time=11, arrival_time_target=12), ] profile = NodeProfileSimple(walk_to_target_duration=5) for pair in pairs: profile.update_pareto_optimal_tuples(pair) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 10) self.assertAlmostEqual(5, analyzer.max_temporal_distance()) self.assertAlmostEqual(2, analyzer.min_temporal_distance()) self.assertAlmostEqual((7 * 5 + 3 * (5 + 2) / 2.) / 10.0, analyzer.mean_temporal_distance()) self.assertAlmostEqual(5, analyzer.median_temporal_distance())
def test_all_plots(self): profile = NodeProfileSimple(25) pt1 = LabelTimeSimple(departure_time=10, arrival_time_target=30) profile.update_pareto_optimal_tuples(pt1) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 10) analyzer.plot_temporal_distance_profile(plot_tdist_stats=True) analyzer.plot_temporal_distance_cdf() analyzer.plot_temporal_distance_pdf() plt.show() profile = NodeProfileSimple() profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=2 * 60, arrival_time_target=11 * 60)) profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=20 * 60, arrival_time_target=25 * 60)) profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=40 * 60, arrival_time_target=45 * 60)) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 60 * 60) analyzer.plot_temporal_distance_profile() analyzer.plot_temporal_distance_cdf() analyzer.plot_temporal_distance_pdf() profile = NodeProfileSimple() profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=2 * 60, arrival_time_target=3 * 60)) profile.update_pareto_optimal_tuples( LabelTimeSimple(departure_time=4 * 60, arrival_time_target=25 * 60)) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 5 * 60) analyzer.plot_temporal_distance_profile() analyzer.plot_temporal_distance_cdf() analyzer.plot_temporal_distance_pdf() pt1 = LabelTimeSimple(departure_time=1, arrival_time_target=2) pt2 = LabelTimeSimple( departure_time=4, arrival_time_target=5) # not taken into account by the analyzer profile = NodeProfileSimple(1.5) profile.update_pareto_optimal_tuples(pt1) profile.update_pareto_optimal_tuples(pt2) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 3) analyzer.plot_temporal_distance_profile() analyzer.plot_temporal_distance_cdf() plt.show()
def test_temporal_distance_statistics_with_walk2(self): pt1 = LabelTimeSimple(departure_time=10, arrival_time_target=30) profile = NodeProfileSimple(25) profile.update_pareto_optimal_tuples(pt1) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 10) # analyzer.plot_temporal_distance_profile() # plt.show() self.assertAlmostEqual( 25, analyzer.max_temporal_distance()) # 1 -wait-> 2 -travel->4 self.assertAlmostEqual(20, analyzer.min_temporal_distance()) self.assertAlmostEqual((7.5 * 25 + 2.5 * 20) / 10.0, analyzer.mean_temporal_distance()) self.assertAlmostEqual(25, analyzer.median_temporal_distance())
def test_time_offset(self): max_distances = [] for offset in [0, 10, 100, 1000]: labels = [ LabelTimeSimple(departure_time=7248 + offset, arrival_time_target=14160 + offset), ] profile = NodeProfileSimple(walk_to_target_duration=float('inf')) for label in labels: profile.update_pareto_optimal_tuples(label) analyzer = NodeProfileAnalyzerTime.from_profile( profile, 0 + offset, 7200 + offset) max_distances.append(analyzer.max_temporal_distance()) max_distances = numpy.array(max_distances) assert ((max_distances == max_distances[0]).all())
def test_temporal_distance_pdf_with_walk(self): profile = NodeProfileSimple(25) pt1 = LabelTimeSimple(10, 30) profile.update_pareto_optimal_tuples(pt1) analyzer = NodeProfileAnalyzerTime.from_profile(profile, 0, 10) self.assertEqual( len(analyzer.profile_block_analyzer._temporal_distance_pdf()), 3) split_points, densities, delta_peaks = analyzer.profile_block_analyzer._temporal_distance_pdf( ) self.assertEqual(len(split_points), 2) self.assertEqual(split_points[0], 20) self.assertEqual(split_points[1], 25) self.assertEqual(len(densities), 1) self.assertEqual(densities[0], 0.1) self.assertIn(25, delta_peaks) self.assertEqual(delta_peaks[25], 0.5)