Skip to content

Simplification plan #230

@shashi

Description

@shashi

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 Expressions. 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.

  1. Make Variables maintain their domain: this is at least a type such as Number or an AbstractArray{Number}, this can be tedious to define, so I propose all @variable defs are Numbers 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
  2. 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 a Number).
  • @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.
  1. 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 generic as and bs.).
  • termtype(f, a, b) allows us to decide what kind of rules apply when simplifying f(a,b) for example, termtype(*, a, b) would return ACTerm() if the domain of a and b are numbers, but will generally return ATerm() (btw @HarrisonGrodin ATerm doesn't yet exist?). By default it returns FreeTerm() 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.)
  1. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions