斐波那契(Fibonacci)迭代法求解函數極值(附代碼)

目錄

Fibonacci數列:

迭代公式:

算法步驟:

例題

C++代碼:


Fibonacci數列又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖爲例子而引入,故又稱爲“兔子數列”,Fibonacci迭代法可以求解函數零點、函數極值等,本文用c++語言實現Fibonacci迭代法求解函數極值。

Fibonacci數列:

                                     \left\{\begin{matrix} F_{0}=F{1}=1\\ F_{i+1}=F_{i-1}+F_{i},i=1,2,... \end{matrix}\right.

迭代公式:

                        \left\{\begin{matrix} \lambda _{k}=a_{k}+\frac{F_{n-k-1}}{F_{n-k+1}}(b_{k}-a_{k}),k=1,2,...,n-1\\ \mu _{k}=a_{k}+\frac{F_{n-k}}{F_{n-k+1}}(b_{k}-a_{k}),k=1,2,...,n-1 \end{matrix}\right.

算法步驟:

step1.給定初始搜索區間[a_{1},b_{1}]和允許誤差\varepsilon,辨別係數\delta> 0,求解迭代次數n,使

                                        F_{n}\geqslant \frac{b_{1}-a_{1}}{\varepsilon }

step2.計算初始值

                                \left\{\begin{matrix} \lambda _{1}=a_{1}+\frac{F_{n-2}}{F_{n}}(b_{1}-a_{1})\\\mu _{1}=a_{1}+\frac{F_{n-1}}{F_{n}}(b _{1}-a_{1})\\f_{\lambda }=f(\lambda _{1})\\f_{\mu }=f(\mu _{1}) \end{matrix}\right.

step3.開始循環k=k+1,轉step4,若k>=n-2則退出循環,轉step7.

step4 判斷f_{\lambda }<f_{\mu }?,是轉step5,否轉step6;

step5.令

               a_{k+1}=a_{k},b_{k+1}=\mu _{k},\mu _{k+1}=\lambda _{k},f_{\mu }=f_{\lambda }

               \lambda _{k+1}=a_{k+1}+\frac{F_{n-k-2}}{F_{n-k}}(b_{k+1}-a_{k+1})

               f_{\lambda }=f(\lambda _{k +1})

step6.令

               a_{k+1}=\lambda _{k},b_{k+1}=b _{k},\lambda _{k+1}=\mu _{k},f_{\lambda }=f_{\mu }

               \mu _{k+1}=a_{k+1}+\frac{F_{n-k-1}}{F_{n-k}}(b_{k+1}-a_{k+1})

               f_{\mu }=f(\mu _{k +1})

step7.令

          \lambda _{n}=\lambda _{n-1}\mu _{n}=\lambda _{n-1}+\delta

          判斷f_{\lambda_{n} }<f_{\mu_{n} }?,是,極小點所在的區間爲[a _{n-1},\mu _{n}];否,極小點所在的區間爲[\lambda _{n},b _{n-1}]

          極值點爲:                                                                   

                         f_{min}=(f_a_{n} +f_b_{n})/2

例題

求解函數f(x)=x^{2}-x+2在區間[-1,3]上的極小點,要求求解的區間不大於原始區間長度的0.0008倍。

程序求解結果如圖:

 

C++代碼:

#include <iostream>
#include <vector>
#include <iomanip> 
using namespace std;
double fx(double x)
{
	double fx;
	fx = pow(x, 2) - x + 2;
	return fx;
}
int main()
{
	double epsilon = 0.08, f_min;
	vector<double>fn(2);
	fn[0] = 1; fn[1] = 1;
	int i;
	double a_fib = -1.0, b_fib = 3.0, f_lambda = 0, f_mu = 0;
	for (i = 2; fn[i - 1] < 1.0 / epsilon; i++)
	{
		fn.push_back(fn[i - 2] + fn[i - 1]);
	}
	int n_fib = i - 1;
	cout <<"n取值:    "<< n_fib <<endl << endl;
	double lambda = a_fib + (fn[n_fib - 2] / fn[n_fib])*(b_fib - a_fib), mu = a_fib + (fn[n_fib -1] / fn[n_fib])*(b_fib - a_fib);
	f_lambda = fx(lambda);
	f_mu = fx(mu);
	cout << "區間迭代:  " <<  endl;
	for (int i = 0; i < n_fib-2; i++)
	{
		if ( f_lambda<f_mu)
		{
			a_fib = a_fib, b_fib = mu, mu = lambda, f_mu = f_lambda;
			lambda = a_fib + (fn[n_fib - i - 3] / fn[n_fib-1 - i])*(b_fib - a_fib);
			f_lambda = fx(lambda);
		}
		else
		{
			a_fib = lambda, b_fib = b_fib, lambda = mu, f_lambda = f_mu;
			mu = a_fib + (fn[n_fib - i - 2] / fn[n_fib -1-i])*(b_fib - a_fib);
			f_mu = fx(mu);
		}
		cout << fixed << setw(12) << setprecision(5) << a_fib << fixed << setw(12) << setprecision(5) << lambda << fixed << setw(12) << setprecision(5) << mu << fixed << setw(12) << setprecision(5) << b_fib << endl;
	}
	mu = lambda + 0.001;
	f_mu = fx(mu);
	if (f_lambda < f_mu)
	{
		a_fib = a_fib, b_fib = mu,f_min=0.5*(fx(a_fib)+fx(b_fib));
	}
	else 
	{
		a_fib = lambda, b_fib = b_fib, f_min = 0.5*(fx(a_fib) + fx(b_fib));

	}
	cout << endl << "極小值區間:" << fixed << setw(9) << setprecision(5) << a_fib << fixed << setw(12) << setprecision(5) << b_fib << endl;
	cout << "極小值:  " << fixed << setw(12) << setprecision(5) << f_min << endl;
}

 

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