-
-
Notifications
You must be signed in to change notification settings - Fork 232
Description
I've been trying to make the symbolic simplifier (currenlty simply_constants) worth using.
I attempted to write a type (that itself behaves like an Expression
) that simplifies linear combinations of Expression
s. It turns out that Rewrite does it very similarly. I think there's value in using Rewrite instead to do it: it will not only work for LinearCombination type of terms, but a lot of other cases as well.
My assessment has lead me to make this plan that I'm willing to implement. Note that many of these features existed in Simplify.jl, but weren't using Rewrite.jl to implement them. @HarrisonGrodin probably intended to do these same things:
I'm going to use the word Term
below to mean ModelingToolkit.Expression
and/or Rewrite.AbstractTerm
. I think they should all be represented with the same type, which is a detail I intend to take care of.
- Make Variables maintain their domain: this is at least a type such as
Number
or anAbstractArray{Number}
, this can be tedious to define, so I propose all@variable
defs areNumbers
by default, but we can optionally allow users to specify other domains. I say at least a type because it might well be SpecialSets of values - Make Variables also maintain a list of properties. This is extra information useful for transformations such as
Square
,Hermitian
,Orthonormal
.
So the@variables
syntax could be:
@variables x y z[1:10]
(behaves as it does now, but also designates each variable as aNumber
).@variables type=AbstractMatrix{<:Number} A B C[1:10]
@variables type=AbstractMatrix{<:Number} props=[Orthonormal] Q[1:10]
Defines 10 orthonormal matrix variables. One might even make this simpler by assuming:@variables props=[Orthonormal] Q[1:10]
means Q is a AbstractMatrix of numbers by default.
- For every
f
we care about (e.g. nice mathematical functions) define
f(a::Term, b::Term) = term(termtype(f, a, b), f, a, b; props=promote_props(f,a,b))
(and the methods that work with generica
s andb
s.).
termtype(f, a, b)
allows us to decide what kind of rules apply when simplifyingf(a,b)
for example,termtype(*, a, b)
would returnACTerm()
if the domain ofa
andb
are numbers, but will generally returnATerm()
(btw @HarrisonGrodin ATerm doesn't yet exist?). By default it returnsFreeTerm()
so we only need to define this on+
and*
to get an amazing simplifier in comparison to the status quo.promote_props(f,a,b)
: Defines properties of the resultant term. E.g.Q1 + Q2
is hermitian if Q1 and Q2 are too (note that the props stuff is optional at all times.)
- Rule definition enhancements: I would like to propose an extended syntax for better flexibility than what Rewrite currently provides:
@rules RuleSet begin
:x + :z => iszero(z) => x
:A * :A' => hasprop(A, Orthonormal) => I
end
I am asking that it be allowed to 1) distinguish between exact matches e.g. the symbols +
and *
, and '
in the examples, v.s. variable matches e.g. :A ``:x
and :z
, 2) an additional custom predicate initial match pattern in the rule definition syntax. We can compile this to maximally efficient functions much like Rewrite does right now.
This is going to be the first, surface level phase of simplifier. Another level of simplification would involve writing expressions as polynomials of made up variables (for terms that cannot be simplified) and then performing polynomial GCD to coerce it into various useful forms: (e.g. reduce number of flops). That's a problem for another day.
cc @YingboMa @MasonProtter @HarrisonGrodin @dpsanders @ChrisRackauckas