From 5f35c29db34801b44196de82add877f67582a06e Mon Sep 17 00:00:00 2001 From: Andres Ladino Date: Thu, 12 Nov 2020 14:29:10 +0100 Subject: [PATCH 1/7] =?UTF-8?q?=F0=9F=97=91=20Cleaning?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itstools/connectv2x/connectv2x.py | 1 - itstools/vplatoon/vplatoon.py | 1 - 2 files changed, 2 deletions(-) delete mode 100644 itstools/connectv2x/connectv2x.py delete mode 100644 itstools/vplatoon/vplatoon.py diff --git a/itstools/connectv2x/connectv2x.py b/itstools/connectv2x/connectv2x.py deleted file mode 100644 index dd0b80e..0000000 --- a/itstools/connectv2x/connectv2x.py +++ /dev/null @@ -1 +0,0 @@ -"""Main module.""" diff --git a/itstools/vplatoon/vplatoon.py b/itstools/vplatoon/vplatoon.py deleted file mode 100644 index dd0b80e..0000000 --- a/itstools/vplatoon/vplatoon.py +++ /dev/null @@ -1 +0,0 @@ -"""Main module.""" From ae983be90b7214a02c6c59904450e415b8c79eef Mon Sep 17 00:00:00 2001 From: Andres Ladino Date: Thu, 12 Nov 2020 14:30:11 +0100 Subject: [PATCH 2/7] =?UTF-8?q?=E2=99=BF=EF=B8=8F=20=20Vissibility=20of=20?= =?UTF-8?q?functions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itstools/connectv2x/__init__.py | 9 ++++----- itstools/vplatoon/__init__.py | 8 +++----- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/itstools/connectv2x/__init__.py b/itstools/connectv2x/__init__.py index 599062b..0cee31d 100644 --- a/itstools/connectv2x/__init__.py +++ b/itstools/connectv2x/__init__.py @@ -1,5 +1,4 @@ -"""Top-level package for connectv2x.""" - -__author__ = """Andres Ladino""" -__email__ = 'aladinoster@gmail.com' -__version__ = '0.3.0' +from .carfollow import Tampere +from .support import sigmoid, speed_pulse +from .plottools import plot_xva +from .messages import Msg2, Msg1 diff --git a/itstools/vplatoon/__init__.py b/itstools/vplatoon/__init__.py index 6104d0b..f67b271 100644 --- a/itstools/vplatoon/__init__.py +++ b/itstools/vplatoon/__init__.py @@ -1,5 +1,3 @@ -"""Top-level package for vplatoon.""" - -__author__ = """Andres Ladino""" -__email__ = 'aladinoster@gmail.com' -__version__ = '0.3.0' +from .traffic import FundamentalDiagram +from .vehicles import System, Integrator +from .pid import PID, PIDlim, PIDantiwindup From b01eb6bce4e1d8e8556e288ed7af5dfd6536893e Mon Sep 17 00:00:00 2001 From: Andres Ladino Date: Thu, 12 Nov 2020 16:09:18 +0100 Subject: [PATCH 3/7] =?UTF-8?q?=F0=9F=8E=A8=20=20Update=20Fundamental=20di?= =?UTF-8?q?agram?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itstools/connectv2x/traffic.py | 16 ++++++---------- itstools/vplatoon/traffic.py | 16 ++++++---------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/itstools/connectv2x/traffic.py b/itstools/connectv2x/traffic.py index fe719c3..d1516ee 100644 --- a/itstools/connectv2x/traffic.py +++ b/itstools/connectv2x/traffic.py @@ -6,6 +6,7 @@ # Imports # ============================================================================== +from dataclasses import dataclass import numpy as np from bokeh.plotting import figure, show from .vehicles import K_X, W_I, U_I @@ -15,11 +16,12 @@ # ============================================================================== +@dataclass class FundamentalDiagram: - def __init__(self, w=W_I, u=U_I, k_x=K_X): - self.w = w - self.k_x = k_x - self.u = u + + w: float = W_I + k_x: float = K_X + u: float = U_I @property def C(self): @@ -57,9 +59,3 @@ def plot_diagram(self): p.xaxis.axis_label = xlabel p.yaxis.axis_label = ylabel return p - - def __repr__(self): - return f"{self.__class__.__name__}({self.w},{self.u},{self.k_x})" - - def __str__(self): - return f"Fundamental diagram w: {self.w}, u:{self.u}, k_x:{self.k_x}" diff --git a/itstools/vplatoon/traffic.py b/itstools/vplatoon/traffic.py index fe719c3..d1516ee 100644 --- a/itstools/vplatoon/traffic.py +++ b/itstools/vplatoon/traffic.py @@ -6,6 +6,7 @@ # Imports # ============================================================================== +from dataclasses import dataclass import numpy as np from bokeh.plotting import figure, show from .vehicles import K_X, W_I, U_I @@ -15,11 +16,12 @@ # ============================================================================== +@dataclass class FundamentalDiagram: - def __init__(self, w=W_I, u=U_I, k_x=K_X): - self.w = w - self.k_x = k_x - self.u = u + + w: float = W_I + k_x: float = K_X + u: float = U_I @property def C(self): @@ -57,9 +59,3 @@ def plot_diagram(self): p.xaxis.axis_label = xlabel p.yaxis.axis_label = ylabel return p - - def __repr__(self): - return f"{self.__class__.__name__}({self.w},{self.u},{self.k_x})" - - def __str__(self): - return f"Fundamental diagram w: {self.w}, u:{self.u}, k_x:{self.k_x}" From 4e89e649bc6bc2e4f946f52c421801cbb5c5f924 Mon Sep 17 00:00:00 2001 From: Andres Ladino Date: Mon, 16 Nov 2020 10:10:16 +0100 Subject: [PATCH 4/7] =?UTF-8?q?=F0=9F=9A=91=20=20Fixing=20tests=20Although?= =?UTF-8?q?=20tests=20need=20still=20to=20be=20created?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/test_macrotrasim.py | 2 +- tests/test_vplatoon.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_macrotrasim.py b/tests/test_macrotrasim.py index d55cb60..eeaa199 100644 --- a/tests/test_macrotrasim.py +++ b/tests/test_macrotrasim.py @@ -5,7 +5,7 @@ import pytest -from itstools.macrotrasim import macrotrasim +from itstools.macrotrasim import FundamentalDiagram @pytest.fixture diff --git a/tests/test_vplatoon.py b/tests/test_vplatoon.py index 3a07bcb..d14e679 100644 --- a/tests/test_vplatoon.py +++ b/tests/test_vplatoon.py @@ -5,7 +5,7 @@ import pytest -from itstools.vplatoon import vplatoon +from itstools.vplatoon import PID @pytest.fixture From 4a17f58e0439b38086ca644a4b2afab63492d383 Mon Sep 17 00:00:00 2001 From: Andres Ladino Date: Mon, 16 Nov 2020 15:31:24 +0100 Subject: [PATCH 5/7] =?UTF-8?q?=F0=9F=9A=A7=20=20Adding=20Macroscopic=20tr?= =?UTF-8?q?affic=20Objects=20for=20macroscopic=20traffic=20simulator,=20ne?= =?UTF-8?q?twork,=20lights?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itstools/macrotrasim/__init__.py | 8 +- itstools/macrotrasim/constants.py | 7 + itstools/macrotrasim/demand.py | 0 itstools/macrotrasim/lights.py | 46 ++++++ itstools/macrotrasim/macrotrasim.py | 1 - itstools/macrotrasim/manhattan.py | 80 +++++++++++ itstools/macrotrasim/metaclass.py | 13 ++ itstools/macrotrasim/network.py | 212 ++++++++++++++++++++++++++++ itstools/macrotrasim/traffic.py | 72 ++++++++++ setup.py | 1 + 10 files changed, 434 insertions(+), 6 deletions(-) create mode 100644 itstools/macrotrasim/constants.py create mode 100644 itstools/macrotrasim/demand.py create mode 100644 itstools/macrotrasim/lights.py delete mode 100644 itstools/macrotrasim/macrotrasim.py create mode 100644 itstools/macrotrasim/manhattan.py create mode 100644 itstools/macrotrasim/metaclass.py create mode 100644 itstools/macrotrasim/network.py create mode 100644 itstools/macrotrasim/traffic.py diff --git a/itstools/macrotrasim/__init__.py b/itstools/macrotrasim/__init__.py index e8160c3..e52ca04 100644 --- a/itstools/macrotrasim/__init__.py +++ b/itstools/macrotrasim/__init__.py @@ -1,5 +1,3 @@ -"""Top-level package for macrotrasim.""" - -__author__ = """Andres Ladino""" -__email__ = 'aladinoster@gmail.com' -__version__ = '0.1.0' +from .traffic import FundamentalDiagram +from .network import Network +from .lights import Light diff --git a/itstools/macrotrasim/constants.py b/itstools/macrotrasim/constants.py new file mode 100644 index 0000000..ee04ce8 --- /dev/null +++ b/itstools/macrotrasim/constants.py @@ -0,0 +1,7 @@ +RANDOM_SEED = 100 +TRAFFIC_LIGHT_PERIOD = 90 + +U_I = 25 +W_I = 6.25 # 5 # 6.25 +K_X = 0.16 # 0.2 # 0.16 +DT = 1 / (W_I * K_X) diff --git a/itstools/macrotrasim/demand.py b/itstools/macrotrasim/demand.py new file mode 100644 index 0000000..e69de29 diff --git a/itstools/macrotrasim/lights.py b/itstools/macrotrasim/lights.py new file mode 100644 index 0000000..70ec64f --- /dev/null +++ b/itstools/macrotrasim/lights.py @@ -0,0 +1,46 @@ +# ============================================================================== +# STANDARD IMPORTS +# ============================================================================== + +from dataclasses import dataclass, field +import numpy as np + +# ============================================================================== +# INTERNAL IMPORTS +# ============================================================================== + +from .constants import TRAFFIC_LIGHT_PERIOD as T +from .constants import RANDOM_SEED + +# ============================================================================== +# CLASS AND DEFINITIONS +# ============================================================================== + +RANDOM_SEED = 100 +np.random.state = RANDOM_SEED +np.random.seed = RANDOM_SEED + + +def random_initializer(period: int = T): + green_time = np.random.randint(period) + return np.concatenate([np.ones(green_time), np.zeros(T - green_time)]) + + +@dataclass +class Light: + state: np.array = field(default_factory=random_initializer) + period: int = T + + @property + def duty(self): + """Duty cycle""" + return np.sum(self.state) / len(self.state) + + def __index__(self, value): + return self.state[value] + + def setlight(self, duty: float = 0): + green_time = 10 + self.state = np.concatenate( + [np.ones(green_time), np.zeros(self.period - green_time)] + ) diff --git a/itstools/macrotrasim/macrotrasim.py b/itstools/macrotrasim/macrotrasim.py deleted file mode 100644 index dd0b80e..0000000 --- a/itstools/macrotrasim/macrotrasim.py +++ /dev/null @@ -1 +0,0 @@ -"""Main module.""" diff --git a/itstools/macrotrasim/manhattan.py b/itstools/macrotrasim/manhattan.py new file mode 100644 index 0000000..3adad53 --- /dev/null +++ b/itstools/macrotrasim/manhattan.py @@ -0,0 +1,80 @@ +""" +Manhattan Network +================= +""" + +import networkx as nx +from networkx.readwrite.edgelist import write_weighted_edgelist + + +def create_manhattan_intersections(m: int = 10, n: int = 10): + """ Build a manhattan grid road graph of n by m roads + + Args: + m (int): number of rows + n (int): number of columns + + N,W,E,S: North,Weast,East,South + """ + nodes = tuple((i, j) for i in range(m) for j in range(n)) + vert_edgesSN = tuple( + (o, d) for o, d in zip(nodes, nodes[1:]) if o[1] != n - 1 and o[0] % 2 + ) + vert_edgesNS = tuple( + (d, o) for o, d in zip(nodes, nodes[1:]) if o[1] != n - 1 and ~o[0] % 2 + ) + vert_edges = vert_edgesSN + vert_edgesNS + + # Suplementary external nodes/edges South + nodes_S = tuple((-1, i) for i in range(n)) + edges_S = tuple(((-1, i), (0, i)) for i in range(n) if i % 2) + tuple( + ((0, i), (-1, i)) for i in range(n) if ~i % 2 + ) + + # Suplementary external nodes/edges North + nodes_N = tuple((m, i) for i in range(n)) + edges_N = tuple(((m, i), (m - 1, i)) for i in range(n) if ~i % 2) + tuple( + ((m - 1, i), (m, i)) for i in range(n) if i % 2 + ) + + nodes = nodes + nodes_S + nodes_N + + nodes_transposed = tuple((i, j) for j in range(n) for i in range(m)) + horz_edgesEW = tuple( + (o, d) + for o, d in zip(nodes_transposed, nodes_transposed[1:]) + if o[0] != m - 1 and o[1] % 2 + ) + horz_edgesWE = tuple( + (d, o) + for o, d in zip(nodes_transposed, nodes_transposed[1:]) + if o[0] != m - 1 and ~o[1] % 2 + ) + horz_edges = horz_edgesEW + horz_edgesWE + + # Suplementary external nodes/edges West + nodes_W = tuple((i, -1) for i in range(m)) + edges_W = tuple(((i, -1), (i, 0)) for i in range(n) if i % 2) + tuple( + ((i, 0), (i, -1)) for i in range(n) if ~i % 2 + ) + + # Suplementary external nodes/edges East + nodes_E = tuple((i, n) for i in range(m)) + edges_E = tuple(((i, n), (i, n - 1)) for i in range(n) if ~i % 2) + tuple( + ((i, n - 1), (i, n)) for i in range(n) if i % 2 + ) + + nodes = nodes + nodes_W + nodes_E + K = 10 # Scale factor + # Positions + nodesnpos = tuple((n,) + ({"pos": (K * n[0], K * n[1])},) for n in nodes) + + edges = horz_edges + vert_edges + edges_S + edges_N + edges_E + edges_W + weightededges = tuple(e + (0,) for e in edges) + + G = nx.DiGraph() + G.add_nodes_from(nodesnpos) + G.add_weighted_edges_from(weightededges, weight="density") + + pos = {n: G.nodes[n]["pos"] for n in G.nodes} + return G, pos diff --git a/itstools/macrotrasim/metaclass.py b/itstools/macrotrasim/metaclass.py new file mode 100644 index 0000000..5dc8b84 --- /dev/null +++ b/itstools/macrotrasim/metaclass.py @@ -0,0 +1,13 @@ +import abc +import networkx as nx +from dataclasses import dataclass + + +@dataclass +class NetworkAbs(metaclass=abc.ABCMeta): + @abc.abstractproperty + def supply(self): + pass + + def demand(self): + return 2 diff --git a/itstools/macrotrasim/network.py b/itstools/macrotrasim/network.py new file mode 100644 index 0000000..7cbee06 --- /dev/null +++ b/itstools/macrotrasim/network.py @@ -0,0 +1,212 @@ +# ============================================================================== +# STANDARD IMPORTS +# ============================================================================== + +from typing import ItemsView + +from networkx.algorithms.link_prediction import within_inter_cluster +from .metaclass import NetworkAbs +import networkx as nx +from dataclasses import dataclass +import pandas as pd + +from .lights import Light +from .traffic import RoadLink +from .manhattan import create_manhattan_intersections + +# ============================================================================== +# CLASS AND DEFINITIONS +# ============================================================================== + + +@dataclass +class Network(NetworkAbs): + sampleTime: int = 1 + period: int = 90 + lights: int = 0 + isControlled: bool = True + rTurning: float = 0.65 + m: int = 2 + n: int = 2 + + def __post_init__(self): + print(f"Initializing network: {self.n} x {self.m}") + self.network, self._netpos = create_manhattan_intersections( + m=self.m, n=self.n + ) + self.populate_road_objects() + self.create_adjacency_road_xssing_matrix() + self.create_road_graph() + + def populate_road_objects(self): + """ Populate with road objects and traffic lights + """ + self._roadObjects = { + i: {"id": n, "road": RoadLink(), "light": Light()} + for n, i in enumerate(self.network.edges()) + } + self._roads = tuple(v["id"] for i, v in self._roadObjects.items()) + self._roadinter_map = {v["id"]: k for k, v in self._roadObjects.items()} + + @property + def roads(self): + """ Return road identifiers + """ + return self._roads + + def create_adjacency_road_xssing_matrix(self): + """ Creates the road-intersection adajacency matrix noted by + m x n : m roads / n intersections + + i->j means road i is upstream of intersection j. eq intersection j is downstream of road i + + j->i means road i is downstream of intersection j. eq intersection j is upstream of road i + + (i,j): -1 if i->j , 1 if j-> i, 0 elsewhere + """ + self._intersectionMatrix = pd.DataFrame( + index=self.roads, columns=self.network.nodes(), data=0 + ) + for road in self.roads: + origin, destination = self._roadinter_map[road] + self._intersectionMatrix.loc[road, origin] = -1 + self._intersectionMatrix.loc[road, destination] = 1 + + def create_road_graph(self): + """ Creates a graph for roads only with the only purpose to reduce + online computational burden + + Adjacency matrix: + i->j means road i is upstream of road j. eq road j is downstream of road i + """ + + def road_positions(roadid): + data = self._roadinter_map[roadid] + origin = self.network.nodes[data[0]]["pos"] + destination = self.network.nodes[data[1]]["pos"] + x = (destination[0] + origin[0]) / 2 + y = (destination[1] + origin[1]) / 2 + return x, y + + self.roadgraph = nx.DiGraph() + self._roadpos = [road_positions(road) for road in self.roads] + self.roadgraph.add_nodes_from( + [ + (road, {"pos": road_positions(road), "density": 0.0}) + for road in self.roads + ] + ) + + # Adding edges + + edges = [] + for road in self.roads: + downstream, ratios = self.get_downstream_roads(road) + [ + self.roadgraph.add_edge(road, d, ratio=r) + for d, r in zip(downstream, ratios) + ] + upstream, ratios = self.get_upstream_roads(road) + [ + self.roadgraph.add_edge(u, road, ratio=r) + for u, r in zip(upstream, ratios) + ] + + def get_downstream_roads(self, road): + """ Returns the downstream roads of road i + """ + upstream_xssing, downstream_xssing = self._roadinter_map[road] + downstream = self._intersectionMatrix[ + self._intersectionMatrix[downstream_xssing].eq(-1) + ].index.tolist() + + if downstream: + + # Downstream xssings + dst_xssings = [self.get_downstream_xssing(d) for d in downstream] + + ratios = [] + for d in dst_xssings: + o = upstream_xssing + if o[0] == d[0] or o[1] == d[1]: + ratios.append(self.rTurning) + else: + ratios.append(1 - self.rTurning) + else: + ratios = [] + + return downstream, ratios + + def get_upstream_roads(self, road): + """ Returns the upstream roads of road i + """ + upstream_xssing, downstream_xssing = self._roadinter_map[road] + upstream = self._intersectionMatrix[ + self._intersectionMatrix[upstream_xssing].eq(1) + ].index.tolist() + + if upstream: + + # Upstream xssings + ust_xssings = [self.get_upstream_xssing(d) for d in upstream] + + ratios = [] + for o in ust_xssings: + d = downstream_xssing + if o[0] == d[0] or o[1] == d[1]: + ratios.append(self.rTurning) + else: + ratios.append(1 - self.rTurning) + else: + ratios = [] + + return upstream, ratios + + def get_downstream_xssing(self, road): + """Return downstream intersection of road i + """ + return self._roadinter_map[road][1] + + def get_upstream_xssing(self, road): + """Return upstream intersection of road i + """ + return self._roadinter_map[road][0] + + def plot_road_network( + self, xssing_labels=False, road_labels=False, figsize=(20, 10) + ): + """ Plots the road graph + """ + from matplotlib import pyplot as plt + + f, ax = plt.subplots(1, 2, figsize=figsize) + options = {"node_size": 500, "alpha": 0.5} + nx.draw( + self.network, + pos=self._netpos, + with_labels=xssing_labels, + ax=ax[0], + font_size=8, + **options, + ) + nx.draw_networkx_nodes( + self.roadgraph, + pos=self._roadpos, + node_color="red", + ax=ax[0], + node_size=10, + ) + ax[0].set_title("Intersection Graph") + nx.draw( + self.roadgraph, + pos=self._roadpos, + node_color="red", + with_labels=road_labels, + ax=ax[1], + font_size=8, + **options, + ) + ax[1].set_title("Road Graph") + + def supply(self): + pass diff --git a/itstools/macrotrasim/traffic.py b/itstools/macrotrasim/traffic.py new file mode 100644 index 0000000..1531694 --- /dev/null +++ b/itstools/macrotrasim/traffic.py @@ -0,0 +1,72 @@ +""" + Traffic information +""" + +# ============================================================================== +# Imports +# ============================================================================== + +from dataclasses import dataclass +from itertools import count +from typing import Iterable + +import numpy as np +from bokeh.plotting import figure, show +from .constants import K_X, W_I, U_I + +# ============================================================================== +# Clases +# ============================================================================== + + +@dataclass +class FundamentalDiagram: + + w: float = W_I + k_x: float = K_X + u: float = U_I + + @property + def C(self): + """ Capacity""" + return self.u * self.k_c + + @property + def k_c(self): + """ Critical density""" + return self.w * self.k_x / (self.w + self.u) + + @property + def s_x(self): + """ Critical spacing""" + return 1 / self.k_x + + def compute_flow(self, k): + free_branch = lambda x: self.u * x + cong_branch = lambda x: -(x - self.k_x) * self.w + flow = np.piecewise( + k, [k < self.k_c, k >= self.k_c], [free_branch, cong_branch] + ) + return flow + + def plot_diagram(self): + k = np.linspace(0, self.k_x, 100) + q = self.compute_flow(k) + + title = f"Fundamental diagram w: {self.w}, u:{self.u}, k_x:{self.k_x}" + xlabel = "Density [veh/km]" + ylabel = "Flow [veh/h]" + + p = figure(title=title, tools=[], plot_height=500, plot_width=500) + p.line(k, q) + p.xaxis.axis_label = xlabel + p.yaxis.axis_label = ylabel + return p + + +@dataclass +class RoadLink: + _idx: Iterable[int] = count(0) + + def __post_init__(self): + self.idx = next(self.__class__._idx) diff --git a/setup.py b/setup.py index 6f338f0..a49191e 100644 --- a/setup.py +++ b/setup.py @@ -15,6 +15,7 @@ "bokeh>=2.1.1", "pandas>=1.0.0", "matplotlib>=3.2.2", + "scipy>=1.5.4", "jupyter>=1.0.0", ] From a1c0f7dc80ec74f330a7469629dff7c750026854 Mon Sep 17 00:00:00 2001 From: Andres Ladino Date: Mon, 16 Nov 2020 18:42:36 +0100 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=9A=A7=20Adding=20Demand=20info?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- itstools/macrotrasim/__init__.py | 2 +- itstools/macrotrasim/demand.py | 0 itstools/macrotrasim/network.py | 10 ++++++++- itstools/macrotrasim/traffic.py | 38 +++++++++++++++++++++++++++++++- setup.py | 2 ++ 5 files changed, 49 insertions(+), 3 deletions(-) delete mode 100644 itstools/macrotrasim/demand.py diff --git a/itstools/macrotrasim/__init__.py b/itstools/macrotrasim/__init__.py index e52ca04..c978002 100644 --- a/itstools/macrotrasim/__init__.py +++ b/itstools/macrotrasim/__init__.py @@ -1,3 +1,3 @@ -from .traffic import FundamentalDiagram +from .traffic import FundamentalDiagram, RoadLink, Demand from .network import Network from .lights import Light diff --git a/itstools/macrotrasim/demand.py b/itstools/macrotrasim/demand.py deleted file mode 100644 index e69de29..0000000 diff --git a/itstools/macrotrasim/network.py b/itstools/macrotrasim/network.py index 7cbee06..a2f3aaa 100644 --- a/itstools/macrotrasim/network.py +++ b/itstools/macrotrasim/network.py @@ -97,7 +97,7 @@ def road_positions(roadid): ] ) - # Adding edges + # Adding edges edges = [] for road in self.roads: @@ -172,6 +172,14 @@ def get_upstream_xssing(self, road): """ return self._roadinter_map[road][0] + def get_entry_roads(self): + """ Return entry roads ids""" + return [x for x in self.roads if not self.get_downstream_roads(x)[0]] + + def get_exit_roads(self): + """ Return exit roads ids""" + return [x for x in self.roads if not self.get_upstream_roads(x)[0]] + def plot_road_network( self, xssing_labels=False, road_labels=False, figsize=(20, 10) ): diff --git a/itstools/macrotrasim/traffic.py b/itstools/macrotrasim/traffic.py index 1531694..41478e5 100644 --- a/itstools/macrotrasim/traffic.py +++ b/itstools/macrotrasim/traffic.py @@ -6,13 +6,18 @@ # Imports # ============================================================================== -from dataclasses import dataclass +from dataclasses import dataclass, field from itertools import count from typing import Iterable +import pandas as pd import numpy as np from bokeh.plotting import figure, show from .constants import K_X, W_I, U_I +import holoviews as hv +import hvplot.pandas + +hv.extension("bokeh") # ============================================================================== # Clases @@ -70,3 +75,34 @@ class RoadLink: def __post_init__(self): self.idx = next(self.__class__._idx) + + +@dataclass +class Demand: + sampling_time: float = 15 + fd: FundamentalDiagram = FundamentalDiagram() + cycle_time: float = 90 + + def __init__(self, network, simulation_steps=50): + self._entry_roads = network.get_entry_roads() + time_vector = np.arange( + 0, simulation_steps * self.cycle_time, self.sampling_time + ) + self._demand = pd.DataFrame( + data=0, columns=network.roads, index=time_vector + ) + self.set_burst_value(self.fd.C) + + def set_burst_value(self, burst_value): + """ Sets the burst values for incomming roads""" + self._demand[self._entry_roads] = burst_value + + def plot(self): + return self._demand.hvplot.heatmap() + + def __iter__(self): + self._it = self._demand.iterrows() + return self._it + + def __next__(self): + yield next(self._it) diff --git a/setup.py b/setup.py index a49191e..831854a 100644 --- a/setup.py +++ b/setup.py @@ -16,6 +16,8 @@ "pandas>=1.0.0", "matplotlib>=3.2.2", "scipy>=1.5.4", + "holoviews>=1.13.5", + "hvplot>=0.6.0", "jupyter>=1.0.0", ] From cdec5d9bdae87e62a80d436cd7e174e17f462a24 Mon Sep 17 00:00:00 2001 From: Andres Ladino Date: Mon, 11 Jan 2021 18:59:14 +0100 Subject: [PATCH 7/7] Adding networkx --- itstools/macrotrasim/network.py | 5 +++++ setup.py | 1 + 2 files changed, 6 insertions(+) diff --git a/itstools/macrotrasim/network.py b/itstools/macrotrasim/network.py index a2f3aaa..68ac6d3 100644 --- a/itstools/macrotrasim/network.py +++ b/itstools/macrotrasim/network.py @@ -19,6 +19,11 @@ # ============================================================================== +@dataclass +class Link: + pass + + @dataclass class Network(NetworkAbs): sampleTime: int = 1 diff --git a/setup.py b/setup.py index 831854a..d6f71c1 100644 --- a/setup.py +++ b/setup.py @@ -19,6 +19,7 @@ "holoviews>=1.13.5", "hvplot>=0.6.0", "jupyter>=1.0.0", + "networkx>=2.4.0", ] setup_requirements = [