diff --git a/src/categorical_algebra/FinCats.jl b/src/categorical_algebra/FinCats.jl index 30c3254d2..e05054548 100644 --- a/src/categorical_algebra/FinCats.jl +++ b/src/categorical_algebra/FinCats.jl @@ -25,13 +25,14 @@ using DataStructures: IntDisjointSets, in_same_set, num_groups using ACSets using ...GATs import ...GATs: equations -using ...Theories: ThCategory, ThSchema, ThPointedSetCategory, ThPointedSetSchema, ObExpr, HomExpr, AttrExpr, AttrTypeExpr, FreeSchema, FreePointedSetCategory, zeromap +using ...Theories: ThCategory, ThSchema, ThPointedSetCategory, ThPointedSetSchema, + ObExpr, HomExpr, AttrExpr, AttrTypeExpr, FreeSchema, FreePointedSetCategory, zeromap import ...Theories: dom, codom, id, compose, ⋅, ∘ using ...Graphs import ...Graphs: edges, src, tgt, enumerate_paths -import ...Graphs.BasicGraphs: vertex_named, vertex_name, DiagramGraph, edge_named, edge_name @reexport using ..Categories import ..Categories: CatSize, ob, hom, ob_map, hom_map, component, op + # Categories ############ @@ -110,7 +111,7 @@ hom generators are indexable, other than one explicitly generated by a graph. """ function graph(C::FinCat) - g = DiagramGraph() + g = NamedGraph{Symbol,Symbol}() obgens = ob_generators(C) homgens = hom_generators(C) add_vertices!(g,length(obgens);vname=nameof.(obgens)) diff --git a/src/categorical_algebra/FunctorialDataMigrations.jl b/src/categorical_algebra/FunctorialDataMigrations.jl index dcfd4d2c0..b69b0a053 100644 --- a/src/categorical_algebra/FunctorialDataMigrations.jl +++ b/src/categorical_algebra/FunctorialDataMigrations.jl @@ -6,22 +6,19 @@ export SigmaMigration, DeltaMigration, migrate, migrate!, internal_hom, SigmaMigrationFunctor, DeltaMigrationFunctor, DataMigrationFunctor, functor -#maybe should only define DeltaMigrationFunctor at this point +using MLStyle: @match + using ACSets using ACSets.DenseACSets: constructor, datatypes using ...GATs using ...Theories: ob, hom, dom, codom, attr, AttrTypeExpr, ⋅ using ..Categories, ..FinCats, ..Limits, ..Diagrams, ..FinSets, ..CSets, ..HomSearch using ...Graphs, ..FreeDiagrams -using ...Graphs.BasicGraphs: NamedGraph, vertex_named import ..Categories: ob_map, hom_map import ...GATs: functor using ..FinCats: make_map, mapvals, presentation_key -using ..Diagrams -import ..FinCats: FinCatPresentation using ..Chase: collage, crel_type, pres_to_eds, add_srctgt, chase using ..FinSets: VarSet -using MLStyle: @match # Data types ############ diff --git a/src/graphs/BasicGraphs.jl b/src/graphs/BasicGraphs.jl index 1e67bb462..092a87f51 100644 --- a/src/graphs/BasicGraphs.jl +++ b/src/graphs/BasicGraphs.jl @@ -1,10 +1,14 @@ """ Data structures for graphs, based on C-sets. -Provides the category theorist's four basic kinds of graphs: graphs (aka -directed multigraphs), symmetric graphs, reflexive graphs, and symmetric -reflexive graphs. Also defines half-edge graphs. The API generally follows that -of [Graphs.jl](https://github.com/JuliaGraphs/Graphs.jl), with some departures -due to differences between the data structures. +This module provides the category theorist's four basic kinds of graphs: graphs +(aka directed multigraphs), symmetric graphs, reflexive graphs, and symmetric +reflexive graphs. It also defines half-edge graphs, which are isomorphic to +symmetric graphs, and a few standard kinds of attributed graphs, such as +weighted graphs. + +The graphs API generally follows that of +[Graphs.jl](https://github.com/JuliaGraphs/Graphs.jl), with some departures due +to differences between the data structures. """ module BasicGraphs export HasVertices, HasGraph, AbstractGraph, Graph, SchGraph, @@ -117,6 +121,7 @@ has_vertex(g::HasVertices, v) = has_part(g, :V, v) """ Whether the graph has the given edge, or an edge between two vertices. """ has_edge(g::HasGraph, e) = has_part(g, :E, e) + function has_edge(g::HasGraph, s::Int, t::Int) (1 <= s <= nv(g)) || return false for e in outedges(g,s) @@ -572,32 +577,4 @@ function Base.reverse!(g::G) where G<:HasGraph end Base.reverse(g::G) where G<:HasGraph = g |> deepcopy |> reverse! -vertex_name(G::HasGraph, v) = v -edge_name(G::HasGraph, e) = e - -@present SchNamedGraph <: SchGraph begin - VName::AttrType - EName::AttrType - vname::Attr(V, VName) - ename::Attr(E, EName) -end - -""" Abstract type for graph with named vertices and edges. -""" -@abstract_acset_type AbstractNamedGraph <: AbstractGraph - -""" Graph with named vertices and edges. -The default graph type used to construct the graph underlying -a finite category given by a presentation. -""" -@acset_type NamedGraph(SchNamedGraph, index=[:src,:tgt,:ename], - unique_index=[:vname]) <: AbstractNamedGraph -vertex_name(g::AbstractNamedGraph, args...) = subpart(g, args..., :vname) -edge_name(g::AbstractNamedGraph, args...) = subpart(g, args..., :ename) - -vertex_named(g::AbstractNamedGraph, name) = only(incident(g, name, :vname)) -edge_named(g::AbstractNamedGraph, name)= only(incident(g, name, :ename)) -const DiagramGraph = NamedGraph{Symbol,Symbol} - - end # module diff --git a/src/graphs/Searching.jl b/src/graphs/GraphSearching.jl similarity index 99% rename from src/graphs/Searching.jl rename to src/graphs/GraphSearching.jl index 3b675cf3a..d35e47bc8 100644 --- a/src/graphs/Searching.jl +++ b/src/graphs/GraphSearching.jl @@ -1,4 +1,4 @@ -module Searching +module GraphSearching export bfs_parents, bfs_tree, dfs_parents, dfs_tree using ACSets diff --git a/src/graphs/Graphs.jl b/src/graphs/Graphs.jl index 300056816..520538b41 100644 --- a/src/graphs/Graphs.jl +++ b/src/graphs/Graphs.jl @@ -4,16 +4,18 @@ using Reexport include("BasicGraphs.jl") include("BipartiteGraphs.jl") +include("NamedGraphs.jl") include("PropertyGraphs.jl") include("GraphAlgorithms.jl") include("GraphGenerators.jl") -include("Searching.jl") +include("GraphSearching.jl") @reexport using .BasicGraphs @reexport using .BipartiteGraphs +@reexport using .NamedGraphs @reexport using .PropertyGraphs @reexport using .GraphAlgorithms @reexport using .GraphGenerators -@reexport using .Searching +@reexport using .GraphSearching end diff --git a/src/graphs/NamedGraphs.jl b/src/graphs/NamedGraphs.jl new file mode 100644 index 000000000..bfedb75d6 --- /dev/null +++ b/src/graphs/NamedGraphs.jl @@ -0,0 +1,69 @@ +""" Extends the basic graph types with vertex and/or edge names. + +Naming vertices and edges and looking them up by name is a common requirement. +This module provides a simple interface and default graph types for named +graphs. Names are understood to be unique within the graph but are *not* assumed +to be strings or symbols. +""" +module NamedGraphs +export vertex_name, edge_name, vertex_named, edge_named, + AbstractNamedGraph, NamedGraph + +using ACSets +using ...GATs, ..BasicGraphs + +# Names interface +################# + +""" Name of a vertex in a graph. + +By default, the name of a vertex is its ID. +""" +vertex_name(g::HasVertices, v) = v + +""" Name of an edge in a graph. + +By default, the name of an edge is its ID. +""" +edge_name(g::HasGraph, e) = e + +""" Get vertex in graph with given name. +""" +function vertex_named(g::HasVertices, name) + @assert has_vertex(g, name) + name +end + +""" Get edge in graph with given name. +""" +function edge_named(g::HasGraph, name) + @assert has_edge(g, name) + name +end + +# Named graphs +############## + +@present SchNamedGraph <: SchGraph begin + VName::AttrType + EName::AttrType + vname::Attr(V, VName) + ename::Attr(E, EName) +end + +""" Abstract type for graph with named vertices and edges. +""" +@abstract_acset_type AbstractNamedGraph <: AbstractGraph + +""" Graph with named vertices and edges. +""" +@acset_type NamedGraph(SchNamedGraph, index=[:src,:tgt,:ename], + unique_index=[:vname]) <: AbstractNamedGraph + +vertex_name(g::AbstractNamedGraph, args...) = subpart(g, args..., :vname) +edge_name(g::AbstractNamedGraph, args...) = subpart(g, args..., :ename) + +vertex_named(g::AbstractNamedGraph, name) = only(incident(g, name, :vname)) +edge_named(g::AbstractNamedGraph, name)= only(incident(g, name, :ename)) + +end diff --git a/test/graphs/GraphAlgorithms.jl b/test/graphs/GraphAlgorithms.jl index d7941b20d..dd042f24f 100644 --- a/test/graphs/GraphAlgorithms.jl +++ b/test/graphs/GraphAlgorithms.jl @@ -72,17 +72,4 @@ ep = enumerate_paths(g) (2, 3, [3]) (3, 3, [])] -# Trees -####### - -g = Searching.tree([1, 1, 1, 2, 2]) -g′ = @acset Graph begin - V = 5 - E = 4 - src = [1, 1, 2, 2] - tgt = [2, 3, 4, 5] -end - -@test is_isomorphic(g,g′) - end diff --git a/test/graphs/Searching.jl b/test/graphs/GraphSearching.jl similarity index 60% rename from test/graphs/Searching.jl rename to test/graphs/GraphSearching.jl index 7a4482add..529091e20 100644 --- a/test/graphs/Searching.jl +++ b/test/graphs/GraphSearching.jl @@ -1,10 +1,9 @@ -module TestSearching +module TestGraphSearching using Test -using Catlab.Graphs.BasicGraphs, Catlab.Graphs.Searching -import Catlab.Graphs.Searching: tree - -# Tests stolen from Graphs.jl +using Catlab.Graphs.BasicGraphs, Catlab.Graphs.GraphSearching +using Catlab.Graphs.GraphSearching: tree +using Catlab.CategoricalAlgebra: @acset, is_isomorphic # BFS #---- @@ -24,8 +23,7 @@ parents = bfs_parents(g, 1) t1 = @inferred(bfs_tree(g, 1)) t2 = tree(parents) @test t1 == t2 -@test is_directed(t2) -@test typeof(t2) <: AbstractGraph +@test t2 isa AbstractGraph @test ne(t2) < nv(t2) # DFS @@ -36,6 +34,17 @@ add_edges!(g, [1,2,1,3], [2,3,3,4]) z = @inferred(dfs_tree(g, 1)) @test ne(z) == 3 && nv(z) == 4 @test !has_edge(z, 1, 3) -@test !is_cyclic(g) + +# Trees +#------ + +g = tree([1, 1, 1, 2, 2]) +g′ = @acset Graph begin + V = 5 + E = 4 + src = [1, 1, 2, 2] + tgt = [2, 3, 4, 5] +end +@test is_isomorphic(g, g′) end diff --git a/test/graphs/Graphs.jl b/test/graphs/Graphs.jl index 7285f148d..512113209 100644 --- a/test/graphs/Graphs.jl +++ b/test/graphs/Graphs.jl @@ -10,6 +10,10 @@ end include("BipartiteGraphs.jl") end +@testset "NamedGraphs" begin + include("NamedGraphs.jl") +end + @testset "PropertyGraphs" begin include("PropertyGraphs.jl") end @@ -22,4 +26,8 @@ end include("GraphGenerators.jl") end +@testset "GraphSearching" begin + include("GraphSearching.jl") +end + end diff --git a/test/graphs/NamedGraphs.jl b/test/graphs/NamedGraphs.jl new file mode 100644 index 000000000..258d0e9cc --- /dev/null +++ b/test/graphs/NamedGraphs.jl @@ -0,0 +1,25 @@ +module TestNamedGraphs +using Test + +using Catlab.Graphs + +# Basic graphs +############## + +g = path_graph(Graph, 3) +@test vertex_name(g, 2) == 2 +@test vertex_named(g, 2) == 2 +@test edge_name(g, 1) == 1 +@test edge_named(g, 1) == 1 + +# Named graphs +############## + +g = path_graph(NamedGraph{Symbol,Symbol}, 3, + V=(vname=[:x,:y,:z],), E=(ename=[:f,:g],)) +@test vertex_name(g, 2) == :y +@test vertex_named(g, :y) == 2 +@test edge_name(g, 1) == :f +@test edge_named(g, :f) == 1 + +end