Symbolics.jl expressions that don't reduce to single type


I’m trying to use Symbolics.jl to simplify some expressions in the domain of quantum mechanics. The problem I’m facing is that I would like to simplify a partial expression that does not exactly reduce to a single type.

For example

using Symbolics
using SymbolicUtils

abstract type MyType end

@syms a::MyType b::Number
@acrule(*(~~a) + *(~b, ~~a) => *(1 + ~b, (~~a)...))

simplify(a + a*b)

brings up MethodError: no method matching *(::SymbolicUtils.BasicSymbolic{Number}, ::SymbolicUtils.BasicSymbolic{MyType}).

How could I simplify the expression as far as it can using the rules, even if all operations are not defined?

You’ll need to define a custom rule set and pass that into simplify.

Okay, thanks.

I’m not super familiar with the syntax but I can’t seem to even apply single rule to my expression, or am I missing something here?

using Symbolics
using SymbolicUtils

abstract type MyType end

@syms a::MyType b::Number
rule = @acrule(*(~~a) + *(~b, ~~a) => *(1 + ~b, (~~a)...))

rule(a + b*a)

brings up the same error as before.

The issue is not with the rules so far, it’s with a*b

We only define the arithmetic methods for Symbolic{<:Number}, that’s why * is not defined for Symbolic{MyType}.

It should work if you make MyType a subtype of Number. It will have the default behavior that is suitable for numbers, you can of course overload specific methods if they behave differently.

As for applying the rules, you can use the Rewriters to compose the rules into something that does what you want (e.g. traverse the tree and apply the rule to each node, etc.) The docs for this are here SymbolicUtils.jl


Thanks for the insightful response, but the problem is that making MyType a subtype of Number makes it behave like a number (commute in multiplication etc.) which is the behaviour I want to avoid by making my own type.

By this I meant that you might have to define your own * method on Symbolic{MyType} objects.

1 Like