From fc55906311b29518dcbd800fcfb9c7477cd10d60 Mon Sep 17 00:00:00 2001 From: rbSparky Date: Tue, 19 Mar 2024 02:39:32 +0530 Subject: [PATCH 01/16] add ppr diffusion --- test/GNNGraphs/transform.jl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/GNNGraphs/transform.jl b/test/GNNGraphs/transform.jl index be3b8773a..8fa7b6310 100644 --- a/test/GNNGraphs/transform.jl +++ b/test/GNNGraphs/transform.jl @@ -519,4 +519,25 @@ end @test g.graph[(:A, :to1, :A)][3] == vcat([2, 2, 2], fill(1, n)) end +end + +@testset "ppr_diffusion" begin + if GRAPH_T == :coo + s = [1, 1, 2, 3] + t = [2, 3, 4, 5] + eweights = [0.1, 0.2, 0.3, 0.4] + + g = GNNGraph(s,t,eweights) + get_edge_weight(g) + + g_new = ppr_diffusion(g) + w_new = get_edge_weight(g_new) + + check_ew = Float32[0.012749999 + 0.025499998 + 0.038249996 + 0.050999995] + + isequal(w_new, check_ew) + end end \ No newline at end of file From aece851dd795d1ac2b7d143ba8230f3a1fd1425e Mon Sep 17 00:00:00 2001 From: rbSparky Date: Tue, 19 Mar 2024 02:41:03 +0530 Subject: [PATCH 02/16] add ppr diffusion --- src/GNNGraphs/transform.jl | 50 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index 3790a6bce..237714cfc 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1078,3 +1078,53 @@ ci2t(ci::AbstractVector{<:CartesianIndex}, dims) = ntuple(i -> map(x -> x[i], ci @non_differentiable remove_self_loops(x...) # TODO this is wrong, since g carries feature arrays, needs rrule @non_differentiable dense_zeros_like(x...) +""" + ppr_diffusion(g::GNNGraph; alpha_f32::Float32=0.85f0) -> GNNGraph + +Calculates the Personalized PageRank (PPR) diffusion based on the edge weight matrix of a GNNGraph and updates the graph with new edge weights derived from the PPR matrix. + +The function performs the following steps: +1. Constructs a modified adjacency matrix `A` using the graph's edge weights, where `A` is adjusted by `(α - 1) * A + I`, with `α` being the damping factor (`alpha_f32`) and `I` the identity matrix. +2. Normalizes `A` to ensure each column sums to 1, representing transition probabilities. +3. Applies the PPR formula `α * (I + (α - 1) * A)^-1` to compute the diffusion matrix. +4. Updates the original edge weights of the graph based on the PPR diffusion matrix, assigning new weights for each edge from the PPR matrix. + +# Arguments +- `g::GNNGraph`: The input graph for which PPR diffusion is to be calculated. It should have edge weights available. +- `alpha_f32::Float32`: The damping factor used in PPR calculation, controlling the teleport probability in the random walk. Defaults to `0.85f0`. + +# Returns +- A new `GNNGraph` instance with the same structure as `g` but with updated edge weights according to the PPR diffusion calculation. +""" +function ppr_diffusion(g::GNNGraph; alpha_f32::Float32=0.85f0) + s, t = edge_index(g) + w = get_edge_weight(g) + + N = g.num_nodes + + A = zeros(Float32, N, N) + + for (idx, src, dst) in zip(1:length(s), s, t) + A[dst, src] += w[idx] + end + + A .*= (alpha_f32 - 1) + + for i in 1:N + A[i, i] += 1 + end + + # α * (I + (α - 1) * A)^-1 + PPR = alpha_f32 * inv(A) + println(PPR) + + new_w = Float32[] + for (src, dst) in zip(s, t) + push!(new_w, PPR[dst, src]) + end + + return GNNGraph((s, t, new_w), + g.num_nodes, length(s), g.num_graphs, + g.graph_indicator, + g.ndata, g.edata, g.gdata) +end \ No newline at end of file From 700129437971b58fd513c69f2a7e8791a9d0b904 Mon Sep 17 00:00:00 2001 From: rbSparky Date: Tue, 19 Mar 2024 02:55:19 +0530 Subject: [PATCH 03/16] add function to GNNGraphs.jl --- src/GNNGraphs/GNNGraphs.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/GNNGraphs/GNNGraphs.jl b/src/GNNGraphs/GNNGraphs.jl index 2f989c9b1..c470f8b7b 100644 --- a/src/GNNGraphs/GNNGraphs.jl +++ b/src/GNNGraphs/GNNGraphs.jl @@ -78,6 +78,7 @@ export add_nodes, to_unidirected, random_walk_pe, remove_nodes, + ppr_diffusion, # from Flux batch, unbatch, From e7857f02c07d3424983f71dde2748ec1b9d21d9c Mon Sep 17 00:00:00 2001 From: rbSparky Date: Tue, 19 Mar 2024 14:32:40 +0530 Subject: [PATCH 04/16] :coo --- src/GNNGraphs/transform.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index 237714cfc..9394b0201 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1079,7 +1079,7 @@ ci2t(ci::AbstractVector{<:CartesianIndex}, dims) = ntuple(i -> map(x -> x[i], ci @non_differentiable dense_zeros_like(x...) """ - ppr_diffusion(g::GNNGraph; alpha_f32::Float32=0.85f0) -> GNNGraph + ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) -> GNNGraph Calculates the Personalized PageRank (PPR) diffusion based on the edge weight matrix of a GNNGraph and updates the graph with new edge weights derived from the PPR matrix. @@ -1096,7 +1096,7 @@ The function performs the following steps: # Returns - A new `GNNGraph` instance with the same structure as `g` but with updated edge weights according to the PPR diffusion calculation. """ -function ppr_diffusion(g::GNNGraph; alpha_f32::Float32=0.85f0) +function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) s, t = edge_index(g) w = get_edge_weight(g) From ce1e3c84814f0951d8b9f9007c6c7c3450abf11c Mon Sep 17 00:00:00 2001 From: Rishabh <59335537+rbSparky@users.noreply.github.com> Date: Tue, 19 Mar 2024 16:07:51 +0530 Subject: [PATCH 05/16] Update transform.jl --- src/GNNGraphs/transform.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index 9394b0201..161599aab 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1081,7 +1081,8 @@ ci2t(ci::AbstractVector{<:CartesianIndex}, dims) = ntuple(i -> map(x -> x[i], ci """ ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) -> GNNGraph -Calculates the Personalized PageRank (PPR) diffusion based on the edge weight matrix of a GNNGraph and updates the graph with new edge weights derived from the PPR matrix. +Calculates the Personalized PageRank (PPR) diffusion based on the edge weight matrix of a GNNGraph and updates the graph with new edge weights derived from the PPR matrix as introduced in the paper [The pagerank citation ranking: Bringing order to the web](http://ilpubs.stanford.edu:8090/422) + The function performs the following steps: 1. Constructs a modified adjacency matrix `A` using the graph's edge weights, where `A` is adjusted by `(α - 1) * A + I`, with `α` being the damping factor (`alpha_f32`) and `I` the identity matrix. @@ -1127,4 +1128,4 @@ function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) g.num_nodes, length(s), g.num_graphs, g.graph_indicator, g.ndata, g.edata, g.gdata) -end \ No newline at end of file +end From 0241b4bab6e3b5337fbea8b00bf6e1f3329cefa5 Mon Sep 17 00:00:00 2001 From: rbSparky Date: Tue, 19 Mar 2024 19:03:55 +0530 Subject: [PATCH 06/16] try --- src/GNNGraphs/transform.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index 161599aab..f7082fd3f 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1081,7 +1081,8 @@ ci2t(ci::AbstractVector{<:CartesianIndex}, dims) = ntuple(i -> map(x -> x[i], ci """ ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) -> GNNGraph -Calculates the Personalized PageRank (PPR) diffusion based on the edge weight matrix of a GNNGraph and updates the graph with new edge weights derived from the PPR matrix as introduced in the paper [The pagerank citation ranking: Bringing order to the web](http://ilpubs.stanford.edu:8090/422) +Calculates the Personalized PageRank (PPR) diffusion based on the edge weight matrix of a GNNGraph and updates the graph with new edge weights derived from the PPR matrix. +References paper: [The pagerank citation ranking: Bringing order to the web](http://ilpubs.stanford.edu:8090/422) The function performs the following steps: From 81105a239ff76f66250b73f52682cb16a7b7f80c Mon Sep 17 00:00:00 2001 From: Rishabh <59335537+rbSparky@users.noreply.github.com> Date: Thu, 9 May 2024 07:41:10 +0530 Subject: [PATCH 07/16] Made function non-mutating uses SparseArrays --- src/GNNGraphs/transform.jl | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index f7082fd3f..cd02373f8 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1100,33 +1100,24 @@ The function performs the following steps: """ function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) s, t = edge_index(g) - w = get_edge_weight(g) + w = ones(Float32, g.num_edges) N = g.num_nodes - A = zeros(Float32, N, N) - - for (idx, src, dst) in zip(1:length(s), s, t) - A[dst, src] += w[idx] - end + initial_A = sparse(t, s, w, N, N) + scaled_A = (alpha_f32 - 1) * initial_A - A .*= (alpha_f32 - 1) + I_sparse = sparse(Diagonal(ones(Float32, N))) + A_sparse = I_sparse + scaled_A - for i in 1:N - A[i, i] += 1 - end + A_dense = Matrix(A_sparse) - # α * (I + (α - 1) * A)^-1 - PPR = alpha_f32 * inv(A) - println(PPR) + PPR = alpha_f32 * inv(A_dense) - new_w = Float32[] - for (src, dst) in zip(s, t) - push!(new_w, PPR[dst, src]) - end + new_w = [PPR[dst, src] for (src, dst) in zip(s, t)] return GNNGraph((s, t, new_w), - g.num_nodes, length(s), g.num_graphs, - g.graph_indicator, - g.ndata, g.edata, g.gdata) + g.num_nodes, length(s), g.num_graphs, + g.graph_indicator, + g.ndata, g.edata, g.gdata) end From b3eabc3322262b9450c1dc9406d419725d5bd085 Mon Sep 17 00:00:00 2001 From: Rishabh <59335537+rbSparky@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:34:47 +0530 Subject: [PATCH 08/16] Update src/GNNGraphs/transform.jl rename args Co-authored-by: Carlo Lucibello --- src/GNNGraphs/transform.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index cd02373f8..315a737eb 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1079,7 +1079,7 @@ ci2t(ci::AbstractVector{<:CartesianIndex}, dims) = ntuple(i -> map(x -> x[i], ci @non_differentiable dense_zeros_like(x...) """ - ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) -> GNNGraph + ppr_diffusion(g::GNNGraph{<:COO_T}, alpha =0.85f0) -> GNNGraph Calculates the Personalized PageRank (PPR) diffusion based on the edge weight matrix of a GNNGraph and updates the graph with new edge weights derived from the PPR matrix. References paper: [The pagerank citation ranking: Bringing order to the web](http://ilpubs.stanford.edu:8090/422) From 71afac7ae7de4034834cf0cdeafda4840e8b893e Mon Sep 17 00:00:00 2001 From: Rishabh <59335537+rbSparky@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:35:00 +0530 Subject: [PATCH 09/16] Update test/GNNGraphs/transform.jl clean code Co-authored-by: Carlo Lucibello --- test/GNNGraphs/transform.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/GNNGraphs/transform.jl b/test/GNNGraphs/transform.jl index 8fa7b6310..b5d1ff164 100644 --- a/test/GNNGraphs/transform.jl +++ b/test/GNNGraphs/transform.jl @@ -527,7 +527,7 @@ end t = [2, 3, 4, 5] eweights = [0.1, 0.2, 0.3, 0.4] - g = GNNGraph(s,t,eweights) + g = GNNGraph(s, t, eweights) get_edge_weight(g) g_new = ppr_diffusion(g) From c7f98973ad232919cf359c3eefb7a9b27467f2e5 Mon Sep 17 00:00:00 2001 From: Rishabh <59335537+rbSparky@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:35:27 +0530 Subject: [PATCH 10/16] Update test/GNNGraphs/transform.jl remove unneeded line Co-authored-by: Carlo Lucibello --- test/GNNGraphs/transform.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/GNNGraphs/transform.jl b/test/GNNGraphs/transform.jl index b5d1ff164..21fc4701f 100644 --- a/test/GNNGraphs/transform.jl +++ b/test/GNNGraphs/transform.jl @@ -528,7 +528,6 @@ end eweights = [0.1, 0.2, 0.3, 0.4] g = GNNGraph(s, t, eweights) - get_edge_weight(g) g_new = ppr_diffusion(g) w_new = get_edge_weight(g_new) From 46cd8370e42fa224a5f3378e8cc3335b4e9f4ead Mon Sep 17 00:00:00 2001 From: Rishabh <59335537+rbSparky@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:35:57 +0530 Subject: [PATCH 11/16] Update src/GNNGraphs/transform.jl args fix Co-authored-by: Carlo Lucibello --- src/GNNGraphs/transform.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index 315a737eb..ee3e01401 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1098,7 +1098,7 @@ The function performs the following steps: # Returns - A new `GNNGraph` instance with the same structure as `g` but with updated edge weights according to the PPR diffusion calculation. """ -function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha_f32::Float32=0.85f0) +function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha = 0.85f0) s, t = edge_index(g) w = ones(Float32, g.num_edges) From d113050d37f36d57a735dde4899ac2843ac1438b Mon Sep 17 00:00:00 2001 From: Rishabh <59335537+rbSparky@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:36:08 +0530 Subject: [PATCH 12/16] Update src/GNNGraphs/transform.jl rename var Co-authored-by: Carlo Lucibello --- src/GNNGraphs/transform.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index ee3e01401..6a830048d 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1105,7 +1105,7 @@ function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha = 0.85f0) N = g.num_nodes initial_A = sparse(t, s, w, N, N) - scaled_A = (alpha_f32 - 1) * initial_A + scaled_A = (Float32(alpha) - 1) * initial_A I_sparse = sparse(Diagonal(ones(Float32, N))) A_sparse = I_sparse + scaled_A From 17434c0f93c793e8d962257d942c456576a5b43e Mon Sep 17 00:00:00 2001 From: rbSparky Date: Thu, 27 Jun 2024 15:54:29 +0530 Subject: [PATCH 13/16] empty weights --- src/GNNGraphs/transform.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index 29b7c29f2..7639e144d 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1190,7 +1190,10 @@ The function performs the following steps: """ function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha = 0.85f0) s, t = edge_index(g) - w = ones(Float32, g.num_edges) + w = get_edge_weight(g) + if isnothing(w) + w = ones(Float32, g.num_edges) + end N = g.num_nodes From f593e524238992399bddaf37246e9d443b261909 Mon Sep 17 00:00:00 2001 From: rbSparky Date: Thu, 27 Jun 2024 15:56:24 +0530 Subject: [PATCH 14/16] indent --- test/GNNGraphs/transform.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/GNNGraphs/transform.jl b/test/GNNGraphs/transform.jl index fef59021f..8ae84aaae 100644 --- a/test/GNNGraphs/transform.jl +++ b/test/GNNGraphs/transform.jl @@ -609,9 +609,9 @@ end w_new = get_edge_weight(g_new) check_ew = Float32[0.012749999 - 0.025499998 - 0.038249996 - 0.050999995] + 0.025499998 + 0.038249996 + 0.050999995] isequal(w_new, check_ew) end From 7a19471b38875f6dc3c0bf092aa7ff9fa2595cda Mon Sep 17 00:00:00 2001 From: rbSparky Date: Thu, 27 Jun 2024 15:59:56 +0530 Subject: [PATCH 15/16] fixes --- src/GNNGraphs/transform.jl | 2 +- test/GNNGraphs/transform.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GNNGraphs/transform.jl b/src/GNNGraphs/transform.jl index 7639e144d..f05d14a12 100644 --- a/src/GNNGraphs/transform.jl +++ b/src/GNNGraphs/transform.jl @@ -1205,7 +1205,7 @@ function ppr_diffusion(g::GNNGraph{<:COO_T}; alpha = 0.85f0) A_dense = Matrix(A_sparse) - PPR = alpha_f32 * inv(A_dense) + PPR = alpha * inv(A_dense) new_w = [PPR[dst, src] for (src, dst) in zip(s, t)] diff --git a/test/GNNGraphs/transform.jl b/test/GNNGraphs/transform.jl index 8ae84aaae..2ea4a1d89 100644 --- a/test/GNNGraphs/transform.jl +++ b/test/GNNGraphs/transform.jl @@ -613,6 +613,6 @@ end 0.038249996 0.050999995] - isequal(w_new, check_ew) + isapprox(w_new, check_ew) end end \ No newline at end of file From a5886b152be5f114324fa258fe244326ed96c4c1 Mon Sep 17 00:00:00 2001 From: Carlo Lucibello Date: Fri, 28 Jun 2024 11:12:42 +0200 Subject: [PATCH 16/16] Update test/GNNGraphs/transform.jl --- test/GNNGraphs/transform.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/GNNGraphs/transform.jl b/test/GNNGraphs/transform.jl index 2ea4a1d89..af414bbd1 100644 --- a/test/GNNGraphs/transform.jl +++ b/test/GNNGraphs/transform.jl @@ -613,6 +613,6 @@ end 0.038249996 0.050999995] - isapprox(w_new, check_ew) + @test w_new ≈ check_ew end end \ No newline at end of file