Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,18 @@ Functions that compute properties of the graph:
```@docs
nv
ne
vertices
has_vertex
has_edge
edges
neighbors
all_neighbors
inneighbors
outneighbors
degree
indegree
outdegree
density
is_bipartite
is_directed
```
75 changes: 72 additions & 3 deletions src/BipartiteFactorGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,24 @@ module BipartiteFactorGraphs

using Graphs
import Graphs:
add_edge!, has_edge, edges, neighbors, nv, ne, all_neighbors, degree, indegree, outdegree, density, is_bipartite
AbstractGraph,
vertices,
has_vertex,
add_edge!,
has_edge,
edges,
neighbors,
nv,
ne,
all_neighbors,
inneighbors,
outneighbors,
degree,
indegree,
outdegree,
density,
is_bipartite,
is_directed

export BipartiteFactorGraph,
add_variable!,
Expand All @@ -19,18 +36,23 @@ export BipartiteFactorGraph,
num_variables,
num_factors,
# Reexport used Graphs functions
vertices,
has_vertex,
add_edge!,
has_edge,
edges,
neighbors,
nv,
ne,
all_neighbors,
inneighbors,
outneighbors,
degree,
indegree,
outdegree,
density,
is_bipartite
is_bipartite,
is_directed

struct UnorderedPair{T}
a::T
Expand Down Expand Up @@ -97,7 +119,7 @@ struct BipartiteFactorGraph{
DVars <: AbstractDict{Int, TVar},
DFacs <: AbstractDict{Int, TFac},
DE <: AbstractDict{UnorderedPair{Int}, E}
}
} <: AbstractGraph{Int}
graph::SimpleGraph{Int}
variable_data::DVars
factor_data::DFacs
Expand Down Expand Up @@ -289,6 +311,26 @@ Get the number of factor nodes in the graph.
"""
num_factors(g::BipartiteFactorGraph) = length(g.factor_data)

"""
vertices(g::BipartiteFactorGraph)

Get all vertices in the graph. Note, that it returns vertices that represent both variable and factor nodes.
Use [`variables`](@ref) and [`factors`](@ref) to get only variable or factor nodes.
"""
function Graphs.vertices(g::BipartiteFactorGraph)
return Graphs.vertices(g.graph)
end

"""
has_vertex(g::BipartiteFactorGraph, v::Int)

Check if vertex `v` is in the graph. Note, that it returns true for both variable and factor nodes.
Use [`is_variable`](@ref) and [`is_factor`](@ref) to check existence of a node with a specific type.
"""
function Graphs.has_vertex(g::BipartiteFactorGraph, v::Int)
return Graphs.has_vertex(g.graph, v)
end

"""
has_edge(g::BipartiteFactorGraph, var::Int, fac::Int)

Expand Down Expand Up @@ -340,6 +382,24 @@ function all_neighbors(g::BipartiteFactorGraph, v::Int)
return Graphs.neighbors(g.graph, v)
end

"""
inneighbors(g::BipartiteFactorGraph, v::Int)

Return a list of all in-neighbors of vertex `v` in graph `g`.
"""
function inneighbors(g::BipartiteFactorGraph, v::Int)
return Graphs.inneighbors(g.graph, v)
end

"""
outneighbors(g::BipartiteFactorGraph, v::Int)

Return a list of all out-neighbors of vertex `v` in graph `g`.
"""
function outneighbors(g::BipartiteFactorGraph, v::Int)
return Graphs.outneighbors(g.graph, v)
end

"""
degree(g::BipartiteFactorGraph[, v])

Expand Down Expand Up @@ -405,4 +465,13 @@ function is_bipartite(g::BipartiteFactorGraph)
return Graphs.is_bipartite(g.graph)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to return true for is_bipartite? Is it even possible to create a non-bipartite graph under the hood?

end

"""
is_directed(g::BipartiteFactorGraph)

Check if the graph is directed. For BipartiteFactorGraph this is always false since the graph is undirected.
"""
function is_directed(g::BipartiteFactorGraph)
return false
end

end # module
58 changes: 58 additions & 0 deletions test/graph_api_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@

g = BipartiteFactorGraph(Float64, String, Bool)

@test !is_directed(g)

# Test empty graph properties
@test Graphs.nv(g) == 0
@test Graphs.ne(g) == 0
@test Graphs.density(g) == 0.0
@test Graphs.eltype(g) == Int

@test isempty(vertices(g))

# Add some nodes and edges
v1 = add_variable!(g, 1.0)
Expand All @@ -17,15 +22,68 @@
f1 = add_factor!(g, "factor1")
f2 = add_factor!(g, "factor2")

@test !isempty(vertices(g))
@test length(vertices(g)) == 5
@test length(edges(g)) == 0

@test v1 in vertices(g)
@test f1 in vertices(g)
@test v2 in vertices(g)
@test f2 in vertices(g)
@test v3 in vertices(g)

@test v1 in variables(g)
@test v2 in variables(g)
@test v3 in variables(g)

@test f1 in factors(g)
@test f2 in factors(g)

@test !(v1 in factors(g))
@test !(v2 in factors(g))
@test !(v3 in factors(g))

@test !(f1 in variables(g))
@test !(f2 in variables(g))

@test has_vertex(g, v1)
@test has_vertex(g, v2)
@test has_vertex(g, v3)
@test has_vertex(g, f1)
@test has_vertex(g, f2)
@test !has_vertex(g, -1)

@test !has_edge(g, v1, f1)
@test !has_edge(g, v2, f1)
@test !has_edge(g, v2, f2)
@test !has_edge(g, v3, f2)
@test !has_edge(g, v1, f2)

add_edge!(g, v1, f1, true)
add_edge!(g, v2, f1, true)
add_edge!(g, v2, f2, false)
add_edge!(g, v3, f2, true)

@test length(edges(g)) == 4

@test has_edge(g, v1, f1)
@test has_edge(g, v2, f1)
@test has_edge(g, v2, f2)
@test has_edge(g, v3, f2)
@test !has_edge(g, v1, f2)

@test inneighbors(g, v1) == [f1]
@test inneighbors(g, v2) == [f1, f2]
@test inneighbors(g, v3) == [f2]
@test inneighbors(g, f1) == [v1, v2]
@test inneighbors(g, f2) == [v2, v3]

@test outneighbors(g, v1) == [f1]
@test outneighbors(g, v2) == [f1, f2]
@test outneighbors(g, v3) == [f2]
@test outneighbors(g, f1) == [v1, v2]
@test outneighbors(g, f2) == [v2, v3]

# Test graph properties
@test Graphs.nv(g) == 5 # 3 variables + 2 factors
@test Graphs.ne(g) == 4 # 4 edges
Expand Down