diff --git a/evrouting/gasstation/routing.py b/evrouting/gasstation/routing.py index 1566f213ff9deccf5379c077ccdb525d8bad39cc..4849b2f5cff5336f585c783f035343115f01ac5c 100644 --- a/evrouting/gasstation/routing.py +++ b/evrouting/gasstation/routing.py @@ -1,4 +1,4 @@ -from typing import Set, Callable, List, Any, Dict +from typing import Set, Callable, List, Any, Dict, Tuple import networkx as nx from evrouting.T import Node, SoC @@ -14,7 +14,7 @@ Path = List[Node] DistFunction = Callable[[nx.Graph, Node, Node, str], Path] -def dijkstra(G: nx.Graph, u: Any, v: Any, weight: str = 'weight') -> Path: +def dijkstra(G: nx.Graph, u: Any, v: Any, weight: str = 'weight') -> list: return nx.algorithms.shortest_path(G, u, v, weight=weight) @@ -161,8 +161,25 @@ def state_graph(G: nx.Graph, capacity: SoC) -> nx.DiGraph: return H -def compose_result(G: nx.Graph, path: Path) -> dict: - return {'trip_time': 0, 'path': path} +def compose_result(graph_core: nx.Graph, extended_graph: nx.DiGraph, path: List[Tuple[Node, Node]], + dist=dijkstra) -> dict: + charge_path = [(path[0][0], 0)] # Start Node + trip_time = sum([extended_graph.edges[u, v]['weight'] for u, v in zip(path[:-1], path[1:])]) + + for i in range(1, len(path) - 1): + u, g_u = path[i] + v, g_v = path[i + 1] + t = extended_graph.edges[(u, g_u), (v, g_v)]['weight'] + charge_time_u = t - fold_path( + graph_core, + dist(graph_core, u, v, weight=DISTANCE_KEY), + weight=DISTANCE_KEY + ) + charge_path.append((u, charge_time_u)) + + charge_path.append((path[-1][0], 0)) # Final Node + + return {'trip_time': trip_time, 'path': charge_path} def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node, @@ -178,12 +195,32 @@ def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node, :param U: Capacity :return: """ - S: nx.Graph = contract_graph(G, charging_stations, capacity) - H = state_graph(S, capacity) - - insert_start_node(s, G, charging_stations, H, capacity, initial_soc) - insert_final_node(t, G, charging_stations, H, capacity, final_soc) - - path: Path = dijkstra(H, (s, 0), (t, 0)) - - return compose_result(H, path) + contracted_graph: nx.Graph = contract_graph(G, charging_stations, capacity) + extended_graph = state_graph(contracted_graph, capacity) + + extended_graph = insert_start_node( + s=s, + graph_core=G, + graph_contracted=contracted_graph, + gas_stations=charging_stations, + graph_extended=extended_graph, + capacity=capacity, + initial_soc=initial_soc + ) + + extended_graph = insert_final_node( + t=t, + graph_core=G, + gas_stations=charging_stations, + graph_extended=extended_graph, + capacity=capacity, + final_soc=final_soc + ) + + path: List[Tuple[Node, Node]] = dijkstra(extended_graph, (s, initial_soc), (t, final_soc)) + + return compose_result( + graph_core=G, + extended_graph=extended_graph, + path=path + ) diff --git a/tests/config.py b/tests/config.py index 963d0e05c5a37ac229b6fcb49e7c9890134f7d1c..102e4c335e95634625930c544ef3a4b5de021642 100644 --- a/tests/config.py +++ b/tests/config.py @@ -94,11 +94,11 @@ edge_case_start_node_no_cs = { } gasstation_complete = { - 'beta_s': 0, + 'beta_s': 4, 'beta_t': 0, 'U': 4, 's': 0, - 't': 2, + 't': 3, 'nodes': [ TemplateNode(), TemplateNode(charging_coeff=1), diff --git a/tests/gasstation/test_gasstation_routing.py b/tests/gasstation/test_gasstation_routing.py index da7e6cdbbd6af4381ecdd06fb350068fea5d1fec..62d09a5d7c4f29aa2d2eebc3e5e8aca598a2c172 100644 --- a/tests/gasstation/test_gasstation_routing.py +++ b/tests/gasstation/test_gasstation_routing.py @@ -1,20 +1,20 @@ from evrouting.gasstation.routing import ( shortest_path, ) -from tests.config import edge_case, get_graph +from tests.config import gasstation_complete, init_config -class TestRouting: - def test_shortest_path(self): - G = get_graph(edge_case) +def test_shortest_path(): + conf = init_config(gasstation_complete) - path = shortest_path( - G, - s=edge_case['s'], - t=edge_case['t'], - b_0=edge_case['b_0'], - b_t=edge_case['b_t'], - U=edge_case['U'] - ) + path = shortest_path( + G=conf['G'], + charging_stations=conf['charging_stations'], + s=conf['s'], + t=conf['t'], + initial_soc=conf['initial_soc'], + final_soc=conf['final_soc'], + capacity=conf['capacity'] + ) - assert path == [(0, 4), (2, 0)] + assert path == {'path': [(0, 0), (1, 1), (3, 0)], 'trip_time': 11} diff --git a/tests/gasstation/test_transformations.py b/tests/gasstation/test_transformations.py index a5e0b46d9c5848edc984602f853c7f0af0ea2aca..1640cb995cb8894bf28ad09344f366f9f375423e 100644 --- a/tests/gasstation/test_transformations.py +++ b/tests/gasstation/test_transformations.py @@ -1,7 +1,6 @@ import networkx as nx import pytest -from evrouting.T import ChargingCoefficient from evrouting.gasstation.routing import ( contract_graph, dijkstra, @@ -9,16 +8,14 @@ from evrouting.gasstation.routing import ( get_possible_arriving_soc, state_graph, insert_final_node, - insert_start_node + insert_start_node, + compose_result ) from evrouting.graph_tools import ( label, CONSUMPTION_KEY, DISTANCE_KEY, - CHARGING_COEFFICIENT_KEY, - consumption, - distance, - charging_cofficient + CHARGING_COEFFICIENT_KEY ) from tests.config import edge_case, gasstation, init_config, gasstation_complete @@ -244,8 +241,7 @@ class TestStateGraph(MinimalExamples): assert len(H.edges) == 0 -class TestIntegration: - +class Integration: @pytest.fixture def graph_config(self): return init_config(gasstation_complete) @@ -292,6 +288,9 @@ class TestIntegration: final_soc=0 ) + +class TestIntegration(Integration): + def test_contracted_graph(self, contracted_graph): G = contracted_graph assert len(G.nodes) == 2 @@ -340,3 +339,13 @@ class TestIntegration: assert set(inserted_t.nodes) == {(0, 4), (2, 3), (1, 1), (2, 1), (1, 0), (2, 0), (3, 0)} assert len(inserted_t.edges) == 11 assert inserted_t.edges[u, v]['weight'] == weight + + +class TestResult(Integration): + def test_compose_result(self, graph, inserted_t): + path = [(0, 4), (1, 1), (3, 0)] + result = compose_result(graph, inserted_t, path) + assert result == { + 'trip_time': 6 + 1 + 4, + 'path': [(0, 0), (1, 1), (3, 0)] + }