Sympy:多元多项式组合
Sympy: Multivariate Polynomial Composition
我在变量 (x,y) 中有一个复杂的多元多项式,我需要通过设置
获得一个在变量 (a,b) 中的新多项式
x = (a+b) / sqrt(2)
y = -i (a-b) / sqrt(2)
您可能将其视为变量的变化 from/to 复坐标。
我知道函数“compose”,但它似乎只能替换我的多项式的“x”变量,有没有办法进行多元组合?
谢谢,
马可
也许你的意思是要将 a 和 b 重写为 x 和 y 的函数?
from sympy.abc import a,b,x,y
from sympy import I, sqrt, solve
eqs = [
x - (a+b) / sqrt(2),
y - -I* (a-b) / sqrt(2)]
>>> solve(eqs,(a,b))
{a: sqrt(2)*x/2 + sqrt(2)*I*y/2, b: sqrt(2)*x/2 - sqrt(2)*I*y/2}
正如评论中指出的,使用方法sympy.core.basic.Basic.subs
可以同时替换,例如:
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = sympy.poly(x + y)
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is:
# Poly(sqrt(2)*a/2 - sqrt(2)*I*a/2 + sqrt(2)*b/2 + sqrt(2)*I*b/2,
# sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2, domain='EX')
# so the following assertions pass
assert str(new_poly.gens) == '(sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2)', (
new_poly.gens)
assert new_poly.monoms() == [(0, 0)], new_poly.monoms()
# worth remarking that
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
# by converting from an instance of the class `sympy.polys.polytools.Poly`
# to an instance of the class `sympy.core.expr.Expr`, and
# back to an instance of the class `sympy.polys.polytools.Poly`,
# the generators become as expected
new_poly = new_poly.as_expr().as_poly()
# the previous statement is equivalent, as far as I know,
# to the statement:
# `new_poly = sympy.poly(new_poly.as_expr())`
# However, the latter raises an exception for some expressions
# (for an example, see below).
# The exception is avoided by using the expression method `as_poly`.
assert str(new_poly.gens) == '(a, b, sqrt(2))', new_poly.gens
assert new_poly.monoms() == [(1, 0, 1), (0, 1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
打印:
polynomial: Poly((1/2 - I/2)*a*(sqrt(2)) + (1/2 + I/2)*b*(sqrt(2)), a, b, sqrt(2), domain='QQ_I')
generators: (a, b, sqrt(2))
monomials: [(1, 0, 1), (0, 1, 1)]
coefficients: [1/2 - I/2, 1/2 + I/2]
并确保,按照评论中的要求,生成的多项式具有 generators 如果我们从头开始构造新多项式时我们期望的表达式,即
import sympy
a, b = sympy.symbols('a b')
expr = (
(1/2 - sympy.I/2) * a * (sympy.sqrt(2))
+ (1/2 + sympy.I/2) * b *(sympy.sqrt(2)))
new_poly = expr.as_poly()
assert str(new_poly.gens) == '(a, b, sqrt(2))', new_poly.gens
事实上,以这种方式获得的多项式是相等的,但表示方式略有不同,具体来说是小数而不是分数,即new_poly
在这种情况下是Poly((0.5 - I/2)*a*(sqrt(2)) + (0.5 + I/2)*b*(sqrt(2)), a, b, sqrt(2), domain='EX')
。
值得注意的是,仅当 poly
是 class sympy.polys.polytools.Poly
的实例时,才需要上述从多项式到表达式再返回到多项式的转换,因为在上面。
使用表达式可以避免将最终结果从多项式转换为表达式再转换回多项式的需要。相反,从表达式到多项式的转换就足够了,如下所示(如果有兴趣调用方法 monoms
,则需要转换为多项式,因为表达式是 class sympy.core.expr.Expr
的实例,它没有方法 monoms
):
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = x + y
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is an instance of the
# class `sympy.core.expr.Expr`,
# so it does not have methods `monoms` and `gens`,
# thus a conversion to polynomial is needed.
# This conversion creates the expected generators, monomials,
# and coefficients, as follows.
new_poly = new_poly.as_expr().as_poly()
assert str(new_poly.gens) == '(a, b, sqrt(2))', new_poly.gens
assert new_poly.monoms() == [(1, 0, 1), (0, 1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
此代码块打印与第一个代码块相同的输出。
并对感兴趣的多项式重复上述两种方法x**2 + y**2
(该多项式已在评论中注明):
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = sympy.poly(x**2 + y**2)
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is:
# Poly(2*a*b, sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2, domain='ZZ[a,b]')
# so the following assertions pass
assert str(new_poly.gens) == '(sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2)', (
new_poly.gens)
assert new_poly.monoms() == [(0, 0)], new_poly.monoms()
# worth remarking that
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
# by converting from an instance of the class `sympy.polys.polytools.Poly`
# to an instance of the class `sympy.core.expr.Expr`, and
# back to an instance of the class `sympy.polys.polytools.Poly`,
# the generators become as expected
new_poly = new_poly.as_expr().as_poly()
assert str(new_poly.gens) == '(a, b)', new_poly.gens
assert new_poly.monoms() == [(1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
打印输出:
polynomial: Poly(2*a*b, a, b, domain='ZZ')
generators: (a, b)
monomials: [(1, 1)]
coefficients: [2]
和代码块:
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = x**2 + y**2
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is an instance of the
# class `sympy.core.expr.Expr`,
# so it does not have methods `monoms` and `gens`,
# thus a conversion to polynomial is needed.
# This conversion creates the expected generators, monomials,
# and coefficients, as follows.
new_poly = new_poly.as_expr().as_poly()
# if the previous statement is replaced with the statement:
# `new_poly = sympy.poly(new_poly.as_expr())`
# then an exception is raised:
# `CoercionFailed: expected an integer, got 1/2`
assert str(new_poly.gens) == '(a, b)', new_poly.gens
assert new_poly.monoms() == [(1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
它打印与前一个代码块相同的输出。
可以找到关于方法 subs
的其他文档 in the sympy
documentation(即使那里的讨论是关于表达式实例,它也适用于多项式实例,因为 subclass class Basic
而不覆盖方法 subs
).
另请注意,不是标识符的子表达式的替换大致通过搜索表达式的语法树来查找与要替换的子表达式的语法树匹配的子树,然后替换子树。但是,如 所述以及方法的文档字符串 sympy.core.basic.Basic.subs
.
中,有一些关于启发式的警告
(此外,问题中似乎缺少乘号。)
我在变量 (x,y) 中有一个复杂的多元多项式,我需要通过设置
获得一个在变量 (a,b) 中的新多项式x = (a+b) / sqrt(2)
y = -i (a-b) / sqrt(2)
您可能将其视为变量的变化 from/to 复坐标。
我知道函数“compose”,但它似乎只能替换我的多项式的“x”变量,有没有办法进行多元组合?
谢谢, 马可
也许你的意思是要将 a 和 b 重写为 x 和 y 的函数?
from sympy.abc import a,b,x,y
from sympy import I, sqrt, solve
eqs = [
x - (a+b) / sqrt(2),
y - -I* (a-b) / sqrt(2)]
>>> solve(eqs,(a,b))
{a: sqrt(2)*x/2 + sqrt(2)*I*y/2, b: sqrt(2)*x/2 - sqrt(2)*I*y/2}
正如评论中指出的,使用方法sympy.core.basic.Basic.subs
可以同时替换,例如:
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = sympy.poly(x + y)
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is:
# Poly(sqrt(2)*a/2 - sqrt(2)*I*a/2 + sqrt(2)*b/2 + sqrt(2)*I*b/2,
# sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2, domain='EX')
# so the following assertions pass
assert str(new_poly.gens) == '(sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2)', (
new_poly.gens)
assert new_poly.monoms() == [(0, 0)], new_poly.monoms()
# worth remarking that
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
# by converting from an instance of the class `sympy.polys.polytools.Poly`
# to an instance of the class `sympy.core.expr.Expr`, and
# back to an instance of the class `sympy.polys.polytools.Poly`,
# the generators become as expected
new_poly = new_poly.as_expr().as_poly()
# the previous statement is equivalent, as far as I know,
# to the statement:
# `new_poly = sympy.poly(new_poly.as_expr())`
# However, the latter raises an exception for some expressions
# (for an example, see below).
# The exception is avoided by using the expression method `as_poly`.
assert str(new_poly.gens) == '(a, b, sqrt(2))', new_poly.gens
assert new_poly.monoms() == [(1, 0, 1), (0, 1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
打印:
polynomial: Poly((1/2 - I/2)*a*(sqrt(2)) + (1/2 + I/2)*b*(sqrt(2)), a, b, sqrt(2), domain='QQ_I')
generators: (a, b, sqrt(2))
monomials: [(1, 0, 1), (0, 1, 1)]
coefficients: [1/2 - I/2, 1/2 + I/2]
并确保,按照评论中的要求,生成的多项式具有 generators 如果我们从头开始构造新多项式时我们期望的表达式,即
import sympy
a, b = sympy.symbols('a b')
expr = (
(1/2 - sympy.I/2) * a * (sympy.sqrt(2))
+ (1/2 + sympy.I/2) * b *(sympy.sqrt(2)))
new_poly = expr.as_poly()
assert str(new_poly.gens) == '(a, b, sqrt(2))', new_poly.gens
事实上,以这种方式获得的多项式是相等的,但表示方式略有不同,具体来说是小数而不是分数,即new_poly
在这种情况下是Poly((0.5 - I/2)*a*(sqrt(2)) + (0.5 + I/2)*b*(sqrt(2)), a, b, sqrt(2), domain='EX')
。
值得注意的是,仅当 poly
是 class sympy.polys.polytools.Poly
的实例时,才需要上述从多项式到表达式再返回到多项式的转换,因为在上面。
使用表达式可以避免将最终结果从多项式转换为表达式再转换回多项式的需要。相反,从表达式到多项式的转换就足够了,如下所示(如果有兴趣调用方法 monoms
,则需要转换为多项式,因为表达式是 class sympy.core.expr.Expr
的实例,它没有方法 monoms
):
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = x + y
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is an instance of the
# class `sympy.core.expr.Expr`,
# so it does not have methods `monoms` and `gens`,
# thus a conversion to polynomial is needed.
# This conversion creates the expected generators, monomials,
# and coefficients, as follows.
new_poly = new_poly.as_expr().as_poly()
assert str(new_poly.gens) == '(a, b, sqrt(2))', new_poly.gens
assert new_poly.monoms() == [(1, 0, 1), (0, 1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
此代码块打印与第一个代码块相同的输出。
并对感兴趣的多项式重复上述两种方法x**2 + y**2
(该多项式已在评论中注明):
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = sympy.poly(x**2 + y**2)
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is:
# Poly(2*a*b, sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2, domain='ZZ[a,b]')
# so the following assertions pass
assert str(new_poly.gens) == '(sqrt(2)*(a + b)/2, -sqrt(2)*I*(a - b)/2)', (
new_poly.gens)
assert new_poly.monoms() == [(0, 0)], new_poly.monoms()
# worth remarking that
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
# by converting from an instance of the class `sympy.polys.polytools.Poly`
# to an instance of the class `sympy.core.expr.Expr`, and
# back to an instance of the class `sympy.polys.polytools.Poly`,
# the generators become as expected
new_poly = new_poly.as_expr().as_poly()
assert str(new_poly.gens) == '(a, b)', new_poly.gens
assert new_poly.monoms() == [(1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
打印输出:
polynomial: Poly(2*a*b, a, b, domain='ZZ')
generators: (a, b)
monomials: [(1, 1)]
coefficients: [2]
和代码块:
import sympy
a, b, x, y = sympy.symbols('a b x y')
poly = x**2 + y**2
let = {x: (a + b) / sympy.sqrt(2), y: - sympy.I * (a - b) / sympy.sqrt(2)}
new_poly = poly.subs(let, simultaneous=True)
# at this point, `new_poly` is an instance of the
# class `sympy.core.expr.Expr`,
# so it does not have methods `monoms` and `gens`,
# thus a conversion to polynomial is needed.
# This conversion creates the expected generators, monomials,
# and coefficients, as follows.
new_poly = new_poly.as_expr().as_poly()
# if the previous statement is replaced with the statement:
# `new_poly = sympy.poly(new_poly.as_expr())`
# then an exception is raised:
# `CoercionFailed: expected an integer, got 1/2`
assert str(new_poly.gens) == '(a, b)', new_poly.gens
assert new_poly.monoms() == [(1, 1)], new_poly.monoms()
assert new_poly.free_symbols == {a, b}, new_poly.free_symbols
print(f'polynomial: {new_poly}')
print(f'generators: {new_poly.gens}')
print(f'monomials: {new_poly.monoms()}')
print(f'coefficients: {new_poly.coeffs()}')
它打印与前一个代码块相同的输出。
可以找到关于方法 subs
的其他文档 in the sympy
documentation(即使那里的讨论是关于表达式实例,它也适用于多项式实例,因为 subclass class Basic
而不覆盖方法 subs
).
另请注意,不是标识符的子表达式的替换大致通过搜索表达式的语法树来查找与要替换的子表达式的语法树匹配的子树,然后替换子树。但是,如 sympy.core.basic.Basic.subs
.
(此外,问题中似乎缺少乘号。)