# Expression substitution fails: why?

Hi, I recently ran into a weird problem where substituting one equation into another sometimes fails with a MemoryError, depending on how the original equation was derived. In the code below I have been able to isolate the issue (my actual code sometimes stumbles on the third approach, and I will have to see how I can change its structure to work around the issue).

In all three approaches, the printout of real_expr is identical. However, when trying to execute the subsequent substitution, it looks like there must be a difference between the three, at least in their internal representation. Note that the MemoryError does not occur when the substitution is simpler, i.e. expr_real.subs(f=2) works fine.

Am I missing something, or is this just a bug?

BTW: I am running Sage 9.1, but the problem also occurs on SageCell (which I presume is running 9.2).

Updated code

# First declare a bunch of variables
var('A, L, G, R', domain='positive')
var('f, k, n, q, u', domain='positive')
var('beta', domain='positive')
var('gamma', domain='positive')

# Here is a complex expression
expr_complex = (I*R^2*f^3*k*q*A*u
/((2*pi*L*R^2*G*f^4*k^2*q
- 2*pi*L*R^2*G*f^4*q
- 2*pi*L*R^2*beta^2*G*q
+ (2*I*pi*L*R^2*beta*gamma*q + 2*I*pi*L*R*(beta + q))*G*f^3
+ 2*(pi*(beta^2 + 1)*L*R^2*q + pi*L*R*beta*gamma*q + pi*L*beta)*G*f^2
+ (-2*I*pi*L*R^2*beta*gamma*q - 2*I*pi*(beta^2*q + beta)*L*R)*G*f)*n))

# Use three different approaches to derive a real expression from the complex one

# This approach works well
expr_real_1 = (expr_complex.real()^2+expr_complex.imag()^2).factor()
show(expr_real_1)
show(expr_real_1.subs(f=2*beta))

# This approach is fine too
expr_real_2 = (sqrt(expr_complex.real()^2+expr_complex.imag()^2)^2).factor()
print(bool(expr_real_1 == expr_real_2))
show(expr_real_2.subs(f=2*beta))

# This approach causes Sage to run out of memory
expr_real_3 = ((sqrt(expr_complex.real()^2+expr_complex.imag()^2).factor())^2).factor()
print(bool(expr_real_3 == expr_real_1))
print(bool(expr_real_3 == expr_real_2))
show(expr_real_3.subs(f=2*beta)) # This step yields a MemoryError (verified on SageCell)

edit retag close merge delete

To check what Sage version runs at SageCell, use print(version()). : )

( 2020-12-29 12:29:07 +0200 )edit

Sort by » oldest newest most voted

WorksForMe(TM) on Sagemath 9.3.beta5 :

sage: reset()
sage: version()
'SageMath version 9.3.beta5, Release Date: 2020-12-27'
sage: var('A, L, G, R, f, k, n, q, u, beta, gamma', domain="positive") # Shortcut
(A, L, G, R, f, k, n, q, u, beta, gamma)
sage: expr_complex = (I*R^2*f^3*k*q*A*u/ ((2*pi*L*R^2*G*f^4*k^2*q - 2*pi*L*R^2*G*f^4*q - 2*pi*L*R^2*beta^2*G*q + (2*I*pi*L*R^2*beta*gamma*q + 2*I*pi*L*R*(beta + q))*G*f^3 + 2*(pi*(beta^2 + 1)*L*R^2*q + pi*L*R*beta*gamma*q + pi*L*beta)*G*f^2+ (-2*I*pi*L*R^2*beta*gamma*q - 2*I*pi*(beta^2*q + beta)*L*R)*G*f)*n))
sage: R1=(expr_complex.real()^2+expr_complex.imag()^2).factor()
sage: R2=(sqrt(expr_complex.real()^2+expr_complex.imag()^2)^2).factor()
sage: bool(R1==R2)
True
sage: R3=((sqrt(expr_complex.real()^2+expr_complex.imag()^2).factor())^2).factor()
sage: bool(R1==R3)
True
sage: bool(R2==R3)
True


HTH,

EDIT : The expressins are correct, but indeed, Sage's default mechanism for substitutions faits to work on R3. Sympy's subs works :

sage: import sympy
sage: bool(sympy.sympify(R3).subs(f,2*beta)._sage_()==R1.subs(f=2*beta))
True


More troubling : mathematica seems to faile somehow :

sage: bool(mathematica.Replace(R3,mathematica.Rule(f,2*beta)).sage()==R1.subs(f=2*beta))
False


And, indeed,

sage: bool(R3.subs(f=2*beta)==R1.subs(f=2*beta))


never returns.

This is now Trac#31137.

more

Thanks for the response. However, Sagemath 9.1 and 9.2 also yield True when testing the three expressions for equality; see the updated code in my original question. The problem is with the substitution (third line of the three approaches). How does Sagemath 9.3beta5 handle this?

BTW: Thanks for showing the shortcut domain='positive'; I didn't know this one yet.

( 2020-12-29 22:03:38 +0200 )edit

Indeed , I oversaw the subs problem, which I could reproduce. Answer edited, ticket filed.

( 2020-12-30 08:43:04 +0200 )edit

On my local 9.1 installation, the expression show(real_expr_3.subs(f=2*beta)) does not return either. However, I see python3.7 memory usage growing to roughly 4 GB after one minute, 5 GB after two minutes, 3 GB after three minutes, and staying between 3 and 4 GB for several more minutes, after which I restarted the kernel. I ran into the MemoryError on SageCell, presumably because it limits the amount of memory available:

MemoryError: failed to allocate 25165848 bytes
Exception ignored in: 'sage.libs.pynac.pynac.py_repr'
Traceback (most recent call last):
File "sage/rings/integer.pyx", line 1013, in sage.rings.integer.Integer.__repr__(build/cythonized/sage/rings/integer.c:8430)

( 2020-12-30 13:13:32 +0200 )edit