ó žÃÒYc@@sŠdZddlmZddlZddlmZmZddlmZm Z ddgZ defd „ƒYZ de fd „ƒYZ dS( sŽ ***************************** Time-respecting VF2 Algorithm ***************************** An extension of the VF2 algorithm for time-respecting graph ismorphism 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. i(tabsolute_importN(tdatetimet timedeltai(t GraphMatchertDiGraphMatchertTimeRespectingGraphMatchertTimeRespectingDiGraphMatchercB@s,eZd„Zd„Zd„Zd„ZRS(cC@s/||_||_tt|ƒj||ƒdS(s 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 >>> 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(ttemporal_attribute_nametdeltatsuperRt__init__(tselftG1tG2RR((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR Ps  cC@sÐg}x~|D]v}t|ƒttjƒƒkrP|j||||jƒq x0|||jƒD]}|j||jƒqeWq Wtd„|Dƒƒr¬tdƒ‚n| pÏt|ƒt |ƒ|j kS(s| Edges one hop out from a node in the mapping should be time-respecting with respect to each other. cs@s|]}|dkVqdS(N(tNone(t.0tx((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pys qss,Datetime not supplied for at least one edge.( ttypetnxtGraphtappendRtvaluestanyt ValueErrortmaxtminR(R tGxtGx_nodet neighborstdatestntedge((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pytone_hopes c@s#t‡‡‡‡fd†|DƒƒS(sK Paths of length 2 from Gx_node should be time-respecting. c3@sN|]D}ˆjˆ|gˆ|D]}|ˆkr |^q ˆgƒVqdS(N(R (RtvR(RRtcore_xR (s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pys ys(tall(R RR"RR((RRR"R s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyttwo_hopuscC@sqg|j|D]}||jkr|^q}|j|j||ƒsKtS|j|j|j||ƒsmtStS(sReturns 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. (R tcore_1R tFalseR$tTrue(R tG1_nodetG2_nodeRR((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pytsemantic_feasibility{s /(t__name__t __module__R R R$R*(((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyRNs   cB@sqeZd„Zd„Zd„Zd„Zd„Zd„Zd d„Z d d„Z d„Z d „Z d „Z RS( cC@s/||_||_tt|ƒj||ƒdS(s2Initialize 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 >>> 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)) N(RRR RR (R R R RR((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR Žs  cC@sœg}t|ƒttjƒƒkrTxq|D]"}|j||||jƒq+WnDxA|D]9}x0|||jƒD]}|j||jƒqvWq[W|S(s; Get the dates of edges from predecessors. (RRtDiGraphRRR(R RRR"tpredt pred_datesRR((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pytget_pred_dates£s # cC@sœg}t|ƒttjƒƒkrTxq|D]"}|j||||jƒq+WnDxA|D]9}x0|||jƒD]}|j||jƒqvWq[W|S(s7 Get the dates of edges to successors. (RRR-RRR(R RRR"tsucct succ_datesRR((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pytget_succ_dates±s # cC@sR|j||||ƒ}|j||||ƒ}|j||ƒoQ|j||ƒS(s The ego node. (R0R3ttest_onettest_two(R RRR"R.R1R/R2((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR ¿sc@s#t‡‡‡‡fd†|DƒƒS(s4 The predeccessors of the ego node. c 3@sK|]A}ˆjˆ|ˆˆjˆˆ|ƒˆjˆˆ|ˆƒƒVqdS(N(R tpredstsuccs(Rtp(RRR"R (s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pys Ës(R#(R RRR"R.((RRR"R s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyt two_hop_predÇsc@s#t‡‡‡‡fd†|DƒƒS(s1 The successors of the ego node. c 3@sK|]A}ˆjˆ|ˆˆjˆˆ|ˆƒˆjˆˆ|ƒƒVqdS(N(R R6R7(Rts(RRR"R (s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pys Ñs(R#(R RRR"R1((RRR"R s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyt two_hop_succÍscC@sHg|j|ƒD]}||kr|^q}|rD|j|ƒn|S(N(t predecessorsR(R RR"R!RRR.((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR6Ós.cC@sHg|j|ƒD]}||kr|^q}|rD|j|ƒn|S(N(t successorsR(R RR"R!RRR1((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR7Ùs.cC@szt}||}td„|Dƒƒr5tdƒ‚n|jƒdt|ƒkrv|d|d|jk rvt}n|S(sž Edges one hop out from Gx_node in the mapping should be time-respecting with respect to each other, regardless of direction. cs@s|]}|dkVqdS(N(R(RR((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pys èss4Date or datetime not supplied for at least one edge.iiÿÿÿÿ(R'RRtsorttlenRR&(R R/R2ttime_respectingR((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR4ßs  . cC@s_t}|jƒ|jƒdt|ƒkr[dt|ƒkr[|d|dkr[t}n|S(sq Edges from a dual Gx_node in the mapping should be ordered in a time-respecting manner. iiÿÿÿÿ(R'R>R?R&(R R/R2R@((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR5ðs   8 cC@sÖg|jj|ƒD]}||jkr|^qg|jj|ƒD]}||jkrD|^qD}}|j|j||j||ƒsŽtS|j|j||j|ƒs°tS|j|j||j|ƒsÒtStS(sReturns 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. ( R R<R%R=R R&R9R;R'(R R(R)RR.R1((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyR*ýsi!N(R+R,R R0R3R R9R;RR6R7R4R5R*(((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pyRŒs          ( t__doc__t __future__RtnetworkxRRRt isomorphvf2RRt__all__RR(((s‰/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/isomorphism/temporalisomorphvf2.pytCs  >