如何使用sympy / python查找给定根的多项式

问题描述 投票:-1回答:5

假设我有一个以-2、1、3为根的三次多项式,如何找到方程式? sympy是否可以解决此问题,或者一般来说python还有其他方法?

函数可能喜欢,我想求解abcd

f = lambda x: a*x**3+b*x**2+c*x+d

同时,如果多项式是五阶?

更新:

感谢您的回答。似乎使用Vieta的公式简化了问题。但是有时第N次多项式的根数不等于N。例如,第五次多项式可以表示为以下形式:

(x-a)**2*(x-b)**2(x-c)

如果是这样,这仍然可以解决吗?

请在下面的更新中查看我的解决方案

python numpy sympy
5个回答
2
投票

这应该在任何程度上都可以解决多项式的问题。星号允许任意数量的参数。

def c_find(*roots):
    from sympy import Symbol
    x = Symbol('x')
    whole =1
    for root in roots:
        whole *=(x-root)
    print('f(x) =',whole.expand())

呼叫c_find(3,4,5)返回f(x) = x**3 - 12*x**2 + 47*x - 60


2
投票

poly中有一组基本的numpy功能:

In [44]: f = np.poly([-2,1,3])
In [45]: f
Out[45]: array([ 1., -2., -5.,  6.])
In [46]: np.roots(f)
Out[46]: array([-2.,  3.,  1.])
In [49]: np.polyval(f, np.arange(-3,5))
Out[49]: array([-24.,   0.,   8.,   6.,   0.,  -4.,   0.,  18.])

也可以使用以下方式评估值范围内的值:

In [53]: np.dot(np.arange(-3,5)[:,None]**np.array([3,2,1,0]), f)
Out[53]: array([-24.,   0.,   8.,   6.,   0.,  -4.,   0.,  18.])

1
投票

使用sympy从根开始构建多项式,然后获得系数:

from sympy import Symbol, poly

x = Symbol('x')

roots = [-1, 1]
expr = 1

# polynomial in format (x-a)(x-b)(x-c)...
for i in roots:
  expr *= (x - i)

p = poly(expr, x)
print(p)
print(p.all_coeffs())

输出:

Poly(x**2 - 1, x, domain='ZZ')
[1, 0, -1]

注意,这将适用于任意长的根列表。

例如,如果根是[-1, 1, 2, 3, 4, 5, 6]

输出:

Poly(x**7 - 20*x**6 + 154*x**5 - 560*x**4 + 889*x**3 - 140*x**2 - 1044*x + 720, x, domain='ZZ')
[1, -20, 154, -560, 889, -140, -1044, 720]

1
投票
def f(x): return (x - (-2)) * (x - 1) * (x - 2)

出于评估x处的多项式的目的,这应该与将符号乘以倍数一样好。要制作多个由根定义的多项式函数,请使用函数工厂。

def poly3(r1, r2, r3):
    def _poly3(x):
        return (x - r1) * (x - r2) * (x - r3)
    return _poly3

f2 = poly3(-2, 1, 2)

for i in range(-10, 11):
    assert f(i) == f2(i)
# no AssertionError means all tests pass

以下内容概括为n个根。

def polyn(*roots):
    def _polyn(x):
        val = 1
        for r in roots:
            val *= x - r
        return val
    return _polyn

f3 = polyn(-2, 1, 2)

for i in range(-10, 11):
    assert f(i) == f3(i)
# Above code passed on Win 10, 3.7.2

0
投票

感谢所有答案。在解决您的解决方案之后。对于具有重复根源的Update,我提出了以下解决方案:

def find_all_polys(degree, roots):
    '''find all formats of polynomials with given degree and roots

    Args:
        degree (int): the degree of the polynomial
        roots (list): the list contains all given roots

    Returns:
        All simplified formats of polynomials with a given degree

    Notes:
        1. The degree of a polynomial determines its maximum number of
           all possible real roots.
        2. Each combination of roots for a given degree polynomial
           determines a simplified format of the polynomial (i.e., the
           coefficient of the highest-degree term is 1)
        3. The number of all possible formats for a n-th degree
           polynomial with m roots is defined as:
                            H(m, n-m)=C(m, n-m+m-1)
           Since the given roots will always be contained in the roots
           combination, the number of format variations depends on the
           combination of duplicated roots, which can be considered as
           a combination with repetition problem as defined above.

    '''

    from math import factorial
    from sympy import Symbol

    # counting number of all possible roots combinations
    nHr = lambda n,r: factorial(n+r-1)/(factorial(r)*factorial(n-1))
    n_all_roots = nHr(len(roots), degree-len(roots))

    # getting all roots combinations
    if len(np.unique(roots)) == len(roots):
        n_dups = degree-len(roots)
        roots_all_dups = []
        while True:
            # randomly select from the given roots
            roots_dups = np.random.choice(roots, n_dups).tolist()
            roots_dups.sort()

            # testing if the combination already exists
            if roots_dups not in roots_all_dups:
               roots_all_dups.append(roots_dups)
            else:
                if len(roots_all_dups) == n_all_roots:
                    break

        # adding duplicated roots to all given roots list
        for dups in roots_all_dups:
            dups.extend(roots)
        all_roots_combs = roots_all_dups

        # finding all possible formats of polynomials
        for counter, roots_combs in enumerate(all_roots_combs):
            x = Symbol('x'); term = 1
            for root in all_roots_combs[counter]:
                term *= (x-root)
            print(f'f(x) = {term.expand()}')

    else:
        raise ValueError('The root list should not contain duplicated roots')

例如:

roots = [-2, 1, 3]
find_all_polys(degree=6, roots=roots)

将返回:

f(x) = x**6 - 4*x**5 - 6*x**4 + 32*x**3 + x**2 - 60*x + 36
f(x) = x**6 - 6*x**5 + 50*x**3 - 45*x**2 - 108*x + 108
f(x) = x**6 - 9*x**5 + 24*x**4 + 2*x**3 - 99*x**2 + 135*x - 54
f(x) = x**6 - x**5 - 15*x**4 + 5*x**3 + 70*x**2 + 12*x - 72
f(x) = x**6 + 4*x**5 - 5*x**4 - 40*x**3 - 40*x**2 + 32*x + 48
f(x) = x**6 + x**5 - 11*x**4 - 13*x**3 + 26*x**2 + 20*x - 24
f(x) = x**6 - 2*x**5 - 8*x**4 + 14*x**3 + 11*x**2 - 28*x + 12
f(x) = x**6 - 11*x**5 + 40*x**4 - 30*x**3 - 135*x**2 + 297*x - 162
f(x) = x**6 - 5*x**5 + 4*x**4 + 14*x**3 - 31*x**2 + 23*x - 6
f(x) = x**6 - 7*x**5 + 12*x**4 + 14*x**3 - 59*x**2 + 57*x - 18
© www.soinside.com 2019 - 2024. All rights reserved.