o
    3ήc*                     @   sH   d Z ddlZddlmZmZ ddgZG dd deZG dd deZdS )	u  
*****************************
Time-respecting VF2 Algorithm
*****************************

An extension of the VF2 algorithm for time-respecting graph isomorphism
testing in temporal graphs.

A temporal graph is one in which edges contain a datetime attribute,
denoting when interaction occurred between the incident nodes. A
time-respecting subgraph of a temporal graph is a subgraph such that
all interactions incident to a node occurred within a time threshold,
delta, of each other. A directed time-respecting subgraph has the
added constraint that incoming interactions to a node must precede
outgoing interactions from the same node - this enforces a sense of
directed flow.

Introduction
------------

The TimeRespectingGraphMatcher and TimeRespectingDiGraphMatcher
extend the GraphMatcher and DiGraphMatcher classes, respectively,
to include temporal constraints on matches. This is achieved through
a semantic check, via the semantic_feasibility() function.

As well as including G1 (the graph in which to seek embeddings) and
G2 (the subgraph structure of interest), the name of the temporal
attribute on the edges and the time threshold, delta, must be supplied
as arguments to the matching constructors.

A delta of zero is the strictest temporal constraint on the match -
only embeddings in which all interactions occur at the same time will
be returned. A delta of one day will allow embeddings in which
adjacent interactions occur up to a day apart.

Examples
--------

Examples will be provided when the datetime type has been incorporated.


Temporal Subgraph Isomorphism
-----------------------------

A brief discussion of the somewhat diverse current literature will be
included here.

References
----------

[1] Redmond, U. and Cunningham, P. Temporal subgraph isomorphism. In:
The 2013 IEEE/ACM International Conference on Advances in Social
Networks Analysis and Mining (ASONAM). Niagara Falls, Canada; 2013:
pages 1451 - 1452. [65]

For a discussion of the literature on temporal networks:

[3] P. Holme and J. Saramaki. Temporal networks. Physics Reports,
519(3):97–125, 2012.

Notes
-----

Handles directed and undirected graphs and graphs with parallel edges.

    N   )DiGraphMatcherGraphMatcherTimeRespectingGraphMatcherTimeRespectingDiGraphMatcherc                       s4   e Zd Z fddZdd Zdd Zdd Z  ZS )	r   c                       || _ || _t || dS )ai  Initialize TimeRespectingGraphMatcher.

        G1 and G2 should be nx.Graph or nx.MultiGraph instances.

        Examples
        --------
        To create a TimeRespectingGraphMatcher which checks for
        syntactic and semantic feasibility:

        >>> from networkx.algorithms import isomorphism
        >>> from datetime import timedelta
        >>> G1 = nx.Graph(nx.path_graph(4, create_using=nx.Graph()))

        >>> G2 = nx.Graph(nx.path_graph(4, create_using=nx.Graph()))

        >>> GM = isomorphism.TimeRespectingGraphMatcher(
        ...     G1, G2, "date", timedelta(days=1)
        ... )
        Ntemporal_attribute_namedeltasuper__init__selfG1G2r	   r
   	__class__ Z/tmp/pip-target-vg8gfxp4/lib/python/networkx/algorithms/isomorphism/temporalisomorphvf2.pyr   L      z#TimeRespectingGraphMatcher.__init__c                 C   s   g }|D ](}t |tjr||| | | j  q|| |  D ]
}||| j  q!qtdd |D r:td| pGt|t	| | j
kS )z|
        Edges one hop out from a node in the mapping should be
        time-respecting with respect to each other.
        c                 s       | ]}|d u V  qd S Nr   .0xr   r   r   	<genexpr>r       z5TimeRespectingGraphMatcher.one_hop.<locals>.<genexpr>z,Datetime not supplied for at least one edge.)
isinstancenxGraphappendr	   valuesany
ValueErrormaxminr
   )r   GxGx_node	neighborsdatesnedger   r   r   one_hopd   s   z"TimeRespectingGraphMatcher.one_hopc                       t  fdd|D S )zK
        Paths of length 2 from Gx_node should be time-respecting.
        c                 3   s6    | ]}  |fd d | D g V  qdS )c                       g | ]}| v r|qS r   r   r   r*   core_xr   r   
<listcomp>{       z@TimeRespectingGraphMatcher.two_hop.<locals>.<genexpr>.<listcomp>N)r,   )r   vr&   r'   r1   r   r   r   r   z   s
    $
z5TimeRespectingGraphMatcher.two_hop.<locals>.<genexpr>all)r   r&   r1   r'   r(   r   r5   r   two_hopv   s   z"TimeRespectingGraphMatcher.two_hopc                    sH    fdd j | D }  j ||sdS   j  j||s"dS dS )  Returns True if adding (G1_node, G2_node) is semantically
        feasible.

        Any subclass which redefines semantic_feasibility() must
        maintain the self.tests if needed, to keep the match() method
        functional. Implementations should consider multigraphs.
        c                       g | ]	}| j v r|qS r   core_1r/   r   r   r   r2          zCTimeRespectingGraphMatcher.semantic_feasibility.<locals>.<listcomp>FT)r   r,   r8   r<   )r   G1_nodeG2_noder(   r   r=   r   semantic_feasibility   s   z/TimeRespectingGraphMatcher.semantic_feasibility)__name__
__module____qualname__r   r,   r8   rA   __classcell__r   r   r   r   r   K   s
    	c                       sp   e Zd Z fddZdd Zdd Zdd Zd	d
 Zdd ZdddZ	dddZ
dd Zdd Zdd Z  ZS )r   c                    r   )a{  Initialize TimeRespectingDiGraphMatcher.

        G1 and G2 should be nx.DiGraph or nx.MultiDiGraph instances.

        Examples
        --------
        To create a TimeRespectingDiGraphMatcher which checks for
        syntactic and semantic feasibility:

        >>> from networkx.algorithms import isomorphism
        >>> from datetime import timedelta
        >>> G1 = nx.DiGraph(nx.path_graph(4, create_using=nx.DiGraph()))

        >>> G2 = nx.DiGraph(nx.path_graph(4, create_using=nx.DiGraph()))

        >>> GM = isomorphism.TimeRespectingDiGraphMatcher(
        ...     G1, G2, "date", timedelta(days=1)
        ... )
        Nr   r   r   r   r   r      r   z%TimeRespectingDiGraphMatcher.__init__c                 C   sj   g }t |tjr|D ]}||| | | j  q
|S |D ]}|| |  D ]
}||| j  q'q|S )z;
        Get the dates of edges from predecessors.
        r   r   DiGraphr    r	   r!   )r   r&   r'   r1   pred
pred_datesr*   r+   r   r   r   get_pred_dates      z+TimeRespectingDiGraphMatcher.get_pred_datesc                 C   sj   g }t |tjr|D ]}||| | | j  q
|S |D ]}|| |  D ]
}||| j  q'q|S )z7
        Get the dates of edges to successors.
        rF   )r   r&   r'   r1   succ
succ_datesr*   r+   r   r   r   get_succ_dates   rK   z+TimeRespectingDiGraphMatcher.get_succ_datesc                 C   s8   |  ||||}| ||||}| ||o| ||S )z
        The ego node.
        )rJ   rN   test_onetest_two)r   r&   r'   r1   rH   rL   rI   rM   r   r   r   r,      s
   z$TimeRespectingDiGraphMatcher.one_hopc                    r-   )z4
        The predeccessors of the ego node.
        c                 3   s8    | ]}  | | |V  qd S r   r,   predssuccs)r   pr5   r   r   r      s    
z<TimeRespectingDiGraphMatcher.two_hop_pred.<locals>.<genexpr>r6   )r   r&   r'   r1   rH   r   r5   r   two_hop_pred      z)TimeRespectingDiGraphMatcher.two_hop_predc                    r-   )z1
        The successors of the ego node.
        c                 3   s8    | ]}  | | |V  qd S r   rQ   )r   sr5   r   r   r      s    
z<TimeRespectingDiGraphMatcher.two_hop_succ.<locals>.<genexpr>r6   )r   r&   r'   r1   rL   r   r5   r   two_hop_succ   rV   z)TimeRespectingDiGraphMatcher.two_hop_succNc                    *    fdd| |D }|r|| |S )Nc                    r.   r   r   r/   r0   r   r   r2      r3   z6TimeRespectingDiGraphMatcher.preds.<locals>.<listcomp>)predecessorsr    )r   r&   r1   r4   r'   rH   r   r0   r   rR         
z"TimeRespectingDiGraphMatcher.predsc                    rY   )Nc                    r.   r   r   r/   r0   r   r   r2      r3   z6TimeRespectingDiGraphMatcher.succs.<locals>.<listcomp>)
successorsr    )r   r&   r1   r4   r'   rL   r   r0   r   rS      r[   z"TimeRespectingDiGraphMatcher.succsc                 C   sX   d}|| }t dd |D rtd|  dt|k r*|d |d  | jks*d}|S )z
        Edges one hop out from Gx_node in the mapping should be
        time-respecting with respect to each other, regardless of
        direction.
        Tc                 s   r   r   r   r   r   r   r   r     r   z8TimeRespectingDiGraphMatcher.test_one.<locals>.<genexpr>z4Date or datetime not supplied for at least one edge.r   F)r"   r#   sortlenr
   )r   rI   rM   time_respectingr)   r   r   r   rO      s   "z%TimeRespectingDiGraphMatcher.test_onec                 C   sD   d}|   |   dt|k r dt|k r |d |d k r d}|S )zq
        Edges from a dual Gx_node in the mapping should be ordered in
        a time-respecting manner.
        Tr   r]   F)r^   r_   )r   rI   rM   r`   r   r   r   rP     s   

z%TimeRespectingDiGraphMatcher.test_twoc                    s    fdd j |D  fdd j |D }}  j | j||s(dS   j | j|s4dS   j | j|s@dS dS )r9   c                    r:   r   r;   r/   r=   r   r   r2   (  r>   zETimeRespectingDiGraphMatcher.semantic_feasibility.<locals>.<listcomp>c                    r:   r   r;   r/   r=   r   r   r2   )  r>   FT)r   rZ   r\   r,   r<   rU   rX   )r   r?   r@   rH   rL   r   r=   r   rA     s   	z1TimeRespectingDiGraphMatcher.semantic_feasibilityr   )rB   rC   rD   r   rJ   rN   r,   rU   rX   rR   rS   rO   rP   rA   rE   r   r   r   r   r      s    


)	__doc__networkxr   isomorphvf2r   r   __all__r   r   r   r   r   r   <module>   s    CE