11"""
2- TemporalSnapshotsGNNGraph(snapshots::AbstractVector{<:GNNGraph} )
2+ TemporalSnapshotsGNNGraph(snapshots)
33
4- A type representing a temporal graph as a sequence of snapshots. In this case a snapshot is a [`GNNGraph`](@ref).
4+ A type representing a time-varying graph as a sequence of snapshots,
5+ each snapshot being a [`GNNGraph`](@ref).
56
6- `TemporalSnapshotsGNNGraph` can store the feature array associated to the graph itself as a [`DataStore`](@ref) object,
7- and it uses the [`DataStore`](@ref) objects of each snapshot for the node and edge features.
8- The features can be passed at construction time or added later.
7+ The argument `snapshots` is a collection of `GNNGraph`s with arbitrary
8+ number of nodes and edges each.
99
10- # Constructor Arguments
10+ Calling `tg` the temporal graph, `tg[t]` returns the `t`-th snapshot.
1111
12- - `snapshot`: a vector of snapshots, where each snapshot must have the same number of nodes.
12+ The snapshots can contain node/edge/graph features, while global features for the
13+ whole temporal sequence can be stored in `tg.tgdata`.
1314
14- # Examples
15+ See [`add_snapshot`](@ref) and [`remove_snapshot`](@ref) for adding and removing snapshots.
1516
16- ```julia
17- julia> using GNNGraphs
17+ # Examples
1818
19- julia> snapshots = [rand_graph(10,20) for i in 1:5];
19+ ```jldoctest
20+ julia> snapshots = [rand_graph(i , 2*i) for i in 10:10:50];
2021
2122julia> tg = TemporalSnapshotsGNNGraph(snapshots)
2223TemporalSnapshotsGNNGraph:
23- num_nodes: [10, 10, 10, 10, 10 ]
24- num_edges: [20, 20, 20, 20, 20 ]
24+ num_nodes: [10, 20, 30, 40, 50 ]
25+ num_edges: [20, 40, 60, 80, 100 ]
2526 num_snapshots: 5
2627
27- julia> tg.tgdata.x = rand(4); # add temporal graph feature
28+ julia> tg.num_snapshots
29+ 5
30+
31+ julia> tg.num_nodes
32+ 5-element Vector{Int64}:
33+ 10
34+ 20
35+ 30
36+ 40
37+ 50
2838
29- julia> tg # show temporal graph with new feature
39+ julia> tg[1]
40+ GNNGraph:
41+ num_nodes: 10
42+ num_edges: 20
43+
44+ julia> tg[2:3]
3045TemporalSnapshotsGNNGraph:
31- num_nodes: [10, 10, 10, 10, 10]
32- num_edges: [20, 20, 20, 20, 20]
33- num_snapshots: 5
34- tgdata:
35- x = 4-element Vector{Float64}
46+ num_nodes: [20, 30]
47+ num_edges: [40, 60]
48+ num_snapshots: 2
49+
50+ julia> tg[1] = rand_graph(10, 16)
51+ GNNGraph:
52+ num_nodes: 10
53+ num_edges: 16
3654```
3755"""
38- struct TemporalSnapshotsGNNGraph
39- num_nodes:: AbstractVector {Int}
40- num_edges:: AbstractVector {Int}
56+ struct TemporalSnapshotsGNNGraph{G <: GNNGraph , D <: DataStore }
57+ num_nodes:: Vector {Int}
58+ num_edges:: Vector {Int}
4159 num_snapshots:: Int
42- snapshots:: AbstractVector{<:GNNGraph }
43- tgdata:: DataStore
60+ snapshots:: Vector{G }
61+ tgdata:: D
4462end
4563
46- function TemporalSnapshotsGNNGraph (snapshots:: AbstractVector{<:GNNGraph} )
47- @assert all ([s . num_nodes == snapshots[ 1 ] . num_nodes for s in snapshots]) " all snapshots must have the same number of nodes "
64+ function TemporalSnapshotsGNNGraph (snapshots)
65+ snapshots = collect ( snapshots)
4866 return TemporalSnapshotsGNNGraph (
4967 [s. num_nodes for s in snapshots],
5068 [s. num_edges for s in snapshots],
5169 length (snapshots),
52- snapshots,
70+ collect ( snapshots) ,
5371 DataStore ()
5472 )
5573end
@@ -67,7 +85,25 @@ function Base.getindex(tg::TemporalSnapshotsGNNGraph, t::Int)
6785end
6886
6987function Base. getindex (tg:: TemporalSnapshotsGNNGraph , t:: AbstractVector )
70- return TemporalSnapshotsGNNGraph (tg. num_nodes[t], tg. num_edges[t], length (t), tg. snapshots[t], tg. tgdata)
88+ return TemporalSnapshotsGNNGraph (tg. num_nodes[t], tg. num_edges[t],
89+ length (t), tg. snapshots[t], tg. tgdata)
90+ end
91+
92+ function Base. length (tg:: TemporalSnapshotsGNNGraph )
93+ return tg. num_snapshots
94+ end
95+
96+ # Allow broadcasting over the temporal snapshots
97+ Base. broadcastable (tg:: TemporalSnapshotsGNNGraph ) = tg. snapshots
98+
99+ Base. iterate (tg:: TemporalSnapshotsGNNGraph ) = Base. iterate (tg. snapshots)
100+ Base. iterate (tg:: TemporalSnapshotsGNNGraph , i) = Base. iterate (tg. snapshots, i)
101+
102+ function Base. setindex! (tg:: TemporalSnapshotsGNNGraph , g:: GNNGraph , t:: Int )
103+ tg. snapshots[t] = g
104+ tg. num_nodes[t] = g. num_nodes
105+ tg. num_edges[t] = g. num_edges
106+ return tg
71107end
72108
73109"""
@@ -78,8 +114,6 @@ Return a `TemporalSnapshotsGNNGraph` created starting from `tg` by adding the sn
78114# Examples
79115
80116```jldoctest
81- julia> using GNNGraphs
82-
83117julia> snapshots = [rand_graph(10, 20) for i in 1:5];
84118
85119julia> tg = TemporalSnapshotsGNNGraph(snapshots)
@@ -185,58 +219,26 @@ end
185219function Base. getproperty (tg:: TemporalSnapshotsGNNGraph , prop:: Symbol )
186220 if prop ∈ fieldnames (TemporalSnapshotsGNNGraph)
187221 return getfield (tg, prop)
188- elseif prop == :ndata
189- return [s. ndata for s in tg. snapshots]
190- elseif prop == :edata
191- return [s. edata for s in tg. snapshots]
192- elseif prop == :gdata
193- return [s. gdata for s in tg. snapshots]
194- else
195- return [getproperty (s,prop) for s in tg. snapshots]
222+ else
223+ return [getproperty (s, prop) for s in tg. snapshots]
196224 end
197225end
198226
199227function Base. show (io:: IO , tsg:: TemporalSnapshotsGNNGraph )
200- print (io, " TemporalSnapshotsGNNGraph($(tsg. num_snapshots) ) with " )
201- print_feature_t (io, tsg. tgdata)
202- print (io, " data" )
228+ print (io, " TemporalSnapshotsGNNGraph($(tsg. num_snapshots) )" )
203229end
204230
205231function Base. show (io:: IO , :: MIME"text/plain" , tsg:: TemporalSnapshotsGNNGraph )
206232 if get (io, :compact , false )
207- print (io, " TemporalSnapshotsGNNGraph($(tsg. num_snapshots) ) with " )
208- print_feature_t (io, tsg. tgdata)
209- print (io, " data" )
233+ print (io, " TemporalSnapshotsGNNGraph($(tsg. num_snapshots) )" )
210234 else
211235 print (io,
212236 " TemporalSnapshotsGNNGraph:\n num_nodes: $(tsg. num_nodes) \n num_edges: $(tsg. num_edges) \n num_snapshots: $(tsg. num_snapshots) " )
213237 if ! isempty (tsg. tgdata)
214238 print (io, " \n tgdata:" )
215239 for k in keys (tsg. tgdata)
216- print (io, " \n\t $k = $(shortsummary (tsg. tgdata[k])) " )
217- end
218- end
219- end
220- end
221-
222- function print_feature_t (io:: IO , feature)
223- if ! isempty (feature)
224- if length (keys (feature)) == 1
225- k = first (keys (feature))
226- v = first (values (feature))
227- print (io, " $(k) : $(dims2string (size (v))) " )
228- else
229- print (io, " (" )
230- for (i, (k, v)) in enumerate (pairs (feature))
231- print (io, " $k : $(dims2string (size (v))) " )
232- if i == length (feature)
233- print (io, " )" )
234- else
235- print (io, " , " )
236- end
240+ print (io, " \n $k = $(shortsummary (tsg. tgdata[k])) " )
237241 end
238242 end
239- else
240- print (io, " no" )
241243 end
242244end
0 commit comments