# How to find arbitrary complex constants in symbolic expressions?

How do I go about finding terms in a symbolic expression containing arbitrary complex constants? I had hoped that the code fragment below would yield something like [2Ix], [Ix], [I], and [2I]. However, instead it yields [], [I*x], [], and []. Is there another way to isolate the terms containing an arbitrary complex constant?

w0 = SR.wild(0)

f = x^2 + 2*I*x + 1
g = x^2 + I*x + 1
h = x^2 + 2*x + I
k = x^2 + x + 2*I

print(f.find(I*w0))
print(g.find(I*w0))
print(h.find(I*w0))
print(k.find(I*w0))

edit retag close merge delete

Sort by » oldest newest most voted Edited. This was the original answer

It seems that, in your expressions, $x$ denotes a real number. If this were the case, you can get the coefficients of I by taking the imaginary part of the expression:

sage: f = x^2 + 2*I*x + 1
sage: g = x^2 + I*x + 1
sage: h = x^2 + 2*x + I
sage: k = x^2 + x + 2*I
sage: assume(x,'real')
sage: for expression in [f, g, h, k]:
....:     print(expression.imag())
2*x
x
1
2


New answer. I have improved your approach, based on wildcards. It seems that I is not detected because it is not a symbolic variable. So, we can temporarily transform I into such a variable, find the coefficients of I in the expressions and then restore I:

w0 = SR.wild(0)
var("I")
f = x^2 + 2*I*x + 1
g = x^2 + I*x + 1
h = x^2 + 2*x + I
k = x^2 + x + 2*I
m = sqrt(1-x^2) + I*(1-x^3)^(1/3)
n = sqrt(1-x^2) + 2*I*(1-x^3)^(1/3)
p = x^2 + 2*x - I
q = x^2 + 2*x

expressions = [f, g, h, k, m, n, p, q]
for expression in expressions:
print("\nExpression: ",expression)
if expression.has(I):
if expression.has(w0*I):
aux = expression.find(w0*I)
coef = aux.match(w0*I)[w0]
else:
coef = 1
print(f"The coefficient of I is {coef}")
else:
print("The expression does not contain I")
restore("I")


This is the output:

Expression:  2*I*x + x^2 + 1
The coefficient of I is 2*x

Expression:  I*x + x^2 + 1
The coefficient of I is x

Expression:  x^2 + I + 2*x
The coefficient of I is 1

Expression:  x^2 + 2*I + x
The coefficient of I is 2

Expression:  (-x^3 + 1)^(1/3)*I + sqrt(-x^2 + 1)
The coefficient of I is (-x^3 + 1)^(1/3)

Expression:  2*(-x^3 + 1)^(1/3)*I + sqrt(-x^2 + 1)
The coefficient of I is 2*(-x^3 + 1)^(1/3)

Expression:  x^2 - I + 2*x
The coefficient of I is -1

Expression:  x^2 + 2*x
The expression does not contain I

more

Thanks for the answer. You are correct that I meant x to be a real number. I thought of this approach too, but unfortunately, it breaks down when the expression becomes a more complex. Here is an example.

w0 = SR.wild(0)

f = sqrt(1-x^2) + I*(1-x^3)^(1/3)
g = sqrt(1-x^2) + 2*I*(1-x^3)^(1/3)

assume(x, 'real')

print(f.find(I*w0))
print(g.find(I*w0))

print(f.imag())
print(g.imag())


In this example, .find(I*w0) yields the term containing the cube root from f, but not from g. However, .imag() yields complicated expressions for both f and g because it takes into account that abs(x) may be greater than 1.

Thanks again. The updated approach works when we know the expressions up front. However, one step more difficult is when they result from a computation. Here is another example. Interestingly enough, when solving the equation for x, the .find(I*w0) approach works. However, when solving for y, it doesn't.

w0 = SR.wild(0)

var('y')
assume(x, 'real')
assume(y, 'real')

eqn = (x^3 + y^3 / 27 == 1)

sols = solve(eqn, x)

f, g, h = [sol.rhs() for sol in sols]

expressions = [f, g, h]

for expr in expressions:
print(expr.find(I*w0))

sols = solve(eqn, y)

f, g, h = [sol.rhs() for sol in sols]

expressions = [f, g, h]

for expr in expressions:
print(expr.find(I*w0)