Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edge weights not properly documented for GNNHeteroGraphs (and implement new function to add new edge weights?) #331

Closed
codetalker7 opened this issue Sep 1, 2023 · 1 comment · Fixed by #337

Comments

@codetalker7
Copy link

I was experimenting with edge weights for GNNHeteroGraphs, but I had to dig deep in the documentation (and the docstrings from the source code) to see how edge weights work for heterographs. It'll be nice to add some examples to the documentation page for heterographs covering all operations that one can perform.

Also, it seems like there's no nice function to add new edges with weights to existing graphs. For instance, suppose I create a heterograph with some edge weights:

julia> using GraphNeuralNetworks
julia> g_het = GNNHeteroGraph((:user, :rate, :movie) => ([1,1,2,3], [7,13,5,7], [0.1, 0.2, 0.3, 0.4]))
GNNHeteroGraph:
  num_nodes: Dict(:movie => 13, :user => 3)
  num_edges: Dict((:user, :rate, :movie) => 4)

julia> get_edge_weight(g_het, (:user, :rate, :movie))          # gives us the edge weights
4-element Vector{Float64}:
 0.1
 0.2
 0.3
 0.4

But I can't add new edges with edge weights. Ideally, something like the following will be great:

julia> g_het = add_edges(g_het, (:user, :like, :actor) => ([1, 2], [3, 4], [0.5, 0.6]));          # no method supporting this currently

Also, this leads to some weird behavior; I can't even add edges without weights to g_het:

julia> g_het = add_edges(g_het, (:user, :like, :actor) => ([1, 2], [3, 4]))
ERROR: MethodError: Cannot `convert` an object of type Nothing to an object of type Vector{Float64}

Closest candidates are:
  convert(::Type{T}, ::LinearAlgebra.Factorization) where T<:AbstractArray
   @ LinearAlgebra ~/julia-1.9.0/share/julia/stdlib/v1.9/LinearAlgebra/src/factorization.jl:59
  convert(::Type{Array{T, N}}, ::StaticArraysCore.SizedArray{S, T, N, N, Array{T, N}}) where {S, T, N}
   @ StaticArrays ~/.julia/packages/StaticArrays/9KYrc/src/SizedArray.jl:88
  convert(::Type{Array{T, N}}, ::StaticArraysCore.SizedArray{S, T, N, M, TData} where {M, TData<:AbstractArray{T, M}}) where {T, S, N}
   @ StaticArrays ~/.julia/packages/StaticArrays/9KYrc/src/SizedArray.jl:82
  ...

Stacktrace:
 [1] cvt1
   @ ./essentials.jl:418 [inlined]
 [2] ntuple
   @ ./ntuple.jl:50 [inlined]
 [3] convert(#unused#::Type{Tuple{Vector{Int64}, Vector{Int64}, Vector{Float64}}}, x::Tuple{Vector{Int64}, Vector{Int64}, Nothing})
   @ Base ./essentials.jl:419
 [4] setindex!(h::Dict{Tuple{Symbol, Symbol, Symbol}, Tuple{Vector{Int64}, Vector{Int64}, Vector{Float64}}}, v0::Tuple{Vector{Int64}, Vector{Int64}, Nothing}, key::Tuple{Symbol, Symbol, Symbol})
   @ Base ./dict.jl:369
 [5] add_edges(g::GNNHeteroGraph{Tuple{Vector{Int64}, Vector{Int64}, Vector{Float64}}}, edge_t::Tuple{Symbol, Symbol, Symbol}, snew::Vector{Int64}, tnew::Vector{Int64}; edata::Nothing, num_nodes::Dict{Symbol, Int64})
   @ GraphNeuralNetworks.GNNGraphs ~/fluxml/GraphNeuralNetworks.jl/src/GNNGraphs/transform.jl:223
 [6] add_edges(g::GNNHeteroGraph{Tuple{Vector{Int64}, Vector{Int64}, Vector{Float64}}}, edge_t::Tuple{Symbol, Symbol, Symbol}, snew::Vector{Int64}, tnew::Vector{Int64})
   @ GraphNeuralNetworks.GNNGraphs ~/fluxml/GraphNeuralNetworks.jl/src/GNNGraphs/transform.jl:172
 [7] add_edges(g::GNNHeteroGraph{Tuple{Vector{Int64}, Vector{Int64}, Vector{Float64}}}, data::Pair{Tuple{Symbol, Symbol, Symbol}, Tuple{Vector{Int64}, Vector{Int64}}}; kws::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ GraphNeuralNetworks.GNNGraphs ~/fluxml/GraphNeuralNetworks.jl/src/GNNGraphs/transform.jl:170
 [8] add_edges(g::GNNHeteroGraph{Tuple{Vector{Int64}, Vector{Int64}, Vector{Float64}}}, data::Pair{Tuple{Symbol, Symbol, Symbol}, Tuple{Vector{Int64}, Vector{Int64}}})
   @ GraphNeuralNetworks.GNNGraphs ~/fluxml/GraphNeuralNetworks.jl/src/GNNGraphs/transform.jl:170
 [9] top-level scope
   @ REPL[83]:1

But ofcourse, I can add new edges if the original graph doesn't contain any weights:

julia> g_het2 = GNNHeteroGraph((:user, :rate, :movie) => ([1,1,2,3], [7,13,5,7]))
GNNHeteroGraph:
  num_nodes: Dict(:movie => 13, :user => 3)
  num_edges: Dict((:user, :rate, :movie) => 4)

julia> g_het2 = add_edges(g_het2, (:user, :like, :actor) => ([1,2], [3,4]))
GNNHeteroGraph:
  num_nodes: Dict(:actor => 4, :movie => 13, :user => 3)
  num_edges: Dict((:user, :like, :actor) => 2, (:user, :rate, :movie) => 4)

If this is expected behaviour, it'll be really nice to add these to the documentation.

@CarloLucibello
Copy link
Member

I agree that the heterograph docstring should also mention the edge weights.

add_edges should give the possibility to include edge weights (at the moment this is not possible even for GNNGraphs). I'm working on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants