diff --git a/evrouting/gasstation/routing.py b/evrouting/gasstation/routing.py index e545c4ffcbf2df5466149ac024400dd01add2b65..cac17651455912deca9dd879866708cd977c1f5c 100644 --- a/evrouting/gasstation/routing.py +++ b/evrouting/gasstation/routing.py @@ -1,29 +1,15 @@ -from typing import Set, Callable, List +from typing import Set, Callable, List, Any import networkx as nx from evrouting.T import Node, SoC -from evrouting.graph_tools import CONSUMPTION_KEY, DISTANCE_KEY +from evrouting.graph_tools import ( + CONSUMPTION_KEY, DISTANCE_KEY, CHARGING_COEFFICIENT_KEY) Path = List[Node] DistFunction = Callable[[nx.Graph, Node, Node], Path] -def shortest_path(G: nx.Graph, s, t, b_0: float, b_t: float, U: float): - """ - Calculates shortest path using a generalized gas station algorithm. - - :param G: Input Graph - :param s: Start Node identifier - :param t: End Node identifier - :param b_0: Start SoC - :param b_t: End SoC - :param U: Capacity - :return: - """ - pass - - -def dijkstra(G: nx.Graph, u: Node, v: Node, weight: str = 'weight') -> Path: +def dijkstra(G: nx.Graph, u: Any, v: Any, weight: str = 'weight') -> Path: return nx.algorithms.shortest_path(G, u, v, weight=weight) @@ -31,6 +17,30 @@ def fold_path(G: nx.Graph, path: Path, weight: str): return sum([G.edges[u, v][weight] for u, v in zip(path[:-1], path[1:])]) +def insert_temp_node(temp_node: Node, + graph_core: nx.Graph, + graph_contracted: nx.Graph, + capacity: SoC, + initial_soc: SoC, + dist: DistFunction = dijkstra + ): + # Add cheap charging station + graph_contracted.add_node(temp_node, **{CHARGING_COEFFICIENT_KEY: 0}) + + for cs in graph_contracted.nodes: + min_path = dist(graph_core, temp_node, cs) + consumption = fold_path(graph_core, min_path, CONSUMPTION_KEY) + distance = fold_path(graph_core, min_path, DISTANCE_KEY) + if consumption <= initial_soc: + graph_contracted.add_edge( + temp_node, cs, + **{ + CONSUMPTION_KEY: capacity - initial_soc + consumption, + DISTANCE_KEY: distance + } + ) + + def contract_graph(G: nx.Graph, charging_stations: Set[Node], capacity: SoC, dist: DistFunction = dijkstra) -> nx.Graph: """ @@ -56,7 +66,38 @@ def contract_graph(G: nx.Graph, charging_stations: Set[Node], capacity: SoC, cs, n_cs, **{ CONSUMPTION_KEY: consumption, - DISTANCE_KEY:fold_path(G, min_path, weight=DISTANCE_KEY) + DISTANCE_KEY: fold_path(G, min_path, weight=DISTANCE_KEY) } ) return H + + +def extract_graph(G: nx.Graph, capacity: SoC) -> nx.Graph: + pass + + +def compose_result(G: nx.Graph, path: Path) -> dict: + pass + + +def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node, + initial_soc: SoC, final_soc: SoC, capacity: SoC) -> Dict: + """ + Calculates shortest path using a generalized gas station algorithm. + + :param G: Input Graph + :param s: Start Node identifier + :param t: End Node identifier + :param b_0: Start SoC + :param b_t: End SoC + :param U: Capacity + :return: + """ + H: nx.Graph = contract_graph(G, charging_stations, capacity) + insert_temp_node(s, G, H, capacity, initial_soc) + insert_temp_node(t, G, H, capacity, final_soc) + + extracted_graph = extract_graph(H, capacity) + path: Path = dijkstra(extract_graph(H, capacity), (s, 0), (t, 0)) + + return compose_result(extracted_graph, path) diff --git a/tests/gasstation/test_gasstation_routing.py b/tests/gasstation/test_gasstation_routing.py index 70a0d4d14ded8a6258ce5718942432b5d0288b3e..51d83a793fa83ead20418e4f7125125599c7150c 100644 --- a/tests/gasstation/test_gasstation_routing.py +++ b/tests/gasstation/test_gasstation_routing.py @@ -1,7 +1,8 @@ import networkx as nx import pytest -from evrouting.gasstation.routing import contract_graph, dijkstra, fold_path +from evrouting.gasstation.routing import ( + shortest_path, contract_graph, dijkstra, fold_path) from evrouting.graph_tools import label, CONSUMPTION_KEY, DISTANCE_KEY from tests.config import edge_case, get_graph, gasstation, init_config