【问题标题】:Multivariate Taylor approximation in sympysympy中的多元泰勒近似
【发布时间】:2014-04-04 08:13:38
【问题描述】:

我的目标是使用sympy 编写多维泰勒近似,其中

  • 使用尽可能多的内置代码,
  • 计算两个变量的给定函数的截断泰勒近似
  • 返回结果没有 Big-O-remainder term,例如在sin(x)=x - x**3/6 + O(x**4)

到目前为止,这是我尝试过的:

方法 1

天真地,可以为每个变量组合两次 series 命令,但不幸的是,这不起作用,正如此示例中函数 sin(x*cos(y)) 所示:

sp.sin(x*sp.cos(y)).series(x,x0=0,n=3).series(y,x0=0,n=3)
>>> NotImplementedError: not sure of order of O(y**3) + O(x**3)

方法 2

基于this post我先写了一个一维泰勒近似:

def taylor_approximation(expr, x, max_order):
    taylor_series = expr.series(x=x, n=None)
    return sum([next(taylor_series) for i in range(max_order)])

使用 1D 示例检查它可以正常工作

mport sympy as sp
x=sp.Symbol('x')
y=sp.Symbol('y')
taylor_approximation(sp.sin(x*sp.cos(y)),x,3)

>>> x**5*cos(y)**5/120 - x**3*cos(y)**3/6 + x*cos(y)

但是,如果我知道在 xy 中进行两个扩展的链式调用,sympy 就会挂断

# this does not work
taylor_approximation(taylor_approximation(sp.sin(x*sp.cos(y)),x,3),y,3)

有人知道如何解决这个问题或以其他方式实现它吗?

【问题讨论】:

    标签: python sympy computer-algebra-systems symbolic-computation


    【解决方案1】:

    您可以使用 expr.removeO() 从表达式中删除大 O。


    Oneliner:expr.series(x, 0, 3).removeO().series(y, 0, 3).removeO()

    【讨论】:

    • 谢谢,此提示允许使用单行解决方案expr.series(x,x0=0,n=3).removeO().series(y,x0=0,n=3).removeO()。请将其添加到您的答案中,我会接受它:)
    【解决方案2】:

    这是一个用于 Sympy 的多元泰勒级数展开:

    def Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree):
        """
        Mathematical formulation reference:
        https://math.libretexts.org/Bookshelves/Calculus/Supplemental_Modules_(Calculus)/Multivariable_Calculus/3%3A_Topics_in_Partial_Derivatives/Taylor__Polynomials_of_Functions_of_Two_Variables
        :param function_expression: Sympy expression of the function
        :param variable_list: list. All variables to be approximated (to be "Taylorized")
        :param evaluation_point: list. Coordinates, where the function will be expressed
        :param degree: int. Total degree of the Taylor polynomial
        :return: Returns a Sympy expression of the Taylor series up to a given degree, of a given multivariate expression, approximated as a multivariate polynomial evaluated at the evaluation_point
        """
        from sympy import factorial, Matrix, prod
        import itertools
    
        n_var = len(variable_list)
        point_coordinates = [(i, j) for i, j in (zip(variable_list, evaluation_point))]  # list of tuples with variables and their evaluation_point coordinates, to later perform substitution
    
        deriv_orders = list(itertools.product(range(degree + 1), repeat=n_var))  # list with exponentials of the partial derivatives
        deriv_orders = [deriv_orders[i] for i in range(len(deriv_orders)) if sum(deriv_orders[i]) <= degree]  # Discarding some higher-order terms
        n_terms = len(deriv_orders)
        deriv_orders_as_input = [list(sum(list(zip(variable_list, deriv_orders[i])), ())) for i in range(n_terms)]  # Individual degree of each partial derivative, of each term
    
        polynomial = 0
        for i in range(n_terms):
            partial_derivatives_at_point = function_expression.diff(*deriv_orders_as_input[i]).subs(point_coordinates)  # e.g. df/(dx*dy**2)
            denominator = prod([factorial(j) for j in deriv_orders[i]])  # e.g. (1! * 2!)
            distances_powered = prod([(Matrix(variable_list) - Matrix(evaluation_point))[j] ** deriv_orders[i][j] for j in range(n_var)])  # e.g. (x-x0)*(y-y0)**2
            polynomial += partial_derivatives_at_point / denominator * distances_powered
        return polynomial
    

    这是一个二变量问题的验证,遵循以下练习和答案:https://math.libretexts.org/Bookshelves/Calculus/Supplemental_Modules_(Calculus)/Multivariable_Calculus/3%3A_Topics_in_Partial_Derivatives/Taylor__Polynomials_of_Functions_of_Two_Variables

    # Solving the exercises in section 13.7 of https://math.libretexts.org/Bookshelves/Calculus/Supplemental_Modules_(Calculus)/Multivariable_Calculus/3%3A_Topics_in_Partial_Derivatives/Taylor__Polynomials_of_Functions_of_Two_Variables
    from sympy import symbols, sqrt, atan, ln
    
    # Exercise 1
    x = symbols('x')
    y = symbols('y')
    function_expression = x*sqrt(y)
    variable_list = [x,y]
    evaluation_point = [1,4]
    degree=1
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    degree=2
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    
    # Exercise 3
    x = symbols('x')
    y = symbols('y')
    function_expression = atan(x+2*y)
    variable_list = [x,y]
    evaluation_point = [1,0]
    degree=1
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    degree=2
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    
    # Exercise 5
    x = symbols('x')
    y = symbols('y')
    function_expression = x**2*y + y**2
    variable_list = [x,y]
    evaluation_point = [1,3]
    degree=1
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    degree=2
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    
    # Exercise 7
    x = symbols('x')
    y = symbols('y')
    function_expression = ln(x**2+y**2+1)
    variable_list = [x,y]
    evaluation_point = [0,0]
    degree=1
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    degree=2
    print(Taylor_polynomial_sympy(function_expression, variable_list, evaluation_point, degree))
    

    对结果执行simplify() 会很有用。

    【讨论】:

      【解决方案3】:

      多元泰勒展开式

      def mtaylor(funexpr,x,mu,order=1):
      
          nvars = len(x)
          hlist = ['__h' + str(i+1) for i in range(nvars)]
          command=''
          command="symbols('"+'  '.join(hlist) +"')"
          hvar = eval(command)
          #mtaylor is utaylor for specificly defined function
          t = symbols('t')
          #substitution
          loc_funexpr = funexpr
          for i in range(nvars):
              locvar = x[i]
              locsubs = mu[i]+t*hvar[i]
              loc_funexpr = loc_funexpr.subs(locvar,locsubs)
          #calculate taylorseries
          g = 0
          for i in range(order+1):
              g+=loc_funexpr.diff(t,i).subs(t,0)*t**i/math.factorial(i)
      
          #resubstitute
          for i in range(nvars):
              g = g.subs(hlist[i],x[i]-mu[i])
      
          g = g.subs(t,1)    
          return g
      

      测试一些功能

      x1,x2,x3,x4,x5 = symbols('x1 x2 x3 x4 x5')
      funexpr=1+x1+x2+x1*x2+x1**3
      funexpr=cos(funexpr)
      x=[x1,x2,x3,x4,x5]
      mu=[1,1,1,1,1]
      mygee = mtaylor(funexpr,x,mu,order=4)
      print(mygee)
      

      【讨论】:

      猜你喜欢
      • 2011-08-21
      • 1970-01-01
      • 2017-04-05
      • 2017-04-02
      • 2014-07-11
      • 2020-04-01
      • 2022-06-18
      • 2016-08-09
      • 2019-05-27
      相关资源
      最近更新 更多