數學建模3 插值算法

數模比賽中,常常需要根據已知的函數點進行數據、模型的處理和分析,而有時候現有的數據是極少的,不足以支撐分析的進行,這時就需要使用一些數學的方法,“模擬產生”一些新的但又比較靠譜的值來滿足需求,這是就需要插值法。
插值法是數值分析中最基本的方法之一。 在實際問題中遇到的函數是許許多多的,有的甚至給不出表達式,只供給了一些離散數據,例如,在查對數表時,需要查的數值在表中卻找不到,所以只能先找到它相鄰的數,再從旁邊找出它的更正值,按一定的關係把相鄰的數加以更正,從而找出要找的數,這種更正關係事實上就是一種插值。在實際應用中,採用不同的插值函數,逼近的效果也不同。有五種基本的插值方法,有拉格朗日插值、牛頓插值、分段線性插值、分段三次埃爾米特插值和樣條插值函數。

一、一維插值問題

問題如下:已經有n+1個節點(xi,yi)(i=0,1,…n)其中xi互不相同,不妨假設a=x0<x1<…<xn=b,求任一插值點x*(!=xi)處的插值y*
在這裏插入圖片描述
思路:只需構造出函數fx,使得fx經過所有節點*,把x*代入fx函數中,即可得到y**。
通過上題思路,我們可以簡單理解插值法定義。
插值法定義:
在這裏插入圖片描述

二、插值法分類

一般分爲分段插值,插值多項式,三角插值。

三、插值法原理

在這裏插入圖片描述
多項式經過n+1個點,就可以寫出n+1個等式,解方程組就要把這些係數寫成矩陣的形式,A就是係數矩陣。A如果可逆有唯一解,即A的行列式不得0,A爲範德蒙德行列式,滿足可逆。

在這裏插入圖片描述

四、拉格朗日插值法

兩個點的:
在這裏插入圖片描述
三個點的:
在這裏插入圖片描述
四個點的:
在這裏插入圖片描述

在這裏插入圖片描述

拉格朗日插值法存在的問題:龍格現象
龍格現象:插值多項式次數越高誤差越小嗎?
在這裏插入圖片描述

高次插值會產生龍格現象,即在兩端處波動較大,產生明顯的震盪。在不熟悉曲線運動趨勢的前提下,不要輕易使用高次插值。
由以上可得,插值多項式次數高,精度未必顯著提高。那麼如何提高插值精度呢?因爲存在龍格現象,所以採用分段線性插值來解決。

五、分段插值在這裏插入圖片描述

1、分段線性插值

對於一個多項式的點,我們先找距離這個橫座標最近的兩個點,然後這兩個點連成一個線。然後根據橫座標的點,找到線上縱座標的點。一般我們常用分段二次插值或者分段三次插值。

2、分段二次插值

選取跟節點x最近的三個節點xi-1,xi,xi+1進行二次插值。即在每一個區間[xi-1,xi+1]上,取:
在這裏插入圖片描述
這種分段的低次插值稱爲分段二次插值,在幾何上就是用分段拋物線代替y=f(x),故分段二次插值又稱爲分段拋物插值。

3、牛頓插值法

在這裏插入圖片描述
評價:
與拉格朗日插值法相比,牛頓插值法的計算過程具有繼承性,牛頓插值法每次插值只和前面n項的值有關,這樣每次只要在原來的函數上添加新的項,就能夠產生新的函數,但是牛頓插值也存在龍格現象。

總結:
在這裏插入圖片描述
在這裏插入圖片描述
以上兩種插值法的缺點:1.存在龍格現象,2.上面的兩種插值僅僅要求插值多項式在插值點處與被插函數有相等的函數值,而這種插值多項式卻不能全面反映被插值函數的形態,在實際問題種,不僅僅要求被插函數和插值函數在所有節點處有相同的函數值,也需要在一個或全部節點上插值多項式與被插值函數有相同的低階或者高階的導數值。然而牛頓法和拉格朗日插值法都不能滿足。

4、埃爾米特插值

在這裏插入圖片描述
一般插值的要求是函數值要求,但是更高級的插值法的要求是導數值也要對應起來。甚至要求高階導數值也相等。滿足這種要求的插值多項式就是埃爾米特插值多項式。導數值對應起來的原因是保持插值曲線在節點處有切線,也就是保證曲線光滑,使插值函數和被插值函數的密和程度更好。
在這裏插入圖片描述
直接使用埃爾米特插值得到的多項式次數較高,也存在着龍格現象,因此在實際應用中,往往使用分段三次埃爾米特插值多項式。
分段三次埃爾米特插值,就是找四個點分段三次。

matlab有內置的函數:
p=pchip(x,y,new_x)
x是已知的樣本點的橫座標,y是已知的樣本點的縱座標;new_x是要插入處對應的橫座標。new_x是要插入處對應的橫座標。
例如:

x=-pi:pi;
y=sin(x);
new_x=-pi:0.1:pi;
p=pchip(x,y,new_x);
plot(x,y,'o',new_x,p,'r-')

繪製圖像如下:
在這裏插入圖片描述

5、三次樣條插值

在這裏插入圖片描述
由上可知:需要S(x)是一個三次多項式。還要求S(x)上二階連續可微。
在這裏插入圖片描述
matlab裏面的內置函數爲:spline
p=spline(x,y,new_x)


% 三次樣條插值和分段三次埃爾米特插值的對比
x = -pi:pi; 
y = sin(x); 
new_x = -pi:0.1:pi;
p1 = pchip(x,y,new_x);   %分段三次埃爾米特插值
p2 = spline(x,y,new_x);  %三次樣條插值
figure(2);
plot(x,y,'o',new_x,p1,'r-',new_x,p2,'b-')
legend('樣本點','三次埃爾米特插值','三次樣條插值','Location','SouthEast')   %標註顯示在東南方向
% 說明:
% LEGEND(string1,string2,string3,)
% 分別將字符串1、字符串2、字符串3⋯⋯標註到圖中,每個字符串對應的圖標爲畫圖時的圖標。
% ‘Location’用來指定標註顯示的位置

結果如下:
在這裏插入圖片描述
n維數據的插值:
在這裏插入圖片描述

% n維數據的插值
x = -pi:pi; y = sin(x); 
new_x = -pi:0.1:pi;
p = interpn (x, y, new_x, 'spline');
% 等價於 p = spline(x, y, new_x);
figure(3);
plot(x, y, 'o', new_x, p, 'r-')

舉例
根據過去10年的中國人口數據,預測接下來三年的人口數據:
population=[133126,133770,134413,135069,135738,136427,137122,137866,138639, 139538];



% 人口預測
population=[133126,133770,134413,135069,135738,136427,137122,137866,138639, 139538];
year = 2009:2018;
p1 = pchip(year, population, 2019:2021)  %分段三次埃爾米特插值預測
p2 = spline(year, population, 2019:2021) %三次樣條插值預測
figure(4);
plot(year, population,'o',2019:2021,p1,'r*-',2019:2021,p2,'bx-')
legend('樣本點','三次埃爾米特插值預測','三次樣條插值預測','Location','SouthEast')

在這裏插入圖片描述

plot函數用法:


% plot函數用法:
% plot(x1,y1,x2,y2) 
% 線方式: - 實線 :點線 -. 虛點線 - - 波折線 
% 點方式: . 圓點  +加號  * 星號  x x形  o 小圓
% 顏色: y黃; r紅; g綠; b藍; w白; k黑; m紫; c青


建模實例:
MathorCup第六屆A題 淡水養殖池塘水華髮生及池水淨化處理
附件一給的是1-15週數據,附件二給的是奇數1,3,5,…,15週數據
在這裏插入圖片描述
上面是數據,附件一中給出的是15周的數據,而附件二給出的是奇數十五週的數據。數據是不對稱的。最好的方法是將附件二中缺失的值使用插值算法插進去,使得附件二的數據也是15周。
答案代碼:

%插值預測中間周的水體評價指標
load Z.mat
x=Z(1,:); %Z的第一行是星期Z: 1     3     5     7     9    11    13    15
[n,m]=size(Z);%n爲Z的行數,m爲Z的列數
% 注意Matlab的數組中不能保存字符串,如果要生成字符串數組,就需要使用元胞數組,其用大括號{}定義和引用
ylab={'週數','輪蟲','溶氧','COD','水溫','PH值','鹽度','透明度','總鹼度','氯離子','透明度','生物量'};  % 等會要畫的圖形的標籤
disp(['共有' num2str(n-1) '個指標要進行插值。'])
disp('正在對一號池三次埃爾米特插值,請等待')%一號池共有十一組要插值的數據,算上星期所在的第一行,共十二行
P=zeros(11,15);%對要儲存數據的矩陣P賦予初值
for i=2:n%從第二行開始都是要進行插值的指標
    y=Z(i,:);%將每一行依次賦值給y
    new_x=1:15;%要進行插值的x
    p1=pchip(x,y,new_x);%調用三次埃爾米特插值函數
    subplot(4,3,i-1);%將所有圖依次變現在4*3的一幅大圖上
    plot(x,y,'ro',new_x,p1,'-');%畫出每次循環處理後的圖像
    axis([0 15,-inf,inf])  %設置座標軸的範圍,這裏設置橫座標軸0-15,縱座標不變化
    %  xlabel('星期')%x軸標題
    ylabel(ylab{i})%y軸標題  這裏是直接引用元胞數組中的字符串哦
    P(i-1,:)=p1;%將每次插值之後的結果保存在P矩陣中       
end
legend('原始數據','三次埃爾米特插值數據','Location','SouthEast')%加上標註,注意要手動在圖中拖動標註到圖片右下角哦
P = [1:15; P]  %把P的第一行加上週數

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章