Skip to content

Commit

Permalink
Read and write FinFunction JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
lukem12345 committed Oct 31, 2023
1 parent dda1489 commit 5e24202
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/categorical_algebra/CategoricalAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ include("Chase.jl")
include("FunctorialDataMigrations.jl")
include("StructuredCospans.jl")
include("Slices.jl")
include("JSONCSetTransformations.jl")

@reexport using .Categories
@reexport using .FinCats
Expand All @@ -43,4 +44,6 @@ include("Slices.jl")
@reexport using .StructuredCospans
@reexport using .Slices

@reexport using .JSONCSetTransformations

end
136 changes: 136 additions & 0 deletions src/categorical_algebra/JSONCSetTransformations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
""" JSON serialization of acset transformations.
"""
module JSONCSetTransformations
export generate_json_fin_function, parse_json_fin_function,
read_json_fin_function, write_json_fin_function#=,
generate_json_acset_transformation, parse_json_acset_transformation,
read_json_acset_transformation, write_json_acset_transformation=#

import JSON
using DataStructures: OrderedDict
#import Pkg
#import Tables

using ..FinSets, ..CSets
# TODO: Some of these `using`s might not be necessary.
using ACSets.ACSetInterface, ACSets.Schemas, ACSets.DenseACSets
using ACSets.DenseACSets: attr_type
using ACSets.ColumnImplementations: AttrVar

# ACSetTransformation serialization
#####################

""" Generate JSON-able object representing a FinFunction.
Inverse to [`parse_json_fin_function`](@ref).
"""
function generate_json_fin_function(F::FinFunction)
OrderedDict{Symbol,Any}(
:dom => dom( F),
:codom => codom( F),
:map => collect(F))
end

""" Serialize a FinFunction object to a JSON file.
Inverse to [`read_json_fin_function`](@ref).
"""
function write_json_fin_function(x::FinFunction, fname::AbstractString)
open(fname, "w") do f
write(f, JSON.json(generate_json_fin_function(x)))
end
end

function parse_json_fin_function(input::AbstractDict)
FinFunction(
Int.(input["map"]),
input["dom"]["n"],
input["codom"]["n"])
end

""" Deserialize a FinFunction object from a JSON file.
Inverse to [`write_json_fin_function`](@ref).
"""
function read_json_fin_function(fname::AbstractString)
parse_json_fin_function(JSON.parsefile(fname))
end

""" Generate JSON-able object representing an ACSetTransformation.
Inverse to [`parse_json_acset_transformation`](@ref).
"""
function generate_json_acset_transformation(X::ACSetTransformation)
OrderedDict{Symbol,Any}(
:dom => (generate_json_acset dom)(X),
:codom => (generate_json_acset codom)(X),
:components => OrderedDict{Symbol,Any}(
Iterators.map((keys components)(X), (values components)(X)) do (k,v)
k => k (attrtypes acset_schema dom)(X) ?
"foo" :
generate_json_fin_function(k)
end))
end


#attr_to_json(var::AttrVar) = (_var = var.val,)
#attr_to_json(val) = val
#
#""" Parse JSON-able object or JSON string representing an ACSet.
#
#Inverse to [`generate_json_acset`](@ref).
#"""
#parse_json_acset_transformation(cons, input::AbstractDict) =
# parse_json_acset!(cons(), input)
#parse_json_acset_transformation(cons, input::AbstractString) =
# parse_json_acset_transformation(cons, JSON.parse(input))
#parse_json_acset_transformation(acs::ACSet, input::AbstractDict) =
# parse_json_acset_transformation(constructor(acs), input)
#
## TODO
#function parse_json_acset_transformation!(out::ACSetTransformation, input::AbstractDict)
# schema = acset_schema(out)
# parts = Iterators.map(input) do (type, rows)
# Symbol(type) => add_parts!(out, Symbol(type), length(rows))
# end |> Dict
# for rows ∈ values(input)
# for (rownum, row) ∈ enumerate(rows)
# for (k, v) ∈ pairs(row)
# k = Symbol(k)
# if k == :_id
# # For now, IDs are assumed to coincide with row number.
# @assert rownum == v
# continue
# end
# if k ∈ attrs(schema; just_names=true)
# vtype = attr_type(out, k)
# v = v isa AbstractDict && haskey(v, "_var") ?
# AttrVar(v["_var"]) : vtype(v)
# end
# set_subpart!(out, parts[dom(schema, k)][rownum], k, v)
# end
# end
# end
# out
#end
#
#""" Deserialize an ACSetTransformation object from a JSON file.
#
#Inverse to [`write_json_acset_transformation`](@ref).
#"""
#function read_json_acset_transformation(ty, fname::AbstractString)
# parse_json_acset_transformation(ty, JSON.parsefile(fname))
#end
#
#""" Serialize an ACSetTransformation object to a JSON file.
#
#Inverse to [`read_json_acset_transformation`](@ref).
#"""
#function write_json_acset_transformation(x::ACSetTransformation, fname::AbstractString)
# open(fname, "w") do f
# write(f, JSON.json(generate_json_acset_transformation(x)))
# end
#end

end # module

4 changes: 4 additions & 0 deletions test/categorical_algebra/CategoricalAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,9 @@ end
include("Slices.jl")
end

@testset "JSONCSetTransformations" begin
include("JSONCSetTransformations.jl")
end


end
33 changes: 33 additions & 0 deletions test/categorical_algebra/JSONCSetTransformations.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# FinFunction serialization
###########################
function roundtrip_json_fin_function(f::T) where T <: FinFunction
mktempdir() do dir
path = joinpath(dir, "fin_function.json")
write_json_fin_function(f, path)
read_json_fin_function(path)
end
end

f = FinFunction([2,3], 2, 4)
g = FinFunction([2], 1, 3)

for ϕ in [f,g]
@test roundtrip_json_fin_function(ϕ) == ϕ
end

# ACSetTransformation serialization
###################################

function roundtrip_json_acset_transformation(x::T) where T <: ACSetTransformation
mktempdir() do dir
path = joinpath(dir, "acset_transformation.json")
write_json_acset_transformation(x, path)
read_json_acset_transformation(T, path)
end
end

g = path_graph(WeightedGraph{Float64}, 2, E=(weight=2,))
h = path_graph(WeightedGraph{Float64}, 4, E=(weight=[1,2,3],))
α = ACSetTransformation((V=[2,3], E=[2]), g, h)
@test_broken roundtrip_json_acset_transformation(g) == g

0 comments on commit 5e24202

Please sign in to comment.