Skip to content

Commit

Permalink
added tests. some modifications were made to tests to allow for new p…
Browse files Browse the repository at this point in the history
…arsing syntax, most significantly the deprecation of Tan for Partial
  • Loading branch information
quffaro committed May 4, 2024
1 parent 170bb5a commit f1d5669
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 63 deletions.
9 changes: 8 additions & 1 deletion src/DiagrammaticEquations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,14 @@ import Unicode
normalize_unicode(s::String) = Unicode.normalize(s, compose=true, stable=true, chartransform=Unicode.julia_chartransform)
normalize_unicode(s::Symbol) = Symbol(normalize_unicode(String(s)))
DerivOp = Symbol("∂ₜ")
append_dot(s::Symbol) = Symbol(string(s)*'\U0307')
# append_dot(s::Symbol) = Symbol(string(s)*'\U0307')
append_dot(s::Symbol) = Symbol(string(s)*'\U0209C')
append_dot(s::Symbol, wrt::Symbol) =
@match wrt begin
:t => Symbol(string(s)*'\U0209C')
:x => Symbol(string(s)*'\U02093')
_ => s
end

include("acset.jl")
include("language.jl")
Expand Down
2 changes: 1 addition & 1 deletion src/colanguage.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function Term(s::SummationDecapode)
y = Var(s[op, [:tgt, :name]])
f = s[op, :op1]
if f == :∂ₜ
Eq(y, Tan(x))
Eq(y, Partial(x, :t, 1))
elseif typeof(f) == Vector{Symbol}
Eq(y, AppCirc1(f, x))
else
Expand Down
2 changes: 1 addition & 1 deletion src/decapodes.it
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
Plus(args::Vector{Term})
Mult(args::Vector{Term})
Tan(var::Term)
Partial(var::Term, wrt::Symbol, order::Int64, iteration::Int64)
Partial(var::Term, wrt::Symbol, order::Int64)
end

struct Judgement
Expand Down
77 changes: 34 additions & 43 deletions src/language.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ term(s::Number) = Lit(Symbol(s))
term(expr::Expr) = begin
@match expr begin
#TODO: Would we want ∂ₜ to be used with general expressions or just Vars?
Expr(:call, :∂ₜ, b) => Tan(Var(b))
Expr(:call, :dt, b) => Tan(Var(b))
Expr(:call, ∂, b) && if ishigherorderpartial(∂) end => Partial(term(b), ∂s[∂]..., 0)
Expr(:call, :∂ₜ, b) => Partial(term(b), :t, 1)
Expr(:call, :dt, b) => Partial(term(b), :t, 1)
# Tan(Var(b))
Expr(:call, ∂, b) && if ishigherorderpartial(∂) end => Partial(term(b), ∂s[∂]...)

Expr(:call, Expr(:call, :, a...), b) => AppCirc1(a, term(b))
Expr(:call, a, b) => App1(a, term(b))
Expand All @@ -33,10 +34,8 @@ ishigherorderpartial(t::Expr) = @match t begin
end

∂s = Dict(:∂ₜ¹ => (:t, 1), :∂ₜ² => (:t, 2), :∂ₜ³ => (:t, 3), :∂ₜ⁴ => (:t, 4), :∂ₜ⁵ => (:t, 5))
ps = Dict(1 => :∂ₜ, 2 => :∂ₜ², 3 => :∂ₜ³)

function parse_decapode(expr::Expr)
# XXX how does flatmap affect maps in this match expression?
stmts = map(expr.args) do line
@match line begin
::LineNumberNode => missing
Expand Down Expand Up @@ -96,63 +95,55 @@ function reduce_term_plus!(ts::Vector{Term}, d::AbstractDecapode, syms::Dict{Sym
return res_var
end

const MULT_SYM = Symbol("*")

# TODO: res=res_var undefined
# TODO this can probably be a fold
function reduce_term_mult!(ts::Vector{Term}, d::AbstractDecapode, syms::Dict{Symbol, Int})
multiplicands = [reduce_term!(t,d,syms) for t in ts]
res_var = add_part!(d, :Var, type=:infer, name=:mult)
m1,m2 = multiplicands[1:2]
add_part!(d, :Op2, proj1=m1, proj2=m2, res=res_var, op2=Symbol("*"))
for m in multiplicands[3:end]
m1 = res_var
m2 = m
res_var = add_part!(d, :Var, type=:infer, name=:mult)
add_part!(d, :Op2, proj1=m1, proj2=m2, res=res_var, op2=Symbol("*"))
end
return res_var
# multiplicands = [reduce_term!.(ts, Ref(d), Ref(syms))]
# out = foldl(((m1, m2) -> add_part!(d, :Op2, proj1=m1, proj2=m2, res=m1, op2=MULT_SYM))
# ,multiplicands, add_part!(d, :Var, type=:infer, name=:mult))
# @info "MULT" out
# out
multiplicands = [reduce_term!(t,d,syms) for t in ts]
res_var = add_part!(d, :Var, type=:infer, name=:mult)
m1, m2 = multiplicands[1:2]
add_part!(d, :Op2, proj1=m1, proj2=m2, res=res_var, op2=Symbol("*"))
for m in multiplicands[3:end]
m1 = res_var
m2 = m
res_var = add_part!(d, :Var, type=:infer, name=:mult)
add_part!(d, :Op2, proj1=m1, proj2=m2, res=res_var, op2=Symbol("*"))
end
return res_var
end

append_doot(s) = Symbol(string(s)*"_1")

# TODO do we want to 1) continue using DerivOp and 2) create a spurious var. with same name?
# TODO change TVar table
function reduce_term_tan!(t::Term, d::AbstractDecapode, syms::Dict{Symbol, Int})
txv = add_part!(d, :Var, type=:infer, name=append_doot(t.name))
tx = add_part!(d, :TVar, incl=txv) # cache tvars in a list
src = incident(d, t.name, :name)[1]
tanop = add_part!(d, :Op1, src=src, tgt=txv, op1=DerivOp)
txv = add_part!(d, :Var, type=:infer, name=append_dot(t.name))
tx = add_part!(d, :TVar, incl=txv)
tanop = add_part!(d, :Op1, src=reduce_term!(t, d, syms), tgt=txv, op1=DerivOp)
return txv
end

function _reduce_term_partial!(t::Term, d::AbstractDecapode, syms::Dict{Symbol, Int})
txv = reduce_term_tan!(t.var, d, syms)
reduce_term!(Partial(Var(d[txv,:name]), t.wrt, t.order-1, t.iteration+1), d, syms)
function reduce_term_partial!(t::Term, d::AbstractDecapode, syms::Dict{Symbol, Int})
src = reduce_term!(Partial(t.var, t.wrt, t.order - 1), d, syms)
txv = add_part!(d, :Var, type=:infer, name=append_dot(d[src,:name]))
tx = add_part!(d, :TVar, incl=txv)
tanop = add_part!(d, :Op1, src=src, tgt=txv, op1=DerivOp)
return txv
end

# TODO george said something about this
function reduce_term_partial!(t::Term, d::AbstractDecapode, syms::Dict{Symbol, Int})
txv = reduce_term!(Partial(t.var, t.wrt, t.order - 1, 0), d, syms)
txv = reduce_term_tan!(Var(d[txv,:name]), d, syms)
return txv
function throw_reduce_error(t::Term)
@match t begin
Partial(expr, _, _) => throw("Partial time derivatives of this expression '$expr' is not yet supported")
_ => throw("Inline judgements are not supported")
end
end

function reduce_term!(t::Term, d::AbstractDecapode, syms::Dict{Symbol, Int})
@match t begin
Var(x) => reduce_term_var!(x, d, syms)
Var(x) || Partial(Var(x), wrt, 0) => reduce_term_var!(x, d, syms)
Lit(x) => reduce_term_lit!(x, d, syms)
App1(f, t) || AppCirc1(f, t) => reduce_term_app1circ!(f, t, d, syms)
App2(f, t1, t2) => reduce_term_app2!(f, t1, t2, d, syms)
Plus(ts) => reduce_term_plus!(ts, d, syms)
Mult(ts) => reduce_term_mult!(ts, d, syms)
Tan(t) || Partial(t, wrt, 1, k) => reduce_term_tan!(t, d, syms)
Partial(u, wrt, n, k) => reduce_term_partial!(t, d, syms)
_ => throw("Inline type Judgements not yet supported!")
Tan(t) => reduce_term_tan!(t, d, syms)
Partial(Var(x), wrt, n) => reduce_term_partial!(t, d, syms)
e => throw_reduce_error(e)
end
end

Expand Down
1 change: 1 addition & 0 deletions src/pretty.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pprint(io::IO, exp::Term, pad=0) = begin
Plus(args) => print(io, "$(join(map(!, args), " + "))")
Mult(args) => print(io, "($(join(map(!, args), " * "))")
Tan(var) => print(io, "∂ₜ($(!var))")
Partial(var, wrt, order) => print(io, "∂ₜ($(!var))")
_ => error("printing $exp")
end
end
Expand Down
4 changes: 2 additions & 2 deletions test/collages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ end

DiffusionSymbols = Dict(
:C => :K,
:Ċ => :,
:Ċ => :Kₜ,
:Cb1 => :Kb1,
:Cb2 => :Kb2,
:Zero => :Null)
Expand All @@ -54,7 +54,7 @@ DiffusionCollage = DiagrammaticEquations.collate(
op1 = Any[:∂ₜ, [:d, :, :d, :]]
op2 = [:rb1_leftwall, :rb2_rightwall, :rb3]
type = [:Form0, :infer, :Form0, :Form0, :Form0, :Form0, :infer, :Form0]
name = [:r1_K, :r3_K̇, :r2_K, :Kb1, :K, :Kb2, :, :Null]
name = [:r1_K, :r3_Kₜ, :r2_K, :Kb1, :K, :Kb2, :Kₜ, :Null]
end

# Note: Since the order does not matter in which rb1 and rb2 are applied, it
Expand Down
127 changes: 114 additions & 13 deletions test/language.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,57 @@ using DiagrammaticEquations

@testset "Parsing" begin

# does
_3pt = @decapode begin
U::Form0
#
∂ₜ³(U) == ∂ₜ³U
end
@test _3pt[:name] == [:U, :Uₜ, :Uₜₜ, :∂ₜ³U]
@test _3pt[:incl] == [2, 3, 4]
@test _3pt[:src] == [1, 2, 3]
@test _3pt[:tgt] == [2, 3, 4]

_3pt_k = @decapode begin
U::Form0
k::Constant
#
∂ₜ³(U) == k*U
end
@test _3pt_k[:name] == [:U, :k, :Uₜ, :Uₜₜ, :Uₜₜₜ]
@test _3pt_k[:incl] == [3, 4, 5]
@test _3pt_k[:src] == [1, 3, 4]
@test _3pt_k[:tgt] == [3, 4, 5]
@test _3pt_k[:proj1] == [2]
@test _3pt_k[:proj2] == [1]
@test _3pt_k[:res] == [5]

_ab = @decapode begin
(A,B)::Form0
#
A == dt(B)
end
@test _ab[:name] == [:A, :B]
@test _ab[:incl] == [1]
@test _ab[:src] == [2]
@test _ab[:tgt] == [1]

_abΣ = @decapode begin
(A,B,C)::Form0
#
A == dt(B)
C == A + B
end

@test _abΣ[:name] == [:A, :B, :C]
@test _abΣ[:incl] == [1]
@test _abΣ[:src] == [2]
@test _abΣ[:tgt] == [1]
@test _abΣ[:summand] == [1, 2]
@test _abΣ[:summation] == [1, 1]



# @present DiffusionSpace2D(FreeExtCalc2D) begin
# X::Space
# k::Hom(Form1(X), Form1(X)) # diffusivity of space, usually constant (scalar multiplication)
Expand Down Expand Up @@ -151,7 +202,7 @@ using DiagrammaticEquations
end
diffExpr7 = parse_decapode(DiffusionExprBody7)
ddp7 = SummationDecapode(diffExpr7)
@test ddp7[:name] == [, :, Symbol("2"), Symbol("2"), :C]
@test ddp7[:name] == [, :Cₜ, Symbol("2"), Symbol("1"), :C]
@test ddp7[:incl] == [2]

# Vars can only be of certain types.
Expand Down Expand Up @@ -192,13 +243,13 @@ using DiagrammaticEquations
E == ∂ₜ(D)
end
pt3 = SummationDecapode(parse_decapode(ParseTest3))
@test pt3[:name] == [:D, :E, :C]
@test pt3[:incl] == [1,2]
@test pt3[:src] == [3, 1]
@test pt3[:tgt] == [1, 2]
@test pt3[:name] == [:D, :C, :E]
@test pt3[:incl] == [1, 3]
@test pt3[:src] == [2, 1]
@test pt3[:tgt] == [1, 3]

dot_rename!(pt3)
@test pt3[:name] == [Symbol('C'*'\U0307'), Symbol('C'*'\U0307'*'\U0307'), :C]
@test pt3[:name] == [Symbol('C'*'\U0209C'), :C, Symbol('C'*'\U0209C'*'\U0209C')]

# TODO: We should eventually recognize this equivalence
#= ParseTest4 = quote
Expand All @@ -218,9 +269,9 @@ using DiagrammaticEquations
∂ₜ(V) == -1*k*(X)
end))

@test pt5[:name] == [:X, :V, :k, :mult_1, Symbol('V'*'\U0307'), Symbol("-1")]
@test pt5[:name] == [:X, :V, :k, :mult_1, Symbol('V'*'\U0209C'), Symbol("-1")]
dot_rename!(pt5)
@test pt5[:name] == [:X, Symbol('X'*'\U0307'), :k, :mult_1, Symbol('X'*'\U0307'*'\U0307'), Symbol("-1")]
@test pt5[:name] == [:X, Symbol('X'*'\U0209C'), :k, :mult_1, Symbol('X'*'\U0209C'*'\U0209C'), Symbol("-1")]

end
Deca = quote
Expand All @@ -237,7 +288,7 @@ end
# @test term(:(∘(k, d₀)(C))) == AppCirc1([:k, :d₀], Var(:C)) #(:App1, ((:Circ, :k, :d₀), Var(:C)))
# @test term(:(∘(k, d₀{X})(C))) == (:App1, ((:Circ, :k, :(d₀{X})), Var(:C)))
@test_throws MethodError term(:(Ċ == (₀⁻¹{X}, dual_d₁{X}, ₁{X})(ϕ)))
@test term(:(∂ₜ(C))) == Tan(Var(:C))
@test term(:(∂ₜ(C))) == Partial(Var(:C), :t, 1)
# @test term(:(∂ₜ{Form0}(C))) == App1(:Tan, Var(:C))
end

Expand Down Expand Up @@ -870,7 +921,57 @@ end
names_types_hx = zip(HeatXfer[:name], HeatXfer[:type])

names_types_expected_hx = [
(:T, :Form0), (:continuity_Ṫ₁, :Form0), (:continuity_diffusion_ϕ, :DualForm1), (:continuity_diffusion_k, :Parameter), (Symbol("continuity_diffusion_•1"), :DualForm2), (Symbol("continuity_diffusion_•2"), :Form1), (Symbol("continuity_diffusion_•3"), :Form1), (:M, :Form1), (:continuity_advection_V, :Form1), (:ρ, :Form0), (:P, :Form0), (:continuity_Ṫₐ, :Form0), (Symbol("continuity_advection_•1"), :Form0), (Symbol("continuity_advection_•2"), :Form1), (Symbol("continuity_advection_•3"), :DualForm2), (Symbol("continuity_advection_•4"), :Form0), (Symbol("continuity_advection_•5"), :DualForm2), (:continuity_Ṫ, :Form0), (:navierstokes_Ṁ, :Form1), (:navierstokes_G, :Form1), (:navierstokes_V, :Form1), (:navierstokes_ṗ, :Form0), (:navierstokes_two, :Parameter), (:navierstokes_three, :Parameter), (:navierstokes_kᵥ, :Parameter), (Symbol("navierstokes_•1"), :DualForm2), (Symbol("navierstokes_•2"), :Form1), (Symbol("navierstokes_•3"), :Form1), (Symbol("navierstokes_•4"), :DualForm1), (Symbol("navierstokes_•5"), :DualForm1), (Symbol("navierstokes_•6"), :DualForm1), (Symbol("navierstokes_•7"), :Form1), (Symbol("navierstokes_•8"), :Form1), (Symbol("navierstokes_•9"), :Form1), (Symbol("navierstokes_•10"), :Form1), (Symbol("navierstokes_•11"), :Form1), (:navierstokes_sum_1, :Form1), (Symbol("navierstokes_•12"), :Form0), (Symbol("navierstokes_•13"), :Form1), (Symbol("navierstokes_•14"), :Form1), (Symbol("navierstokes_•15"), :Form0), (Symbol("navierstokes_•16"), :DualForm0), (Symbol("navierstokes_•17"), :DualForm1), (Symbol("navierstokes_•18"), :Form1), (Symbol("navierstokes_•19"), :Form1), (Symbol("navierstokes_•20"), :Form1), (:navierstokes_sum_2, :Form0), (Symbol("navierstokes_•21"), :Form1), (Symbol("navierstokes_•22"), :Form1), (Symbol("navierstokes_•23"), :DualForm2)]
(:T, :Form0),
(:continuity_Ṫ₁, :Form0),
(:continuity_diffusion_ϕ, :DualForm1),
(:continuity_diffusion_k, :Parameter),
(Symbol("continuity_diffusion_•1"), :DualForm2),
(Symbol("continuity_diffusion_•2"), :Form1),
(Symbol("continuity_diffusion_•3"), :Form1),
(:M, :Form1),
(:continuity_advection_V, :Form1),
(, :Form0),
(:P, :Form0),
(:continuity_Ṫₐ, :Form0),
(Symbol("continuity_advection_•1"), :Form0),
(Symbol("continuity_advection_•2"), :Form1),
(Symbol("continuity_advection_•3"), :DualForm2),
(Symbol("continuity_advection_•4"), :Form0),
(Symbol("continuity_advection_•5"), :DualForm2),
(:continuity_Ṫ, :Form0),
(:navierstokes_Ṁ, :Form1),
(:navierstokes_G, :Form1),
(:navierstokes_V, :Form1),
(:navierstokes_ṗ, :Form0),
(:navierstokes_two, :Parameter),
(:navierstokes_three, :Parameter),
(:navierstokes_kᵥ, :Parameter),
(Symbol("navierstokes_•1"), :DualForm2),
(Symbol("navierstokes_•2"), :Form1),
(Symbol("navierstokes_•3"), :Form1),
(Symbol("navierstokes_•4"), :DualForm1),
(Symbol("navierstokes_•5"), :DualForm1),
(Symbol("navierstokes_•6"), :DualForm1),
(Symbol("navierstokes_•7"), :Form1),
(Symbol("navierstokes_•8"), :Form1),
(Symbol("navierstokes_•9"), :Form1),
(Symbol("navierstokes_•10"), :Form1),
(Symbol("navierstokes_•11"), :Form1),
(:navierstokes_sum_1, :Form1),
(Symbol("navierstokes_•12"), :Form0),
(Symbol("navierstokes_•13"), :Form1),
(Symbol("navierstokes_•14"), :Form1),
(Symbol("navierstokes_•15"), :Form0),
(Symbol("navierstokes_•16"), :DualForm0),
(Symbol("navierstokes_•17"), :DualForm1),
(Symbol("navierstokes_•18"), :Form1),
(Symbol("navierstokes_•19"), :Form1),
(Symbol("navierstokes_•20"), :Form1),
(:navierstokes_sum_2, :Form0),
(Symbol("navierstokes_•21"), :Form1),
(Symbol("navierstokes_•22"), :Form1),
(Symbol("navierstokes_sum_2"), :Form0),
(Symbol("navierstokes_Mₜ"), :DualForm2)]

@test issetequal(names_types_hx, names_types_expected_hx)

Expand Down Expand Up @@ -1077,7 +1178,7 @@ end

∂ₜ(B) == (d₁(E))
end))
Veronis_rec_del = recursive_delete_parents(Veronis, incident(Veronis, :, :name))
Veronis_rec_del = recursive_delete_parents(Veronis, incident(Veronis, :Bₜ, :name))
@test Veronis_rec_del == SummationDecapode(parse_decapode(quote
B::DualForm0{X}
E::Form1{X}
Expand All @@ -1100,7 +1201,7 @@ end

∂ₜ(B) == (d₁(E))
end))
Veronis_rec_del = recursive_delete_parents(Veronis, incident(Veronis, :Ė, :name))
Veronis_rec_del = recursive_delete_parents(Veronis, incident(Veronis, :Eₜ, :name))
# We should test if Decapodes are isomorphic, but Catlab
# doesn't do this yet.
#@test Veronis_rec_del == SummationDecapode(parse_decapode(quote
Expand All @@ -1115,7 +1216,7 @@ end
Op1 = 3

type = [:DualForm0, :Form1, :infer, :infer]
name = [:B, :E, :sum_1, :]
name = [:B, :E, :sum_1, :Bₜ]

incl = [4]

Expand Down
5 changes: 3 additions & 2 deletions test/pretty.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ using DiagrammaticEquations
using DiagrammaticEquations.decapodes

@testset "Pretty Printing" begin

mdl = parse_decapode(quote
(Q, Tₛ, ASR, OLR, HT)::Form0
(α, A,B,C)::Constant
(D,cosϕᵖ,cosϕᵈ)::Constant

#
Tₛ̇ == ∂ₜ(Tₛ)
Tₛ̇ == (ASR - OLR + HT) / C
ASR == (1 - α) * Q
OLR == A + (B * Tₛ)

#
HT == (D ./ cosϕᵖ) * (d(cosϕᵈ * (d(Tₛ))))
end)
output = "Context:\n Q::Form0 over I\n Tₛ::Form0 over I\n ASR::Form0 over I\n OLR::Form0 over I\n HT::Form0 over I\n α::Constant over I\n A::Constant over I\n B::Constant over I\n C::Constant over I\n D::Constant over I\n cosϕᵖ::Constant over I\n cosϕᵈ::Constant over I\nEquations:\nTₛ̇ = ∂ₜ(Tₛ)\nTₛ̇ = ASR - OLR + HT / C\nASR = 1 - α * Q\nOLR = A + B * Tₛ\nHT = D ./ cosϕᵖ * ⋆(d(cosϕᵈ * ⋆(d(Tₛ))))\n"
Expand Down

0 comments on commit f1d5669

Please sign in to comment.