-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
@symbolic_models replicates most of the functionality of @syntax
- Loading branch information
Showing
7 changed files
with
566 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
""" Rewriting for GAT expressions. | ||
The current content of this module exists purely for backwards compatibility | ||
with the existing rewriting in Catlab; the more advanced implementation uses | ||
e-graphs and works with AlgTerms instead of GATExprs. | ||
""" | ||
module GATExprUtils | ||
export associate, associate_unit_inv, associate_unit, | ||
distribute_unary, involute, normalize_zero | ||
|
||
using ..SymbolicModels | ||
|
||
#Warning: assumes expr has only two args! | ||
""" Simplify associative binary operation. | ||
Maintains the normal form `op(e1,e2,...)` where `e1`,`e2`,... are expressions | ||
that are *not* applications of `op()` | ||
""" | ||
function associate(expr::E)::E where E <: GATExpr | ||
op, e1, e2 = head(expr), first(expr), last(expr) | ||
args1 = head(e1) == op ? args(e1) : [e1] | ||
args2 = head(e2) == op ? args(e2) : [e2] | ||
E([args1; args2], gat_type_args(expr)) | ||
end | ||
|
||
""" Simplify associative binary operation with unit. | ||
Reduces a freely generated (typed) monoid to normal form. | ||
""" | ||
function associate_unit(expr::GATExpr, unit::Function)::GATExpr | ||
e1, e2 = first(expr), last(expr) | ||
if (head(e1) == nameof(unit)) e2 | ||
elseif (head(e2) == nameof(unit)) e1 | ||
else associate(expr) end | ||
end | ||
|
||
""" Simplify associative binary operation with unit and inverses. | ||
""" | ||
function associate_unit_inv(expr::E, unit::Function, | ||
inverse::Function)::GATExpr where E <: GATExpr | ||
op, e1, e2 = head(expr), first(expr), last(expr) | ||
if (head(e1) == nameof(unit)) e2 | ||
elseif (head(e2) == nameof(unit)) e1 | ||
else | ||
args1 = head(e1) == op ? args(e1) : [e1] | ||
args2 = head(e2) == op ? args(e2) : [e2] | ||
while !isempty(args1) && !isempty(args2) | ||
l = args1[end]; r = args2[1] | ||
if (head(l) == nameof(inverse) && first(l) == r || | ||
head(r) == nameof(inverse) && l == first(r)) | ||
pop!(args1); popfirst!(args2) | ||
else break end | ||
end | ||
newargs = [args1; args2] | ||
# XXX: Assumes that the unit/identity takes exactly one argument, hence this | ||
# function will not work for the algebraic theory of groups. | ||
if (isempty(newargs)) unit(only(unique(gat_type_args(expr)))) | ||
elseif (length(newargs) == 1) only(newargs) | ||
else E(newargs, gat_type_args(expr)) end | ||
end | ||
end | ||
|
||
""" Distribute unary operation over binary operation. | ||
""" | ||
function distribute_unary(expr::GATExpr, unary::Function, binary::Function; | ||
unit::Union{Function,Nothing}=nothing, | ||
contravariant::Bool=false)::GATExpr | ||
if (head(expr) != nameof(unary)) return expr end | ||
@assert length(args(expr)) == 1 | ||
arg = first(expr) | ||
if head(arg) == nameof(binary) | ||
binary(map(unary, (contravariant ? reverse : identity)(args(arg)))) | ||
elseif !isnothing(unit) && head(arg) == nameof(unit) | ||
arg | ||
else | ||
expr | ||
end | ||
end | ||
|
||
""" Simplify involutive unary operation. | ||
""" | ||
function involute(expr::GATExpr) | ||
@assert length(args(expr)) == 1 | ||
arg = first(expr) | ||
head(expr) == head(arg) ? first(arg) : expr | ||
end | ||
""" | ||
If given GATExpr contains a zero morphism, | ||
collapse the expression to a single zero morphism. | ||
""" | ||
function normalize_zero(expr::E;zname=:zeromap) where E <: GATExpr | ||
ztype = E | ||
for subexpr in args(expr) | ||
if head(subexpr) == zname | ||
ztype = typeof(subexpr) | ||
s,t = gat_type_args(expr) | ||
return ztype([s,t],[s,t]) | ||
end end | ||
expr | ||
end | ||
end |
Oops, something went wrong.