While trying to write a serialized directed wiring diagram ACSet out to file and then read it back in, I encountered an issue with parse_json_acset. write_json_acset and generate_json_acset work (in this case), but read_json_acset does not because parse_json_acset errors. I have included a script demonstrating the issue and a proposed fixed below. Note that the problematic calls to read_json_acset and parse_json_acset have been commented out at lines 36 and 59, respectively, to enable the script to run through entirely.
using Catlab, Catlab.Theories
using Catlab.CategoricalAlgebra
using Catlab.WiringDiagrams
using Catlab.Programs
using Catlab.Programs.RelationalPrograms
import Catlab.WiringDiagrams.DirectedWiringDiagrams: WiringDiagramACSet
# Form OfficeSpace presentation of FreeBiproductCategory
@present OfficeSpace(FreeBiproductCategory) begin
(LatePeter,CubiclePeter,LookLikeWorkingPeter,UncoveredTPSReport,HassledPeter,Milton,StaplerStatus,Lumbergh,BuildingOnFire)::Ob
UseSideDoorSoLumberghDoesntSee::Hom(LatePeter,CubiclePeter)
SpaceOutForAnHour::Hom(CubiclePeter,LookLikeWorkingPeter)
Do15MinActualWork::Hom(LookLikeWorkingPeter,CubiclePeter)
FileTPSReport::Hom(CubiclePeter⊗UncoveredTPSReport,HassledPeter)
TakeStapler::Hom(Milton⊗Lumbergh,BuildingOnFire)
end
# Form case_of_modays wiring diagram of OfficeSpace
case_of_mondays = @program OfficeSpace (lp::LatePeter,m::Milton,tps::UncoveredTPSReport,l::Lumbergh) begin #
cp = UseSideDoorSoLumberghDoesntSee(lp)
llwp = SpaceOutForAnHour(cp)
cp = Do15MinActualWork(llwp)
hassled_status = FileTPSReport(cp,tps)
building_status = TakeStapler(m,l)
return hassled_status, building_status
end
# Round trip of write/read json of wiring diagram acset errors in read_json_acset
function roundtrip_json_acset(x::T) where T <: ACSet
mktempdir() do dir
path = joinpath(dir, "acset.json")
write_json_acset(x, path)
read_json_acset(T, path)
end
end
# rt_json_acset = roundtrip_json_acset(case_of_mondays.diagram)
#=
ERROR: MethodError: no method matching DataType(::String)
Stacktrace:
[1] parse_json_acset(#unused#::Type{WiringDiagramACSet{Any, Any, Any, DataType}}, input::Dict{String, Any})
@ Catlab.CategoricalAlgebra.CSets ~/.julia/packages/Catlab/hMLnj/src/categorical_algebra/CSets.jl:1199
[2] read_json_acset(#unused#::Type{WiringDiagramACSet{Any, Any, Any, DataType}}, fname::String)
@ Catlab.CategoricalAlgebra.CSets ~/.julia/packages/Catlab/hMLnj/src/categorical_algebra/CSets.jl:1216
[3] #29
@ ./REPL[67]:5 [inlined]
[4] mktempdir(fn::var"#29#30"{WiringDiagramACSet{Any, Any, Any, DataType}, WiringDiagramACSet{Any, Any, Any, DataType}}, parent::String; prefix::String)
@ Base.Filesystem ./file.jl:764
[5] mktempdir (repeats 2 times)
@ ./file.jl:760 [inlined]
[6] roundtrip_json_acset(x::WiringDiagramACSet{Any, Any, Any, DataType})
@ Main ./REPL[67]:2
[7] top-level scope
@ REPL[69]:1
=#
# Round trip of generate/parse json of acset errors in parse_json_acset
json_from_wd_acset = generate_json_acset(case_of_mondays.diagram)
# rt_wd_acset = parse_json_acset(WiringDiagramACSet{Any,Any,Any,Any},json_from_wd_acset)
#=
ERROR: MethodError: no method matching iterate(::Symbol)
Closest candidates are:
iterate(::Union{LinRange, StepRangeLen}) at range.jl:872
iterate(::Union{LinRange, StepRangeLen}, ::Integer) at range.jl:872
iterate(::T) where T<:Union{Base.KeySet{<:Any, <:Dict}, Base.ValueIterator{<:Dict}} at dict.jl:712
...
Stacktrace:
[1] indexed_iterate(I::Symbol, i::Int64)
@ Base ./tuple.jl:91
[2] parse_json_acset(#unused#::Type{WiringDiagramACSet{Any, Any, Any, DataType}}, input::OrderedCollections.OrderedDict{Symbol, Vector})
@ Catlab.CategoricalAlgebra.CSets ~/.julia/packages/Catlab/hMLnj/src/categorical_algebra/CSets.jl:1196
[3] top-level scope
@ REPL[66]:1
=#
#**********
# HOWEVER *
#**********
# Modifying the parse_json_acset function from CSets.jl as follows works
function new_parse_json_acset(::Type{T}, input::AbstractDict) where T <: ACSet
out = T()
for (k,v) ∈ input
add_parts!(out, Symbol(k), length(v))
end
for l ∈ values(input)
for (i, j) ∈ enumerate(l)
for k ∈ keys(j) # (k,v) = j #
v = j[k]
vtype = eltype(out[Symbol(k)])
if !(v isa vtype)
v = vtype(v)
end
set_subpart!(out, i, Symbol(k), v)
end
end
end
out
end
rt_wd_acset = new_parse_json_acset(WiringDiagramACSet{Any,Any,Any,DataType},json_from_wd_acset)
println("Check Roundtrip WD ACSet Equals Original WD ACSet")
println(rt_wd_acset == case_of_mondays.diagram)
println("")
rt_wd = WiringDiagram{ThBiproductCategory,Any,Any,Any}(rt_wd_acset,nothing)
println("Check Roundtrip WD Equals Original WD")
println(rt_wd == case_of_mondays)
println("")
# This check is actually for comparison with a separate issue that has been avoided here
println("Check Types of Roundtrip WD ACSet and Original WD ACSet")
print("Orig: ")
println(typeof(case_of_mondays.diagram))
print("RT: ")
println(typeof(rt_wd_acset))
print("Equality of types: ")
println(typeof(rt_wd_acset) == typeof(case_of_mondays.diagram))
While trying to write a serialized directed wiring diagram ACSet out to file and then read it back in, I encountered an issue with
parse_json_acset
.write_json_acset
andgenerate_json_acset
work (in this case), butread_json_acset
does not becauseparse_json_acset
errors. I have included a script demonstrating the issue and a proposed fixed below. Note that the problematic calls toread_json_acset
andparse_json_acset
have been commented out at lines 36 and 59, respectively, to enable the script to run through entirely.