diff --git a/evaluation/configs/example_rank.yaml b/evaluation/configs/example_rank.yaml index 34f99df1f3f2035dca702858d123476a088ffae6..a4376273ead7b2811a54c94e51d112d8f5a3e730 100644 --- a/evaluation/configs/example_rank.yaml +++ b/evaluation/configs/example_rank.yaml @@ -4,9 +4,9 @@ description: > type: rank charging_stations: charging_stations.json maps: - - oberpfalz-latest.osm + - medium_nurnberg.osm queries_per_rank: 20 -ranks: [2, 4, 6, 8, 10, 12, 14] +ranks: [2, 4, 6, 8, 10, 12, 14, 16] setups: - mu_s: 40 # Start and Target Soc mu_t: 0 diff --git a/evaluation/lib/benchmarks.py b/evaluation/lib/benchmarks.py index 2b999f905e5c4493e6fff23e5454c0d417cd4bb3..c7109df35610751e5088bec28558f8c35f9a5142 100644 --- a/evaluation/lib/benchmarks.py +++ b/evaluation/lib/benchmarks.py @@ -62,7 +62,7 @@ def _run_queries(graph, start_nodes, target_nodes, setup, q, result_dir): result_data = func(graph, setup, s, t) with result_dir.joinpath(file_names[func]).open('a') as f: write_row(f, result_data) - + logger.debug(f'Queries completed.') # Delete cached graphs for key in list(queries.CACHE.keys()): del queries.CACHE[key] @@ -78,6 +78,34 @@ def _get_target_with_rank(graph, start_node, rank): ) +def _get_ranked_tasks(graph, rank, number): + """ + Generate <number> start and target nodes with Dijkstra Rank of <rank>. + + This is done by randomly sampling start nodes and finding for each of + them a target nodes with the according rank by executing a modified + Dijkstra routine. + + """ + target_nodes = [] + start_nodes = [] + attempts = 0 + # Try three times to find a tasks with the required rank. + # If not enough nodes can be found, return what you have. + while len(target_nodes) < number and attempts < 3: + attempts += 1 + for s in random.sample(list(graph.nodes), number): + try: + target_nodes.append(_get_target_with_rank(graph, s, rank)) + except nx.NetworkXNoPath: + continue + start_nodes.append(s) + if len(target_nodes) == number: + break + + return start_nodes, target_nodes + + def query(graphs, charging_stations, conf, result_dir): _init_result_files(result_dir) for map_name, G in zip(conf['maps'], graphs): @@ -112,19 +140,14 @@ def rank(graphs, charging_stations, conf, result_dir): _insert_charging_stations(graph, charging_stations) for r in ranks: - start_nodes = random.sample(list(graph.nodes), queries_per_rank) - logger.debug( - f'Getting {queries_per_rank} target nodes with rank {r}.' - ) + f'Getting {queries_per_rank} target nodes with rank {r}.') + + start = perf_counter() + start_nodes, target_nodes = _get_ranked_tasks(graph, r, queries_per_rank) + end = perf_counter() - start - target_nodes = [] - for s in start_nodes: - try: - target_nodes.append(_get_target_with_rank(graph, s, r)) - except nx.NetworkXNoPath: - start_nodes = start_nodes[:len(target_nodes)] - break + logger.debug(f'Ranked nodes generated in {end:.2f} s') for setup in conf['setups']: _run_queries(graph, start_nodes, target_nodes, diff --git a/evaluation/lib/queries.py b/evaluation/lib/queries.py index 618e1317070b63897969fe5f8a8a637a4ea6c77a..508a4138716e11abb68a9e2b92f81d3a894c0b38 100644 --- a/evaluation/lib/queries.py +++ b/evaluation/lib/queries.py @@ -1,6 +1,5 @@ import logging import gc -from collections import namedtuple from dataclasses import dataclass from time import perf_counter @@ -14,7 +13,11 @@ from evrouting.graph_tools import ( DISTANCE_KEY ) from evrouting.osm.profiles import car -from evrouting.osm.routing import GasstationAccessFunctions, a_start_heuristic +from evrouting.osm.routing import ( + GasstationAccessFunctions, + a_start_heuristic, + get_coordinates +) from evaluation.lib.algorithm import ranked_dijkstra @@ -117,6 +120,11 @@ def no_gc(func): return inner +def _format_node(G, n): + lon, lat = get_coordinates(G, n) + return f"{lon}:{lat}" + + _cache_contraction_graph_key = 'contraction' _cache_state_graph_key = 'state_graph' @@ -202,8 +210,8 @@ def insert_nodes_into_state_graph(graph, conf, s, t): time_target = perf_counter() - start return InsertQueryRow( - start_node=s[0], - target_node=t[0], + start_node=s, + target_node=t, charging_stations=len(graph.charging_stations), time_insert_start=time_insertion, time_insert_target=time_target @@ -251,11 +259,11 @@ def gasstation_query(graph, conf, s, t): @no_gc def charge_query(graph, conf, s, t): - start = perf_counter() if conf['consumption'].get('type', 'distance') == 'time': c = consumption_function_time_factory(conf['consumption']['consumption_coefficient']) else: c = consumption_function_distance_factory(conf['consumption']['consumption_coefficient']) + start = perf_counter() result = charge.shortest_path( G=graph, charging_stations=graph.charging_stations, @@ -269,8 +277,8 @@ def charge_query(graph, conf, s, t): runtime = perf_counter() - start charge_stops = [t for n, t in result.charge_path if t > 0] return ChargeQueryRow( - start_node=s, - target_node=t, + start_node=_format_node(graph, s), + target_node=_format_node(graph, s), query_time=runtime, trip_time=result.trip_time, nodes=len(graph.nodes), @@ -291,8 +299,8 @@ def classic_query(graph, conf, s, t): runtime = perf_counter() - start return ClassicQueryRow( - start_node=s, - target_node=t, + start_node=_format_node(graph, s), + target_node=_format_node(graph, t), query_time=runtime, trip_time=result, nodes=len(graph.nodes),