Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(co)products/(co)equalizers for Fincats and Diagrams #609

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
7a320b2
(co)products/(co)equalizers for Fincats and Diagrams
kris-brown Mar 18, 2022
4711108
universal for FinCat (co)limits
kris-brown Mar 19, 2022
7626855
Universal properties of (co)products for fincats/diagrams
kris-brown Mar 19, 2022
0e712e4
equalizer universal property for diagrams
kris-brown Mar 20, 2022
190f62b
ENH: made copy into a compile-time parameter for incident
olynch Jan 26, 2022
e1b92ea
ENH: removed dynamic allocation of named tuple in rem_part!
olynch Jan 26, 2022
86b5736
ENH: sprinkled in some happy little @inbounds
olynch Jan 26, 2022
ce19360
ENH: use a named tuple instead of keyword arguments
olynch Jan 26, 2022
3bdcb84
ENH: added ability to preallocate indices for acsets
olynch Jan 26, 2022
2a77689
ENH: added search algorithms
olynch Jan 26, 2022
4c892d5
ENH: set_subpart returns subpart
olynch Jan 26, 2022
1f4d53a
ENH: inbounds for set_subpart
olynch Jan 26, 2022
a679cc6
ENH: added random graph generators
olynch Jan 26, 2022
1ae04db
ENH: added faster connected component implementation using bfs
olynch Jan 26, 2022
12dbd8f
ENH: added normalize_labeling function to FinSets
olynch Jan 26, 2022
abc5b9b
ENH: more graph functions
olynch Jan 26, 2022
4138f6d
BENCH: more benchmarks
olynch Jan 26, 2022
6fa05e4
ENH: benchmark plotting
olynch Jan 26, 2022
f04b68e
FIX: added back keyword arguments to add_edge!
olynch Jan 26, 2022
5affdcf
FIX: graph generators shouldn't preallocate to be generic
olynch Jan 26, 2022
fbb56e4
CLEANUP: Replace `normalize_labels` with inline function calls.
epatters Jan 30, 2022
5438de6
TEST: added tests for graph generators and searching algorithms
olynch Mar 25, 2022
687d273
DOC: added clarifying comment for add_parts_with_indices!
olynch Mar 25, 2022
c526f13
TEST: added tests for degree
olynch Mar 25, 2022
92e2d40
add hash method for diagram/diagram hom
kris-brown Mar 28, 2022
d908a1d
add tests
kris-brown Mar 28, 2022
c964d26
Merge pull request #610 from AlgebraicJulia/kris-brown-patch-1
epatters Mar 29, 2022
2180056
Merge pull request #588 from AlgebraicJulia/struct-acsets-benchmarks
epatters Mar 29, 2022
81ce2d7
CLEANUP: Use `Base.typename` instead of homemade function `roottype`.
epatters Apr 1, 2022
bb7b81e
Merge pull request #611 from epatters/fix-root-type-of
epatters Apr 1, 2022
35cb13b
BUILD: Release Catlab v0.13.8.
epatters Apr 1, 2022
613c4d9
ENH: made copy into a compile-time parameter for incident
epatters Apr 1, 2022
cbe30ee
curry/uncurry
kris-brown Apr 2, 2022
690c98b
Pushout based chase and wiring diagram interface
kris-brown Mar 23, 2022
1e084e7
replace copairs with oplus/copair, return a morphism from chase
kris-brown Mar 23, 2022
2d4d690
C-Rel/C-Set conversion, distinguish EGDs/TGDs, optionally chase in C-Rel
kris-brown Mar 25, 2022
697e18c
(co)products/(co)equalizers for Fincats and Diagrams
kris-brown Mar 18, 2022
7e859be
universal for FinCat (co)limits
kris-brown Mar 19, 2022
289a47f
Universal properties of (co)products for fincats/diagrams
kris-brown Mar 19, 2022
378249e
equalizer universal property for diagrams
kris-brown Mar 20, 2022
2c860e7
Start ob/hom generalization but not far into it, saving progress
kris-brown Mar 26, 2022
44ad4df
parameterized chase by ob/hom
kris-brown Mar 26, 2022
8a3eadf
Merge branch 'curry_adj' into category_of_diagrams
kris-brown Apr 2, 2022
5a798c8
left kan extensions. equations in (co)product of fincats.
kris-brown Apr 5, 2022
0bb2482
remove revise
kris-brown Apr 5, 2022
846bc27
Left Kan returns natural transformation too / allow eqs in ACSetFunctor
kris-brown Apr 5, 2022
c10c78d
Left kan universal property
kris-brown Apr 5, 2022
c523aae
hash for Presentation, leftkan in Diagrams.jl, coeq of DiagramHoms{id}
kris-brown Apr 7, 2022
4e1cf10
fixed universal prop of leftkan, verbose is_natural
kris-brown Apr 8, 2022
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
Expand Up @@ -2,7 +2,7 @@ name = "Catlab"
uuid = "134e5e36-593f-5add-ad60-77f754baafbe"
license = "MIT"
authors = ["Evan Patterson <evan@epatters.org>"]
version = "0.13.7"
version = "0.13.8"

[deps]
AutoHashEquals = "15f4f7f2-30c1-5605-9d31-71845cf9641f"
Expand Down
125 changes: 115 additions & 10 deletions benchmark/Graphs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,33 @@ using Catlab.Graphs.BasicGraphs: TheoryGraph
using Catlab.WiringDiagrams: query
using Catlab.Programs: @relation

testdatadir = joinpath(dirname(@__FILE__), "..", "test", "testdata")

# Example Graphs
#
################

# Stolen from the Lightgraphs benchmark suite

dg1fn = joinpath(testdatadir, "graph-50-500.jgz")

LG_GRAPHS = Dict{String,LG.DiGraph}(
"complete100" => LG.complete_digraph(100),
# "5000-50000" => LG.loadgraph(dg1fn)["graph-5000-50000"],
"path500" => LG.path_digraph(500)
)

GRAPHS = Dict(k => from_lightgraph(g) for (k,g) in LG_GRAPHS)

LG_SYMGRAPHS = Dict{String,LG.Graph}(
"complete100" => LG.complete_graph(100),
"tutte" => LG.smallgraph(:tutte),
"path500" => LG.path_graph(500),
# "5000-49947" => LG.SimpleGraph(DIGRAPHS["5000-50000"])
)

SYMGRAPHS = Dict(k => from_lightgraph(g) for (k,g) in LG_SYMGRAPHS)

# Helpers
#########

Expand Down Expand Up @@ -49,7 +76,7 @@ end
function bench_iter_neighbors(g)
count = 0
for v in vertices(g)
count += length(neighbors(g, v))
count += length(neighbors(g,v))
end
count
end
Expand All @@ -65,6 +92,8 @@ end
function Graphs.connected_component_projection(g::LG.AbstractGraph)
label = Vector{Int}(undef, LG.nv(g))
LG.connected_components!(label, g)
normalized = searchsortedfirst.(Ref(unique!(sort(label))), label)
FinFunction(normalized)
end

abstract type FindTrianglesAlgorithm end
Expand Down Expand Up @@ -116,29 +145,43 @@ lgbench["has-edge"] = @benchmarkable bench_has_edge($lg)
clbench["iter-neighbors"] = @benchmarkable bench_iter_neighbors($g)
lgbench["iter-neighbors"] = @benchmarkable bench_iter_neighbors($lg)


bench = SUITE["GraphConnComponents"] = BenchmarkGroup()
clbench = bench["Catlab"] = BenchmarkGroup()
lgbench = bench["LightGraphs"] = BenchmarkGroup()

n₀ = 2000
g₀ = path_graph(Graph, n₀)
g = ob(coproduct(fill(g₀, 5)))
lg = LG.DiGraph(g)
clbench["path-graph-components"] =
@benchmarkable connected_component_projection($g)
lgbench["path-graph-components"] =
clbench["path-graph"] =
@benchmarkable connected_component_projection_bfs($g)
lgbench["path-graph"] =
@benchmarkable connected_component_projection($lg)

g₀ = star_graph(Graph, n₀)
g = ob(coproduct(fill(g₀, 5)))
lg = LG.DiGraph(g)
clbench["star-graph-components"] =
@benchmarkable connected_component_projection($g)
lgbench["star-graph-components"] =
clbench["star-graph"] =
@benchmarkable connected_component_projection_bfs($g)
lgbench["star-graph"] =
@benchmarkable connected_component_projection($lg)

for gn in keys(GRAPHS)
clbench[gn] = @benchmarkable connected_component_projection_bfs($(GRAPHS[gn]))
lgbench[gn] = @benchmarkable connected_component_projection($(LG_GRAPHS[gn]))
end

bench = SUITE["GraphTriangles"] = BenchmarkGroup()
clbench = bench["Catlab"] = BenchmarkGroup()
lgbench = bench["LightGraphs"] = BenchmarkGroup()

n = 100
g = wheel_graph(Graph, n)
lg = LG.DiGraph(g)
clbench["wheel-graph-triangles-hom"] =
@benchmarkable ntriangles($g, TriangleBacktrackingSearch())
clbench["wheel-graph-triangles-query"] =
clbench["wheel-graph-triangles"] =
@benchmarkable ntriangles($g, TriangleQuery())

# Symmetric graphs
Expand Down Expand Up @@ -170,6 +213,10 @@ lgbench["has-edge"] = @benchmarkable bench_has_edge($lg)
clbench["iter-neighbors"] = @benchmarkable bench_iter_neighbors($g)
lgbench["iter-neighbors"] = @benchmarkable bench_iter_neighbors($lg)

bench = SUITE["SymmetricGraphConnComponent"] = BenchmarkGroup()
clbench = bench["Catlab"] = BenchmarkGroup()
lgbench = bench["LightGraphs"] = BenchmarkGroup()

n₀ = 2000
g₀ = path_graph(SymmetricGraph, n₀)
g = ob(coproduct(fill(g₀, 5)))
Expand All @@ -187,12 +234,22 @@ clbench["star-graph-components"] =
lgbench["star-graph-components"] =
@benchmarkable connected_component_projection($lg)

for gn in keys(SYMGRAPHS)
clbench[gn] = @benchmarkable connected_component_projection_bfs($(SYMGRAPHS[gn]))
lgbench[gn] = @benchmarkable connected_component_projection($(LG_SYMGRAPHS[gn]))
end

bench = SUITE["SymmetricGraphTriangles"] = BenchmarkGroup()
clbench = bench["Catlab"] = BenchmarkGroup()
lgbench = bench["LightGraphs"] = BenchmarkGroup()

n = 100
g = wheel_graph(SymmetricGraph, n)
lg = LG.Graph(g)
clbench["wheel-graph-triangles-hom"] =
@benchmarkable ntriangles($g, TriangleBacktrackingSearch())
clbench["wheel-graph-triangles-query"] =
# clbench["wheel-graph-triangles-query"] =
clbench["wheel-graph-triangles"] =
@benchmarkable ntriangles($g, TriangleQuery())
lgbench["wheel-graph-triangles"] = @benchmarkable sum(LG.triangles($lg))

Expand All @@ -202,7 +259,7 @@ lgbench["wheel-graph-triangles"] = @benchmarkable sum(LG.triangles($lg))
bench = SUITE["WeightedGraph"] = BenchmarkGroup()
clbench = bench["Catlab"] = BenchmarkGroup()
clvecbench = bench["Catlab-vectorized"] = BenchmarkGroup()
lgbench = bench["LightGraphs"] = BenchmarkGroup()
lgbench = bench["MetaGraphs"] = BenchmarkGroup()

n = 10000
g = path_graph(WeightedGraph{Float64}, n; E=(weight=range(0,1,length=n-1),))
Expand Down Expand Up @@ -305,3 +362,51 @@ lgbench["indexed-lookup"] = @benchmarkable begin
@assert $mg["v$i", :label] == i
end
end

# Random Graphs
###############

bench = SUITE["RandomGraph"] = BenchmarkGroup()
clbench = bench["Catlab"] = BenchmarkGroup()
lgbench = bench["LightGraphs"] = BenchmarkGroup()

sizes = [10000]
ps = [0.001]
for size in sizes, p in ps
clbench["erdos_renyi-$size-$p"] =
@benchmarkable erdos_renyi($Graph, $size, $(p/2))
lgbench["erdos_renyi-$size-$p"] =
@benchmarkable LightGraphs.erdos_renyi($size, $p)
end

ks = [10]

for size in sizes, k in ks
clbench["expected_degree_graph-$size-$k"] =
@benchmarkable expected_degree_graph($Graph, $([min(k,size-1) for _ in 1:size]))
lgbench["expected_degree_graph-$size-$k"] =
@benchmarkable LightGraphs.expected_degree_graph($([min(k,size-1) for _ in 1:size]))
end

for size in sizes, k in ks
clbench["watts_strogatz-$size-$k"] =
@benchmarkable watts_strogatz($Graph, $size, $(min(k,size-1)), 0.5)
lgbench["watts_strogatz-$size-$k"] =
@benchmarkable LightGraphs.watts_strogatz($size, $(min(k,size-1)), 0.5)
end

# Searching
###########

bench = SUITE["Searching"] = BenchmarkGroup()
clbench = bench["Catlab"] = BenchmarkGroup()
lgbench = bench["LightGraphs"] = BenchmarkGroup()

for size in sizes, p in ps
local g = erdos_renyi(Graph, size, p)
local lg = LightGraphs.SimpleDiGraph(g)
clbench["bfs_erdos_renyi-$size-$p"] = @benchmarkable bfs_parents($g,1)
lgbench["bfs_erdos_renyi-$size-$p"] = @benchmarkable LightGraphs.bfs_parents($lg,1)
clbench["dfs_erdos_renyi-$size-$p"] = @benchmarkable dfs_parents($g,1)
lgbench["dfs_erdos_renyi-$size-$p"] = @benchmarkable LightGraphs.dfs_parents($lg,1)
end
7 changes: 7 additions & 0 deletions benchmark/make_plots.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
include("benchmarks.jl")

include("plots.jl")

results = run(SUITE)
data = graphbench_data(results)
plot_all_subcats(data)
57 changes: 57 additions & 0 deletions benchmark/plots.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Plots, StatsPlots
using Plots.PlotMeasures
using DataFrames, Query
using BenchmarkTools

function graphbench_data(suite)
data = DataFrame(subcat=String[],bench=String[],platform=String[],
mt_normalized=Float64[],mediantime=Float64[])
graphbenches = suite["Graphs"]
noncatlab_times = Dict{Tuple{String,String},Float64}()
for (subcat,subsuite) in graphbenches
for (platform,results) in subsuite
for (bench,result) in results
if platform ∈ ["LightGraphs", "MetaGraphs"]
noncatlab_times[(subcat,bench)] = median(result).time
end
new_row = (subcat=subcat,
bench=bench,
platform=platform,
mt_normalized=0.,
mediantime=median(result).time)
push!(data, new_row)
end
end
end
for i in 1:length(data.subcat)
key = (data[i,:subcat], data[i,:bench])
if key ∈ keys(noncatlab_times)
data[i,:mt_normalized] = data[i,:mediantime] / noncatlab_times[key]
end
end
data
end

function subcat_data(dat,subcat)
dat |>
@filter(_.subcat==subcat) |>
@filter(_.platform == ["Catlab"]) |>
@orderby((_.bench,_.platform)) |>
@select(-:subcat) |>
DataFrame
end

function plot_subcat(dat,subcat,yscale=:linear)
subcat_data(dat,subcat) |>
@df groupedbar(:bench,:mt_normalized,group=:platform,
xrotation=45,legend=:outerright,bar_width=0.5,
yscale=yscale, yguide="Rel. time", bottom_margin=50px)
end

function plot_all_subcats(dat)
for subcat in unique(dat[!,:subcat])
yscale = subcat ∈ ["WeightedGraph", "LabeledGraph"] ? :log : :linear
fig = plot_subcat(dat,subcat,yscale)
savefig(fig, string("figures/",subcat,".pdf"))
end
end
22 changes: 12 additions & 10 deletions src/categorical_algebra/ACSetInterface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ of `[:src,:vattr]` as two independent columns does not even make sense, since
they have different domains (belong to different tables).
"""
function subpart end
@inline subpart(acs, part, name) = view_or_slice(subpart(acs, name), part)
@inline Base.@propagate_inbounds subpart(acs, part, name) = view_or_slice(subpart(acs, name), part)

function view_or_slice end
@inline view_or_slice(x::AbstractVector, i::Union{Integer,StaticArray}) = x[i]
@inline view_or_slice(x::AbstractVector, ::Colon) = x
@inline view_or_slice(x::AbstractVector, i) = @view x[i]
@inline Base.@propagate_inbounds view_or_slice(x::AbstractVector, i) = @view x[i]

@inline subpart(acs, expr::GATExpr{:generator}) = subpart(acs, first(expr))
@inline subpart(acs, expr::GATExpr{:id}) = parts(acs, first(dom(expr)))
Expand Down Expand Up @@ -120,16 +120,18 @@ end
incident(acs, part, expr::GATExpr; kw...) =
incident(acs, part, subpart_names(expr); kw...)

@inline add_part!(acs, type; kw...) = add_part!(acs, type, (;kw...))

""" Add part of given type to acset, optionally setting its subparts.

Returns the ID of the added part.

See also: [`add_parts!`](@ref).
"""
@inline function add_part!(acs, type::Symbol, args...; kw...)
@inline function add_part!(acs, type::Symbol, kw)
part = only(add_parts!(acs,type,1))
try
set_subparts!(acs, part, args...; kw...)
set_subparts!(acs, part, kw)
catch e
rem_part!(acs, type, part)
rethrow(e)
Expand All @@ -145,10 +147,12 @@ See also: [`add_part!`](@ref).
"""
function add_parts! end

@inline function add_parts!(acs, type::Symbol, n::Int, args...; kw...)
@inline add_parts!(acs, type::Symbol, n::Int; kw...) = add_parts!(acs, type, n, (;kw...))

@inline function add_parts!(acs, type::Symbol, n::Int, kw)
parts = add_parts!(acs, type, n)
try
set_subparts!(acs, parts, args...; kw...)
set_subparts!(acs, parts, kw)
catch e
rem_parts!(acs, type, parts)
rethrow(e)
Expand Down Expand Up @@ -183,10 +187,8 @@ Both single and vectorized assignment are supported.

See also: [`set_subpart!`](@ref).
"""
@inline function set_subparts!(acs, part, kw::NamedTuple)
for name in keys(kw)
set_subpart!(acs, part, name, kw[name])
end
@inline @generated function set_subparts!(acs, part, kw::NamedTuple{keys}) where {keys}
Expr(:block,[:(set_subpart!(acs, part, $(Expr(:quote, name)), kw.$name)) for name in keys]...)
end

@inline set_subparts!(acs, part; kw...) = set_subparts!(acs, part, (;kw...))
Expand Down
Loading