ラグランジュ補間
0.はじめに
学校の課題です。余談ですが、実験3.3のグラフがロールシャッハテストに見えません?
1.概説
ラグランジュ補間とは数値解析において、データ群を多項式で表し一意的な関数で補間する、多項式補間に用いられる手法である。名称は1795年の本手法の発表者である18世紀のフランス数学者であるジョゼフ=ルイ・ラグランジュに因んだものだが、それより以前にイギリスの数学者であるエドワード・ウェアリングが発見者であるといわれている。
2.説明
ラグランジュ補間は複数のデータに対して連続した関数を求めたい際に用いられる手法である。データ群から関数を導出する手法といえば最小二乗法が有名であると思うが、本手法を含めた多項式補間はそれらと違い、各点の推移ではなくその座標を性格に通る関数となっている。即ち、データ群を全て正確なものとして扱っているので、全データを通過点とするような関数が導出される。
2.1 ルンゲ現象
ルンゲ現象とは、多項式補間において導出関数の次数の増加に対して誤差が大きくなってしまう問題である。
本来であれば、データが多いほど次数もあがり関数も一意的なものへと収束していくはずだが、後述の実験のように特定の関数に対しては次数の増加に伴い誤差が大きくなってしまう。このような関数をルンゲ関数、もしくはコーシー・ローレンツ関数と呼ぶ。
関数とN次補間多項式の誤差は、関数のN次導関数に制限される。このことから関数の導関数が増加するような関数に対してはルンゲ現象が発生してしまうのだと考えられる。
2.2 多項式補間
ラグランジュ補間多項式は等間隔で取った節点だと上下に振動するような大きな誤差を起こすルンゲ現象の可能性がある。これを防ぐためには節点を等間隔ではなくチェビシェフ多項式より求められるチェビシェフ節点を用いると解消される。
3.実験
以下にラグランジュ補間を行うプログラムの条件と入出力を示す。
3.1 実験1
条件:(1,1),(3,2),(4,5)をデータ群とする
入力:区間を-1,5と入力
出力:
https://gyazo.com/7ff140fa8649a4f07a1ed5e0d687b354
3.2 実験2
条件:$ \frac{1}{1+25x^2}をデータ群用関数とし、入力値分等間隔にデータを取る
入力:データ個数を5個と入力、データ区間を-1,1と入力
出力:
https://gyazo.com/79b1b11308310e70b5cf9fc46296a15e
3.3 実験3
条件:$ \frac{1}{1+25x^2}をデータ群用関数とし、入力値分等間隔にデータを取る
入力:データ個数を11個と入力、データ区間を-1,1と入力
出力:
https://gyazo.com/7d0745af24d2a9a932591ac48b49fff7
3.4 実験4
条件:$ \frac{1}{1+25x^2}をデータ群用関数とし、入力値分等間隔にデータを取る
入力:データ個数を21個と入力、データ区間を-1,1と入力
出力:
https://gyazo.com/7e461735b6cf61e0fce18289f4430e5c
4.参考文献
森北出版 数値計算法 第2版 新装版
5.サンプルプログラム
以下に実験1と実験2 3 4で用いたプログラムを添付する。
code:lagrange.py
import math
import matplotlib.pyplot as plt
def lagrange(f_x,f_y,f_ans_x):
result =0
for k in range(len(f_x)):
z = 1
for i in range(len(f_x)):
if not(i==k):
z=z*(f_ans_x - f_xi)/(f_xk - f_xi) result = result + (f_yk*z) return result
if __name__=='__main__':
result_x = []
result_y = []
_start = int(input("Please input range start point.(integer)"))
_end = int(input("Please input range end point.(integer)"))
for ans_x in range(_start*10,_end*10):
ans_y = lagrange(_x,_y,ans_x/10)
result_x.append(ans_x/10)
result_y.append(ans_y)
print("ans_x=" +str(ans_x/10) + "ans_y="+str(ans_y))
plt.plot(result_x,result_y,marker="v",color ="blue",linestyle = ":")
plt.legend()
plt.show()
code:runge.py
import math
import matplotlib.pyplot as plt
def lagrange(f_x,f_y,f_ans_x):
result =0
for k in range(len(f_x)):
z = 1
for i in range(len(f_x)):
if not(i==k):
z=z*(f_ans_x - f_xi)/(f_xk - f_xi) result = result + (f_yk*z) return result
def target(f_x):
f_y = 1/(1+25*f_x*f_x)
return f_y
if __name__=='__main__':
plot_num = int(input("Please input plot num.(intger)"))
_x = []
_y = []
for i in range(plot_num):
_x.append(i*(2/(plot_num-1))-1)
print(_x)
print(_y)
result_x = []
result_y = []
_start = int(input("Please input range start point.(integer)"))
_end = int(input("Please input range end point.(integer)"))
for ans_x in range(_start*10,_end*10+1):
ans_y = lagrange(_x,_y,ans_x/10)
result_x.append(ans_x/10)
result_y.append(ans_y)
print("ans_x=" +str(ans_x/10) + "ans_y="+str(ans_y))
plt.plot(result_x,result_y,marker="v",color ="blue",linestyle = ":")
plt.legend()
plt.show()
https://gyazo.com/4031bb41108a1756d5556efc02346660記述日:2021年01月09日03:38https://gyazo.com/0902b55512d817b36596c44228e2d840 https://twitter.com/intent/tweet?text=%E3%81%B2%E3%82%86%E3%81%86%E3%81%AF%E3%81%98%E3%82%81%E3%81%95%E3%82%93%E3%81%AEScrapbox%E3%81%AE%E8%A8%98%E4%BA%8B%E3%82%92%E5%85%B1%E6%9C%89%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82%0D%0Ahttps://scrapbox.io/hiyu-hajime/%25E3%2583%25A9%25E3%2582%25B0%25E3%2583%25A9%25E3%2583%25B3%25E3%2582%25B8%25E3%2583%25A5%25E8%25A3%259C%25E9%2596%2593