【Python算法】数值分析—拉格朗日插值法(1-未知原函数做预测)——附源码

一、背景

        拉格朗日插值法可在未知原函数,只知道节点值、节点函数值时,以多项式的形式拟合出原函数。

对于已知原函数,想分析拟合结果的讨论,请移步2-已知原函数做拟合分析

拟合出的多项式:

L_{n} (x)=l_{i}(x)*f(x_{i})

l_{i}(x)=\frac{(x-x_{0}) \dots (x-x_{i-1})(x-x_{i+1})\dots(x-x_{n})}{(x_{i} -x_{0}) \dots (x_{i}-x_{i-1})(x_{i}-x_{i+1})\dots(x_{i}-x_{n})}

x_{i}f(x_{i})是已知量,是实际容易测得的值,如一天内的时间和温度值,其拟合出的L_{n} (x)就是温度关于时间变化的函数表达式

二、函数逻辑(function文件,完整代码在文末

         逻辑思路:

  • 计算l_{i} (x)的分子
  • 计算l_{i} (x)的分母
  • 通过 l_{i} (x)的分子分母组合出L_{n} (x)

 1.计算l_{i} (x)的分子

def get_li_numerator(list_x):
    """ 计算li(x)的分子部分,返回分子的表达式 """
    x = sp.symbols('x')
    numerator = [1 for _ in range(0, len(list_x))]  # 初始化分子列表,全置为1
    for i in list(range(0, len(list_x))):
        for j in list(range(0, len(list_x))):
            # 循环计算到自己时,跳过此次循环
            if j == i:
                continue
            value_item = x - list_x[j]
            numerator[i] = numerator[i] * value_item
    return numerator

 2.计算l_{i} (x)的分母

def get_li_denominator(list_x):
    """ 计算li(x)的分母部分 """
    denominator = [1 for _ in range(0, len(list_x))]  # 初始化分母列表,全置为1
    for i in list(range(0, len(list_x))):
        for j in list(range(0, len(list_x))):
            # 循环计算到自己时,跳过此次循环
            if j == i:
                continue
            value_item = list_x[i] - list_x[j]
            denominator[i] = denominator[i] * value_item
    return denominator

 3.组合出l_{i} (x)的表达式

def get_expression_li(list_x):
    """ 计算li(x)的表达式 """
    # 获取分子表达式
    numerator = get_li_numerator(list_x)
    # 获取分母的数值列表
    denominator = get_li_denominator(list_x)
    # 初始化li的表达式列表
    expression_li = []
    for i in list(range(0, len(numerator))):
        expression_li.append(numerator[i] / denominator[i])
    return expression_li

4.组合出L_{n} (x)表达式

def get_expression_lagrange(list_fx, list_x):
    """ 获取拉格朗日差值多项式的表达式 """
    # 获取li(x)的表达式
    expression_li = get_expression_li(list_x)
    # 初始化拉格朗日插值多项式为0
    expression_lagrange = 0
    for i in list(range(0, len(list_x))):
        expression_lagrange += expression_li[i] * list_fx[i]
    return expression_lagrange

 5.使用拟合出的多项式,对一点进行求值以此来做预测

def get_value_expression_lagrange(expression_lagrange,  # 拉格朗日差值多项式的表达式
                                  x,  # 某一点x
                                  precision=5  # 计算保留的有效数字
                                  ):
    """ 计算拉格朗日差值多项式在某一点x的值 """
    return expression_lagrange.evalf(subs={'x': x}, n=precision)

三、最终实现(main文件,完整代码

import function as fun
import sympy as sp


x = sp.symbols('x')
# 设置原始数据,节点值、节点函数值
list_x = [0, 0.2, 0.4, 0.6, 0.8, 1]
list_fx = [1, 2, 3, 4, 5, 6]
# 设置待预测的点
interpolation_x = 2
# 计算拉格朗日插值多项式
expression_lagrange = fun.get_expression_lagrange(list_fx, list_x)
# 计算该多项式在计算点的值
result_interpolation = fun.get_value_expression_lagrange(expression_lagrange, interpolation_x)

 简单输出结果

print("拉格朗日插值多项式:", expression_lagrange)
print("插值结果:", result_interpolation)

部分结果展示 


function文件完整代码

import sympy as sp


def get_li_numerator(list_x):
    """ 计算li(x)的分子部分,返回分子的表达式 """
    x = sp.symbols('x')
    numerator = [1 for _ in range(0, len(list_x))]  # 初始化分子列表,全置为1
    for i in list(range(0, len(list_x))):
        for j in list(range(0, len(list_x))):
            # 循环计算到自己时,跳过此次循环
            if j == i:
                continue
            value_item = x - list_x[j]
            numerator[i] = numerator[i] * value_item
    return numerator


def get_li_denominator(list_x):
    """ 计算li(x)的分母部分 """
    denominator = [1 for _ in range(0, len(list_x))]  # 初始化分母列表,全置为1
    for i in list(range(0, len(list_x))):
        for j in list(range(0, len(list_x))):
            # 循环计算到自己时,跳过此次循环
            if j == i:
                continue
            value_item = list_x[i] - list_x[j]
            denominator[i] = denominator[i] * value_item
    return denominator


def get_expression_li(list_x):
    """ 计算li(x)的表达式 """
    # 获取分子表达式
    numerator = get_li_numerator(list_x)
    # 获取分母的数值列表
    denominator = get_li_denominator(list_x)
    # 初始化li的表达式列表
    expression_li = []
    for i in list(range(0, len(numerator))):
        expression_li.append(numerator[i] / denominator[i])
    return expression_li


def get_expression_lagrange(list_fx, list_x):
    """ 获取拉格朗日差值多项式的表达式 """
    # 获取li(x)的表达式
    expression_li = get_expression_li(list_x)
    # 初始化拉格朗日插值多项式为0
    expression_lagrange = 0
    for i in list(range(0, len(list_x))):
        expression_lagrange += expression_li[i] * list_fx[i]
    return expression_lagrange


def get_value_expression_lagrange(expression_lagrange,  # 拉格朗日差值多项式的表达式
                                  x,  # 某一点x
                                  precision=5  # 计算保留的有效数字
                                  ):
    """ 计算拉格朗日差值多项式在某一点x的值 """
    return expression_lagrange.evalf(subs={'x': x}, n=precision)

demo源码链接如下

github地址:https://github.com/method_lagrange_interpolation

gitee地址:https://gitee.com/darlingxyz/method_lagrange_interpolation

你可能感兴趣的:(数学物理编程,python,算法,pycharm,线性代数)