1
1
"""
2
- rand_graph(n, m; bidirected=true, seed=-1 , edge_weight = nothing, kws...)
2
+ rand_graph([rng,] n, m; bidirected=true, edge_weight = nothing, kws...)
3
3
4
4
Generate a random (Erdós-Renyi) `GNNGraph` with `n` nodes and `m` edges.
5
5
@@ -10,7 +10,7 @@ In any case, the output graph will contain no self-loops or multi-edges.
10
10
A vector can be passed as `edge_weight`. Its length has to be equal to `m`
11
11
in the directed case, and `m÷2` in the bidirected one.
12
12
13
- Use a `seed > 0` for reproducibility .
13
+ Pass a random number generator as the first argument to make the generation reproducible .
14
14
15
15
Additional keyword arguments will be passed to the [`GNNGraph`](@ref) constructor.
16
16
@@ -36,25 +36,42 @@ GNNGraph:
36
36
# Each edge has a reverse
37
37
julia> edge_index(g)
38
38
([1, 3, 3, 4], [3, 4, 1, 3])
39
-
40
39
```
41
40
"""
42
- function rand_graph (n:: Integer , m:: Integer ; bidirected = true , seed = - 1 , edge_weight = nothing , kws... )
41
+ function rand_graph (n:: Integer , m:: Integer ; seed= - 1 , kws... )
42
+ if seed != - 1
43
+ Base. depwarn (" Keyword argument `seed` is deprecated, pass an rng as first argument instead." , :rand_graph )
44
+ rng = MersenneTwister (seed)
45
+ else
46
+ rng = Random. default_rng ()
47
+ end
48
+ return rand_graph (rng, n, m; kws... )
49
+ end
50
+
51
+ function rand_graph (rng:: AbstractRNG , n:: Integer , m:: Integer ;
52
+ bidirected:: Bool = true ,
53
+ edge_weight:: Union{AbstractVector, Nothing} = nothing , kws... )
43
54
if bidirected
44
- @assert iseven (m) " Need even number of edges for bidirected graphs, given m=$m ."
55
+ @assert iseven (m) lazy " Need even number of edges for bidirected graphs, given m=$m."
56
+ s, t, _ = _rand_edges (rng, n, m ÷ 2 ; directed= false , self_loops= false )
57
+ s, t = vcat (s, t), vcat (t, s)
58
+ if edge_weight != = nothing
59
+ edge_weight = vcat (edge_weight, edge_weight)
60
+ end
61
+ else
62
+ s, t, _ = _rand_edges (rng, n, m; directed= true , self_loops= false )
45
63
end
46
- m2 = bidirected ? m ÷ 2 : m
47
- return GNNGraph (Graphs. erdos_renyi (n, m2; is_directed = ! bidirected, seed); edge_weight, kws... )
64
+ return GNNGraph ((s, t, edge_weight); num_nodes= n, kws... )
48
65
end
49
66
50
67
"""
51
- rand_heterograph(n, m; seed=-1, bidirected=false, kws...)
68
+ rand_heterograph([rng,] n, m; bidirected=false, kws...)
52
69
53
- Construct an [`GNNHeteroGraph`](@ref) with number of nodes and edges
70
+ Construct an [`GNNHeteroGraph`](@ref) with random edges and with number of nodes and edges
54
71
specified by `n` and `m` respectively. `n` and `m` can be any iterable of pairs
55
72
specifing node/edge types and their numbers.
56
73
57
- Use a `seed > 0` for reproducibility .
74
+ Pass a random number generator as a first argument to make the generation reproducible .
58
75
59
76
Setting `bidirected=true` will generate a bidirected graph, i.e. each edge will have a reverse edge.
60
77
Therefore, for each edge type `(:A, :rel, :B)` a corresponding reverse edge type `(:B, :rel, :A)`
@@ -76,17 +93,27 @@ function rand_heterograph end
76
93
77
94
# for generic iterators of pairs
78
95
rand_heterograph (n, m; kws... ) = rand_heterograph (Dict (n), Dict (m); kws... )
96
+ rand_heterograph (rng:: AbstractRNG , n, m; kws... ) = rand_heterograph (rng, Dict (n), Dict (m); kws... )
79
97
80
- function rand_heterograph (n:: NDict , m:: EDict ; bidirected = false , seed = - 1 , kws... )
81
- rng = seed > 0 ? MersenneTwister (seed) : Random. GLOBAL_RNG
98
+ function rand_heterograph (n:: NDict , m:: EDict ; seed= - 1 , kws... )
99
+ if seed != - 1
100
+ Base. depwarn (" Keyword argument `seed` is deprecated, pass an rng as first argument instead." , :rand_heterograph )
101
+ rng = MersenneTwister (seed)
102
+ else
103
+ rng = Random. default_rng ()
104
+ end
105
+ return rand_heterograph (rng, n, m; kws... )
106
+ end
107
+
108
+ function rand_heterograph (rng:: AbstractRNG , n:: NDict , m:: EDict ; bidirected:: Bool = false , kws... )
82
109
if bidirected
83
110
return _rand_bidirected_heterograph (rng, n, m; kws... )
84
111
end
85
112
graphs = Dict (k => _rand_edges (rng, (n[k[1 ]], n[k[3 ]]), m[k]) for k in keys (m))
86
113
return GNNHeteroGraph (graphs; num_nodes = n, kws... )
87
114
end
88
115
89
- function _rand_bidirected_heterograph (rng, n:: NDict , m:: EDict ; kws... )
116
+ function _rand_bidirected_heterograph (rng:: AbstractRNG , n:: NDict , m:: EDict ; kws... )
90
117
for k in keys (m)
91
118
if reverse (k) ∈ keys (m)
92
119
@assert m[k] == m[reverse (k)] " Number of edges must be the same in reverse edge types for bidirected graphs."
@@ -104,43 +131,60 @@ function _rand_bidirected_heterograph(rng, n::NDict, m::EDict; kws...)
104
131
return GNNHeteroGraph (graphs; num_nodes = n, kws... )
105
132
end
106
133
107
- function _rand_edges (rng, (n1, n2), m)
108
- idx = StatsBase. sample (rng, 1 : (n1 * n2), m, replace = false )
109
- s, t = edge_decoding (idx, n1, n2)
110
- val = nothing
111
- return s, t, val
112
- end
113
134
114
135
"""
115
- rand_bipartite_heterograph(n1, n2, m; [bidirected, seed, node_t, edge_t, kws...])
116
- rand_bipartite_heterograph((n1, n2), m; ...)
117
- rand_bipartite_heterograph((n1, n2), (m1, m2); ...)
136
+ rand_bipartite_heterograph([rng,]
137
+ (n1, n2), (m12, m21);
138
+ bidirected = true,
139
+ node_t = (:A, :B),
140
+ edge_t = :to,
141
+ kws...)
118
142
119
- Construct an [`GNNHeteroGraph`](@ref) with number of nodes and edges
120
- specified by `n1`, `n2` and `m1` and `m2` respectively .
143
+ Construct an [`GNNHeteroGraph`](@ref) with random edges representing a bipartite graph.
144
+ The graph will have two types of nodes, and edges will only connect nodes of different types .
121
145
122
- See [`rand_heterograph`](@ref) for a more general version.
146
+ The first argument is a tuple `(n1, n2)` specifying the number of nodes of each type.
147
+ The second argument is a tuple `(m12, m21)` specifying the number of edges connecting nodes of type `1` to nodes of type `2`
148
+ and vice versa.
123
149
124
- # Keyword arguments
150
+ The type of nodes and edges can be specified with the `node_t` and `edge_t` keyword arguments,
151
+ which default to `(:A, :B)` and `:to` respectively.
125
152
126
- - `bidirected`: whether to generate a bidirected graph. Default is `true`.
127
- - `seed`: random seed. Default is `-1` (no seed).
128
- - `node_t`: node types. If `bipartite=true`, this should be a tuple of two node types, otherwise it should be a single node type.
129
- - `edge_t`: edge types. If `bipartite=true`, this should be a tuple of two edge types, otherwise it should be a single edge type.
130
- """
131
- function rand_bipartite_heterograph end
153
+ If `bidirected=true` (default), the reverse edge of each edge will be present. In this case
154
+ `m12 == m21` is required.
155
+
156
+ A random number generator can be passed as the first argument to make the generation reproducible.
157
+
158
+ Additional keyword arguments will be passed to the [`GNNHeteroGraph`](@ref) constructor.
159
+
160
+ See [`rand_heterograph`](@ref) for a more general version.
161
+
162
+ # Examples
132
163
133
- rand_bipartite_heterograph (n1:: Int , n2:: Int , m:: Int ; kws... ) = rand_bipartite_heterograph ((n1, n2), (m, m); kws... )
164
+ ```julia-repl
165
+ julia> g = rand_bipartite_heterograph((10, 15), 20)
166
+ GNNHeteroGraph:
167
+ num_nodes: (:A => 10, :B => 15)
168
+ num_edges: ((:A, :to, :B) => 20, (:B, :to, :A) => 20)
134
169
135
- rand_bipartite_heterograph ((n1, n2):: NTuple{2,Int} , m:: Int ; kws... ) = rand_bipartite_heterograph ((n1, n2), (m, m); kws... )
170
+ julia> g = rand_bipartite_heterograph((10, 15), (20, 0), node_t=(:user, :item), edge_t=:-, bidirected=false)
171
+ GNNHeteroGraph:
172
+ num_nodes: Dict(:item => 15, :user => 10)
173
+ num_edges: Dict((:item, :-, :user) => 0, (:user, :-, :item) => 20)
174
+ ```
175
+ """
176
+ rand_bipartite_heterograph (n, m; kws... ) = rand_bipartite_heterograph (Random. default_rng (), n, m; kws... )
136
177
137
- function rand_bipartite_heterograph ((n1, n2):: NTuple{2,Int} , (m1, m2):: NTuple{2,Int} ; bidirected= true ,
138
- node_t = (:A , :B ), edge_t = :to , kws... )
139
- if edge_t isa Symbol
140
- edge_t = (edge_t, edge_t)
178
+ function rand_bipartite_heterograph (rng:: AbstractRNG , (n1, n2):: NTuple{2,Int} , m; bidirected= true ,
179
+ node_t = (:A , :B ), edge_t:: Symbol = :to , kws... )
180
+ if m isa Integer
181
+ m12 = m21 = m
182
+ else
183
+ m12, m21 = m
141
184
end
142
- return rand_heterograph (Dict (node_t[1 ] => n1, node_t[2 ] => n2),
143
- Dict ((node_t[1 ], edge_t[1 ], node_t[2 ]) => m1, (node_t[2 ], edge_t[2 ], node_t[1 ]) => m2);
185
+
186
+ return rand_heterograph (rng, Dict (node_t[1 ] => n1, node_t[2 ] => n2),
187
+ Dict ((node_t[1 ], edge_t, node_t[2 ]) => m12, (node_t[2 ], edge_t, node_t[1 ]) => m21);
144
188
bidirected, kws... )
145
189
end
146
190
0 commit comments