Skip to content

Commit

Permalink
Merge pull request #142 from AlgebraicJulia/add_eqs
Browse files Browse the repository at this point in the history
Add equations to schemas
  • Loading branch information
kris-brown authored Jun 12, 2024
2 parents 80abf4f + bcf41ca commit 6407367
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 23 deletions.
11 changes: 11 additions & 0 deletions .buildkite/jobscript.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

pwd; hostname; date

module load julia

echo "Running Tests..."
julia --project -e 'using Pkg; Pkg.status(); Pkg.test()'

echo "Building Documentation..."
julia -t 16 --project=docs -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.status(); Pkg.instantiate(); include("docs/make.jl")'
20 changes: 20 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
env:
JULIA_VERSION: "1.10.2"

steps:

- label: ":hammer: Build Project"
command:
- "module load julia"
- "julia --project=docs --color=yes -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate(); Pkg.precompile()'"

- wait

- label: ":scroll: Build docs and run tests"
command:
- "srun --cpus-per-task=16 --mem=8G --time=1:00:00 --output=.buildkite/build_%j.log --unbuffered .buildkite/jobscript.sh"
env:
JULIA_PROJECT: "docs/"

- wait

2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ NautyACSetsExt = "nauty_jll"
XLSXACSetsExt = "XLSX"

[compat]
AlgebraicInterfaces = "0.1"
AlgebraicInterfaces = "0.1.3"
Base64 = "1.9"
CompTime = "0.1"
DataStructures = "0.18"
Expand Down
2 changes: 1 addition & 1 deletion src/DenseACSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ function ACSetTableSchema(s::Schema{Symbol}, ob::Symbol)
attrs = filter(Schemas.attrs(s)) do (f,d,c)
d == ob
end
BasicSchema{Symbol}([ob], [], attrtypes(s), attrs)
BasicSchema{Symbol}([ob], [], attrtypes(s), attrs, [])
end

function ACSetTableDataType(::Type{<:StructACSet{S,Ts}}, ob::Symbol) where {S,Ts}
Expand Down
45 changes: 30 additions & 15 deletions src/Schemas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ module Schemas
export Schema, TypeLevelSchema, BasicSchema, TypeLevelBasicSchema, typelevel,
objects, attrtypes, attrtype_instantiation, homs, attrs, arrows, dom, codom,
ob, hom, attrtype, attr, dom_nums, codom_nums, adom_nums, acodom_nums, types,
TypedSchema
TypedSchema, equations

using StructEquality
import AlgebraicInterfaces: dom, codom, ob, hom, attr, attrtype
import AlgebraicInterfaces: dom, codom, ob, hom, attr, attrtype, equations

# Schemas
#########
Expand Down Expand Up @@ -112,44 +112,55 @@ function codom end
# Basic Schemas
###############

abstract type TypeLevelBasicSchema{Name, obs, homs, attrtypes, attrs} <: TypeLevelSchema{Name} end
abstract type TypeLevelBasicSchema{Name, obs, homs, attrtypes, attrs, eqs} <: TypeLevelSchema{Name} end

const TypeLevelBasicCSetSchema{Name, obs, homs} = TypeLevelBasicSchema{Name, obs, homs, Tuple{}, Tuple{}}
const TypeLevelBasicCSetSchema{Name, obs, homs} = TypeLevelBasicSchema{Name, obs, homs, Tuple{}, Tuple{}, Tuple{}}

# A path has sequence of hom/attr names
const Pth{Name}= Tuple{Vararg{Name}}

# An Eq has an optional name, a dom, a codom, and pair of paths
const Eq{Name} = Tuple{Union{Nothing, Name}, Name, Name, Tuple{Pth{Name},Pth{Name}}}

@struct_hash_equal struct BasicSchema{Name} <: Schema{Name}
obs::Vector{Name}
homs::Vector{Tuple{Name,Name,Name}}
attrtypes::Vector{Name}
attrs::Vector{Tuple{Name,Name,Name}}
function BasicSchema{Name}(obs, homs, attrtypes, attrs) where {Name}
new{Name}(obs, homs, attrtypes, attrs)
eqs::Vector{Eq{Name}}
function BasicSchema{Name}(obs, homs, attrtypes, attrs, eqs) where {Name}
new{Name}(obs, homs, attrtypes, attrs, eqs)
end
function BasicSchema(obs::Vector{Name}, homs, attrtypes, attrs) where {Name}
new{Name}(obs, homs, attrtypes, attrs)
function BasicSchema(obs::Vector{Name}, homs, attrtypes, attrs, eqs=nothing) where {Name}
eqs = isnothing(eqs) ? Eq{Name}[] : eqs
new{Name}(obs, homs, attrtypes, attrs, eqs)
end
function BasicSchema(obs::Vector{Name}, homs) where {Name}
new{Name}(obs, homs, Name[], Tuple{Name,Name,Name}[])
function BasicSchema(obs::Vector{Name}, homs, eqs=nothing) where {Name}
eqs = isnothing(eqs) ? Eq{Name}[] : eqs
new{Name}(obs, homs, Name[], Tuple{Name,Name,Name}[], eqs)
end
function BasicSchema{Name}() where {Name}
new(
Vector{Name}(),
Vector{Tuple{Name,Name,Name}}(),
Vector{Name}(),
Vector{Tuple{Name,Name,Name}}()
Vector{Tuple{Name,Name,Name}}(),
Vector{Eq{Name}}()
)
end
end

function Base.copy(s::BasicSchema{Name}) where {Name}
BasicSchema{Name}(copy(s.obs), copy(s.homs), copy(s.attrtypes), copy(s.attrs))
BasicSchema{Name}(copy(s.obs), copy(s.homs), copy(s.attrtypes), copy(s.attrs), copy(s.eqs))
end

function Schema(::Type{TypeLevelBasicSchema{Name, obs, homs, attrtypes, attrs}}) where {Name, obs, homs, attrtypes, attrs}
function Schema(::Type{TypeLevelBasicSchema{Name, obs, homs, attrtypes, attrs, eqs}}) where {Name, obs, homs, attrtypes, attrs, eqs}
BasicSchema{Name}(
[obs.parameters...],
[homs.parameters...],
[attrtypes.parameters...],
[attrs.parameters...]
[attrs.parameters...],
[eqs.parameters...]
)
end

Expand All @@ -165,6 +176,9 @@ attrtypes(S::Type{<:TypeLevelBasicSchema}) = Tuple(S.parameters[4].parameters)

types(S::Union{Schema,Type{<:TypeLevelSchema}}) = [objects(S)..., attrtypes(S)...]

equations(S::BasicSchema) = S.eqs
equations(S::Type{<:TypeLevelBasicSchema}) = Tuple(S.parameters[6].parameters)

attrtype_instantiation(S::Type{<:TypeLevelBasicSchema}, Ts, a::Symbol) =
Ts.parameters[findfirst(attrtypes(S) .== a)]

Expand Down Expand Up @@ -247,7 +261,8 @@ function typelevel(s::BasicSchema{Name}) where {Name}
Tuple{s.obs...},
Tuple{s.homs...},
Tuple{s.attrtypes...},
Tuple{s.attrs...}
Tuple{s.attrs...},
Tuple{s.eqs...}
}
end

Expand Down
14 changes: 13 additions & 1 deletion src/serialization/JSONACSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ function generate_json_acset_schema(schema::Schema)
"Attr" => map(attrs(schema)) do (f, x, y)
Dict("name" => string(f), "dom" => string(x), "codom" => string(y))
end,
"equations" => map(equations(schema)) do (n, x, y, eqs)
Dict("dom" => string(x), "codom" => string(y),
"name" => isnothing(n) ? n : string(n),
"paths" => [string.(eq) for eq in collect.(eqs)], )
end,

)
end

Expand All @@ -152,7 +158,13 @@ function parse_json_acset_schema(::Type{BasicSchema}, data::AbstractDict)
attrs = map(data["Attr"]) do d
map(Symbol, (d["name"], d["dom"], d["codom"]))
end
BasicSchema(obs, homs, attrtypes, attrs)
eqs = map(data[:equations]) do d
name = isnothing(d["name"]) ? nothing : Symbol(d["name"])
(name, Symbol(d["dom"]), Symbol(d["codom"]), tuple(map(d["paths"]) do p
tuple(Symbol.(p)...)
end...))
end
BasicSchema(obs, homs, attrtypes, attrs, eqs)
end

function parse_json_acset_schema(T, input::AbstractString)
Expand Down
6 changes: 5 additions & 1 deletion test/Schemas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ module TestSchemas
using Test
using ACSets.Schemas

bsch = BasicSchema([:E,:V], [(:src,:E,:V),(:tgt,:E,:V)],[:Weight],[(:weight,:E,:Weight)])
@test BasicSchema{Symbol}() isa BasicSchema

bsch = BasicSchema([:E,:V], [(:src,:E,:V),(:tgt,:E,:V)],[:Weight],
[(:weight,:E,:Weight)], [(nothing, :E,:V,((:src,),(:tgt,)))])
tsch = typelevel(bsch)
for sch in [bsch, tsch]
@test collect(ob(sch)) == collect(objects(sch)) == [:E,:V]
Expand All @@ -19,6 +22,7 @@ for sch in [bsch, tsch]
@test codom_nums(sch) == (2,2)
@test adom_nums(sch) == (1,)
@test acodom_nums(sch) == (1,)
@test collect(equations(sch)) == [(nothing, :E,:V,((:src,),(:tgt,)),)]
end

@test attrtype_instantiation(tsch, Tuple{Int}, :Weight) == Int
Expand Down
9 changes: 5 additions & 4 deletions test/serialization/JSONACSets.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ add_parts!(g, :V, 3)
add_parts!(g, :E, 2, src=[1,2], tgt=[2,3], weight=[0.5,1.5])
@test roundtrip_json_acset(g) == g

SchLabeledDDS = BasicSchema([:X], [(,:X,:X)], [:Label], [(:label,:X,:Label)])
@acset_type LabeledDDS(SchLabeledDDS, index=[])
SchLabeledDDS4 = BasicSchema([:X], [(,:X,:X)], [:Label], [(:label,:X,:Label)],
[(:cycle4,:X,:X,((),(,,,)))])
@acset_type LabeledDDS4(SchLabeledDDS4, index=[])

ldds = LabeledDDS{Symbol}()
ldds = LabeledDDS4{Symbol}()
add_parts!(ldds, :Label, 2)
add_parts!(ldds, :X, 4, Φ=[2,3,4,1], label=[AttrVar(1), :a, :b, AttrVar(2)])
@test roundtrip_json_acset(ldds) == ldds
Expand All @@ -67,7 +68,7 @@ end

json_schema = JSONSchema.Schema(acset_schema_json_schema())

for schema in [SchGraph, SchWeightedGraph, SchLabeledDDS]
for schema in [SchGraph, SchWeightedGraph, SchLabeledDDS4]
schema_dict = generate_json_acset_schema(schema)
@test isnothing(JSONSchema.validate(json_schema, schema_dict))
@test roundtrip_json_acset_schema(schema) == schema
Expand Down

0 comments on commit 6407367

Please sign in to comment.