From f60b1cf164ca61e27c93e1cfa09b29f18a234195 Mon Sep 17 00:00:00 2001 From: stecrotti Date: Mon, 30 Jun 2025 16:28:39 +0200 Subject: [PATCH 1/4] replace variable and factor with v_vertex and f_vertex --- Project.toml | 2 +- docs/src/index.md | 8 ++-- src/IndexedFactorGraphs.jl | 2 +- src/factorgraph.jl | 61 ++++++++++++++-------------- src/infinite_regular_factorgraph.jl | 22 +++++----- test/factorgraph.jl | 26 ++++++------ test/infinite_regular_factorgraph.jl | 16 ++++---- test/runtests.jl | 20 ++++----- 8 files changed, 79 insertions(+), 78 deletions(-) diff --git a/Project.toml b/Project.toml index 8b72ac7..2a09bbf 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "IndexedFactorGraphs" uuid = "edf0a622-c16b-410a-a162-e53dc16a76ae" authors = ["stecrotti "] -version = "0.1.3" +version = "0.2.0" [deps] FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" diff --git a/docs/src/index.md b/docs/src/index.md index fd578a7..f9a51d8 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -38,9 +38,9 @@ FactorGraph{Int64} with 5 variables, 3 factors, and 6 edges ### Graph navigation Given a factor graph with $N$ variables and $M$ factors, variables are indexed by $i\in\{1,\ldots,N\}$, factors are indexed by $a\in\{1,\ldots,M\}$. -Properties of a vertex can be queried by wrapping the vertex index in a `variable` or `factor`. For example, the list of neighbors of variable $i=2$ is found by +Properties of a vertex can be queried by wrapping the vertex index in a `v_vertex` or `f_vertex`. For example, the list of neighbors of variable $i=2$ is found by ```julia -julia> ∂i = neighbors(g, variable(2)); +julia> ∂i = neighbors(g, v_vertex(2)); julia> collect(∂i) 2-element Vector{Int64}: @@ -51,7 +51,7 @@ where $1,3$ are to be interpreted as indices of factor vertices. The list of edges adjacent to factor $a=1$ is found by ```julia -julia> ea = inedges(g, factor(1)); +julia> ea = inedges(g, f_vertex(1)); julia> collect(ea) 3-element Vector{IndexedGraphs.IndexedEdge{Int64}}: @@ -63,7 +63,7 @@ julia> collect(ea) Querying properties of a vertex without specifying whether it's a variable or a factor will throw an error ```julia julia> outedges(g, 3) -ERROR: ArgumentError: Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `variable` or `factor` wrapper instead. +ERROR: ArgumentError: Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `v_vertex` or `f_vertex` wrapper instead. ``` ## See also diff --git a/src/IndexedFactorGraphs.jl b/src/IndexedFactorGraphs.jl index c2a797c..7ab8385 100644 --- a/src/IndexedFactorGraphs.jl +++ b/src/IndexedFactorGraphs.jl @@ -19,7 +19,7 @@ include("factorgraph.jl") include("generators.jl") include("infinite_regular_factorgraph.jl") -export AbstractFactorGraph, FactorGraph, nvariables, nfactors, variables, factors, factor, variable, +export AbstractFactorGraph, FactorGraph, nvariables, nfactors, v_vertices, f_vertices, f_vertex, v_vertex, pairwise_interaction_graph, neighbors, edges, src, dst, idx, ne, nv, degree, edge_indices, inedges, outedges, diff --git a/src/factorgraph.jl b/src/factorgraph.jl index 3e49fca..12e6128 100644 --- a/src/factorgraph.jl +++ b/src/factorgraph.jl @@ -1,27 +1,27 @@ -const Factor = Left -const Variable = Right +const FactorVertex = Left +const VariableVertex = Right """ FactorGraphVertex A type to represent a vertex in a bipartite graph, to be passed as an argument to [`neighbors`](@ref), [`inedges`](@ref), [`outedges`](@ref), see examples therein. -It is recommended to use the [`variable`](@ref) and [`factor`](@ref) constructors. +It is recommended to use the [`v_vertex`](@ref) and [`fvertex`](@ref) constructors. """ const FactorGraphVertex = BipartiteGraphVertex """ - factor(a::Integer) + f_vertex(a::Integer) -Wraps index `a` in a container such that other functions like [`neighbors`](@ref), [`inedges`](@ref), [`outedges`](@ref), knowing that it indices a factor node. +Wraps index `a` in a container such that other functions like [`neighbors`](@ref), [`inedges`](@ref), [`outedges`](@ref), knowing that it indices a factor vertex. """ -factor(a::Integer) = vertex(a, Factor) +f_vertex(a::Integer) = vertex(a, FactorVertex) """ - variable(i::Integer) + v_vertex(i::Integer) -Wraps index `i` in a container such that other functions like [`neighbors`](@ref), [`inedges`](@ref), [`outedges`](@ref), knowing that it indices a variable node. +Wraps index `i` in a container such that other functions like [`neighbors`](@ref), [`inedges`](@ref), [`outedges`](@ref), knowing that it indices a variable vertex. """ -variable(i::Integer) = vertex(i, Variable) +v_vertex(i::Integer) = vertex(i, VariableVertex) abstract type AbstractFactorGraph{T} end @@ -82,22 +82,23 @@ nvariables(g::FactorGraph) = nv_right(g.g) Return the number of actors vertices in `g`. """ nfactors(g::FactorGraph) = nv_left(g.g) + IndexedGraphs.nv(g::FactorGraph) = nv(g.g) IndexedGraphs.ne(g::FactorGraph) = ne(g.g) """ - variables(g::FactorGraph) + v_vertices(g::FactorGraph) Return a lazy iterator to the indices of variable vertices in `g`. """ -variables(g::FactorGraph) = 1:nvariables(g) +v_vertices(g::FactorGraph) = 1:nvariables(g) """ - factors(g::FactorGraph) + f_vertices(g::FactorGraph) Return a lazy iterator to the indices of factor vertices in `g`. """ -factors(g::FactorGraph) = 1:nfactors(g) +f_vertices(g::FactorGraph) = 1:nfactors(g) """ IndexedGraphs.neighbors(g::FactorGraph, v::FactorGraphVertex) @@ -115,20 +116,20 @@ julia> g = FactorGraph([0 1 1 0; 0 0 1 1]) FactorGraph{Int64} with 4 variables, 3 factors, and 5 edges -julia> collect(neighbors(g, variable(3))) +julia> collect(neighbors(g, v_vertex(3))) 2-element Vector{Int64}: 1 3 -julia> collect(neighbors(g, factor(2))) +julia> collect(neighbors(g, f_vertex(2))) 1-element Vector{Int64}: 1 ``` """ -function IndexedGraphs.neighbors(g::FactorGraph, a::FactorGraphVertex{Factor}) +function IndexedGraphs.neighbors(g::FactorGraph, a::FactorGraphVertex{FactorVertex}) return @view g.g.X.rowval[nzrange(g.g.X, a.i)] end -function IndexedGraphs.neighbors(g::FactorGraph, i::FactorGraphVertex{Variable}) +function IndexedGraphs.neighbors(g::FactorGraph, i::FactorGraphVertex{VariableVertex}) return @view g.g.A.rowval[nzrange(g.g.A, i.i)] end @@ -153,9 +154,9 @@ FactorGraph{Int64} with 4 variables, 3 factors, and 5 edges julia> edgeprops = randn(ne(g)); -julia> indices = (idx(e) for e in outedges(g, variable(3))); +julia> indices = (idx(e) for e in outedges(g, v_vertex(3))); -julia> indices_noalloc = edge_indices(g, variable(3)); +julia> indices_noalloc = edge_indices(g, v_vertex(3)); julia> @assert edgeprops[collect(indices)] == edgeprops[indices_noalloc] @@ -164,10 +165,10 @@ Test Passed Thrown: ArgumentError ``` """ -function edge_indices(g::FactorGraph, a::FactorGraphVertex{Factor}) +function edge_indices(g::FactorGraph, a::FactorGraphVertex{FactorVertex}) return @view g.g.X.nzval[nzrange(g.g.X, a.i)] end -function edge_indices(g::FactorGraph, i::FactorGraphVertex{Variable}) +function edge_indices(g::FactorGraph, i::FactorGraphVertex{VariableVertex}) return nzrange(g.g.A, i.i) end @@ -195,21 +196,21 @@ julia> g = FactorGraph([0 1 1 0; 0 0 1 1]) FactorGraph{Int64} with 4 variables, 3 factors, and 5 edges -julia> collect(inedges(g, factor(2))) +julia> collect(inedges(g, f_vertex(2))) 1-element Vector{IndexedGraphs.IndexedEdge{Int64}}: Indexed Edge 1 => 2 with index 1 -julia> collect(inedges(g, variable(3))) +julia> collect(inedges(g, v_vertex(3))) 2-element Vector{IndexedGraphs.IndexedEdge{Int64}}: Indexed Edge 1 => 3 with index 3 Indexed Edge 3 => 3 with index 4 ``` """ -function IndexedGraphs.inedges(g::FactorGraph, a::FactorGraphVertex{Factor}) +function IndexedGraphs.inedges(g::FactorGraph, a::FactorGraphVertex{FactorVertex}) return (IndexedEdge(i, a.i, id) for (i, id) in zip(neighbors(g, a), edge_indices(g, a))) end -function IndexedGraphs.inedges(g::FactorGraph, i::FactorGraphVertex{Variable}) +function IndexedGraphs.inedges(g::FactorGraph, i::FactorGraphVertex{VariableVertex}) return (IndexedEdge(a, i.i, id) for (a, id) in zip(neighbors(g, i), edge_indices(g, i))) end @@ -230,20 +231,20 @@ julia> g = FactorGraph([0 1 1 0; 0 0 1 1]) FactorGraph{Int64} with 4 variables, 3 factors, and 5 edges -julia> collect(outedges(g, factor(2))) +julia> collect(outedges(g, f_vertex(2))) 1-element Vector{IndexedGraphs.IndexedEdge{Int64}}: Indexed Edge 2 => 1 with index 1 -julia> collect(outedges(g, variable(3))) +julia> collect(outedges(g, v_vertex(3))) 2-element Vector{IndexedGraphs.IndexedEdge{Int64}}: Indexed Edge 3 => 1 with index 3 Indexed Edge 3 => 3 with index 4 ``` """ -function IndexedGraphs.outedges(g::FactorGraph, a::FactorGraphVertex{Factor}) +function IndexedGraphs.outedges(g::FactorGraph, a::FactorGraphVertex{FactorVertex}) return (IndexedEdge(a.i, i, id) for (i, id) in zip(neighbors(g, a), edge_indices(g, a))) end -function IndexedGraphs.outedges(g::FactorGraph, i::FactorGraphVertex{Variable}) +function IndexedGraphs.outedges(g::FactorGraph, i::FactorGraphVertex{VariableVertex}) return (IndexedEdge(i.i, a, id) for (a, id) in zip(neighbors(g, i), edge_indices(g, i))) end @@ -282,7 +283,7 @@ end for method in [:(IndexedGraphs.degree), :(IndexedGraphs.inedges), :(IndexedGraphs.outedges), :(IndexedGraphs.neighbors), :(edge_indices)] @eval begin function $method(::AbstractFactorGraph, ::Integer) - return throw(ArgumentError("Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `variable` or `factor` wrapper instead.\n")) + return throw(ArgumentError("Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `v_vertex` or `fvertex` wrapper instead.\n")) end end end diff --git a/src/infinite_regular_factorgraph.jl b/src/infinite_regular_factorgraph.jl index f0823e5..45d483e 100644 --- a/src/infinite_regular_factorgraph.jl +++ b/src/infinite_regular_factorgraph.jl @@ -13,7 +13,7 @@ struct InfiniteRegularFactorGraph{T<:Integer} <: AbstractFactorGraph{T} Construct an `InfiniteRegularFactorGraph` with variable degree `kᵢ` and factor degree `kₐ` """ function InfiniteRegularFactorGraph(kᵢ::T, kₐ::T) where {T<:Integer} - kᵢ > 0 || throw(ArgumentError("Factor degree must be positive, got $kᵢ")) + kᵢ > 0 || throw(ArgumentError("Variable degree must be positive, got $kᵢ")) kₐ > 0 || throw(ArgumentError("Factor degree must be positive, got $kₐ")) return new{T}(kᵢ, kₐ) end @@ -27,31 +27,31 @@ nvariables(::InfiniteRegularFactorGraph) = 1 nfactors(::InfiniteRegularFactorGraph) = 1 Graphs.ne(::InfiniteRegularFactorGraph) = 1 Graphs.edges(::InfiniteRegularFactorGraph) = (IndexedEdge(1,1,1) for _ in 1:1) -variables(::InfiniteRegularFactorGraph) = 1:1 -factors(::InfiniteRegularFactorGraph) = 1:1 +v_vertices(::InfiniteRegularFactorGraph) = 1:1 +f_vertices(::InfiniteRegularFactorGraph) = 1:1 IndexedGraphs.degree(g::InfiniteRegularFactorGraph, v::FactorGraphVertex) = length(neighbors(g, v)) -function IndexedGraphs.neighbors(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Factor}) +function IndexedGraphs.neighbors(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{FactorVertex}) return Fill(1, g.kₐ) end -function IndexedGraphs.neighbors(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Variable}) +function IndexedGraphs.neighbors(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{VariableVertex}) return Fill(1, g.kᵢ) end -edge_indices(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Factor}) = Fill(1, g.kₐ) -edge_indices(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Variable}) = Fill(1, g.kᵢ) +edge_indices(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{FactorVertex}) = Fill(1, g.kₐ) +edge_indices(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{VariableVertex}) = Fill(1, g.kᵢ) -function IndexedGraphs.inedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Factor}) +function IndexedGraphs.inedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{FactorVertex}) return (IndexedEdge(1,1,1) for _ in 1:g.kₐ) end -function IndexedGraphs.inedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Variable}) +function IndexedGraphs.inedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{VariableVertex}) return (IndexedEdge(1,1,1) for _ in 1:g.kᵢ) end -function IndexedGraphs.outedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Factor}) +function IndexedGraphs.outedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{FactorVertex}) return (IndexedEdge(1,1,1) for _ in 1:g.kₐ) end -function IndexedGraphs.outedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{Variable}) +function IndexedGraphs.outedges(g::InfiniteRegularFactorGraph, ::FactorGraphVertex{VariableVertex}) return (IndexedEdge(1,1,1) for _ in 1:g.kᵢ) end \ No newline at end of file diff --git a/test/factorgraph.jl b/test/factorgraph.jl index 4821e1c..9a12828 100644 --- a/test/factorgraph.jl +++ b/test/factorgraph.jl @@ -7,15 +7,15 @@ g = FactorGraph(A) @testset "Basics" begin @test @inferred nfactors(g) == m @test @inferred nvariables(g) == n - @test all(@inferred degree(g, factor(a)) == length(@inferred neighbors(g,factor(a))) for a in factors(g)) - @test all(@inferred degree(g, variable(i)) == length(@inferred neighbors(g,variable(i))) for i in variables(g)) + @test all(@inferred degree(g, f_vertex(a)) == length(@inferred neighbors(g,f_vertex(a))) for a in f_vertices(g)) + @test all(@inferred degree(g, v_vertex(i)) == length(@inferred neighbors(g,v_vertex(i))) for i in v_vertices(g)) @test length(collect(@inferred edges(g))) == @inferred ne(g) - @test all(all(src(e)==a for (e,a) in zip(inedges(g, variable(i)), neighbors(g, variable(i)))) for i in variables(g)) - @test all(all(src(e)==i for (e,i) in zip(inedges(g, factor(a)), neighbors(g, factor(a)))) for a in factors(g)) - @test all(all(dst(e)==a for (e,a) in zip(outedges(g, variable(i)), neighbors(g, variable(i)))) for i in variables(g)) - @test all(all(dst(e)==i for (e,i) in zip(outedges(g, factor(a)), neighbors(g, factor(a)))) for a in factors(g)) + @test all(all(src(e)==a for (e,a) in zip(inedges(g, v_vertex(i)), neighbors(g, v_vertex(i)))) for i in v_vertices(g)) + @test all(all(src(e)==i for (e,i) in zip(inedges(g, f_vertex(a)), neighbors(g, f_vertex(a)))) for a in f_vertices(g)) + @test all(all(dst(e)==a for (e,a) in zip(outedges(g, v_vertex(i)), neighbors(g, v_vertex(i)))) for i in v_vertices(g)) + @test all(all(dst(e)==i for (e,i) in zip(outedges(g, f_vertex(a)), neighbors(g, f_vertex(a)))) for a in f_vertices(g)) @test_throws ArgumentError degree(g, 1) @test_throws ArgumentError neighbors(g, 1) @@ -29,7 +29,7 @@ end end @testset "Broadcasting" begin - ids = [variable(i) for i in rand(1:nvariables(g), 5)] + ids = [v_vertex(i) for i in rand(1:nvariables(g), 5)] @test degree.(g, ids) == degree.((g,), ids) end @@ -40,8 +40,8 @@ end g_factorgraph = pairwise_interaction_graph(g_pairwise) @test all(1:n-1) do i neigs_pairwise = neighbors(g_pairwise, i) - neigs_factorgraph = reduce(vcat, neighbors(g_factorgraph, factor(a)) - for a in neighbors(g_factorgraph, variable(i)); init=Int[]) + neigs_factorgraph = reduce(vcat, neighbors(g_factorgraph, f_vertex(a)) + for a in neighbors(g_factorgraph, v_vertex(i)); init=Int[]) unique!(neigs_factorgraph) filter!(!isequal(i), neigs_factorgraph) neigs_pairwise == neigs_factorgraph @@ -49,11 +49,11 @@ end end @testset "Edge indices" begin - @test all(variables(g)) do i - idx.(collect(inedges(g, variable(i)))) == edge_indices(g, variable(i)) + @test all(v_vertices(g)) do i + idx.(collect(inedges(g, v_vertex(i)))) == edge_indices(g, v_vertex(i)) end - @test all(factors(g)) do a - idx.(collect(inedges(g, factor(a)))) == edge_indices(g, factor(a)) + @test all(f_vertices(g)) do a + idx.(collect(inedges(g, f_vertex(a)))) == edge_indices(g, f_vertex(a)) end end diff --git a/test/infinite_regular_factorgraph.jl b/test/infinite_regular_factorgraph.jl index 2eee6dc..2a2692b 100644 --- a/test/infinite_regular_factorgraph.jl +++ b/test/infinite_regular_factorgraph.jl @@ -3,13 +3,13 @@ kₐ = 4 g = InfiniteRegularFactorGraph(kᵢ, kₐ) @testset "Basics" begin - @test degree(g, variable(100)) == kᵢ - @test degree(g, factor(12)) == kₐ + @test degree(g, v_vertex(100)) == kᵢ + @test degree(g, f_vertex(12)) == kₐ @test nfactors(g) == 1 @test nvariables(g) == 1 @test ne(g) == 1 - @test variables(g) == 1:1 - @test factors(g) == 1:1 + @test v_vertices(g) == 1:1 + @test f_vertices(g) == 1:1 @test all(edges(g)) do (i, j, id) i == 1 && j == 1 && id == 1 end @@ -20,10 +20,10 @@ end end @testset "Edge indices" begin - @test all(variables(g)) do i - idx.(collect(inedges(g, variable(i)))) == edge_indices(g, variable(i)) + @test all(v_vertices(g)) do i + idx.(collect(inedges(g, v_vertex(i)))) == edge_indices(g, v_vertex(i)) end - @test all(factors(g)) do a - idx.(collect(outedges(g, factor(a)))) == edge_indices(g, factor(a)) + @test all(f_vertices(g)) do a + idx.(collect(outedges(g, f_vertex(a)))) == edge_indices(g, f_vertex(a)) end end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index d18f9f1..ff424e2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,16 +17,16 @@ Check type inference for functions that are likely to be called in hot loops """ function test_type_inference(g::AbstractFactorGraph) all_edges = @inferred edge_indices(g) - i = rand(rng, @inferred variables(g)) - a = rand(rng, @inferred factors(g)) - di = @inferred degree(g, @inferred variable(i)) - da = @inferred degree(g, @inferred factor(a)) - ∂i = @inferred neighbors(g, variable(i)) - inei = @inferred inedges(g, variable(i)) - outei = @inferred outedges(g, variable(i)) - ∂a = @inferred neighbors(g, factor(a)) - inea = @inferred inedges(g, factor(a)) - outea = @inferred outedges(g, factor(a)) + i = rand(rng, @inferred v_vertices(g)) + a = rand(rng, @inferred f_vertices(g)) + di = @inferred degree(g, @inferred v_vertex(i)) + da = @inferred degree(g, @inferred f_vertex(a)) + ∂i = @inferred neighbors(g, v_vertex(i)) + inei = @inferred inedges(g, v_vertex(i)) + outei = @inferred outedges(g, v_vertex(i)) + ∂a = @inferred neighbors(g, f_vertex(a)) + inea = @inferred inedges(g, f_vertex(a)) + outea = @inferred outedges(g, f_vertex(a)) end include("factorgraph.jl") From bf521822da5cc664c2e9f48d7873bfceacb4b310 Mon Sep 17 00:00:00 2001 From: stecrotti Date: Tue, 1 Jul 2025 11:11:44 +0200 Subject: [PATCH 2/4] add constructor for pairwise interaction graph from matrix --- src/IndexedFactorGraphs.jl | 2 +- src/factorgraph.jl | 1 + test/factorgraph.jl | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/IndexedFactorGraphs.jl b/src/IndexedFactorGraphs.jl index 7ab8385..712a7d4 100644 --- a/src/IndexedFactorGraphs.jl +++ b/src/IndexedFactorGraphs.jl @@ -2,7 +2,7 @@ module IndexedFactorGraphs using IndexedGraphs: IndexedGraphs, - IndexedEdge, BipartiteIndexedGraph, BipartiteGraphVertex, NullNumber, + IndexedEdge, IndexedGraph, BipartiteIndexedGraph, BipartiteGraphVertex, NullNumber, src, dst, idx, edges, nv, ne, degree, linearindex, inedges, outedges, vertex, nv_left, nv_right, vertex, Left, Right, rand_bipartite_graph, rand_regular_bipartite_graph, rand_bipartite_tree diff --git a/src/factorgraph.jl b/src/factorgraph.jl index 12e6128..8a1f60b 100644 --- a/src/factorgraph.jl +++ b/src/factorgraph.jl @@ -61,6 +61,7 @@ function pairwise_interaction_graph(g::AbstractGraph) A = sparse(I, J, K, E, N) FactorGraph(A) end +pairwise_interaction_graph(A::AbstractMatrix) = pairwise_interaction_graph(IndexedGraph(A)) function Base.show(io::IO, g::FactorGraph{T}) where T nfact = nfactors(g) diff --git a/test/factorgraph.jl b/test/factorgraph.jl index 9a12828..cbc3f1b 100644 --- a/test/factorgraph.jl +++ b/test/factorgraph.jl @@ -38,6 +38,8 @@ end # to test on isolated nodes add_vertex!(g_pairwise) g_factorgraph = pairwise_interaction_graph(g_pairwise) + g_factorgraph_A = pairwise_interaction_graph(adjacency_matrix(g_pairwise)) + @test adjacency_matrix(g_factorgraph) == adjacency_matrix(g_factorgraph) @test all(1:n-1) do i neigs_pairwise = neighbors(g_pairwise, i) neigs_factorgraph = reduce(vcat, neighbors(g_factorgraph, f_vertex(a)) From 0098ae234955bbfa665f85e215f3150230f1b493 Mon Sep 17 00:00:00 2001 From: stecrotti Date: Tue, 8 Jul 2025 19:25:42 +0200 Subject: [PATCH 3/4] rename v_vertices and f_vertices to eachvariable and eachfactor --- src/IndexedFactorGraphs.jl | 2 +- src/factorgraph.jl | 8 ++++---- src/infinite_regular_factorgraph.jl | 4 ++-- test/factorgraph.jl | 16 ++++++++-------- test/infinite_regular_factorgraph.jl | 8 ++++---- test/runtests.jl | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/IndexedFactorGraphs.jl b/src/IndexedFactorGraphs.jl index 712a7d4..05f83cb 100644 --- a/src/IndexedFactorGraphs.jl +++ b/src/IndexedFactorGraphs.jl @@ -19,7 +19,7 @@ include("factorgraph.jl") include("generators.jl") include("infinite_regular_factorgraph.jl") -export AbstractFactorGraph, FactorGraph, nvariables, nfactors, v_vertices, f_vertices, f_vertex, v_vertex, +export AbstractFactorGraph, FactorGraph, nvariables, nfactors, eachvariable, eachfactor, f_vertex, v_vertex, pairwise_interaction_graph, neighbors, edges, src, dst, idx, ne, nv, degree, edge_indices, inedges, outedges, diff --git a/src/factorgraph.jl b/src/factorgraph.jl index 8a1f60b..7cd69e3 100644 --- a/src/factorgraph.jl +++ b/src/factorgraph.jl @@ -88,18 +88,18 @@ IndexedGraphs.nv(g::FactorGraph) = nv(g.g) IndexedGraphs.ne(g::FactorGraph) = ne(g.g) """ - v_vertices(g::FactorGraph) + eachvariable(g::FactorGraph) Return a lazy iterator to the indices of variable vertices in `g`. """ -v_vertices(g::FactorGraph) = 1:nvariables(g) +eachvariable(g::FactorGraph) = 1:nvariables(g) """ - f_vertices(g::FactorGraph) + eachfactor(g::FactorGraph) Return a lazy iterator to the indices of factor vertices in `g`. """ -f_vertices(g::FactorGraph) = 1:nfactors(g) +eachfactor(g::FactorGraph) = 1:nfactors(g) """ IndexedGraphs.neighbors(g::FactorGraph, v::FactorGraphVertex) diff --git a/src/infinite_regular_factorgraph.jl b/src/infinite_regular_factorgraph.jl index 45d483e..20f6e4b 100644 --- a/src/infinite_regular_factorgraph.jl +++ b/src/infinite_regular_factorgraph.jl @@ -27,8 +27,8 @@ nvariables(::InfiniteRegularFactorGraph) = 1 nfactors(::InfiniteRegularFactorGraph) = 1 Graphs.ne(::InfiniteRegularFactorGraph) = 1 Graphs.edges(::InfiniteRegularFactorGraph) = (IndexedEdge(1,1,1) for _ in 1:1) -v_vertices(::InfiniteRegularFactorGraph) = 1:1 -f_vertices(::InfiniteRegularFactorGraph) = 1:1 +eachvariable(::InfiniteRegularFactorGraph) = 1:1 +eachfactor(::InfiniteRegularFactorGraph) = 1:1 IndexedGraphs.degree(g::InfiniteRegularFactorGraph, v::FactorGraphVertex) = length(neighbors(g, v)) diff --git a/test/factorgraph.jl b/test/factorgraph.jl index cbc3f1b..26c77dc 100644 --- a/test/factorgraph.jl +++ b/test/factorgraph.jl @@ -7,15 +7,15 @@ g = FactorGraph(A) @testset "Basics" begin @test @inferred nfactors(g) == m @test @inferred nvariables(g) == n - @test all(@inferred degree(g, f_vertex(a)) == length(@inferred neighbors(g,f_vertex(a))) for a in f_vertices(g)) - @test all(@inferred degree(g, v_vertex(i)) == length(@inferred neighbors(g,v_vertex(i))) for i in v_vertices(g)) + @test all(@inferred degree(g, f_vertex(a)) == length(@inferred neighbors(g,f_vertex(a))) for a in eachfactor(g)) + @test all(@inferred degree(g, v_vertex(i)) == length(@inferred neighbors(g,v_vertex(i))) for i in eachvariable(g)) @test length(collect(@inferred edges(g))) == @inferred ne(g) - @test all(all(src(e)==a for (e,a) in zip(inedges(g, v_vertex(i)), neighbors(g, v_vertex(i)))) for i in v_vertices(g)) - @test all(all(src(e)==i for (e,i) in zip(inedges(g, f_vertex(a)), neighbors(g, f_vertex(a)))) for a in f_vertices(g)) - @test all(all(dst(e)==a for (e,a) in zip(outedges(g, v_vertex(i)), neighbors(g, v_vertex(i)))) for i in v_vertices(g)) - @test all(all(dst(e)==i for (e,i) in zip(outedges(g, f_vertex(a)), neighbors(g, f_vertex(a)))) for a in f_vertices(g)) + @test all(all(src(e)==a for (e,a) in zip(inedges(g, v_vertex(i)), neighbors(g, v_vertex(i)))) for i in eachvariable(g)) + @test all(all(src(e)==i for (e,i) in zip(inedges(g, f_vertex(a)), neighbors(g, f_vertex(a)))) for a in eachfactor(g)) + @test all(all(dst(e)==a for (e,a) in zip(outedges(g, v_vertex(i)), neighbors(g, v_vertex(i)))) for i in eachvariable(g)) + @test all(all(dst(e)==i for (e,i) in zip(outedges(g, f_vertex(a)), neighbors(g, f_vertex(a)))) for a in eachfactor(g)) @test_throws ArgumentError degree(g, 1) @test_throws ArgumentError neighbors(g, 1) @@ -51,10 +51,10 @@ end end @testset "Edge indices" begin - @test all(v_vertices(g)) do i + @test all(eachvariable(g)) do i idx.(collect(inedges(g, v_vertex(i)))) == edge_indices(g, v_vertex(i)) end - @test all(f_vertices(g)) do a + @test all(eachfactor(g)) do a idx.(collect(inedges(g, f_vertex(a)))) == edge_indices(g, f_vertex(a)) end end diff --git a/test/infinite_regular_factorgraph.jl b/test/infinite_regular_factorgraph.jl index 2a2692b..a7999c3 100644 --- a/test/infinite_regular_factorgraph.jl +++ b/test/infinite_regular_factorgraph.jl @@ -8,8 +8,8 @@ g = InfiniteRegularFactorGraph(kᵢ, kₐ) @test nfactors(g) == 1 @test nvariables(g) == 1 @test ne(g) == 1 - @test v_vertices(g) == 1:1 - @test f_vertices(g) == 1:1 + @test eachvariable(g) == 1:1 + @test eachfactor(g) == 1:1 @test all(edges(g)) do (i, j, id) i == 1 && j == 1 && id == 1 end @@ -20,10 +20,10 @@ end end @testset "Edge indices" begin - @test all(v_vertices(g)) do i + @test all(eachvariable(g)) do i idx.(collect(inedges(g, v_vertex(i)))) == edge_indices(g, v_vertex(i)) end - @test all(f_vertices(g)) do a + @test all(eachfactor(g)) do a idx.(collect(outedges(g, f_vertex(a)))) == edge_indices(g, f_vertex(a)) end end \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index ff424e2..4881033 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -17,8 +17,8 @@ Check type inference for functions that are likely to be called in hot loops """ function test_type_inference(g::AbstractFactorGraph) all_edges = @inferred edge_indices(g) - i = rand(rng, @inferred v_vertices(g)) - a = rand(rng, @inferred f_vertices(g)) + i = rand(rng, @inferred eachvariable(g)) + a = rand(rng, @inferred eachfactor(g)) di = @inferred degree(g, @inferred v_vertex(i)) da = @inferred degree(g, @inferred f_vertex(a)) ∂i = @inferred neighbors(g, v_vertex(i)) From 0d2919961ba8c6b6bb37907771797dbca367c1af Mon Sep 17 00:00:00 2001 From: stecrotti Date: Tue, 8 Jul 2025 19:40:55 +0200 Subject: [PATCH 4/4] fix error in docstring and readme --- README.md | 4 ++-- src/factorgraph.jl | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 511e00a..7805110 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ FactorGraph{Int64} with 5 variables, 3 factors, and 6 edges ### Graph navigation Given a factor graph with $N$ variables and $M$ factors, variables are indexed by $i\in\{1,\ldots,N\}$, factors are indexed by $a\in\{1,\ldots,M\}$. -Properties of a vertex can be queried by wrapping the vertex index in a `variable` or `factor`. For example, the list of neighbors of variable $i=2$ is found by +Properties of a vertex can be queried by wrapping the vertex index in a `v_vertex` or `f_vertex`. For example, the list of neighbors of variable $i=2$ is found by ```julia julia> ∂i = neighbors(g, variable(2)); @@ -59,7 +59,7 @@ julia> collect(ea) Querying properties of a vertex without specifying whether it's a variable or a factor will throw an error ```julia julia> outedges(g, 3) -ERROR: ArgumentError: Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `variable` or `factor` wrapper instead. +ERROR: ArgumentError: Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `v_vertex` or `f_vertex` wrapper instead. ``` ## See also diff --git a/src/factorgraph.jl b/src/factorgraph.jl index 7cd69e3..fd4e7a3 100644 --- a/src/factorgraph.jl +++ b/src/factorgraph.jl @@ -5,7 +5,7 @@ const VariableVertex = Right FactorGraphVertex A type to represent a vertex in a bipartite graph, to be passed as an argument to [`neighbors`](@ref), [`inedges`](@ref), [`outedges`](@ref), see examples therein. -It is recommended to use the [`v_vertex`](@ref) and [`fvertex`](@ref) constructors. +It is recommended to use the [`v_vertex`](@ref) and [`f_vertex`](@ref) constructors. """ const FactorGraphVertex = BipartiteGraphVertex @@ -284,7 +284,7 @@ end for method in [:(IndexedGraphs.degree), :(IndexedGraphs.inedges), :(IndexedGraphs.outedges), :(IndexedGraphs.neighbors), :(edge_indices)] @eval begin function $method(::AbstractFactorGraph, ::Integer) - return throw(ArgumentError("Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `v_vertex` or `fvertex` wrapper instead.\n")) + return throw(ArgumentError("Properties of a vertex of an `AbstractFactorGraph` such as degree, neighbors, etc. cannot be accessed by an integer. Use a `v_vertex` or `f_vertex` wrapper instead.\n")) end end end