diff --git a/Project.toml b/Project.toml
new file mode 100644
index 0000000..c8fde90
--- /dev/null
+++ b/Project.toml
@@ -0,0 +1,5 @@
+[deps]
+ACSets = "227ef7b5-1206-438b-ac65-934d6da304b8"
+JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
+MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
+Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
diff --git a/src/julia/amr.jl b/src/julia/amr.jl
new file mode 100644
index 0000000..25db0f7
--- /dev/null
+++ b/src/julia/amr.jl
@@ -0,0 +1,416 @@
+module AMR
+
+export Math, MathML, ExpressionFormula, Unit, Distribution, Observable, Expression,
+ Rate, Initial, Parameter, Time,
+ StandardUniform, Uniform, StandardNormal, Normal, PointMass,
+ Semantic, Header, ODERecord, ODEList, Typing, ASKEModel,
+ distro_string, amr_to_string
+
+using Reexport
+@reexport using MLStyle
+@reexport using ACSets
+using ACSets.ADTs
+using ACSets.ACSetInterface
+
+@data MathML begin
+ Math(String)
+ Presentation(String)
+end
+
+nomath = Math("")
+
+@as_record struct ExpressionFormula{T}
+ expression::T
+ expression_mathml::MathML
+end
+
+@as_record struct Unit
+ expression::String
+ expression_mathml::MathML
+end
+
+
+nounit = Unit("", nomath)
+
+@data Distribution begin
+ StandardUniform
+ Uniform(min, max)
+ StandardNormal
+ Normal(mean, variance)
+ PointMass(value)
+end
+
+@as_record struct Observable{T}
+ id::Symbol
+ name::String
+ states::Vector{Symbol}
+ f::ExpressionFormula
+end
+
+@data Expression begin
+ Rate(target::Symbol, f::ExpressionFormula)
+ Initial(target::Symbol, f::ExpressionFormula)
+ Parameter(id::Symbol, name::String, description::String, units::Unit, value::Float64, distribution::Distribution)
+ Time(id::Symbol, units::Unit)
+end
+
+@data Semantic begin
+ ODEList(statements::Vector{Expression})
+ ODERecord(rates::Vector{Rate}, initials::Vector{Initial}, parameters::Vector{Parameter}, time::Time)
+ # Metadata
+ Typing(system::ACSetSpec, map::Vector{Pair})
+ # Stratification
+end
+
+@as_record struct Header
+ name::String
+ schema::String
+ description::String
+ schema_name::String
+ model_version::String
+end
+
+@as_record struct ASKEModel
+ header::Header
+ model::ACSetSpec
+ semantics::Vector{Semantic}
+end
+
+function distro_string(d::Distribution)
+ @match d begin
+ StandardUniform => "U(0,1)"
+ Uniform(min, max) => "U($min,$max)"
+ StandardNormal => "N(0,1)"
+ Normal(mu, var) => "N($mu,$var)"
+ PointMass(value) => "δ($value)"
+ end
+end
+
+function distro_expr(d::Distribution)
+ return Base.Meta.parse(distro_string(d))
+end
+
+padlines(ss::Vector, n) = map(ss) do s
+ " "^n * s
+end
+padlines(s::String, n=2) = join(padlines(split(s, "\n"), n), "\n")
+
+function amr_to_string(amr)
+ let ! = amr_to_string
+ @match amr begin
+ s::String => s
+ Math(s) => !s
+ Presentation(s) => " $s "
+ u::Unit => !u.expression
+ d::Distribution => distro_string(d)
+ Time(id, u) => "$id::Time{$(!u)}\n"
+ Rate(t, f) => "$t::Rate = $(f.expression)"
+ Initial(t, f) => "$t::Initial = $(f.expression)"
+ Observable(id, n, states, f) => "# $n\n$id::Observable = $(f.expression)($states)\n"
+ Header(name, s, d, sn, mv) => "\"\"\"\nASKE Model Representation: $name$mv :: $sn \n $s\n\n$d\n\"\"\""
+ Parameter(t, n, d, u, v, dist) => "\n# $n-- $d\n$t::Parameter{$(!u)} = $v ~ $(!dist)\n"
+ m::ACSetSpec => "Model = begin\n$(padlines(ADTs.to_string(m),2))\nend"
+ ODEList(l) => "ODE_Equations = begin\n" * padlines(join(map(!, l), "\n")) * "\nend"
+ ODERecord(rts, init, para, time) => join(vcat(["ODE_Record = begin\n"], !rts , !init, !para, [!time, "end"]), "\n")
+ vs::Vector{Pair} => map(vs) do v; "$(v[1]) => $(v[2])," end |> x-> join(x, "\n")
+ vs::Vector{Semantic} => join(map(!, vs), "\n\n")
+ xs::Vector => map(!, xs)
+ Typing(system, map) => "Typing = begin\n$(padlines(!system, 2))\nTypeMap = [\n$(padlines(!map, 2))]\nend"
+ ASKEModel(h, m, s) => "$(!h)\n$(!m)\n\n$(!s)"
+ end
+ end
+end
+
+block(exprs) = begin
+ q = :(begin
+
+ end)
+ append!(q.args, exprs)
+ return q
+end
+
+extract_acsetspec(s::String) = join(split(s, " ")[2:end], " ") |> Meta.parse
+
+function amr_to_expr(amr)
+ let ! = amr_to_expr
+ @match amr begin
+ s::String => s
+ Math(s) => :(Math($(!s)))
+ Presentation(s) => :(Presentation($(!s)))
+ u::Unit => u.expression
+ d::Distribution => distro_expr(d)
+ Time(id, u) => :($id::Time{$(!u)})
+ Rate(t, f) => :($t::Rate = $(f.expression))
+ Initial(t, f) => :($t::Initial = $(f.expression))
+ Observable(id, n, states, f) => begin "$n"; :(@doc $x $id::Observable = $(f.expression)($states)) end
+ Header(name, s, d, sn, mv) => begin x = "ASKE Model Representation: $name$mv :: $sn \n $s\n\n$d"; :(@doc $x) end
+ Parameter(t, n, d, u, v, dist) => begin x = "$n-- $d"; :(@doc $x $t::Parameter{$(!u)} = $v ~ $(!dist)) end
+ m::ACSetSpec => :(Model = begin $(extract_acsetspec(ADTs.to_string(m))) end)
+ ODEList(l) => :(ODE_Equations = $(block(map(!, l))))
+ ODERecord(rts, init, para, time) => :(ODE_Record = (rates=$(!rts), initials=$(!init), parameters=$(!para), time=!time))
+ vs::Vector{Pair} => begin ys = map(vs) do v; :($(v[1]) => $(v[2])) end; block(ys) end
+ vs::Vector{Semantic} => begin ys = map(!, vs); block(ys) end
+ xs::Vector => begin ys = map(!, xs); block(ys) end
+ Typing(system, map) => :(Typing = $(!system); TypeMap = $(block(map)))
+ ASKEModel(h, m, s) => :($(!h);$(!m);$(!s))
+ end
+ end
+end
+
+optload(d, path, default=nothing) = begin
+ let ! = optload
+ @match path begin
+ s::Symbol => !(d, string(s), default)
+ s::String => get(d, s, default)
+ [addr] => !(d, addr, default)
+ [head, args...] => !(get(d, head, Dict()), args, default)
+ _=> error("Bad recursion in optload($d, $path)")
+ end
+ end
+end
+
+function petrispec(dict::AbstractDict)
+ findkwarg(kwarg::Symbol, d::AbstractDict, path, default=nothing) = Kwarg(kwarg, Value(optload(d, path, default)))
+ loadstate(s) = begin
+ Statement(:S, [findkwarg(k, s, p, :nothing) for (k,p) in [(:id, "id"), (:name, "name"), (:units, ["units", "expression"])]])
+ end
+ states = [loadstate(s) for s in dict["states"]]
+ transi = [
+ Statement(:T,
+ [Kwarg(:id, Value(Symbol(t["id"]))), Kwarg(:name, Value(t["properties"]["name"])), Kwarg(:desc, Value(t["properties"]["description"])) ]
+ ) for t in dict["transitions"]]
+
+ inputs = [[
+ Statement(:I,
+ [Kwarg(:is, Value(i)), Kwarg(:it, Value(t["id"]))]) for i in t["input"]] for t in dict["transitions"]
+ ] |> Base.Flatten |> collect
+ outputs = [[
+ Statement(:O,
+ [Kwarg(:os, Value(i)), Kwarg(:ot, Value(t["id"]))]) for i in t["output"]] for t in dict["transitions"]
+ ] |> Base.Flatten |> collect
+ ACSetSpec(:AMRPetriNet, vcat(states, transi, inputs, outputs))
+end
+
+function load(::Type{Unit}, d::AbstractDict)
+ ud = get(d, "units", Dict("expression"=>"", "expression_mathml"=>""))
+ u = Unit(ud["expression"], Presentation(ud["expression_mathml"]))
+end
+
+function load(::Type{Time}, t::AbstractDict)
+ Time(Symbol(t["id"]), load(Unit, t))
+end
+
+function load(::Type{Rate}, r::AbstractDict)
+ f = ExpressionFormula(r["expression"], Presentation(r["expression_mathml"]))
+ Rate(Symbol(r["target"]), f)
+end
+
+function load(::Type{Initial}, d::AbstractDict)
+ f = ExpressionFormula(d["expression"], Presentation(d["expression_mathml"]))
+ Initial(Symbol(d["target"]), f)
+end
+
+function load(::Type{Distribution}, d::AbstractDict)
+ @match d begin
+ Dict("type"=>"StandardUniform1") => StandardUniform
+ Dict("type"=>"StandardNormal") => StandardNormal
+ Dict("type"=>"Uniform", "parameters"=>p) => Uniform(p["minimum"], p["maximum"])
+ Dict("type"=>"Uniform1", "parameters"=>p) => Uniform(p["minimum"], p["maximum"])
+ Dict("type"=>"Normal", "parameters"=>p) => Normal(p["mu"], p["var"])
+ Dict("type"=>"PointMass", "parameters"=>p) => PointMass(p["value"])
+ end
+end
+
+load(::Type{Distribution}, ::Nothing) = PointMass(missing)
+
+
+function load(::Type{Parameter}, d::AbstractDict)
+ u = load(Unit, d)
+ Parameter(
+ Symbol(d["id"]),
+ d["name"],
+ d["description"],
+ u,
+ d["value"],
+ load(Distribution, get(d,"distribution", nothing))
+ )
+end
+
+function load(::Type{ODERecord}, d::AbstractDict)
+ time = load(Time, d["time"])
+ rate(x) = load(Rate, x)
+ initial(x) = load(Initial, x)
+ parameter(x) = load(Parameter, x)
+ rates = rate.(d["rates"])
+ initials = initial.(d["initials"])
+ parameters = parameter.(d["parameters"])
+
+ ODERecord(rates, initials, parameters, time)
+end
+
+function load(::Type{Header}, d::AbstractDict)
+ @match d begin
+ Dict("name"=>n, "schema"=>s, "description"=>d, "schema_name"=>sn, "model_version"=>mv) => Header(n,s,d,sn,mv)
+ _ => error("Information for Header was not found in $d")
+ end
+end
+
+function load(::Type{Typing}, d::AbstractDict)
+ @match d begin
+ Dict("type_system"=>s, "type_map"=>m) => begin @show m; Typing(petrispec(s), [x[1]=> x[2] for x in m]) end
+ _ => error("Typing judgement was not properly encoded in $d")
+ end
+end
+
+function load(::Type{ASKEModel}, d::AbstractDict)
+ hdr = load(Header, d)
+ hdr.schema_name == "petrinet" || error("only petrinet models are supported")
+ mdl = petrispec(d["model"])
+ sem = []
+ if haskey(d["semantics"], "ode")
+ push!(sem, load(ODERecord, d["semantics"]["ode"]))
+ end
+ if haskey(d["semantics"], "typing")
+ push!(sem, load(Typing, d["semantics"]["typing"]))
+ end
+ ASKEModel(hdr, mdl, sem)
+end
+
+using MLStyle.Modules.AST
+
+function load(::Type{Time}, ex::Expr)
+ @matchast ex quote
+ $a::Time{} => Time(a, Unit("", Math("")))
+ $a::Time{$b} => Time(a, load(Unit, b))
+ _ => error("Time was not properly encoded as Expr $ex")
+ end
+end
+
+function load(::Type{Unit}, ex::Union{Symbol, Expr})
+ Unit(string(ex), Math(""))
+end
+
+function load(::Type{ExpressionFormula}, ex::Expr)
+ ExpressionFormula(string(ex), Math(string(ex)))
+end
+
+function load(::Type{Rate}, ex::Expr)
+ @matchast ex quote
+ ($a::Rate = $ex) => Rate(a, load(ExpressionFormula, ex))
+ ($a::Rate{$u} = $ex) => Rate(a, load(ExpressionFormula, ex))
+ _ => error("Rate was not properly encoded as Expr $ex")
+ end
+end
+
+function load(::Type{Initial}, ex::Expr)
+ @matchast ex quote
+ ($a::Initial = $ex) => Rate(a, load(ExpressionFormula, ex))
+ ($a::Initial{$u} = $ex) => Rate(a, load(ExpressionFormula, ex))
+ _ => error("Rate was not properly encoded as Expr $ex")
+ end
+end
+
+function docval(exp::Expr)
+ s, ex = @match exp begin
+ Expr(:macrocall, var"@doc", _, s, ex) => (s,ex)
+ _ => error("Could not match documented value in $exp")
+ end
+ name, desc = split(s, "--")
+ return strip(name), strip(desc), ex
+end
+
+function load(d::Type{Distribution}, ex::Expr)
+ @matchast ex quote
+ U(0,1) => StandardUniform
+ U($min,$max) => Uniform(min, max)
+ N(0,1) => StandardNormal
+ N($mu,$var) => Normal(mu, var)
+ δ($value) => PointMass(value)
+ _ => error("Failed to find distribution in $ex")
+ end
+end
+
+
+function load(::Type{Parameter}, ex::Expr)
+ name, desc, ex = docval(ex)
+ id, u, val, dist = @matchast ex quote
+ ($id::Parameter{} = ($val ~ $d)) => (id, nounit, val, load(Distribution, d))
+ ($id::Parameter{$u} = ($val ~ $d)) => (id, load(Unit, u), val, load(Distribution, d))
+ ($id::Parameter{} = $val) => (id, nounit, val, PointMass(missing))
+ ($id::Parameter{$u} = $val) => (id, load(Unit, u), val, PointMass(missing))
+ end
+ Parameter(id, name, desc, u, val, dist)
+end
+
+function load(::Type{ODEList}, ex::Expr)
+ map(ex.args[2].args) do arg
+ try
+ return load(Rate, arg)
+ catch ErrorException
+ try
+ return load(Initial, arg)
+ catch ErrorException
+ try
+ return load(Parameter, arg)
+ catch ErrorException
+ try
+ return load(Time, arg)
+ catch
+ return nothing
+ end
+ end
+ end
+ end
+ end |> x->filter(!isnothing, x) |> ODEList
+end
+
+function load(::Type{Header}, ex::String)
+ hdr, schema, _, desc, _ = split(ex, "\n")
+ hdr, schema_name = split(hdr, "::")
+ _, hdr = split(hdr, ":")
+ name, version = split(hdr, "@")
+ Header(strip(name), strip(schema), strip(desc), strip(schema_name), strip(version))
+end
+
+function load(::Type{ACSetSpec}, ex::Expr)
+ let ! = x->load(ACSetSpec, x)
+ @match ex begin
+ Expr(:(=), name, body) => @match body.args[2] begin
+ Expr(:(=), type, body) => acsetspec(type, body)
+ end
+ Expr(:block, lnn, body) => !(body)
+ _ => ex
+ end
+ end
+end
+
+function load(::Type{Typing}, ex::Expr)
+ let !(x) = load(Typing, x)
+ @match ex begin
+ Expr(:(=), :Model, body) => load(ACSetSpec, ex)
+ Expr(:(=), :TypeMap, list) => !list
+ Expr(:(=), :Typing, body) => Typing(!(body.args[2]), !(body.args[4]))
+ Expr(:vect, args...) => map(args) do arg
+ @match arg begin
+ Expr(:call, :(=>), a, b) => Pair(a,b)
+ _ => error("The type map is expected to be pairs defined with a => fa. Got $arg")
+ end
+ end
+ _ => error("Could not processing Typing assignment from $ex")
+ end
+ end
+end
+
+function load(::Type{ASKEModel}, ex::Expr)
+ elts = map(ex.args) do arg
+ @match arg begin
+ Expr(:macrocall, var"@doc", _, s, ex) => (load(Header, s), load(ACSetSpec, ex))
+ Expr(:(=), :ODE_Record, body) => load(ODEList, arg)
+ Expr(:(=), :ODE_Equations, body) => load(ODEList, arg)
+ Expr(:(=), :Typing, body) => load(Typing, arg)
+ _ => arg
+ end
+ end
+ ASKEModel(elts[2][1], elts[2][2], [elts[4], elts[6]])
+end
+end # module end
\ No newline at end of file
diff --git a/src/julia/amr_examples.jl b/src/julia/amr_examples.jl
new file mode 100644
index 0000000..8e588bc
--- /dev/null
+++ b/src/julia/amr_examples.jl
@@ -0,0 +1,551 @@
+module AMRExamples
+include("amr.jl")
+using .AMR
+using Test
+
+nomath = Math("")
+header = Header("SIR", "amr-schemas:petri_schema.json", "The SIR Model of disease", "petrinet", "0.2")
+model = acsetspec(:(LabelledPetriNet{Symbol}), quote
+ S(label=:S)
+ S(label=:I)
+ S(label=:R)
+
+ T(label=:inf)
+ T(label=:rec)
+
+ I(is=:S, it=:inf)
+ I(is=:I, it=:inf)
+ I(is=:I, it=:rec)
+
+ O(os=:I, it=:inf)
+ O(os=:I, it=:inf)
+ O(os=:R, it=:rec)
+end)
+
+ode = ODERecord([Rate(:inf, ExpressionFormula( "S*I*β", nomath)),
+ Rate(:rec, ExpressionFormula("I*γ", nomath))],
+
+ [Initial(:S, ExpressionFormula("S₀", nomath)),
+ Initial(:I, ExpressionFormula("I₀", nomath)),
+ Initial(:R, ExpressionFormula("R₀", nomath)),],
+
+ [Parameter(:β, "β", "the beta parameter", Unit("1/(persons^2*day)", nomath), 1e-2, Uniform(1e-3, 2e-2)),
+ Parameter(:γ, "γ", "the gama parameter", Unit("1/(persons*day)", nomath), 3, Uniform(1, 2e+2)),
+
+ Parameter(:S₀, "S₀", "the initial susceptible population", Unit("persons", nomath), 300000000.0, Uniform(1e6, 4e6)),
+ Parameter(:I₀, "I₀", "the initial infected population", Unit("persons", nomath), 1.0, Uniform(1, 1)),
+ Parameter(:R₀, "R₀", "the initial recovered population", Unit("persons", nomath), 0.0, Uniform(0, 4)),
+ ],
+ Time(:t, Unit("day", nomath)))
+
+odelist = ODEList([
+ Time(:t, Unit("day", nomath)),
+ Parameter(:β, "β", "the beta parameter", Unit("1/(persons^2*day)", nomath), 1e-2, Uniform(1e-3, 2e-2)),
+ Rate(:inf, ExpressionFormula("S*I*β", nomath)),
+
+ Parameter(:γ, "γ", "the gama parameter", Unit("1/(persons*day)", nomath), 3, Uniform(1, 2e+2)),
+ Rate(:rec, ExpressionFormula("I*γ", nomath)),
+
+ Parameter(:S₀, "S₀", "the initial susceptible population", Unit("persons", nomath), 300000000.0, Uniform(1e6, 4e6)),
+ Initial(:S₀, ExpressionFormula("S₀", nomath)),
+
+ Parameter(:I₀, "I₀", "the initial infected population", Unit("persons", nomath), 1.0, Uniform(1, 1)),
+ Initial(:I₀, ExpressionFormula("I₀", nomath)),
+
+ Parameter(:R₀, "R₀", "the initial recovered population", Unit("persons", nomath), 0.0, Uniform(0, 4)),
+ Initial(:R₀, ExpressionFormula("R₀", nomath)),
+
+ ])
+
+amr₁ = ASKEModel(header,
+ model,
+ [ode]
+)
+
+typesystem = acsetspec(:(LabelledPetriNet{Symbol}), quote
+ S(label=:Pop)
+
+ T(label=:inf)
+ T(label=:disease)
+ T(label=:strata)
+
+ I(is=:Pop, it=:inf)
+ I(is=:Pop, it=:inf)
+ I(is=:Pop, it=:disease)
+ I(is=:Pop, it=:strata)
+
+ O(os=:Pop, it=:inf)
+ O(os=:Pop, it=:inf)
+ O(os=:Pop, it=:disease)
+ O(os=:Pop, it=:strata)
+end)
+
+
+typing = Typing(
+ typesystem,
+ [
+ (:S=>:Pop),
+ (:I=>:Pop),
+ (:R=>:Pop),
+ (:inf=>:inf),
+ (:rec=>:disease)
+ ]
+)
+
+amr₂ = ASKEModel(header,
+ model,
+ [
+ odelist,
+ typing
+ ]
+)
+
+println()
+println(amr_to_string(amr₁))
+println()
+println(amr_to_string(amr₂))
+
+AMR.amr_to_expr(amr₁) |> println
+AMR.amr_to_expr(amr₂.header) |> println
+AMR.amr_to_expr(amr₂.model) |> println
+map(AMR.amr_to_expr(amr₂.semantics[1]).args[2].args) do s; println(s) end
+AMR.amr_to_expr(amr₂.semantics[1]).args[2]
+AMR.amr_to_expr(amr₂.semantics[1])
+AMR.amr_to_expr(amr₂) |> println
+
+h = AMR.load(Header, Dict("name" => "SIR Model",
+"schema" => "https://raw.githubusercontent.com/DARPA-ASKEM/Model-Representations/petrinet_v0.5/petrinet/petrinet_schema.json",
+"description" => "SIR model",
+"schema_name" => "petrinet",
+"model_version" => "0.1"))
+
+@test AMR.amr_to_string(h) == "\"\"\"\nASKE Model Representation: SIR Model0.1 :: petrinet \n https://raw.githubusercontent.com/DARPA-ASKEM/Model-Representations/petrinet_v0.5/petrinet/petrinet_schema.json\n\nSIR model\n\"\"\""
+
+mjson = raw"""{
+ "states": [
+ {
+ "id": "S",
+ "name": "Susceptible",
+ "description": "Number of individuals that are 'susceptible' to a disease infection",
+ "grounding": {
+ "identifiers": {
+ "ido": "0000514"
+ }
+ },
+ "units": {
+ "expression": "person",
+ "expression_mathml": "person"
+ }
+ },
+ {
+ "id": "I",
+ "name": "Infected",
+ "description": "Number of individuals that are 'infected' by a disease",
+ "grounding": {
+ "identifiers": {
+ "ido": "0000511"
+ }
+ },
+ "units": {
+ "expression": "person",
+ "expression_mathml": "person"
+ }
+ },
+ {
+ "id": "R",
+ "name": "Recovered",
+ "description": "Number of individuals that have 'recovered' from a disease infection",
+ "grounding": {
+ "identifiers": {
+ "ido": "0000592"
+ }
+ },
+ "units": {
+ "expression": "person",
+ "expression_mathml": "person"
+ }
+ }
+ ],
+ "transitions": [
+ {
+ "id": "inf",
+ "input": [
+ "S",
+ "I"
+ ],
+ "output": [
+ "I",
+ "I"
+ ],
+ "properties": {
+ "name": "Infection",
+ "description": "Infective process between individuals"
+ }
+ },
+ {
+ "id": "rec",
+ "input": [
+ "I"
+ ],
+ "output": [
+ "R"
+ ],
+ "properties": {
+ "name": "Recovery",
+ "description": "Recovery process of a infected individual"
+ }
+ }
+ ]
+ }
+ """
+using JSON
+modeldict = JSON.parse(mjson)
+using ACSets.ADTs
+
+AMR.petrispec(modeldict) |> ACSets.ADTs.to_string |> println
+
+semantics_str = raw"""{
+ "ode": {
+ "rates": [
+ {
+ "target": "inf",
+ "expression": "S*I*beta",
+ "expression_mathml": "SIbeta"
+ },
+ {
+ "target": "rec",
+ "expression": "I*gamma",
+ "expression_mathml": "Igamma"
+ }
+ ],
+ "initials": [
+ {
+ "target": "S",
+ "expression": "S0",
+ "expression_mathml": "S0"
+ },
+ {
+ "target": "I",
+ "expression": "I0",
+ "expression_mathml": "I0"
+ },
+ {
+ "target": "R",
+ "expression": "R0",
+ "expression_mathml": "R0"
+ }
+ ],
+ "parameters": [
+ {
+ "id": "beta",
+ "name": "β",
+ "description": "infection rate",
+ "units": {
+ "expression": "1/(person*day)",
+ "expression_mathml": "1personday"
+ },
+ "value": 2.7e-7,
+ "distribution": {
+ "type": "StandardUniform1",
+ "parameters": {
+ "minimum": 2.6e-7,
+ "maximum": 2.8e-7
+ }
+ }
+ },
+ {
+ "id": "gamma",
+ "name": "γ",
+ "description": "recovery rate",
+ "grounding": {
+ "identifiers": {
+ "askemo": "0000013"
+ }
+ },
+ "units": {
+ "expression": "1/day",
+ "expression_mathml": "1day"
+ },
+ "value": 0.14,
+ "distribution": {
+ "type": "StandardUniform1",
+ "parameters": {
+ "minimum": 0.1,
+ "maximum": 0.18
+ }
+ }
+ },
+ {
+ "id": "S0",
+ "name": "S₀",
+ "description": "Total susceptible population at timestep 0",
+ "value": 1000
+ },
+ {
+ "id": "I0",
+ "name": "I₀",
+ "description": "Total infected population at timestep 0",
+ "value": 1
+ },
+ {
+ "id": "R0",
+ "name": "R₀",
+ "description": "Total recovered population at timestep 0",
+ "value": 0
+ }
+ ],
+ "observables": [
+ {
+ "id": "noninf",
+ "name": "Non-infectious",
+ "states": [
+ "S",
+ "R"
+ ],
+ "expression": "S+R",
+ "expression_mathml": "SR"
+ }
+ ],
+ "time": {
+ "id": "t",
+ "units": {
+ "expression": "day",
+ "expression_mathml": "day"
+ }
+ }
+ }
+}
+"""
+semantics_dict = JSON.parse(semantics_str)
+@show semantics_dict
+
+AMR.load(ODERecord, semantics_dict["ode"]) |> AMR.amr_to_string |> println
+
+sirmodel_dict = JSON.parsefile(joinpath([@__DIR__, "..", "..", "petrinet", "examples", "sir.json"]))
+AMR.optload(AMRExamples.sirmodel_dict, ["model", :states], nothing) |> show
+sirmodel = AMR.load(ASKEModel, sirmodel_dict)
+sirmodel |> AMR.amr_to_string |> println
+
+sirmodel_dict = JSON.parsefile(joinpath([@__DIR__, "..", "..", "petrinet", "examples", "sir_typed.json"]))
+semtyp = sirmodel_dict["semantics"]["typing"]
+
+sirmodel = AMR.load(Typing, semtyp) |> AMR.amr_to_string |> println
+
+sirmodel = AMR.load(ASKEModel, sirmodel_dict)
+sirmodel |> AMR.amr_to_string |> println
+
+# Deserializing from Human readable strings
+
+
+@testset "Loading Time" begin
+ @test AMR.load(AMR.Time, Base.Meta.parse("t::Time{}")) == AMR.Time(:t, AMR.Unit("", nomath))
+ @test AMR.load(AMR.Time, Base.Meta.parse("t::Time{day}")) == AMR.Time(:t, AMR.Unit("day", nomath))
+ @test AMR.load(AMR.Time, Base.Meta.parse("t::Time{day^2}")) == AMR.Time(:t, AMR.Unit("day ^ 2", nomath))
+ @test_throws ErrorException AMR.load(AMR.Time, Base.Meta.parse("t::time{}"))
+ @test_throws ErrorException AMR.load(AMR.Time, Base.Meta.parse("t::time"))
+end
+
+@testset "Loading Rates" begin
+ infspec = Meta.parse("inf::Rate = S*I*beta")
+ @test AMR.load(AMR.Rate, infspec).target == :inf
+ @test AMR.load(AMR.Rate, infspec).f.expression == "S * I * beta"
+ infspec = Meta.parse("inf::Rate{persons/time} = S*I*beta")
+ @test AMR.load(AMR.Rate, infspec).target == :inf
+ @test AMR.load(AMR.Rate, infspec).f.expression == "S * I * beta"
+end
+@testset "Loading Initials" begin
+ infspec = Meta.parse("S0::Initial = S*I*beta")
+ @test AMR.load(AMR.Initial, infspec).target == :S0
+ @test AMR.load(AMR.Initial, infspec).f.expression == "S * I * beta"
+ infspec = Meta.parse("S0::Initial{persons/time} = S*I*beta")
+ @test AMR.load(AMR.Initial, infspec).target == :S0
+ @test AMR.load(AMR.Initial, infspec).f.expression == "S * I * beta"
+end
+
+@testset "Loading Parameters" begin
+ @testset "No Units" begin
+ paramstr = raw"""
+ \"\"\"
+ R₀ -- Total recovered population at timestep 0
+ \"\"\"
+ R0::Parameter{} = 0.0 ~ δ(missing)
+ """
+ paramexp = Meta.parse(paramstr)
+ param = AMR.load(Parameter, paramexp)
+ @test param.units == AMR.nounit
+ @test param.id == :R0
+ end
+ @testset "Units" begin
+
+ paramstr = raw"""
+ \"\"\"
+ R₀ -- Total recovered population at timestep 0
+ \"\"\"
+ R0::Parameter{persons/day} = 0.0 ~ δ(missing)
+ """
+ paramexp = Meta.parse(paramstr)
+ param = AMR.load(Parameter, paramexp)
+ @test param.id == :R0
+ @test param.units == Unit("persons / day", AMR.nomath)
+ @test param.distribution == PointMass(:missing)
+
+ paramstr = raw"""
+ \"\"\"
+ R₀ -- Total recovered population at timestep 0
+ \"\"\"
+ R0::Parameter{persons/day} = 0.0 ~ δ(0.0)
+ """
+ paramexp = Meta.parse(paramstr)
+ param = AMR.load(Parameter, paramexp)
+ @test param.id == :R0
+ @test param.units == Unit("persons / day", AMR.nomath)
+ @test param.distribution == PointMass(0.0)
+ end
+end
+
+odelist_expr = Meta.parse(raw"""
+ODE_Record = begin
+
+inf::Rate = S*I*beta
+rec::Rate = I*gamma
+S::Initial = S0
+I::Initial = I0
+R::Initial = R0
+
+\"\"\" β -- infection rate \"\"\"
+beta::Parameter{} = 0.027 ~ U(0,1)
+
+
+\"\"\" γ -- recovery rate \"\"\"
+gamma::Parameter{} = 0.14 ~ U(0,1)
+
+
+\"\"\" S₀ -- Total susceptible population at timestep 0 \"\"\"
+S0::Parameter{} = 1000.0 ~ δ(missing)
+
+
+\"\"\" I₀ -- Total infected population at timestep 0\"\"\"
+I0::Parameter{} = 1.0 ~ δ(missing)
+
+
+\"\"\" R₀ -- Total recovered population at timestep 0\"\"\"
+R0::Parameter{} = 0.0 ~ δ(missing)
+
+t::Time{day}
+end
+""")
+
+ol = AMR.load(ODEList, odelist_expr)
+AMR.amr_to_string(ol) |> println
+
+
+header_expr = Meta.parse(raw"""
+\"\"\"
+ASKE Model Representation: SIR Model@v0.1 :: petrinet
+ https://raw.githubusercontent.com/DARPA-ASKEM/Model-Representations/petrinet_v0.5/petrinet/petrinet_schema.json
+
+Typed SIR model created by Nelson, derived from the one by Ben, Micah, Brandon
+\"\"\"
+""")
+
+AMR.load(Header, header_expr)
+
+modelrep = raw"""
+begin
+\"\"\"
+ASKE Model Representation: SIR Model@0.1 :: petrinet
+ https://raw.githubusercontent.com/DARPA-ASKEM/Model-Representations/petrinet_v0.5/petrinet/petrinet_schema.json
+
+Typed SIR model created by Nelson, derived from the one by Ben, Micah, Brandon
+\"\"\"
+Model = begin
+ AMRPetriNet = begin
+ S(id=S,name=Susceptible,units=nothing)
+ S(id=I,name=Infected,units=nothing)
+ S(id=R,name=Recovered,units=nothing)
+ T(id=inf,name=Infection,desc="Infective process between individuals")
+ T(id=rec,name=Recovery,desc="Recovery process of a infected individual")
+ I(is=S,it=inf)
+ I(is=I,it=inf)
+ I(is=I,it=rec)
+ O(os=I,ot=inf)
+ O(os=I,ot=inf)
+ O(os=R,ot=rec)
+ end
+end
+
+ODE_Record = begin
+
+inf::Rate = S*I*beta
+rec::Rate = I*gamma
+S::Initial = S0
+I::Initial = I0
+R::Initial = R0
+
+\"\"\" β -- infection rate \"\"\"
+beta::Parameter{} = 0.027 ~ U(0,1)
+
+
+\"\"\" γ -- recovery rate \"\"\"
+gamma::Parameter{} = 0.14 ~ U(0,1)
+
+
+\"\"\" S₀ -- Total susceptible population at timestep 0 \"\"\"
+S0::Parameter{} = 1000.0 ~ δ(missing)
+
+
+\"\"\" I₀ -- Total infected population at timestep 0\"\"\"
+I0::Parameter{} = 1.0 ~ δ(missing)
+
+
+\"\"\" R₀ -- Total recovered population at timestep 0\"\"\"
+R0::Parameter{} = 0.0 ~ δ(missing)
+
+t::Time{day}
+end
+
+Typing = begin
+ Model = begin
+ AMRPetriNet = begin
+ S(id=Pop,name=Pop,units=nothing)
+ S(id=Vaccine,name=Vaccine,units=nothing)
+ T(id=Infect,name=Infect,desc="2-to-2 process that represents infectious contact between two human individuals.")
+ T(id=Disease,name=Disease,desc="1-to-1 process that represents a change in th edisease status of a human individual.")
+ T(id=Strata,name=Strata,desc="1-to-1 process that represents a change in the demographic division of a human individual.")
+ T(id=Vaccinate,name=Vaccinate,desc="2-to-1 process that represents an human individual receiving a vaccine dose.")
+ T(id=Produce_Vaccine,name="Produce Vaccine",desc="0-to-1 process that represents the production of a single vaccine dose.")
+ I(is=Pop,it=Infect)
+ I(is=Pop,it=Infect)
+ I(is=Pop,it=Disease)
+ I(is=Pop,it=Strata)
+ I(is=Pop,it=Vaccinate)
+ I(is=Vaccine,it=Vaccinate)
+ O(os=Pop,ot=Infect)
+ O(os=Pop,ot=Infect)
+ O(os=Pop,ot=Disease)
+ O(os=Pop,ot=Strata)
+ O(os=Pop,ot=Vaccinate)
+ O(os=Vaccine,ot=Produce_Vaccine)
+ end
+ end
+ TypeMap = [
+ S => Pop,
+ I => Pop,
+ R => Pop,
+ inf => Infect,
+ rec => Disease,]
+end
+end
+"""
+println(modelrep)
+model_expr = Base.Meta.parse(modelrep)
+@test AMR.load(ASKEModel, model_expr).header isa Header
+@test AMR.load(ASKEModel, model_expr).model isa ACSetSpec
+@test length(AMR.load(ODEList, model_expr.args[4]).statements) == 8
+@test length(AMR.load(ASKEModel, model_expr).semantics[1].statements) == 8
+@test AMR.load(Typing, model_expr.args[6]).system isa ACSetSpec
+@test AMR.load(Typing, model_expr.args[6]).map isa Vector{Pair}
+println(AMR.amr_to_string(AMR.load(ASKEModel, model_expr)))
+@test_skip (AMR.amr_to_string(AMR.load(ASKEModel, model_expr))) == modelrep
+
+end