@@ -298,29 +298,32 @@ function LightGraphs.laplacian_matrix(fg::FeaturedGraph, T::DataType=Int; dir::S
298
298
end
299
299
300
300
"""
301
- normalized_laplacian(fg, T=Float32; selfloop =false, dir=:out)
301
+ normalized_laplacian(fg, T=Float32; add_self_loops =false, dir=:out)
302
302
303
303
Normalized Laplacian matrix of graph `g`.
304
304
305
305
# Arguments
306
306
307
307
- `fg`: A `FeaturedGraph`.
308
308
- `T`: result element type.
309
- - `selfloop `: adding self loop while calculating the matrix.
309
+ - `add_self_loops `: add self-loops while calculating the matrix.
310
310
- `dir`: the edge directionality considered (:out, :in, :both).
311
311
"""
312
- function normalized_laplacian (fg:: FeaturedGraph , T:: DataType = Float32; selfloop:: Bool = false , dir:: Symbol = :out )
312
+ function normalized_laplacian (fg:: FeaturedGraph , T:: DataType = Float32;
313
+ add_self_loops:: Bool = false , dir:: Symbol = :out )
314
+ Ã = normalized_adjacency (fg, T; dir, add_self_loops)
315
+ return I - Ã
316
+ end
317
+
318
+ function normalized_adjacency (fg:: FeaturedGraph , T:: DataType = Float32;
319
+ add_self_loops:: Bool = false , dir:: Symbol = :out )
313
320
A = adjacency_matrix (fg, T; dir= dir)
314
- sz = size (A)
315
- @assert sz[1 ] == sz[2 ]
316
- if selfloop
317
- A += I - Diagonal (A)
318
- else
319
- A -= Diagonal (A)
321
+ if add_self_loops
322
+ A += I
320
323
end
321
324
degs = vec (sum (A; dims= 2 ))
322
325
inv_sqrtD = Diagonal (inv .(sqrt .(degs)))
323
- return I - inv_sqrtD * A * inv_sqrtD
326
+ return inv_sqrtD * A * inv_sqrtD
324
327
end
325
328
326
329
@doc raw """
@@ -350,18 +353,23 @@ _eigmax(A) = KrylovKit.eigsolve(Symmetric(A), 1, :LR)[1][1] # also eigs(A, x0, n
350
353
# https://discourse.julialang.org/t/cuda-eigenvalues-of-a-sparse-matrix/46851/5
351
354
352
355
"""
353
- add_self_loops(fg::FeaturedGraph)
356
+ add_self_loops(fg::FeaturedGraph; add_to_existing=true )
354
357
355
358
Return a featured graph with the same features as `fg`
356
359
but also adding edges connecting the nodes to themselves.
360
+
361
+ If `add_to_existing=true`, nodes with already existing
362
+ self-loops will obtain a second self-loop.
357
363
"""
358
- function add_self_loops (fg:: FeaturedGraph{<:COO_T} )
364
+ function add_self_loops (fg:: FeaturedGraph{<:COO_T} ; add_to_existing = true )
359
365
s, t = edge_index (fg)
360
366
@assert edge_feature (fg) === nothing
361
367
@assert edge_weight (fg) === nothing
362
- mask_old_loops = s .!= t
363
- s = s[mask_old_loops]
364
- t = t[mask_old_loops]
368
+ if ! add_to_existing
369
+ mask_old_loops = s .!= t
370
+ s = s[mask_old_loops]
371
+ t = t[mask_old_loops]
372
+ end
365
373
n = fg. num_nodes
366
374
nodes = convert (typeof (s), [1 : n;])
367
375
s = [s; nodes]
@@ -371,11 +379,16 @@ function add_self_loops(fg::FeaturedGraph{<:COO_T})
371
379
node_feature (fg), edge_feature (fg), global_feature (fg))
372
380
end
373
381
374
- function add_self_loops (fg:: FeaturedGraph{<:ADJMAT_T} )
382
+ function add_self_loops (fg:: FeaturedGraph{<:ADJMAT_T} ; add_to_existing = true )
375
383
A = graph (fg)
376
384
@assert edge_feature (fg) === nothing
377
- nold = sum (Diagonal (A)) |> Int
378
- A = A - Diagonal (A) + I
385
+ if add_to_existing
386
+ nold = 0
387
+ A += I
388
+ else
389
+ nold = sum (Diagonal (A)) |> Int
390
+ A += I - Diagonal (A)
391
+ end
379
392
num_edges = fg. num_edges - nold + fg. num_nodes
380
393
FeaturedGraph (A, fg. num_nodes, num_edges,
381
394
node_feature (fg), edge_feature (fg), global_feature (fg))
@@ -396,6 +409,7 @@ function remove_self_loops(fg::FeaturedGraph{<:COO_T})
396
409
end
397
410
398
411
@non_differentiable normalized_laplacian (x... )
412
+ @non_differentiable normalized_adjacency (x... )
399
413
@non_differentiable scaled_laplacian (x... )
400
414
@non_differentiable adjacency_matrix (x... )
401
415
@non_differentiable adjacency_list (x... )
0 commit comments