Source code for pywhy_graphs.classes.timeseries.digraph

import networkx as nx

from pywhy_graphs.classes.timeseries.base import BaseTimeSeriesGraph, TsGraphEdgeMixin


[docs] class TimeSeriesDiGraph(BaseTimeSeriesGraph, TsGraphEdgeMixin, nx.DiGraph): """A class to imbue directed graph with time-series structure. See ``BaseTimeSeriesGraph`` for documentation on the functionality of time-series graphs. """ # whether or not the graph should be assumed to be stationary stationary: bool = False # whether to check for valid time-directionality in edges check_time_direction: bool = True def __init__(self, incoming_graph_data=None, max_lag: int = 1, **attr): if max_lag <= 0: raise ValueError(f"Max lag for time series graph should be at least 1, not {max_lag}.") attr.update(dict(max_lag=max_lag)) self.graph = dict() self.graph["max_lag"] = max_lag super().__init__(incoming_graph_data=None, **attr) # TODO: this is needed because nx.from_edgelist() checks for type of 'create_using', # which does not work with Protocol classes if incoming_graph_data is not None: # we assume a list of tuples of tuples as edges if isinstance(incoming_graph_data, list): self.add_edges_from(incoming_graph_data) elif isinstance(incoming_graph_data, nx.Graph): for edge in incoming_graph_data.edges: self.add_edge(*sorted(edge, key=lambda x: x[1])) else: raise RuntimeError( f"Not implemented yet for incoming graph data that is of " f"type {type(incoming_graph_data)}." )
[docs] class StationaryTimeSeriesDiGraph(TimeSeriesDiGraph): """Stationary time-series directed graph. A stationary graph is one where lagged edges repeat themselves over time. Edges connecting to nodes in time point "t=0" are all the relevant edges needed to depict the time-series graph. Time-series graph nodes are defined as a cross-product of variables and a time-index. Nodes are always a tuple of variables and the lag. For example, a node could be ``('x', -1)`` indicating the 'x' variable at '-1' lag. Parameters ---------- incoming_graph_data : input graph (optional, default: None) Data to initialize graph. If None (default) an empty graph is created. The data can be any format that is supported by the to_networkx_graph() function, currently including edge list, dict of dicts, dict of lists, NetworkX graph, 2D NumPy array, SciPy sparse matrix, or PyGraphviz graph. max_lag : int, optional The max lag, by default 1. attr : keyword arguments, optional (default= no attributes) Attributes to add to graph as key=value pairs. Attributes ---------- stationary : bool Whether or not the graph is stationary. check_time_direction : bool Whether or not to check time directionality is valid, by default True. May set to False for undirected graphs. Notes ----- A stationary time-series graph is one in which edges over time are repeated. In order to properly query for d-separation, one needs to query up to 2 times the maximum lag. A ts-graph's nodes are defined uniquely by its set of variables and the maximum-lag parameter. Given for example, ``('x', 'y', 'z')`` as the set of variables and a maximum-lag of 2, then there would be 9 total nodes in the graph consisting of the cross-product of ``('x', 'y', 'z')`` and ``(0, 1, 2)``. Nodes are automatically added, or deleted depending on the value of the maximum-lag in the graph. """ # whether or not the graph should be assumed to be stationary stationary: bool = True def __init__( self, incoming_graph_data=None, max_lag: int = 1, stationary: bool = True, check_time_direction: bool = True, **attr, ): self.stationary = stationary self.check_time_direction = check_time_direction super(StationaryTimeSeriesDiGraph, self).__init__( incoming_graph_data=incoming_graph_data, max_lag=max_lag, **attr )