[수치 해석] 파이썬 구현 라그랑주 보간

오늘 할 수있는 아무것도에 대한 코드에서이 보간 공식을 달성하기 위해 노력 해왔다 시도하려고합니다.

라그랑주 보간 기동의 간단한 시작! 라그랑주 보간의 기본 사항은 공식, 세부 사항으로 이동 바이두에 많이 검색하지.

기본적인 아이디어는 먼저 원하는 입력의 수와 예상 지점 기반 함수 얻어진 최종 계산 결과에 따라 적절한 샘플 포인트 X 보간 구간을 선택하기 위해, 주어진 샘플 포인트로 파일로부터 판독된다. 코드에서 직접 봐! (참고 : 지점을 여기에 샘플이 매우 정확 아니라고, 정말 난처한 상황에 빠진 더 나은 설명을 찾을 수 없습니다 ...)

str2double

작은 문제가 부동 소수점으로 STR 형 파이썬을 변환하는 방법입니다에게, 우리가 제공 한 후 모든 샘플 포인트는 반드시 항상 정수가되지 않고, 또한 여러으로, 일부 내결함성 처리를 할 필요가 + 더 - 그래서, 그것은해야 정확한 숫자를 식별합니다. 그래서 str2double 방법을 구현한다.

import re
def str2double(str_num):
    pattern = re.compile(r'^((\+*)|(\-*))?(\d+)(.(\d+))?$')
    m = pattern.match(str_num)
    if m is None:
        return m
    else:
        sign = 1 if str_num[0] == '+' or '0' <= str_num[0] <= '9' else -1
        num = re.sub(r'(\++)|(\-+)', "", m.group(0))
        matchObj = re.match(r'^\d+$', num)
        if matchObj is not None:
            num = sign * int(matchObj.group(0))
        else:
            matchObj = re.match(r'^(\d+).(\d+)$', num)
            if matchObj is not None:
                integer = int(matchObj.group(1))
                fraction = int(matchObj.group(2)) * pow(10, -1*(len(matchObj.group(2))))
                num = sign * (integer + fraction)
        return num

내가 달성하기 위해 정규 표현식을 사용하여 pattern = re.compile(r'^((\+*)|(\-*))?(\d+)(.(\d+))?$')정수 내가 위에서 언급 한 부동 소수점의 모든 유형을 일치시킬 수 있습니다 그들이 정수, 직접 반환의 정수 부분 인 경우, 경기 후, 경기는이와 함께, 성공적으로 (int)주조 할 수있는, 그것은 부동 인 경우 포인트는, 다음 사용 (\d+)을 다시 일치하는 정규 표현을 각각 정수와 정수 부분의 상기 처리와 유사한 소수 부분은, 소수 부분이 곱해 pow(10, -小数位数)첨가 될 수 직후 결과로서 생기는. 여기서 + 또는 복수의 지원하기 위해 - 심볼을 제거하고 있으므로 부호가 최종 창 승산 할 수있는 경우, 디지털 서명은 긍정적이거나 부정적 녹화해야 사용의 re.sub 방법.

def binary_search(point_set, n, x):
    first = 0
    length = len(point_set)
    last = length
    while first < last:
        mid = (first + last) // 2
        if point_set[mid][0] < x:
            first = mid + 1
        elif point_set[mid][0] == x:
            return mid
        else:
            last = mid
    last =  last if last != length else last-1

    head = last - 1
    tail = last
    while n > 0:
        if head != -1:
            n -= 1
            head -= 1
        if tail != length:
            n -= 1
            tail += 1
    return [head+1, tail-1] if n == 0 else [head+1, tail-2]

여기서 모든 시료의 point_set 점들의 세트이고, N 보간 입력의 수이고, X는 입력 제안 점이다. 패킷 (X)의 내부, 즉, 가능한 한 적절한 보간 간격을 반환.

상기 입력에 따라 적절한 보간 간격을 얻기 때문에이 기술을 찾는 것을 포함하기 때문이다. 본원에 사용 된 바와 같이, 이진 검색은 제 1 샘플 포인트 세트는 point_set보간 충족 요건의 수까지 확장 된 간격 모두 상기 제 1 샘플 포인트가 예측 된 시점의 요구보다 큰 발견 (오름차순)으로 정렬된다. 여기에 몇 가지 문제가 발생할 수 있음을 깨달았다 n=-1로 인해 tail두 번 지불하고, while외부 루프는 판사, 실시하고 있습니다 n=-1tail-2,이 구현은 확실히 좋지 않다, 버그가있을 수 있습니다. . .

마지막으로, 나머지 내용을 더 잘 이해하고, 직접 모든 코드를 넣습니다.

import re
import matplotlib.pyplot as plt
import numpy as np

def str2double(str_num):
    pattern = re.compile(r'^((\+*)|(\-*))?(\d+)(.(\d+))?$')
    m = pattern.match(str_num)
    if m is None:
        return m
    else:
        sign = 1 if str_num[0] == '+' or '0' <= str_num[0] <= '9' else -1
        num = re.sub(r'(\++)|(\-+)', "", m.group(0))
        matchObj = re.match(r'^\d+$', num)
        if matchObj is not None:
            num = sign * int(matchObj.group(0))
        else:
            matchObj = re.match(r'^(\d+).(\d+)$', num)
            if matchObj is not None:
                integer = int(matchObj.group(1))
                fraction = int(matchObj.group(2)) * pow(10, -1*(len(matchObj.group(2))))
                num = sign * (integer + fraction)
        return num

def preprocess():
    f = open("input.txt", "r")
    lines = f.readlines()
    lines = [line.strip('\n') for line in lines]
    point_set = list()
    for line in lines:
        point = list(filter(None, line.split(" ")))
        point = [str2double(pos) for pos in point]
        point_set.append(point)
    return point_set

def lagrangeFit(point_set, x):
    res = 0
    for i in range(len(point_set)):
        L = 1
        for j in range(len(point_set)):
            if i == j:
                continue
            else:
                L = L * (x - point_set[j][0]) / (point_set[i][0] - point_set[j][0])
        L = L * point_set[i][1]
        res += L
    return res

def showbasis(point_set):
    print("Lagrange Basis Function:\n")
    for i in range(len(point_set)):
        top = ""
        buttom = ""
        for j in range(len(point_set)):
            if i == j:
                continue
            else:
                top += "(x-{})".format(point_set[j][0])
                buttom += "({}-{})".format(point_set[i][0], point_set[j][0])
        print("Basis function{}:".format(i))
        print("\t\t{}".format(top))
        print("\t\t{}".format(buttom))

def binary_search(point_set, n, x):
    first = 0
    length = len(point_set)
    last = length
    while first < last:
        mid = (first + last) // 2
        if point_set[mid][0] < x:
            first = mid + 1
        elif point_set[mid][0] == x:
            return mid
        else:
            last = mid
    last =  last if last != length else last-1

    head = last - 1
    tail = last
    while n > 0:
        if head != -1:
            n -= 1
            head -= 1
        if tail != length:
            n -= 1
            tail += 1
    return [head+1, tail-1] if n == 0 else [head+1, tail-2]

if __name__ == '__main__':
    pred_x = input("Predict x:")
    pred_x = float(pred_x)
    n = input("Interpolation times:")
    n = int(n)
    point_set = preprocess()
    point_set = sorted(point_set, key=lambda a: a[0])
    span = binary_search(point_set, n+1, pred_x)
    print("Chosen points: {}".format(point_set[span[0]:span[1]+1]))
    showbasis(point_set[span[0]:span[1]+1])

    X = np.linspace(-np.pi, np.pi, 256, endpoint=True)
    S = np.sin(X)
    L = [lagrangeFit(point_set, x) for x in X]
    L1 = [lagrangeFit(point_set[span[0]:span[1]+1], x) for x in X]
    
    plt.figure(figsize=(8, 4))
    plt.plot(X, S, label="$sin(x)$", color="red", linewidth=2)
    plt.plot(X, L, label="$LagrangeFit-all$", color="blue", linewidth=2)
    plt.plot(X, L1, label="$LagrangeFit-special$", color="green", linewidth=2)
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title("$sin(x)$ and Lagrange Fit")
    plt.legend()
    plt.show()

입력 소개

라인, 중간에 공간의 각 포인트에 대한 읽기에 사용되는 샘플 포인트 input.txt를.

결과

꽤 좋은 재미 HHH 느낌, 뉴턴 보간 며칠 시도! 바이 바이!

추천

출처www.cnblogs.com/LuoboLiam/p/11706151.html