理论见参考《Practical Optimization》中4.5节,代码实现如下:(
可以将黄金分割法和二次插值法结合起来,想用黄金分割法快速搜索得到最优解,然后用该最优解作为二次插值的初值,可以提高计算精度。Matlab中就是采用此组合策略。
)
OneDimensionalOptimization.h
#ifndef _OneDimensionalOptimization_ #define _OneDimensionalOptimization_ #include <algorithm> using namespace std; class OneDimensionalOptimization { public: //参考《Practical Optimization》中4.5节 double quadraticInterpolationSearch(double(*p)(double x),double& l, double& u, double& x, double tol = 1e-6); }; #endif
OneDimensionalOptimization.cpp
double OneDimensionalOptimization::quadraticInterpolationSearch(double(*p)(double x),double& l, double& u, double& x, double tol) { int mm = 0; //1) double x1 = l; double x3 = u; double x0_aver = 1e99; //2) double x2 = 0.5 * (x1 + x3); double f1 = p(x1); double f2 = p(x2); double f3 = p(x3); //3) while(true) { mm++; double x_aver = ((x2*x2 - x3*x3)*f1 + (x3*x3 - x1*x1)*f2 + (x1*x1 - x2*x2)*f3 )/(2*((x2 - x3)*f1 + (x3 - x1)*f2 + (x1 - x2)*f3)); double f_aver = p(x_aver); if(abs(x_aver - x0_aver) < tol) { x = x_aver; return f_aver; } //4) if(x1 < x_aver && x_aver < x2) { if(f_aver <= f2) { x3 = x2; f3 = f2; x2 = x_aver; f2 = f_aver; } else { x1 = x_aver; f1 = f_aver; } } else if(x2 < x_aver && x_aver < x3) { if(f_aver <= f2) { x1 = x2; f1 = f2; x2 = x_aver; f2 = f_aver; } else { x3 = x_aver; f3 = f_aver; } } x0_aver = x_aver;} }
测试代码如下:
main.cpp#include "src\Optimizer\OneDimensionalOptimization.h" #include <fstream> using namespace std; double p(double x) { return -sin(x); } int main(int argv, char** argc) { OneDimensionalOptimization* one = new OneDimensionalOptimization(); double l = 0; double u = 2*3.1415926; double x; double res1 = one->quadraticInterpolationSearch(p,l,u,x,1e-10); return 1; }