From 12d20b1fbf26b6fe2e80d511fe27675f65029a4c Mon Sep 17 00:00:00 2001 From: "niehues.mark@gmail.com" <niehues.mark@gmail.com> Date: Mon, 30 Mar 2020 11:50:36 +0200 Subject: [PATCH] gv u added --- evrouting/gasstation/routing.py | 39 +++++++-- tests/gasstation/test_gasstation_routing.py | 97 ++++++++++++++++++++- 2 files changed, 127 insertions(+), 9 deletions(-) diff --git a/evrouting/gasstation/routing.py b/evrouting/gasstation/routing.py index cac1765..576fd95 100644 --- a/evrouting/gasstation/routing.py +++ b/evrouting/gasstation/routing.py @@ -1,9 +1,14 @@ -from typing import Set, Callable, List, Any +from typing import Set, Callable, List, Any, Dict import networkx as nx from evrouting.T import Node, SoC from evrouting.graph_tools import ( - CONSUMPTION_KEY, DISTANCE_KEY, CHARGING_COEFFICIENT_KEY) + CONSUMPTION_KEY, + DISTANCE_KEY, + CHARGING_COEFFICIENT_KEY, + consumption, + charging_cofficient +) Path = List[Node] DistFunction = Callable[[nx.Graph, Node, Node], Path] @@ -72,7 +77,26 @@ def contract_graph(G: nx.Graph, charging_stations: Set[Node], capacity: SoC, return H -def extract_graph(G: nx.Graph, capacity: SoC) -> nx.Graph: +def get_possible_arriving_soc(G: nx.Graph, u: Node, capacity: SoC) -> List[SoC]: + """ + :returns: All possible SoC when arriving at node u, according to + the optimal fuelling strategy. + """ + possible_arriving_soc: Set[SoC] = {0} + c_u = charging_cofficient(G, u) + + for n in G.neighbors(u): + arriving_soc = capacity - consumption(G, u, n) + if arriving_soc >= 0 and charging_cofficient(G, n) < c_u and \ + arriving_soc not in possible_arriving_soc: + possible_arriving_soc.add(arriving_soc) + + return list(possible_arriving_soc) + + +def state_graph(G: nx.Graph, capacity: SoC) -> nx.Graph: + node = None + get_possible_arriving_soc(G, node, capacity) pass @@ -93,11 +117,12 @@ def shortest_path(G: nx.Graph, charging_stations: Set[Node], s: Node, t: Node, :param U: Capacity :return: """ - H: nx.Graph = contract_graph(G, charging_stations, capacity) + S: nx.Graph = contract_graph(G, charging_stations, capacity) + H = state_graph(S, 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)) + path: Path = dijkstra(H, (s, 0), (t, 0)) - return compose_result(extracted_graph, path) + return compose_result(H, path) diff --git a/tests/gasstation/test_gasstation_routing.py b/tests/gasstation/test_gasstation_routing.py index 51d83a7..8cfa66c 100644 --- a/tests/gasstation/test_gasstation_routing.py +++ b/tests/gasstation/test_gasstation_routing.py @@ -2,8 +2,18 @@ import networkx as nx import pytest from evrouting.gasstation.routing import ( - shortest_path, contract_graph, dijkstra, fold_path) -from evrouting.graph_tools import label, CONSUMPTION_KEY, DISTANCE_KEY + shortest_path, + contract_graph, + dijkstra, + fold_path, + get_possible_arriving_soc +) +from evrouting.graph_tools import ( + label, + CONSUMPTION_KEY, + DISTANCE_KEY, + CHARGING_COEFFICIENT_KEY +) from tests.config import edge_case, get_graph, gasstation, init_config @@ -73,6 +83,89 @@ class TestContraction: assert H.edges[edge][weight] == value +class TestPossibleArrivingSoC: + U = 4 + w_lower = 3 + w_greater = 5 + + @pytest.fixture + def graph_w_below_U(self): + G = nx.Graph() + G.add_edge(0, 1, **{CONSUMPTION_KEY: self.w_lower, DISTANCE_KEY: 2 * self.w_lower}) + yield G + del G + + @pytest.fixture + def graph_w_gt_U(self): + G = nx.Graph() + G.add_edge(0, 1, **{CONSUMPTION_KEY: self.w_greater, DISTANCE_KEY: 2 * self.w_greater}) + yield G + del G + + @pytest.fixture + def graph_w_eq_U(self): + G = nx.Graph() + G.add_edge(0, 1, **{CONSUMPTION_KEY: self.U, DISTANCE_KEY: 2 * self.U}) + yield G + del G + + def test_unequal_charging_coeff_w_eq_U(self, graph_w_eq_U): + G = graph_w_eq_U + G.add_node(0, **{CHARGING_COEFFICIENT_KEY: 1}) + G.add_node(1, **{CHARGING_COEFFICIENT_KEY: 2}) + + gv_lower = get_possible_arriving_soc(G, 0, self.U) + assert gv_lower == [0] + + gv_higher = get_possible_arriving_soc(G, 1, self.U) + assert gv_higher == [0] + + def test_equal_charging_coeff_w_lt_U(self, graph_w_below_U): + G = graph_w_below_U + G.add_node(0, **{CHARGING_COEFFICIENT_KEY: 1}) + G.add_node(1, **{CHARGING_COEFFICIENT_KEY: 1}) + + gv_lower = get_possible_arriving_soc(G, 0, self.U) + assert gv_lower == [0] + + gv_higher = get_possible_arriving_soc(G, 1, self.U) + assert gv_higher == [0] + + def test_unequal_charging_coeff_w_lt_U(self, graph_w_below_U): + G = graph_w_below_U + G.add_node(0, **{CHARGING_COEFFICIENT_KEY: 1}) + G.add_node(1, **{CHARGING_COEFFICIENT_KEY: 2}) + + gv_lower = get_possible_arriving_soc(G, 0, self.U) + assert gv_lower == [0] + + gv_higher = get_possible_arriving_soc(G, 1, self.U) + assert gv_higher == [0, self.U - self.w_lower] + + def test_equal_charging_coeff_w_eq_U(self, graph_w_eq_U): + G = graph_w_eq_U + G.add_node(0, **{CHARGING_COEFFICIENT_KEY: 1}) + G.add_node(1, **{CHARGING_COEFFICIENT_KEY: 1}) + + gv_lower = get_possible_arriving_soc(G, 0, self.U) + assert gv_lower == [0] + + gv_higher = get_possible_arriving_soc(G, 1, self.U) + assert gv_higher == [0] + + @pytest.mark.parametrize('c_0,c_1', [(1, 2), (1, 1)]) + def test_equal_unreachable(self, graph_w_gt_U, c_0, c_1): + G: nx.Graph = graph_w_gt_U + G.add_node(0, **{CHARGING_COEFFICIENT_KEY: c_0}) + G.add_node(1, **{CHARGING_COEFFICIENT_KEY: c_1}) + + gv_lower = get_possible_arriving_soc(G, 0, self.U) + assert gv_lower == [0] + + gv_higher = get_possible_arriving_soc(G, 1, self.U) + assert gv_higher == [0] + + class TestRouting: def test_shortest_path(self): G = get_graph(edge_case) -- GitLab