Skip to content

Commit

Permalink
Graph: Add adjacency_matrix and laplacian_matrix (#3862)
Browse files Browse the repository at this point in the history
* Graphs: vertex degree in a graph

* Graphs: Add adjacency_matrix and laplacian_matrix

* Graphs: Make adjacency_matrix work for directed graphs, add some documentation

* Graphs: Add test for laplacian_matrix and adjacency_matrix

* Graphs: Add new functions to docs

---------

Co-authored-by: Michael Joswig <joswig@math.tu-berlin.de>
  • Loading branch information
lkastner and micjoswig authored Jun 17, 2024
1 parent 5e624ff commit 3a2bfe3
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 0 deletions.
3 changes: 3 additions & 0 deletions docs/src/Combinatorics/graphs.md
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
102 changes: 102 additions & 0 deletions src/Combinatorics/Graphs/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down Expand Up @@ -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
2 changes: 2 additions & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions test/Combinatorics/Graph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 3a2bfe3

Please sign in to comment.