Sympy:多元多项式组合

马可·贝兰

我在变量 (x,y) 中有一个复杂的多元多项式,我需要通过设置在变量 (a,b) 中获得一个新的多项式

x = (a+b) / sqrt(2)
y = -i (a-b) / sqrt(2)

您可能会将其识别为复杂坐标之间的变量变化。

我知道函数“compose”,但它似乎只替换了多项式的“x”变量,有没有办法进行多元组合?

谢谢,马可

扬尼斯·菲利皮迪斯

正如评论中所指出的,使用方法可以同时替换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('polynomial: {p}'.format(p=new_poly))
print('generators: {g}'.format(g=new_poly.gens))
print('monomials: {m}'.format(m=new_poly.monoms()))
print('coefficients: {c}'.format(c=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]

并确保按要求在评论中,所产生的多项式具有作为发电机,如果我们从头开始构建新的多项式,我们所期望的表达,即

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是类的实例时才需要sympy.polys.polytools.Poly,如上所述。

使用表达式避免了将最终结果从多项式转换为表达式再转换回多项式的需要。相反,从表达式到多项式的转换就足够了,如下(如果有兴趣调用方法monoms则需要转换为多项式,因为表达式是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('polynomial: {p}'.format(p=new_poly))
print('generators: {g}'.format(g=new_poly.gens))
print('monomials: {m}'.format(m=new_poly.monoms()))
print('coefficients: {c}'.format(c=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('polynomial: {p}'.format(p=new_poly))
print('generators: {g}'.format(g=new_poly.gens))
print('monomials: {m}'.format(m=new_poly.monoms()))
print('coefficients: {c}'.format(c=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('polynomial: {p}'.format(p=new_poly))
print('generators: {g}'.format(g=new_poly.gens))
print('monomials: {m}'.format(m=new_poly.monoms()))
print('coefficients: {c}'.format(c=new_poly.coeffs()))

它打印与前一个代码块相同的输出。

subs可以sympy文档中找到有关该方法的其他文档(即使讨论是针对表达式实例,它也适用于多项式的实例,因为两者都将类子类化Basic而不覆盖方法subs)。

还要注意,不是标识符的子表达式的替换大致通过在表达式的语法树中搜索与要替换的子表达式的语法树匹配的子树并替换子树来进行。但是,如本答案和方法的文档字符串中所述,对一些启发式方法有一个警告sympy.core.basic.Basic.subs

(此外,问题中似乎缺少乘号。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章