diff --git a/docs/src/Combinatorics/graphs.md b/docs/src/Combinatorics/graphs.md index 176e1f45d81d..a1294d6925dc 100644 --- a/docs/src/Combinatorics/graphs.md +++ b/docs/src/Combinatorics/graphs.md @@ -51,13 +51,16 @@ rem_vertices!(g::Graph{T}, a::AbstractVector{Int64}) where {T <: Union{Directed, ## Auxiliary functions ```@docs +adjacency_matrix(g::Graph) all_neighbors(g::Graph{T}, v::Int64) where {T <: Union{Directed, Undirected}} automorphism_group_generators(g::Graph{T}) where {T <: Union{Directed, Undirected}} complete_graph(n::Int64) complete_bipartite_graph(n::Int64, m::Int64) +degree(g::Graph, v::Int) edges(g::Graph{T}) where {T <: Union{Directed, Undirected}} has_edge(g::Graph{T}, source::Int64, target::Int64) where {T <: Union{Directed, Undirected}} has_vertex(g::Graph{T}, v::Int64) where {T <: Union{Directed, Undirected}} +laplacian_matrix(g::Graph) n_edges(g::Graph{T}) where {T <: Union{Directed, Undirected}} n_vertices(g::Graph{T}) where {T <: Union{Directed, Undirected}} inneighbors(g::Graph{T}, v::Int64) where {T <: Union{Directed, Undirected}} diff --git a/src/Combinatorics/Graphs/functions.jl b/src/Combinatorics/Graphs/functions.jl index 58bfee8da43f..46ebfed592ff 100644 --- a/src/Combinatorics/Graphs/functions.jl +++ b/src/Combinatorics/Graphs/functions.jl @@ -507,6 +507,23 @@ function neighbors(g::Graph{T}, v::Int64) where {T <: Union{Directed, Undirected return [x+1 for x in result] end +@doc raw""" + degree(g::Graph{T} [, v::Int64]) where {T <: Union{Directed, Undirected}} + +Return the degree of the vertex `v` in the graph `g`. +If `v` is missing, return the list of degrees of all vertices. + +# Examples +```jldoctest +julia> g = vertex_edge_graph(icosahedron()); + +julia> degree(g, 1) +5 +``` +""" +degree(g::Graph, v::Int64) = length(neighbors(g, v)) +degree(g::Graph) = [ length(neighbors(g, v)) for v in 1:n_vertices(g) ] + @doc raw""" inneighbors(g::Graph{T}, v::Int64) where {T <: Union{Directed, Undirected}} @@ -1182,3 +1199,88 @@ function graph_from_edges(edges::Vector{Vector{Int}}, n_vertices::Int=-1) return graph_from_edges(Undirected, [Edge(e[1], e[2]) for e in edges], n_vertices) end + + + +@doc raw""" + adjacency_matrix(g::Graph{T}) where {T <: Union{Directed, Undirected}} + +Return an unsigned (boolean) adjacency matrix representing a graph `g`. If `g` +is undirected, the adjacency matrix will be symmetric. For `g` being directed, +the adjacency matrix has a `1` at `(u,v)` if there is an edge `u->v`. + +# Examples +Adjacency matrix for a directed graph: +```jldoctest +julia> G = Graph{Directed}(3) +Directed graph with 3 nodes and no edges + +julia> add_edge!(G,1,3) +true + +julia> add_edge!(G,1,2) +true + +julia> adjacency_matrix(G) +3×3 IncidenceMatrix +[2, 3] +[] +[] + + +julia> matrix(ZZ, adjacency_matrix(G)) +[0 1 1] +[0 0 0] +[0 0 0] +``` + +Adjacency matrix for an undirected graph: +```jldoctest +julia> G = vertex_edge_graph(cube(2)) +Undirected graph with 4 nodes and the following edges: +(2, 1)(3, 1)(4, 2)(4, 3) + +julia> adjacency_matrix(G) +4×4 IncidenceMatrix +[2, 3] +[1, 4] +[1, 4] +[2, 3] + + +julia> matrix(ZZ, adjacency_matrix(G)) +[0 1 1 0] +[1 0 0 1] +[1 0 0 1] +[0 1 1 0] +``` +""" +adjacency_matrix(g::Graph) = Polymake.call_function(:common, Symbol("IncidenceMatrix::new"), nothing, Polymake.common.adjacency_matrix(pm_object(g))) + + +@doc raw""" + laplacian_matrix(g::Graph{T}) where {T <: Union{Directed, Undirected}} + +Return the Laplacian matrix of the graph `g`. The Laplacian matrix of a graph +can be written as the difference of `D`, where `D` is a quadratic matrix with +the degrees of `g` on the diagonal, and the adjacency matrix of `g`. For an +undirected graph, the Laplacian matrix is symmetric. + +# Examples +``` +julia> G = vertex_edge_graph(cube(2)) +Undirected graph with 4 nodes and the following edges: +(2, 1)(3, 1)(4, 2)(4, 3) + +julia> laplacian_matrix(G) +[ 2 -1 -1 0] +[-1 2 0 -1] +[-1 0 2 -1] +[ 0 -1 -1 2] +``` +""" +function laplacian_matrix(g::Graph) + D = diagonal_matrix(degree(g)) + A = matrix(ZZ, adjacency_matrix(g)) + return D-A +end diff --git a/src/exports.jl b/src/exports.jl index 43549ff23e6f..fb0e12d0906c 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -194,6 +194,7 @@ export add_gluing! export add_vertex! export add_vertices! export adjacency_tree +export adjacency_matrix export adjacent_chamber export adjoint_ideal export adjunction_process @@ -915,6 +916,7 @@ export koszul_complex export koszul_homology export koszul_matrix export labeled_matrix_formatted +export laplacian_matrix export lattice_points export lattice_volume export leading_coefficient diff --git a/test/Combinatorics/Graph.jl b/test/Combinatorics/Graph.jl index d9fd42503a9e..7259ba0716fc 100644 --- a/test/Combinatorics/Graph.jl +++ b/test/Combinatorics/Graph.jl @@ -161,4 +161,15 @@ @test n_edges(G2) == 5 end + + @testset "adjacency_matrix laplacian_matrix" begin + G0 = Graph{Directed}(3) + add_edge!(G0,1,2) + add_edge!(G0,1,3) + @test matrix(ZZ, adjacency_matrix(G0)) == matrix(ZZ, [0 1 1; 0 0 0; 0 0 0]) + @test laplacian_matrix(G0) == matrix(ZZ, [2 -1 -1; 0 0 0; 0 0 0]) + G1 = vertex_edge_graph(cube(2)) + @test matrix(ZZ, adjacency_matrix(G1)) == matrix(ZZ, [0 1 1 0; 1 0 0 1; 1 0 0 1; 0 1 1 0]) + @test laplacian_matrix(G1) == matrix(ZZ, [2 -1 -1 0; -1 2 0 -1; -1 0 2 -1; 0 -1 -1 2]) + end end