diff --git a/evaluation/configs/example_init.yaml b/evaluation/configs/example_init.yaml index c94a53ee548a02450110b239d28eba75205389ba..0f57289431680a6de00172c98ade34cd93060b91 100644 --- a/evaluation/configs/example_init.yaml +++ b/evaluation/configs/example_init.yaml @@ -22,4 +22,37 @@ setups: algorithms: [charge] consumption: type: time - consumption_coefficient: 0.1 # kWh/s \ No newline at end of file + consumption_coefficient: 0.1 # kWh/s + - mu_s: 300 # Start and Target Soc + mu_t: 0 + charging_stations: 4 # Max Number of charging Stations to be inserted. + capacity: 300 # kWh + algorithms: [charge] + consumption: + type: time + consumption_coefficient: 0.1 # kWh/s + - mu_s: 300 # Start and Target Soc + mu_t: 0 + charging_stations: 6 # Max Number of charging Stations to be inserted. + capacity: 300 # kWh + algorithms: [charge] + consumption: + type: time + consumption_coefficient: 0.1 # kWh/s + - mu_s: 300 # Start and Target Soc + mu_t: 0 + charging_stations: 8 # Max Number of charging Stations to be inserted. + capacity: 300 # kWh + algorithms: [charge] + consumption: + type: time + consumption_coefficient: 0.1 # kWh/s + - mu_s: 300 # Start and Target Soc + mu_t: 0 + charging_stations: 10 # Max Number of charging Stations to be inserted. + capacity: 300 # kWh + algorithms: [charge] + consumption: + type: time + consumption_coefficient: 0.1 # kWh/s + diff --git a/evaluation/configs/example_init_query.yaml b/evaluation/configs/example_init_query.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6148a4b752a02008a62f14e2b1d69010f16334d9 --- /dev/null +++ b/evaluation/configs/example_init_query.yaml @@ -0,0 +1,25 @@ +description: > + Compare charge and gasstation problem by assuming for the charge + algorithm also an consumption proportional to driving time. +type: query +charging_stations: charging_stations.json +maps: + - medium_nurnberg.osm +queries_per_setup: 10 +setups: + - mu_s: 300 # Start and Target Soc + mu_t: 0 + charging_stations: 1 # Max Number of charging Stations to be inserted. + capacity: 300 # kWh + algorithms: [charge] + consumption: + type: time + consumption_coefficient: 0.1 # kWh/s + - mu_s: 300 # Start and Target Soc + mu_t: 0 + charging_stations: 2 # Max Number of charging Stations to be inserted. + capacity: 300 # kWh + algorithms: [charge] + consumption: + type: time + consumption_coefficient: 0.1 # kWh/s diff --git a/evaluation/lib/benchmarks.py b/evaluation/lib/benchmarks.py index 910d8ae9e431f2083117984b6e0b46f37ce2f6de..14b4d6a1e346deeccd13f3a0008777b8247f0a8f 100644 --- a/evaluation/lib/benchmarks.py +++ b/evaluation/lib/benchmarks.py @@ -9,10 +9,28 @@ from evrouting.graph_tools import DISTANCE_KEY from evaluation.lib.algorithm import _dijkstra_multisource from evaluation.lib.export import write_head, write_row -from evaluation.lib.queries import query_relations, CACHE +from evaluation.lib import queries logger = logging.getLogger(__name__) +file_names = { + queries.classic_query: 'classic.csv', + queries.astar_query: 'astar.csv', + queries.bidirectional_query: 'bidirectional.csv', + queries.charge_query: 'charge.csv', + queries.gasstation_query: 'gasstation.csv', + queries.init_gasstation_queries: 'init.csv', + queries.insert_nodes_into_state_graph: 'insert.csv' +} + +conf_algorithms = { + 'classic': queries.classic_query, + 'astar': queries.astar_query, + 'bidirectional': queries.bidirectional_query, + 'charge': queries.charge_query, + 'gasstation': queries.gasstation_query +} + def _insert_charging_stations(graph, charging_stations, number=None): start = perf_counter() @@ -25,29 +43,29 @@ def _insert_charging_stations(graph, charging_stations, number=None): )) -def _init_result_files(result_dir, queries=None): - if queries is None: - queries = query_relations.values() +def _init_result_files(result_dir, q=None): + if q is None: + q = conf_algorithms.values() # Remove existing results and write heads - for q in queries: - with result_dir.joinpath(q.filename).open('w') as f: - write_head(f, q.row_class) + for query in q: + with result_dir.joinpath(file_names[query]).open('w') as f: + write_head(f, queries.row_classes[query]) -def _run_queries(graph, start_nodes, target_nodes, setup, queries, result_dir): - for func, filename, _ in queries: +def _run_queries(graph, start_nodes, target_nodes, setup, q, result_dir): + for func in q: logger.info(f'Running {len(start_nodes)} times {func.__name__}') for i, (s, t) in enumerate(zip(start_nodes, target_nodes)): logger.debug(f'{i + 1}/{len(start_nodes)}') result_data = func(graph, setup, s, t) - with result_dir.joinpath(filename).open('a') as f: + with result_dir.joinpath(file_names[func]).open('a') as f: write_row(f, result_data) # Delete cached graphs - for key in list(CACHE.keys()): - del CACHE[key] + for key in list(queries.CACHE.keys()): + del queries.CACHE[key] def _get_target_with_rank(graph, start_node, rank): @@ -77,19 +95,19 @@ def query(graphs, charging_stations, conf, result_dir): algorithms = setup.get('algorithms', [ 'classic', 'astar', 'bidirectional', 'gasstation', 'charge' ]) - queries = [query_relations[key] for key in algorithms] + q = [conf_algorithms[key] for key in algorithms] logger.info(f"Running queries on map {map_name}") - _run_queries(G, start_nodes, target_nodes, setup, queries, result_dir) + _run_queries(G, start_nodes, target_nodes, setup, q, result_dir) def rank(graphs, charging_stations, conf, result_dir): ranks = conf['ranks'] queries_per_rank = conf['queries_per_rank'] algorithms = ['classic', 'charge'] - queries = [query_relations[k] for k in algorithms] + q = [conf_algorithms[k] for k in algorithms] - _init_result_files(result_dir, queries) + _init_result_files(result_dir, q) for graph in graphs: _insert_charging_stations(graph, charging_stations) @@ -111,37 +129,43 @@ def rank(graphs, charging_stations, conf, result_dir): for setup in conf['setups']: _run_queries(graph, start_nodes, target_nodes, - setup, queries, result_dir) + setup, q, result_dir) def init(graphs, charging_stations, conf, result_dir): - queries = [query_relations['charge']] - - _init_result_files(result_dir, queries) + _init_result_files(result_dir, [ + queries.init_gasstation_queries, + queries.insert_nodes_into_state_graph + ]) for map_name, G in zip(conf['maps'], graphs): - nodes = random.sample(list(G.nodes), k=2 * conf['queries_per_setup']) for setup in conf['setups']: - # Random start and target nodes - start_nodes = nodes[:int(len(nodes) / 2)] - target_nodes = nodes[int(len(nodes) / 2):] - # Random adding of charging stations _insert_charging_stations(G, charging_stations, setup['charging_stations']) - logger.info(f"Running queries on map {map_name}") - _run_queries(G, start_nodes, target_nodes, setup, queries, result_dir) + result_data = queries.init_gasstation_queries(G, setup) + filename = file_names[queries.init_gasstation_queries] + with result_dir.joinpath(filename).open('a') as f: + write_row(f, result_data) - # Create state graph etc - func, filename, _ = query_relations['init'] - logger.info(f'Running {len(start_nodes)} times {func.__name__}') - for i, (s, t) in enumerate(zip(start_nodes, target_nodes)): - logger.debug(f'{i + 1}/{len(start_nodes)}') - result_data = func(G, setup, s, t) - with result_dir.joinpath(filename).open('a') as f: - write_row(f, result_data) + # little hacky: get just created state graph from module cache + state_graph, _ = queries.CACHE[queries._cache_state_graph_key] + if len(state_graph.nodes) > 2: + # random start and target nodes of state graph + nodes = random.sample(list(state_graph.nodes), k=2 * conf['queries_per_setup']) + start_nodes = nodes[:int(len(nodes) / 2)] + target_nodes = nodes[int(len(nodes) / 2):] + + _run_queries( + G, + start_nodes, + target_nodes, + setup, + [queries.insert_nodes_into_state_graph], + result_dir + ) # Delete cached graphs - for key in list(CACHE.keys()): - del CACHE[key] + for key in list(queries.CACHE.keys()): + del queries.CACHE[key] diff --git a/evaluation/lib/queries.py b/evaluation/lib/queries.py index a624dcd4c743ad188a01b8c34b15e227e524d5f2..0a7a62ce4d07b6cf48cd1dff0bcd7c09e7364911 100644 --- a/evaluation/lib/queries.py +++ b/evaluation/lib/queries.py @@ -21,15 +21,22 @@ from evaluation.lib.algorithm import ranked_dijkstra @dataclass class InitQueryRow: - start_node: str - target_node: str - query_time: float time_contracted_graph: float time_state_graph: float nodes_state_graph: int edges_state_graph: int nodes_contracted_graph: int edges_contracted_graph: int + charging_stations: int + + +@dataclass +class InsertQueryRow: + start_node: str + target_node: str + charging_stations: int + time_insert_start: float + time_insert_target: float @dataclass @@ -110,7 +117,11 @@ def no_gc(func): return inner -@cached('gasstation') +_cache_contraction_graph_key = 'contraction' +_cache_state_graph_key = 'state_graph' + + +@cached(_cache_contraction_graph_key) def get_contracted_graph(graph, conf, f): start = perf_counter() contracted_graph = gasstation.routing.contract_graph( @@ -127,7 +138,7 @@ def get_contracted_graph(graph, conf, f): return contracted_graph, contraction_time -@cached('state_graph') +@cached(_cache_state_graph_key) def get_state_graph(contracted_graph, conf, f): start = perf_counter() state_graph = gasstation.routing.state_graph( @@ -143,19 +154,19 @@ def get_state_graph(contracted_graph, conf, f): @no_gc -def init_gasstation_queries(graph, conf, s, t): +def init_gasstation_queries(graph, conf): f = GasstationAccessFunctions(conf['consumption']['consumption_coefficient']) contracted_graph, contraction_time = get_contracted_graph(graph, conf, f) state_graph, state_graph_time = get_state_graph(contracted_graph, conf, f) + """ start = perf_counter() nx.shortest_path(state_graph, s, t) runtime = perf_counter() - start + """ return InitQueryRow( - start_node=s[0], - target_node=t[0], - query_time=runtime, + charging_stations=len(graph.charging_stations), time_contracted_graph=contraction_time, time_state_graph=state_graph_time, nodes_state_graph=len(state_graph.nodes), @@ -165,6 +176,46 @@ def init_gasstation_queries(graph, conf, s, t): ) +@no_gc +def insert_nodes_into_state_graph(graph, conf, s, t): + f = GasstationAccessFunctions(conf['consumption']['consumption_coefficient']) + contracted_graph, contraction_time = get_contracted_graph(graph, conf, f) + state_graph, state_graph_time = get_state_graph(contracted_graph, conf, f) + + start = perf_counter() + gasstation.routing.insert_start_node( + s, + graph, + contracted_graph, + graph.charging_stations, + state_graph, + conf['capacity'], + conf['mu_s'], + f + ) + time_insertion = perf_counter() - start + + start = perf_counter() + gasstation.routing.insert_final_node( + t, + graph, + graph.charging_stations, + state_graph, + conf['capacity'], + conf['mu_t'], + f + ) + time_target = perf_counter() - start + + return InsertQueryRow( + start_node=s[0], + target_node=t[0], + charging_stations=len(graph.charging_stations), + time_insert_start=time_insertion, + time_insert_target=time_target + ) + + @no_gc def gasstation_query(graph, conf, s, t): f = GasstationAccessFunctions(conf['consumption']['consumption_coefficient']) @@ -303,13 +354,12 @@ def astar_query(graph, conf, s, t): ) -Query = namedtuple('Query', field_names=['query_function', 'filename', 'row_class']) - -query_relations = { - 'classic': Query(classic_query, 'classic.csv', ClassicQueryRow), - 'astar': Query(astar_query, 'astar.csv', AStarQueryRow), - 'bidirectional': Query(bidirectional_query, 'bidirectional.csv', QueryRow), - 'gasstation': Query(gasstation_query, 'gasstation.csv', GasstationQueryRow), - 'charge': Query(charge_query, 'charge.csv', ChargeQueryRow), - 'init': Query(init_gasstation_queries, 'charge.csv', InitQueryRow), +row_classes = { + classic_query: ClassicQueryRow, + astar_query: AStarQueryRow, + bidirectional_query: QueryRow, + gasstation_query: GasstationQueryRow, + charge_query: ChargeQueryRow, + init_gasstation_queries: InitQueryRow, + insert_nodes_into_state_graph: InsertQueryRow } diff --git a/evaluation/run.py b/evaluation/run.py index 928bb43646eb5077a7c0b612006b5445e6136cf6..e122465eea91415fd54f67929eccb4cd2f4d8d68 100644 --- a/evaluation/run.py +++ b/evaluation/run.py @@ -100,4 +100,10 @@ if __name__ == '__main__': result_dir=results_dir ) elif conf['type'] == 'init': - pass + results_dir = benchmark_dir.joinpath('init') + results_dir.mkdir(exist_ok=True) + benchmarks.init(graphs=graphs, + charging_stations=charging_stations, + conf=conf, + result_dir=results_dir + ) diff --git a/evrouting/gasstation/routing.py b/evrouting/gasstation/routing.py index b4038515e62d7128ef16f3d9a267d205975723b5..0c9522c243040f8107e02b105caca6c7b9a7453c 100644 --- a/evrouting/gasstation/routing.py +++ b/evrouting/gasstation/routing.py @@ -177,6 +177,7 @@ def state_graph(G: nx.Graph, capacity: SoC, f: AccessFunctions = AccessFunctions for u in G.nodes: c_u = f.charging_coefficient(G, u) + H.add_node((u, 0)) for v in G.neighbors(u): w = f.consumption(G, u, v) if w <= capacity: