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.
Two arithmetically-identical diffs that should reduce to 0 under
expand = truedon't:In each case one arm lands in a literal
complex(0, Δ)symbolic Term andthe other in a
(0 + 1im)numeric coefficient. They never combine.Reproduces in plain SymbolicUtils, no Symbolics needed:
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/conjfast paths(SymbolicUtils/src/methods.jl:484, 493, 503), but
to_poly!inpolyform.jlhas no case forf === complex, so underexpandthenode ends up as an opaque
PolyVarand the simplifier never sees theimaginary part.