From a102dc5cf70d08e973c9944a2d7d9faf2a57b257 Mon Sep 17 00:00:00 2001
From: "niehues.mark@gmail.com" <niehues.mark@gmail.com>
Date: Fri, 1 May 2020 19:12:07 +0200
Subject: [PATCH] query evaluation

---
 evaluation/T.py                               | 13 ++-
 evaluation/queries.py                         | 83 ++++++++++++++++---
 evaluation/results/example/queries/astar.csv  | 10 +++
 evaluation/results/example/queries/charge.csv | 12 ++-
 .../results/example/queries/classic.csv       | 10 +++
 .../results/example/queries/gasstation.csv    | 20 ++---
 evaluation/run.py                             | 10 +--
 evrouting/charge/routing.py                   |  2 +
 evrouting/graph_tools.py                      | 15 ++++
 evrouting/osm/routing.py                      | 12 ++-
 10 files changed, 151 insertions(+), 36 deletions(-)

diff --git a/evaluation/T.py b/evaluation/T.py
index 3d70f28..a3fb361 100644
--- a/evaluation/T.py
+++ b/evaluation/T.py
@@ -1,6 +1,15 @@
 from collections import namedtuple
 from dataclasses import dataclass
 
+__all__ = [
+    'GasstationQueryRow',
+    'ClassicQueryRow',
+    'ChargeQueryRow',
+    'AStarQueryRow',
+    'Query'
+]
+
+
 @dataclass
 class QueryRow:
     start_node: str
@@ -20,9 +29,7 @@ class GasstationQueryRow(QueryRow):
 
 @dataclass
 class ChargeQueryRow(QueryRow):
-    time_contracted_graph: float
-    time_state_graph: float
-
+    pass
 
 @dataclass
 class ClassicQueryRow(QueryRow):
diff --git a/evaluation/queries.py b/evaluation/queries.py
index 1ea254d..1810e80 100644
--- a/evaluation/queries.py
+++ b/evaluation/queries.py
@@ -1,3 +1,4 @@
+import networkx as nx
 from time import perf_counter
 
 from evaluation.export import write_row
@@ -10,12 +11,17 @@ from evaluation.T import (
 
 from evrouting.T import Result
 from evrouting import gasstation, charge
-from evrouting.osm.routing import GasstationAccessFunctions
+from evrouting.graph_tools import (
+    consumption_function_distance_factory,
+    DISTANCE_KEY
+)
+from evrouting.osm.profiles import car
+from evrouting.osm.routing import GasstationAccessFunctions, a_start_heuristic
 
 __all__ = ['gasstation_query', 'charge_query', 'classic_query', 'astar_query']
 
 
-def gasstation_query(graph, conf, s, t, file):
+def gasstation_query(graph, conf, s, t):
     f = GasstationAccessFunctions(conf['consumption']['consumption_coefficient'])
 
     start = perf_counter()
@@ -50,10 +56,10 @@ def gasstation_query(graph, conf, s, t, file):
     )
     query_time = perf_counter() - start
 
-    row = GasstationQueryRow(
+    return GasstationQueryRow(
         start_node=s,
         target_node=t,
-        query_time=query_time,
+        query_time=query_time + contraction_time + state_graph_time,
         trip_time=result.trip_time if type(result) == Result else None,
         nodes=len(graph.nodes),
         edges=len(graph.edges),
@@ -62,16 +68,71 @@ def gasstation_query(graph, conf, s, t, file):
         time_state_graph=state_graph_time
     )
 
-    write_row(file, row)
 
+def charge_query(graph, conf, s, t):
+    start = perf_counter()
+    result = charge.shortest_path(
+        G=graph,
+        charging_stations=graph.charging_stations,
+        s=s,
+        t=t,
+        initial_soc=conf['mu_s'],
+        final_soc=conf['mu_t'],
+        capacity=conf['capacity'],
+        c=consumption_function_distance_factory(conf['consumption']['consumption_coefficient'])
+    )
+    runtime = start - perf_counter()
+
+    return ChargeQueryRow(
+        start_node=s,
+        target_node=t,
+        query_time=runtime,
+        trip_time=result.trip_time if type(result) == Result else None,
+        nodes=len(graph.nodes),
+        edges=len(graph.edges),
+        charging_stations=len(graph.charging_stations)
+    )
 
-def charge_query(graph, conf, s, t, file):
-    pass
 
+def classic_query(graph, conf, s, t):
+    start = perf_counter()
+    try:
+        result = nx.shortest_path_length(graph, s, t, weight=DISTANCE_KEY)
+    except nx.NetworkXNoPath:
+        result = None
+    runtime = perf_counter() - start
 
-def classic_query(graph, conf, s, t, file):
-    pass
+    return ClassicQueryRow(
+        start_node=s,
+        target_node=t,
+        query_time=runtime,
+        trip_time=result,
+        nodes=len(graph.nodes),
+        edges=len(graph.edges),
+        charging_stations=len(graph.charging_stations),
+        dijkstra_rank=0
+    )
 
 
-def astar_query(graph, conf, s, t, file):
-    pass
+def astar_query(graph, conf, s, t):
+    start = perf_counter()
+    try:
+        result = nx.astar_path_length(
+            graph,
+            s, t,
+            weight=DISTANCE_KEY,
+            heuristic=a_start_heuristic(graph, car)
+        )
+    except nx.NetworkXNoPath:
+        result = None
+    runtime = perf_counter() - start
+
+    return AStarQueryRow(
+        start_node=s,
+        target_node=t,
+        query_time=runtime,
+        trip_time=result,
+        nodes=len(graph.nodes),
+        edges=len(graph.edges),
+        charging_stations=len(graph.charging_stations)
+    )
diff --git a/evaluation/results/example/queries/astar.csv b/evaluation/results/example/queries/astar.csv
index 19c78db..a802553 100644
--- a/evaluation/results/example/queries/astar.csv
+++ b/evaluation/results/example/queries/astar.csv
@@ -1 +1,11 @@
 start_node,target_node,query_time,trip_time,nodes,edges,charging_stations
+1828418198,317431301,0.00014760599879082292,7.279169256464534,2827,5691,4
+6908239938,7286181357,0.012720081002044026,394.5397247638705,2827,5691,4
+7030626842,2598982037,0.01626204000058351,514.2422639697024,2827,5691,4
+1672334378,7322098499,0.00022359000286087394,None,2827,5691,4
+687135582,4955445788,0.02305627299938351,745.9999671853842,2827,5691,4
+1672334393,6417387131,0.00017938599921762943,None,2827,5691,4
+318650171,426930264,0.0020166660033282824,121.57850376415072,2827,5691,4
+2604684732,2604992913,0.0052501579993986525,278.957847495384,2827,5691,4
+318014996,4226442915,0.0031801030054339208,228.43086492206294,2827,5691,4
+3211622700,321209222,0.009974717999284621,439.60835992391065,2827,5691,4
diff --git a/evaluation/results/example/queries/charge.csv b/evaluation/results/example/queries/charge.csv
index e0eab29..dbfed87 100644
--- a/evaluation/results/example/queries/charge.csv
+++ b/evaluation/results/example/queries/charge.csv
@@ -1 +1,11 @@
-start_node,target_node,query_time,trip_time,nodes,edges,charging_stations,time_contracted_graph,time_state_graph
+start_node,target_node,query_time,trip_time,nodes,edges,charging_stations
+1828418198,317431301,-0.00541873700422002,7.279169256464534,2828,5691,4
+6908239938,7286181357,-0.011799191997852176,None,2827,5691,4
+7030626842,2598982037,-0.009080265001102816,None,2828,5691,4
+1672334378,7322098499,-0.07304622400260996,None,2827,5691,4
+687135582,4955445788,-0.008829377002257388,None,2828,5691,4
+1672334393,6417387131,-0.004487725003855303,None,2827,5691,4
+318650171,426930264,-0.011571786999411415,None,2828,5691,4
+2604684732,2604992913,-0.01105132199882064,None,2827,5691,4
+318014996,4226442915,-0.041451365999819245,None,2828,5691,4
+3211622700,321209222,-0.010363692003011238,None,2827,5691,4
diff --git a/evaluation/results/example/queries/classic.csv b/evaluation/results/example/queries/classic.csv
index ad83ad2..8f03f8b 100644
--- a/evaluation/results/example/queries/classic.csv
+++ b/evaluation/results/example/queries/classic.csv
@@ -1 +1,11 @@
 start_node,target_node,query_time,trip_time,nodes,edges,charging_stations,dijkstra_rank
+1828418198,317431301,4.956599877914414e-05,7.279169256464534,2827,5691,4,0
+6908239938,7286181357,0.0048305089949280955,394.5397247638705,2827,5691,4,0
+7030626842,2598982037,0.004805078999197576,514.2422639697024,2827,5691,4,0
+1672334378,7322098499,6.071800453355536e-05,None,2827,5691,4,0
+687135582,4955445788,0.005866410996532068,745.9999671853842,2827,5691,4,0
+1672334393,6417387131,4.006700328318402e-05,None,2827,5691,4,0
+318650171,426930264,0.0007606210056110285,121.57850376415072,2827,5691,4,0
+2604684732,2604992913,0.002318312006536871,278.957847495384,2827,5691,4,0
+318014996,4226442915,0.0009691689992905594,228.43086492206294,2827,5691,4,0
+3211622700,321209222,0.004724771999462973,439.60835992391065,2827,5691,4,0
diff --git a/evaluation/results/example/queries/gasstation.csv b/evaluation/results/example/queries/gasstation.csv
index 7d84d4c..eec3672 100644
--- a/evaluation/results/example/queries/gasstation.csv
+++ b/evaluation/results/example/queries/gasstation.csv
@@ -1,11 +1,11 @@
 start_node,target_node,query_time,trip_time,nodes,edges,charging_stations,time_contracted_graph,time_state_graph
-2612700813,2632841214,0.005009925000194926,383.4794987778951,2827,5691,3,0.016830534004839137,0.00015566699585178867
-563191193,317944965,0.007466991002729628,446.99022181478455,2827,5691,3,0.017327437999483664,0.00013550499716075137
-7286240208,2604687836,0.00499775999924168,406.2307557413689,2827,5691,3,0.015518132997385692,0.0002068149988190271
-2639898855,574457829,0.0028420240050763823,339.7265922483922,2827,5691,3,0.015539429994532838,0.00013767200289294124
-2612700817,7286181375,0.005542577993765008,372.43394892215343,2827,5691,3,0.015766301003168337,0.00013465899974107742
-2616462194,4955446076,0.006115891002991702,374.0087002891246,2827,5691,3,0.015495608000492211,0.00015103199984878302
-4955446025,1505052669,0.009748128002684098,535.7659858061888,2827,5691,3,0.01556892799999332,0.0001692669975454919
-2700412801,563194900,0.0009064859987120144,161.78412446050507,2827,5691,3,0.015535534999798983,0.00013569000293500721
-5113940072,1768859059,0.05034502399939811,22741.474067970452,2827,5691,3,0.015074203001859132,0.00013480500638252124
-1929118150,687139215,0.041247827000916004,16827.8805214423,2827,5691,3,0.014938869993784465,0.0001336659988737665
+1828418198,317431301,0.013457719011057634,7.279169256464534,2827,5691,3,0.013232094002887607,0.00015533400437561795
+6908239938,7286181357,0.01858366200031014,394.5397247638705,2827,5691,3,0.011774632999731693,0.0001285780017497018
+7030626842,2598982037,0.019493229003273882,514.2422639697024,2827,5691,3,0.012273380998522043,0.0001298909992328845
+1672334378,7322098499,0.011932426001294516,None,2827,5691,3,0.011734421001165174,0.00012836899986723438
+687135582,4955445788,0.06945202999486355,15920.213155107229,2827,5691,3,0.011887456996191759,0.0001311939995503053
+1672334393,6417387131,0.011970645995461382,None,2827,5691,3,0.011739390000002459,0.0001719049978419207
+318650171,426930264,0.012910725999972783,121.57850376415072,2827,5691,3,0.011731954000424594,0.00015385100414277986
+2604684732,2604992913,0.015297935999114998,278.957847495384,2827,5691,3,0.011814755998784676,0.00013210000179242343
+318014996,4226442915,0.01378022700373549,228.43086492206294,2827,5691,3,0.012272058003873099,0.00013237199891591445
+3211622700,321209222,0.0201044030036428,439.60835992391065,2827,5691,3,0.012434723998012487,0.0001317000060225837
diff --git a/evaluation/run.py b/evaluation/run.py
index 522107a..fb7ce1d 100644
--- a/evaluation/run.py
+++ b/evaluation/run.py
@@ -4,17 +4,13 @@ import random
 from pathlib import Path
 
 import yaml
-
 from evrouting.osm.imports import read_osm
-
 from evaluation.T import *
-from evaluation.export import write_head
+from evaluation.export import write_head, write_row
 from evaluation.queries import *
 
 
-def query_benchmark(graphs,
-                    conf,
-                    result_dir):
+def query_benchmark(graphs, conf, result_dir):
     query_conf = [
         Query(query_function=gasstation_query,
               filename='gasstation.csv',
@@ -34,7 +30,7 @@ def query_benchmark(graphs,
                 with result_dir.joinpath(filename).open('w') as f:
                     write_head(f, row_class)
                     for s, t in zip(start_nodes, target_nodes):
-                        func(G, setup, s, t, f)
+                        write_row(f, func(G, setup, s, t))
 
 
 def get_map(osm_path: Path, cs_path: Path):
diff --git a/evrouting/charge/routing.py b/evrouting/charge/routing.py
index ce7bddc..e87efa2 100644
--- a/evrouting/charge/routing.py
+++ b/evrouting/charge/routing.py
@@ -68,6 +68,7 @@ def shortest_path(G: nx.DiGraph, charging_stations: Set[Node], s: Node, t: Node,
         l_set[node_min].append(label_node_min)
 
         if node_min == t:
+            G.remove_node(t)
             return _result(
                 label_node_min, f_soc_factory(label_node_min).minimum
             )
@@ -135,6 +136,7 @@ def shortest_path(G: nx.DiGraph, charging_stations: Set[Node], s: Node, t: Node,
                 if is_new_min:
                     prio_queue.insert(n, **keys(f_soc_factory(label_neighbour)))
 
+    G.remove_node(t)
     return EmptyResult()
 
 
diff --git a/evrouting/graph_tools.py b/evrouting/graph_tools.py
index 81bb8f2..a66eb82 100644
--- a/evrouting/graph_tools.py
+++ b/evrouting/graph_tools.py
@@ -70,6 +70,21 @@ def consumption_function_distance_factory(consumption: float) -> ConsumptionFunc
     return c
 
 
+def consumption_function_time_factory(consumption: float) -> ConsumptionFunction:
+    """
+    :param consumption: in kWh/km
+    """
+
+    def c(G, u, v):
+        """Returns consumption in Wh from u to v."""
+        try:
+            return G[u][v][DISTANCE_KEY] * consumption
+        except KeyError:
+            return G[u][v][CONSUMPTION_KEY]
+
+    return c
+
+
 class AccessFunctions:
     """
     Class for dependency injections to access path
diff --git a/evrouting/osm/routing.py b/evrouting/osm/routing.py
index d04f056..af61eff 100644
--- a/evrouting/osm/routing.py
+++ b/evrouting/osm/routing.py
@@ -34,9 +34,7 @@ def haversine_distance(lon1, lat1, lon2, lat2, unit_m=True):
     return c * r
 
 
-def shortest_path(G, s: point, t: point, profile) -> Result:
-    """Calc A* shortest path."""
-
+def a_start_heuristic(G, profile):
     def dist(u, v):
         return haversine_distance(
             G.nodes[u]['lat'],
@@ -46,8 +44,14 @@ def shortest_path(G, s: point, t: point, profile) -> Result:
             unit_m=True
         ) / profile['maxspeed'] * ms_to_kmh
 
+    return dist
+
+
+def shortest_path(G, s: point, t: point, profile) -> Result:
+    """Calc A* shortest path."""
+
     try:
-        path = nx.astar_path(G, s, t, heuristic=dist)
+        path = nx.astar_path(G, s, t, heuristic=a_start_heuristic(G, profile))
     except nx.NetworkXNoPath:
         return EmptyResult()
 
-- 
GitLab