Really, this is two questions in one.
Suppose I have the following code:
from sympy import * x1, x2, x3, y1, y2, y3 = symbols("x1 x2 x3 y1 y2 y3") term = x1**5 + (x2**2)*(x3**3) + x1**4 + x1**3 + x1**2 + x1 term = term.subs(x1**2, y1) term = term.subs(x2**2, y2) term = term.subs(x3**2, y3)
After the above,
term takes the value
x1**5 + x1**3 + x1 + x3**3*y2 + y1**2 + y1.
Question 1: I would like to turn all x_i^(2n+1) into the form x_i*(y_i^n) – but this leaves the odd powers of x_i alone. Is there any way to achieve this?
Question 2: Is there a way of typing something like
term = term.subs(xi**2, yi), rather than rewriting the substitution for each x_i?
Something like this seems to work. Just be aware of the difference in the index base.
from sympy import * x = symbols("x1 x2 x3") y = symbols("y1 y2 y3") term = x**5 + (x**2)*(x**3) + x**4 + x**3 + x**2 + x for i in range(3): term = term.subs(x[i]**2, y[i]) for n in range(3): term = term.subs(x[i]**(2*n+1), x[i]*y[i]**n) term
You can just tell the
replace method to find powers with odd exponents and replace them as you described in the OP.
sym lambda is a function to give a new symbol to use for the odd case. In the first example  I use the integer attribute to create a new symbol that looks like the one appearing in the power but behaving distinctly (since symbols are known by their attributes). In the second example, I assume that only the first letter is going to be replaced with
y (like you had said).
Since the replace does not care about the name of the variables, there is no need for an explicit loop to check all bases.