寻找根的伴侣矩阵

时间:2018-09-18 07:08:55

标签: python numpy

我正在尝试求解二次方程facebookConnectPlugin.api("<user-id>/?fields=id,email,gender,birthday",["public_profile","user_birthday"], function onSuccess (result) { console.log("Result: ", result); /* logs: { "id": "000000123456789", "email": "myemail@example.com" } */ }, function onError (error) { console.error("Failed: ", error); } );

我的代码并非在所有情况下都给出正确的答案。

x**2 + b * x + c =0

测试功能:

def solve_quad(b, c):

    b= float(b)
    c= float(c)
    import numpy as np

    # definition of companion matrix A of the quadratic equation 

    A = np.array([[0,-c],
                 [1,-b]])

    # roots of the quadratic equation are the eigen values of matrix A

    from numpy.linalg import eig

    e, v = eig(A)

    return e

solve_quad(0,1)

某些答案为“ True”,而其他答案为from numpy import allclose variants = [{'b': 4.0, 'c': 3.0}, {'b': 2.0, 'c': 1.0}, {'b': 0.5, 'c': 4.0}, {'b': 1e10, 'c': 3.0}, {'b': -1e10, 'c': 4.0},] for var in variants: x1, x2 = solve_quad(**var) print(allclose(x1*x2, var['c'])) 。是什么原因造成的?

因此,我尝试使用牛顿方法抛光根部,但是我不确定它是否可以那样工作。     将numpy导入为np

False

当b远大于c时,特征值存在数值误差 所以我们的想法是使用牛顿函数来抛光使用伴随矩阵方法得到的根 因此我们将A特征值的根作为迭代过程中真实根的第一近似值

def solve_quad(b, c):



   b= float(b)
   c= float(c)
   # defining the given function 
   def f(x):
       return x**2 + b*x + c

  # first derivative of the given function 
  def f1(x):
      return 2 * x + b

  # definition of companion matrix A of the quadratic equation  
  A = np.array([[0,-c],
              [1,-b]])

  # roots of the quadratic equation are the eigen values of matrix A

  from numpy.linalg import eigvals
  e = eigvals(A)

2 个答案:

答案 0 :(得分:0)

这可能被视为作弊,但是由于我们知道非零高值结果是根之一,因此我们可以将第二个值设为c/x1

def solve_quad(b, c):

    b= float(b)
    c= float(c)
    import numpy as np

    # definition of companion matrix A of the quadratic equation

    A = np.array([[0,-c],
                 [1,-b]])

    # roots of the quadratic equation are the eigen values of matrix A

    from numpy.linalg import eigvals
    #Used eigvals instead of eig because we are not using the vectors
    e = eigvals(A)

    #Checks for 0 roots where c is not zero, indicating a large root then forces the
    #zero value root to be c/(large value root). This is also not accurate but should
    #validate x1*x2 = c and returns non zero roots to avoid later on divisions 
    #or multiplications by zeroes.
    if any(v == 0. for v in e) and c != 0.:
        e[np.argwhere(e == 0)] = c/(e[np.nonzero(e)])

    return e

使用代数进行计算的另一种更准确的方法是:

(1 + eps)**n = 1 + n.eps起,对于小型eps,我们可以重写:

def solve_quad(b, c):

    b= float(b)
    c= float(c)
    import numpy as np

    # definition of companion matrix A of the quadratic equation

    A = np.array([[0,-c],
                 [1,-b]])

    # roots of the quadratic equation are the eigen values of matrix A

    from numpy.linalg import eigvals
    #Used eigvals instead of eig because we are not using the vectors
    e = eigvals(A)

    # This is much more accurate although the results will appear to be the 
    #same and the multiplication is not exactly equal to c but the error 
    #here are due to the algebraic assumption we made and results are 
    #mathematical instead of forcing the result to be some value.
    if any(v == 0. for v in e) and c != 0.:
        eps = c/b
        e[np.nonzero(e)] += eps
        e[np.argwhere(e == 0)] = -eps

    return e

答案 1 :(得分:0)

因此,我使用牛顿迭代法(Newton Iteration)来抛光从伴随矩阵中获得的根,并且代码如下所示

def solve_quad1(b, c):
"""Solve a quadratic equation, x**2 + bx + c = 0.

Parameters
----------
b, c : float
   Coefficients

Returns
-------
x1, x2 : float or complex
   Roots.
"""
b= float(b)
c= float(c)
# defining the given function 
def f(x):
    return x**2 + b*x + c

# first derivative of the given function 
def f1(x):
    return 2 * x + b

# definition of companion matrix A of the quadratic equation  
A = np.array([[0,-c],
              [1,-b]])

# roots of the quadratic equation are the eigen values of matrix A

from numpy.linalg import eigvals
e = eigvals(A)

#When b is extremely larger than c,there are numerical errors with the eigen 
#values
#so the idea is to use Newton's function to polish the roots we got using the 
#companion matrix method 
#so we are taking the roots from the eigenvalues of A as the first 
#approximations of our true roots
#for the iteration process

n_iter=0
eps= 1e-5
x_curr1=[]

for v in e:
    x_curr= v
    while n_iter < 20:

        x_next = x_curr - f(x_curr)/ f1(x_curr)

        if (abs(x_curr - x_next) < eps):

            break

        x_curr = x_next
        n_iter += 1
    x_curr1.append(x_curr)

return x_curr1

#Example
solve_quad1(1000000,3)