Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a2b1e84
[PartitionedGraphs] Some `QuotientView` fixes and improvements
Nov 24, 2025
be7d219
[PartitionedGraphs] Add directed/undirected graph type methos for `Pa…
Nov 24, 2025
e453d7f
[PartitionedGraphs] Add `similar_type` method for `QuotientView`.
Nov 24, 2025
9487b51
[PartitionedGraphs] Add `quotientview` interface function
Nov 24, 2025
6bfb9b4
[PartitionedGraphs] `quotient_graph` now returns a graph of similar t…
Nov 24, 2025
a7d5a58
Version bump
Nov 24, 2025
b6f1f6b
[PartitionGraphs] fallback method for `show`
Nov 24, 2025
3702ef6
Fix missing import
Nov 24, 2025
4dc4611
Remove broken import
Nov 25, 2025
f1641a2
[PartitionedGraphs] Add `edgeless_quotient_graph` interface function.
Nov 25, 2025
36381cf
[PartitionedGraphs] `quotient_graph` now returns a (un)directed graph…
Dec 3, 2025
703363a
[PartitionedGraphs] Explictly construct edges of correct type when cr…
Dec 3, 2025
d277466
[PartitionedGraphs] `PartitionedGraph` now takes the quotient graph t…
Dec 3, 2025
e55cb9f
Fix typo as `graph_type` -> `graph`.
Dec 3, 2025
fa2608c
[PartitionedGraphs] Add directed/undireced graph constructor function…
Dec 3, 2025
e81da68
Remove redundant `directed_graph` method, add fallbacks `NamedGraph` …
Dec 3, 2025
d7fe1ee
[PartitionedGraphs] Remove overlapping method
Dec 3, 2025
809f5b8
Add fall back for `position_graph_type` based on `promote_op`.
Dec 3, 2025
02789eb
Test structs now implemented the correct interface for `NamedGraphs`
Dec 3, 2025
0ae1425
Add `add_vertices!` method for `AbstractSimpleGraph`;
Dec 4, 2025
e1627a9
Rename `graph_from_vertices` -> `similar_graph` and add single, doubl…
Dec 4, 2025
1929506
Rename `edgeless_quotient_graph` to `similar_quotient_graph`.
Dec 4, 2025
3cd86a3
Add tests for `similar_graph` function
Dec 4, 2025
4ae23ee
Add specific and fallback methods for `Base.reverse` with tests.
Dec 4, 2025
d6d98fa
Remove left over @warn statement in test file.
jack-dunham Dec 9, 2025
93a1707
Remove try/catch from `similar_graph`; remove auto conversion of `ver…
Dec 9, 2025
045d2f3
Collect `edges` before constructing reversed graph
Dec 10, 2025
89891cd
Make `induced_subgraph_grom_vertices` more generic by using `similar_…
Dec 10, 2025
4fcfb58
Add `AbstractGraphIndices` interface
Dec 11, 2025
99bb1e5
Improve vertex conversion functions
Dec 11, 2025
8a101ac
Add quotient edge and vertex iterables a subtypes of `AbstractGraphIn…
Dec 11, 2025
fc13e10
Add `similar_graph` methods for `AbstractSimpleGraph` as to not requi…
Dec 11, 2025
e2b2391
Remove dead function definition.
Dec 11, 2025
0548f24
Improve `AbstractGraphIndices` interface
Dec 12, 2025
76cfdf1
Use `departition` as the basic "field getter" for `QuotientIndInds` t…
Dec 12, 2025
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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "NamedGraphs"
uuid = "678767b0-92e7-4007-89e4-4527a8725b19"
authors = ["Matthew Fishman <mfishman@flatironinstitute.org>, Joseph Tindall <jtindall@flatironinstitute.org> and contributors"]
version = "0.8.2"
version = "0.8.3"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
Expand Down
2 changes: 1 addition & 1 deletion examples/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ NamedGraphs = "678767b0-92e7-4007-89e4-4527a8725b19"

[compat]
Graphs = "1.12.0"
NamedGraphs = "0.8.1"
NamedGraphs = "0.8.3"
1 change: 1 addition & 0 deletions src/NamedGraphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ include("utils.jl")
include("abstractnamededge.jl")
include("namededge.jl")
include("abstractnamedgraph.jl")
include("abstractgraphindices.jl")
include("decorate.jl")
include("simplecycles.jl")
include("shortestpaths.jl")
Expand Down
32 changes: 32 additions & 0 deletions src/abstractgraphindices.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Graphs: AbstractEdge

abstract type AbstractGraphIndices{T} end
abstract type AbstractVertices{V} <: AbstractGraphIndices{V} end
abstract type AbstractEdges{V, E <: AbstractEdge{V}} <: AbstractGraphIndices{E} end

struct Vertices{V, Vs} <: AbstractVertices{V}
vertices::Vs
Vertices(vertices::Vs) where {Vs} = new{eltype(Vs), Vs}(vertices)
end
struct Edges{V, E <: AbstractEdge{V}, Es} <: AbstractEdges{V, E}
edges::Es
function Edges(edges::Es) where {Es}
E = eltype(Es)
return new{vertextype{E}, E, Es}(edges)
end
end

parent_graph_indices(vs::AbstractVertices) = vs.vertices
parent_graph_indices(es::AbstractEdges) = es.edges

# Interface
Base.eltype(::Type{<:AbstractGraphIndices{T}}) where {T} = T

Base.iterate(gi::AbstractGraphIndices) = iterate(parent_graph_indices(gi))
Base.iterate(gi::AbstractGraphIndices, state) = iterate(parent_graph_indices(gi), state)
Base.length(gi::AbstractGraphIndices) = length(parent_graph_indices(gi))

Base.getindex(gi::AbstractGraphIndices, ind) = parent_graph_indices(gi)[ind]

to_graph_indices(graph, indices) = indices
to_graph_indices(graph, indices::Pair) = edgetype(graph)(indices)
35 changes: 19 additions & 16 deletions src/abstractnamedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using Dictionaries: set!
using Graphs:
Graphs,
AbstractGraph,
AbstractSimpleGraph,
IsDirected,
a_star,
add_edge!,
Expand Down Expand Up @@ -34,7 +35,8 @@ using .GraphsExtensions:
incident_edges,
partition_vertices,
rename_vertices,
subgraph
subgraph,
similar_graph
using SimpleTraits: SimpleTraits, Not, @traitfn

abstract type AbstractNamedGraph{V} <: AbstractGraph{V} end
Expand All @@ -45,6 +47,7 @@ abstract type AbstractNamedGraph{V} <: AbstractGraph{V} end

Graphs.vertices(graph::AbstractNamedGraph) = not_implemented()
position_graph(graph::AbstractNamedGraph) = not_implemented()
position_graph(graph::AbstractSimpleGraph) = graph

Graphs.rem_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented()
Graphs.add_vertex!(graph::AbstractNamedGraph, vertex) = not_implemented()
Expand All @@ -61,10 +64,12 @@ end
# graph `position_graph(graph::AbstractNamedGraph)`.
# Inverse map of `ordered_vertices`.
vertex_positions(graph::AbstractNamedGraph) = not_implemented()
vertex_positions(graph::AbstractSimpleGraph) = vertices(graph)

# Outputs an object that when indexed by a vertex position
# returns the corresponding vertex.
ordered_vertices(graph::AbstractNamedGraph) = not_implemented()
ordered_vertices(graph::AbstractSimpleGraph) = vertices(graph)

Graphs.edgetype(graph::AbstractNamedGraph) = edgetype(typeof(graph))
Graphs.edgetype(::Type{<:AbstractNamedGraph}) = not_implemented()
Expand Down Expand Up @@ -102,6 +107,7 @@ end
#

position_graph_type(graph::AbstractNamedGraph) = typeof(position_graph(graph))
position_graph_type(T::Type{<:AbstractNamedGraph}) = Base.promote_op(position_graph, T)

function Graphs.has_vertex(graph::AbstractNamedGraph, vertex)
# TODO: `vertices` should have fast lookup!
Expand All @@ -112,16 +118,6 @@ Graphs.SimpleDiGraph(graph::AbstractNamedGraph) = SimpleDiGraph(position_graph(g

Base.zero(G::Type{<:AbstractNamedGraph}) = G()

# TODO: Implement using `copyto!`?
function GraphsExtensions.directed_graph(graph::AbstractNamedGraph)
digraph = directed_graph_type(typeof(graph))(vertices(graph))
for e in edges(graph)
add_edge!(digraph, e)
add_edge!(digraph, reverse(e))
end
return digraph
end

# Default, can overload
Base.eltype(graph::AbstractNamedGraph) = eltype(vertices(graph))

Expand Down Expand Up @@ -436,11 +432,20 @@ Graphs.is_connected(graph::AbstractNamedGraph) = is_connected(position_graph(gra
Graphs.is_cyclic(graph::AbstractNamedGraph) = is_cyclic(position_graph(graph))

@traitfn function Base.reverse(graph::AbstractNamedGraph::IsDirected)
return not_implemented()
return similar_graph(graph, vertices, map(reverse, collect(edges(graph))))
end

# This wont be the most efficient way for a given graph type.
@traitfn function Base.reverse!(g::AbstractNamedGraph::IsDirected)
return not_implemented()

edge_list = collect(edges(g))

for edge in edge_list
rem_edge!(g, edge)
add_edge!(g, reverse(edge))
end

return g
end

# TODO: Move to `namedgraph.jl`, or make the output generic?
Expand Down Expand Up @@ -493,9 +498,7 @@ end
# traversal algorithms.
function Graphs.tree(graph::AbstractNamedGraph, parents)
n = length(parents)
# TODO: Use `directed_graph` here to make more generic?
## t = GenericNamedGraph(DiGraph(n), vertices(graph))
t = directed_graph_type(typeof(graph))(vertices(graph))
t = similar_graph(directed_graph_type(typeof(graph)), vertices(graph))
for destination in eachindex(parents)
source = parents[destination]
if source != destination
Expand Down
30 changes: 23 additions & 7 deletions src/lib/GraphsExtensions/src/abstractgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,34 @@ undirected_graph_type(g::AbstractGraph) = undirected_graph_type(typeof(g))

@traitfn directed_graph(graph::::IsDirected) = graph

convert_vertextype(::Type{V}, graph::AbstractGraph{V}) where {V} = graph
function convert_vertextype(V::Type, graph::AbstractGraph)
return not_implemented()
convert_vertextype(::Type{V}, G::AbstractGraph{V}) where {V} = G
convert_vertextype(::Type, ::AbstractGraph) = not_implemented()

convert_vertextype(::Type{V}, G::Type{<:AbstractGraph{V}}) where {V} = G
convert_vertextype(::Type, ::Type{<:AbstractGraph}) = not_implemented()

similar_graph(graph::AbstractGraph) = similar_graph(typeof(graph))
similar_graph(T::Type{<:AbstractGraph}) = T()

function similar_graph(graph_or_type, vertices)
new_graph = similar_graph(graph_or_type)
add_vertices!(new_graph, vertices)
return new_graph
end
function similar_graph(graph_or_type, vertices, edges)
new_graph = similar_graph(graph_or_type, vertices)
add_edges!(new_graph, edges)
return new_graph
end

function graph_from_vertices(graph_type::Type{<:AbstractGraph}, vertices)
return graph_type(vertices)
function similar_graph(graph::AbstractGraph, vertex_type::Type)
new_graph = convert_vertextype(vertex_type, similar_graph(typeof(graph)))
return new_graph
end

# TODO: Handle metadata in a generic way
@traitfn function directed_graph(graph::::(!IsDirected))
digraph = graph_from_vertices(directed_graph_type(graph), vertices(graph))
digraph = similar_graph(directed_graph_type(graph), vertices(graph))
for e in edges(graph)
add_edge!(digraph, e)
add_edge!(digraph, reverse(e))
Expand All @@ -74,7 +90,7 @@ end
# to avoid method overwrite warnings, see:
# https://github.com/mauro3/SimpleTraits.jl#method-overwritten-warnings
@traitfn function undirected_graph(graph::::IsDirected)
undigraph = graph_from_vertices(undirected_graph_type(typeof(graph)), vertices(graph))
undigraph = similar_graph(undirected_graph_type(typeof(graph)), vertices(graph))
for e in edges(graph)
# TODO: Check for repeated edges?
add_edge!(undigraph, e)
Expand Down
7 changes: 5 additions & 2 deletions src/lib/GraphsExtensions/src/simplegraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ function permute_vertices(graph::AbstractSimpleGraph, permutation)
end

# https://github.com/JuliaGraphs/Graphs.jl/issues/365
function graph_from_vertices(graph_type::Type{<:AbstractSimpleGraph}, vertices)
@assert vertices == Base.OneTo(length(vertices))
similar_graph(graph_type::Type{<:AbstractSimpleGraph}) = graph_type()
function similar_graph(graph::AbstractSimpleGraph, vertices::Base.OneTo)
return similar_graph(typeof(graph), vertices)
end
function similar_graph(graph_type::Type{<:AbstractSimpleGraph}, vertices::Base.OneTo)
return graph_type(length(vertices))
end

Expand Down
21 changes: 21 additions & 0 deletions src/lib/GraphsExtensions/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ using AbstractTrees:
rootindex
using Dictionaries: Dictionary, Indices
using Graphs:
AbstractGraph,
add_edge!,
add_vertex!,
dst,
Expand Down Expand Up @@ -44,6 +45,7 @@ using NamedGraphs.GraphsExtensions:
add_edge,
add_edges,
add_edges!,
add_vertices!,
all_edges,
arrange_edge,
arranged_edges,
Expand Down Expand Up @@ -83,6 +85,7 @@ using NamedGraphs.GraphsExtensions:
rem_edges!,
rename_vertices,
root_vertex,
similar_graph,
subgraph,
tree_graph_node,
undirected_graph,
Expand All @@ -108,6 +111,7 @@ using Test: @test, @test_broken, @test_throws, @testset
# - random_bfs_tree

@testset "NamedGraphs.GraphsExtensions" begin

# has_vertices
g = path_graph(4)
@test has_vertices(g, 1:3)
Expand Down Expand Up @@ -552,6 +556,23 @@ using Test: @test, @test_broken, @test_throws, @testset
@test_throws ErrorException root_vertex(g)
@test_throws MethodError root_vertex(binary_tree(3))

# similar_graph
g = path_graph(4)
@test similar_graph(g) isa typeof(g)
@test similar_graph(typeof(g)) isa typeof(g)
@test similar_graph(g, vertices(g), edges(g)) == g
@test !(similar_graph(g, vertices(g), edges(g)) === g)
sg = similar_graph(g, vertices(g))
@test vertices(sg) == vertices(g)
@test isempty(edges(sg))

struct Graph <: AbstractGraph{Int}
field
end

g = Graph(1)
@test_throws MethodError similar_graph(g)

# add_edge
g = SimpleGraph(4)
add_edge!(g, 1 => 2)
Expand Down
32 changes: 22 additions & 10 deletions src/lib/PartitionedGraphs/src/abstractpartitionedgraph.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ using Dictionaries: Dictionary
using Graphs:
AbstractEdge,
AbstractGraph,
AbstractSimpleGraph,
Graphs,
add_vertex!,
dst,
Expand All @@ -11,23 +12,40 @@ using Graphs:
rem_vertex!,
src,
vertices
using ..NamedGraphs: NamedGraphs, AbstractNamedGraph, NamedGraph
using ..NamedGraphs: NamedGraphs, AbstractNamedGraph, NamedGraph, NamedDiGraph
using ..NamedGraphs.GraphsExtensions:
GraphsExtensions, add_vertices!, not_implemented, rem_vertices!, subgraph, vertextype
GraphsExtensions,
add_vertices!,
not_implemented,
rem_vertices!,
subgraph,
convert_vertextype

# For you own graph type `g`, you should define a method for this function if you
# desire custom partitioning.
partitioned_vertices(g::AbstractGraph) = [vertices(g)]

#TODO: Write this in terms of traits
function similar_quotient_graph(g::AbstractGraph)
if is_directed(g)
sg = NamedDiGraph()
else
sg = NamedGraph()
end
return convert_vertextype(keytype(partitioned_vertices(g)), sg)
end

# For fast quotient edge checking and graph construction, one should overload this function.
function quotient_graph(g::AbstractGraph)

qg = NamedGraph(keys(partitioned_vertices(g)))
qg = similar_quotient_graph(g)

add_vertices!(qg, keys(partitioned_vertices(g)))

for e in edges(g)
qv_src = parent(quotientvertex(g, src(e)))
qv_dst = parent(quotientvertex(g, dst(e)))
qe = qv_src => qv_dst
qe = edgetype(qg)(qv_src => qv_dst)
if qv_src != qv_dst && !has_edge(qg, qe)
add_edge!(qg, qe)
end
Expand Down Expand Up @@ -117,12 +135,6 @@ function unpartitioned_graph_type(pg::AbstractPartitionedGraph)
return typeof(unpartitioned_graph(pg))
end


# AbstractGraph interface.
function Graphs.is_directed(graph_type::Type{<:AbstractPartitionedGraph})
return is_directed(unpartitioned_graph_type(graph_type))
end

#Functions for the abstract type
Graphs.vertices(pg::AbstractPartitionedGraph) = vertices(unpartitioned_graph(pg))
Graphs.edges(pg::AbstractPartitionedGraph) = edges(unpartitioned_graph(pg))
Expand Down
Loading
Loading