From 8ff21ea2ecd4793b3908d6bfa7115be660f065ba Mon Sep 17 00:00:00 2001 From: Luke Morris Date: Tue, 31 Oct 2023 12:16:14 -0400 Subject: [PATCH] Read and Write JSON ACSetTransformations --- .../JSONCSetTransformations.jl | 118 +++++++----------- .../JSONCSetTransformations.jl | 6 +- 2 files changed, 51 insertions(+), 73 deletions(-) diff --git a/src/categorical_algebra/JSONCSetTransformations.jl b/src/categorical_algebra/JSONCSetTransformations.jl index 6547ea95d..39188ba83 100644 --- a/src/categorical_algebra/JSONCSetTransformations.jl +++ b/src/categorical_algebra/JSONCSetTransformations.jl @@ -2,20 +2,14 @@ """ module JSONCSetTransformations export generate_json_fin_function, parse_json_fin_function, - read_json_fin_function, write_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=# + 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 ##################### @@ -65,72 +59,56 @@ function generate_json_acset_transformation(X::ACSetTransformation) :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) + Iterators.map((keys ∘ components)(X), (values ∘ components)(X)) do k,v + k , k ∈ (attrtypes ∘ acset_schema ∘ dom)(X) ? + # TODO: Support VarFunctions that are not empty. + "TODO: VarFunctions are current not supported." : + generate_json_fin_function(v) end)) end +""" Serialize an ACSetTransformation object to a JSON file. -#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 +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 + +""" Parse JSON-able object or JSON string representing an ACSetTransformation. + +Inverse to [`generate_json_acset_transformation`](@ref). +""" +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) + +function parse_json_acset_transformation(cons, input::AbstractDict) + domain = parse_json_acset(cons(), input["dom"]) + codomain = parse_json_acset(cons(), input["codom"]) + hom_keys = filter(keys(input["components"])) do k + Symbol(k) ∉ (attrtypes ∘ acset_schema)(domain) + end + # TODO: Support VarFunctions that are not empty. + ACSetTransformation( + NamedTuple{Tuple(Symbol.(hom_keys))}( + Iterators.map(hom_keys) do k + parse_json_fin_function(input["components"][k]) + end), + domain, + codomain) +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 end # module diff --git a/test/categorical_algebra/JSONCSetTransformations.jl b/test/categorical_algebra/JSONCSetTransformations.jl index dfc60bef1..2c9efc590 100644 --- a/test/categorical_algebra/JSONCSetTransformations.jl +++ b/test/categorical_algebra/JSONCSetTransformations.jl @@ -18,16 +18,16 @@ end # ACSetTransformation serialization ################################### -function roundtrip_json_acset_transformation(x::T) where T <: ACSetTransformation +function roundtrip_json_acset_transformation(x, t) mktempdir() do dir path = joinpath(dir, "acset_transformation.json") write_json_acset_transformation(x, path) - read_json_acset_transformation(T, 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 +@test roundtrip_json_acset_transformation(α, WeightedGraph{Float64}) == α