Skip to content

simplify(...; expand=true) doesn't reduce diffs with literal complex(re, im) Terms #921

@oameye

Description

@oameye

Two arithmetically-identical diffs that should reduce to 0 under
expand = true don't:

using Symbolics
@variables Δ::Real z::Number

simplify(1im * Δ * z - z * Δ * 1im; expand = true)
# z*complex(0, Δ) + (0 - 1im)*z*Δ

simplify(2im * Δ * z - 2 * (1im * Δ * z); expand = true)
# z*complex(0, 2Δ) - 2z*complex(0, Δ)

In each case one arm lands in a literal complex(0, Δ) symbolic Term and
the other in a (0 + 1im) numeric coefficient. They never combine.

Reproduces in plain SymbolicUtils, no Symbolics needed:

using SymbolicUtils
@syms x::Real
c = Term{SymReal}(complex,
                  [Term{SymReal}(zero, [x]; type = Real), x];
                  type = Complex{Real})
simplify(c - 1im * x; expand = true)
# complex(zero(x), x) - 1im*x

As far as I can tell: Symbolics.unwrap(::Complex{Num})
(Symbolics/src/complex.jl, around line 21) produces a literal
Term(complex, [re, im]) whenever the components are symbolic.
SymbolicUtils pattern-matches that form for the O(1)
real(complex(re, im)) / imag / conj fast paths
(SymbolicUtils/src/methods.jl:484, 493, 503), but to_poly! in
polyform.jl has no case for f === complex, so under expand the
node ends up as an opaque PolyVar and the simplifier never sees the
imaginary part.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions