From ac34daa9f4e8938e01d43226b3fde09a3ffba8fa Mon Sep 17 00:00:00 2001
From: "niehues.mark@gmail.com" <niehues.mark@gmail.com>
Date: Wed, 29 Apr 2020 15:42:31 +0200
Subject: [PATCH] fixing things, finetuning missing

---
 evrouting/gasstation/routing.py  | 33 +++++++++++++++++++++-----------
 evrouting/graph_tools.py         | 22 ++++++++++++++++++---
 evrouting/osm/routing.py         | 19 ++++++++++++++++--
 tests/osm/test_gasstation_osm.py | 18 ++++++++++-------
 4 files changed, 69 insertions(+), 23 deletions(-)

diff --git a/evrouting/gasstation/routing.py b/evrouting/gasstation/routing.py
index 324dacc..ff5d458 100644
--- a/evrouting/gasstation/routing.py
+++ b/evrouting/gasstation/routing.py
@@ -2,7 +2,7 @@ from typing import Set, List
 
 import networkx as nx
 from evrouting.T import Node, SoC, Result, EmptyResult, Time
-from evrouting.gasstation.T import State, DistFunction
+from evrouting.gasstation.T import State
 from evrouting.graph_tools import (
     CONSUMPTION_KEY,
     DISTANCE_KEY,
@@ -23,7 +23,7 @@ def insert_start_node(s: Node,
     graph_extended.add_node((s, initial_soc))
     v: Node
     for v in gas_stations:
-        shortest_p: List[Node] = nx.shortest_path(graph_core, s, v, weight=CONSUMPTION_KEY)
+        shortest_p: List[Node] = nx.shortest_path(graph_core, s, v, weight=DISTANCE_KEY)
         w = f.path_consumption(graph_core, shortest_p)
         if w > initial_soc:
             continue
@@ -65,7 +65,7 @@ def insert_final_node(t: Node,
     graph_extended.add_node((t, final_soc))
     u: Node
     for u in gas_stations:
-        shortest_p: List[Node] = nx.shortest_path(graph_core, t, u, weight=CONSUMPTION_KEY)
+        shortest_p: List[Node] = nx.shortest_path(graph_core, t, u, weight=DISTANCE_KEY)
         w = f.path_consumption(graph_core, shortest_p)
         if w + final_soc > capacity:
             continue
@@ -185,8 +185,17 @@ def compose_result(graph_core: nx.Graph, extended_graph: nx.DiGraph,
     return Result(trip_time=trip_time, charge_path=charge_path)
 
 
-def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node,
-                  initial_soc: SoC, final_soc: SoC, capacity: SoC, f: AccessFunctions = AccessFunctions()) -> Result:
+def shortest_path(G: nx.Graph,
+                  charging_stations: Set[Node],
+                  s: Node,
+                  t: Node,
+                  initial_soc: SoC,
+                  final_soc: SoC,
+                  capacity: SoC,
+                  f: AccessFunctions = AccessFunctions(),
+                  extended_graph=None,
+                  contracted_graph=None
+                  ) -> Result:
     """
     Calculates shortest path using a generalized gas station algorithm.
 
@@ -201,7 +210,7 @@ def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node,
     """
     # Check if t is reachable from s
     try:
-        _path = nx.shortest_path(G, s, t, weight=CONSUMPTION_KEY)
+        _path = nx.shortest_path(G, s, t, weight=DISTANCE_KEY)
     except nx.NetworkXNoPath:
         return EmptyResult()
 
@@ -209,11 +218,11 @@ def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node,
     if _w <= initial_soc:
         return Result(
             trip_time=f.path_distance(G, _path),
-            charge_path=[(s, 0), (t, 0)]
+            charge_path=[(n, 0) for n in _path]
         )
 
-    contracted_graph: nx.Graph = contract_graph(G, charging_stations, capacity)
-    extended_graph = state_graph(contracted_graph, capacity)
+    contracted_graph: nx.Graph = contracted_graph or contract_graph(G, charging_stations, capacity, f)
+    extended_graph = extended_graph or state_graph(contracted_graph, capacity, f)
 
     extended_graph = insert_start_node(
         s=s,
@@ -222,7 +231,8 @@ def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node,
         gas_stations=charging_stations,
         graph_extended=extended_graph,
         capacity=capacity,
-        initial_soc=initial_soc
+        initial_soc=initial_soc,
+        f=f
     )
 
     extended_graph = insert_final_node(
@@ -231,7 +241,8 @@ def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node,
         gas_stations=charging_stations,
         graph_extended=extended_graph,
         capacity=capacity,
-        final_soc=final_soc
+        final_soc=final_soc,
+        f=f
     )
 
     try:
diff --git a/evrouting/graph_tools.py b/evrouting/graph_tools.py
index 6ae2d90..69b7523 100644
--- a/evrouting/graph_tools.py
+++ b/evrouting/graph_tools.py
@@ -72,17 +72,33 @@ def consumption_function_distance_factory(consumption: float) -> ConsumptionFunc
 
 
 class AccessFunctions:
+    """
+    Class for dependency injections to access path
+    attributes in flexible ways.
+    """
+
     def __init__(self,
                  distance=distance,
                  consumption=consumption,
                  charging_coefficient=charging_cofficient
                  ):
-        self.distance = distance
-        self.consumption = consumption
-        self.charging_coefficient = charging_coefficient
+        self._distance = distance
+        self._consumption = consumption
+        self._charging_coefficient = charging_coefficient
+
+    def distance(self, G, u, v):
+        return self._distance(G, u, v)
+
+    def consumption(self, G, u, v):
+        return self._consumption(G, u, v)
+
+    def charging_coefficient(self, G, v):
+        return self._charging_coefficient(G, v)
 
     def path_distance(self, G, path):
+        """:return: Distance of path."""
         return sum_weights(G, path, weight=DISTANCE_KEY)
 
     def path_consumption(self, G, path):
+        """:returns: consumption of given path."""
         return sum_weights(G, path, weight=CONSUMPTION_KEY)
diff --git a/evrouting/osm/routing.py b/evrouting/osm/routing.py
index f94527e..d04f056 100644
--- a/evrouting/osm/routing.py
+++ b/evrouting/osm/routing.py
@@ -5,7 +5,7 @@ import networkx as nx
 
 from evrouting.T import Result, EmptyResult
 from evrouting.graph_tools import (
-    DISTANCE_KEY, sum_weights
+    DISTANCE_KEY, sum_weights, AccessFunctions
 )
 from evrouting.osm.const import ms_to_kmh
 
@@ -76,4 +76,19 @@ def to_coordinates(G, path):
 def get_coordinates(G, n):
     lat = G.nodes[n]['lat']
     lon = G.nodes[n]['lon']
-    return lon, lat
\ No newline at end of file
+    return lon, lat
+
+
+class GasstationAccessFunctions(AccessFunctions):
+    def __init__(self, consumption_coefficient):
+        super().__init__()
+        self.c = consumption_coefficient
+
+    def consumption(self, G, u, v):
+        return self.c * self._distance(G, u, v)
+
+    def charging_coefficient(self, G, v):
+        return 1 / self._charging_coefficient(G, v)
+
+    def path_consumption(self, G, path):
+        return self.c * self.path_distance(G, path)
diff --git a/tests/osm/test_gasstation_osm.py b/tests/osm/test_gasstation_osm.py
index 99dc775..06c2641 100644
--- a/tests/osm/test_gasstation_osm.py
+++ b/tests/osm/test_gasstation_osm.py
@@ -3,8 +3,7 @@ import networkx as nx
 from evrouting import gasstation
 from evrouting.T import Result
 from evrouting.osm.profiles import car
-from evrouting.osm.routing import shortest_path
-from evrouting.graph_tools import charging_cofficient
+from evrouting.osm.routing import shortest_path, GasstationAccessFunctions
 
 
 def test_charge_shortest_route_dimensions(map_graph):
@@ -17,6 +16,9 @@ def test_charge_shortest_route_dimensions(map_graph):
     consumption = 0.5  # kWh/s
     # Traveltime gonna be less than 10 min = 600 sek = 300 kWh.
     # Therefore initial soc of 300 000
+
+    f = GasstationAccessFunctions(consumption)
+
     result = gasstation.shortest_path(G=map_graph,
                                       charging_stations=map_graph.charging_stations,
                                       s=_s,
@@ -24,7 +26,7 @@ def test_charge_shortest_route_dimensions(map_graph):
                                       initial_soc=300000,
                                       final_soc=0,
                                       capacity=300000,
-                                      c=consumption * 1000,
+                                      f=f,
                                       extended_graph=None,
                                       contracted_graph=None
                                       )
@@ -42,7 +44,9 @@ def test_charge_shortest_route_stop(map_graph):
     _s = map_graph.find_nearest(s)
     _t = map_graph.find_nearest(t)
 
-    consumption = 0.5 * 1000 # Wh/s
+    consumption = 0.5 * 1000  # Wh/s
+    f = GasstationAccessFunctions(consumption)
+
     # Traveltime to first charging station is < 5 min = 300 sek := 150 kWh
     # => Initial soc of 150 000 is enough to charge but not to reach target.
     initial_soc = 150000
@@ -53,17 +57,17 @@ def test_charge_shortest_route_stop(map_graph):
                                       initial_soc=initial_soc,
                                       final_soc=0,
                                       capacity=300000,
-                                      c=consumption,
+                                      f=f,
                                       extended_graph=None,
                                       contracted_graph=None
                                       )
     assert type(result) is Result
 
-    charge_nodes = [(n, t) for n, t in result.charge_path if t >0]
+    charge_nodes = [(n, t) for n, t in result.charge_path if t > 0]
     assert len(charge_nodes) == 1
 
     charge_node, charge_time = charge_nodes[0]
-    charging_station_c = charging_cofficient(map_graph, charge_node)
+    charging_station_c = f.charging_coefficient(map_graph, charge_node)
     # calc travel time to charge_node an
     s_to_c = consumption * nx.shortest_path_length(map_graph, _s, charge_node)
     c_to_t = consumption * nx.shortest_path_length(map_graph, charge_node, _t)
-- 
GitLab