ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

【最优化】C++实现逐次插值逼近法(三点二次插值法)

2021-12-08 00:02:38  阅读:168  来源: 互联网

标签:alpha2 alpha3 f2 alpha1 插值法 double C++ 插值逼近 alpha


三点二次插值法代码

#include <iostream>
#include <cmath>
#include <random>
#include <ctime>

int SEED = 0; // 用于设置不同的种子,防止产生相同的随机情况

// 课本P137第6题函数
double f(double t) {
    return 1 - t * exp(- t * t);
}

// 课本P114例3.3.2
double f1(double t) {
    return t*t*t - 3*t + 2;
}

// 产生区间内的随机数
double get_alpha(double a, double b) {
    SEED++; // 每调用一次函数改变一次种子,防止产生相同的随机情况

    std::default_random_engine e; // 新建随机数引擎对象
    e.seed(SEED); // 撒下种子

    // 在此确定随机数区间
    std::uniform_real_distribution<double> u(a,b); // 左闭右闭区间[a,b]
    double alpha = u(e);

    return alpha;
}

// 确定3个alpha,参数传入三个alpha的指针地址
void get3alpha(double(*f)(double), double a, double b, double *alpha1, double *alpha2, double *alpha3, double *f1, double *f2, double *f3) {
    while (true) {
        *alpha1 = get_alpha(a, b);
        *alpha2 = get_alpha(*alpha1, b);
        *alpha3 = get_alpha(*alpha2, b);

        *f1 = f(*alpha1);
        *f2 = f(*alpha2);
        *f3 = f(*alpha3);

        if (*f1 > *f2 && *f3 > *f2) break;
    }
}

/*!
 * 三点二次插值法
 * @param f
 * @param a
 * @param b
 * @return
 */
double three_point_interpolation(double(*f)(double), double a, double b) {
    int iteration = 0;
    double epsilon1 = 0.001;
    double epsilon2 = 0.00001;

    // step 0
    double alpha1, alpha2, alpha3, f1, f2, f3;
    get3alpha(f, a, b, &alpha1, &alpha2, &alpha3, &f1, &f2, &f3);

    double alpha_hat, f_hat = 0;
    while (true) {
        // step 1
        alpha_hat = 0.5 * ( (alpha2 * alpha2 - alpha3 * alpha3) * f1 + (alpha3 * alpha3 - alpha1 * alpha1) * f2 + (alpha1 * alpha1 - alpha2 * alpha2) * f3 ) / ( (alpha2 - alpha3) * f1 + (alpha3 - alpha1) * f2 + (alpha1 - alpha2) * f3 );
        f_hat = f(alpha_hat);

        // step 2
        if (alpha_hat > alpha2) {
            // step 3
            if (f_hat <= f2) {
                alpha1 = alpha2;
                alpha2 = alpha_hat;
                f1 = f2;
                f2 = f_hat; // turn to step 5
            } else {
                alpha3 = alpha_hat;
                f3 = f_hat; // turn to step 5
            }
        } else {
            // step 4
            if (f_hat <= f2) {
                alpha3 = alpha2;
                alpha2 = alpha_hat;
                f3 = f2;
                f2 = f_hat; // turn to step 5
            } else {
                alpha1 = alpha_hat;
                f1 = f_hat; // turn to step 5
            }
        }

        // step 5
        if (std::abs(f2) >= epsilon2) {
            if (std::abs(f2 - f_hat) <= epsilon1 * std::abs(f2)) break;
        } else {
            if (std::abs(f2 - f_hat) <= epsilon1) break;
        }
        iteration++; // test
        std::cout << iteration << std::endl; // test
    }

    // step 5
    if (f_hat < f2) return f_hat;
    else return alpha2;
}

int main() {
    double x = three_point_interpolation(f, 0, 1);
    std::cout << "x* = " << x << std::endl;
    std::cout << "f(x*) = " << f(x) << std::endl;
    return 0;
}

结果:

标签:alpha2,alpha3,f2,alpha1,插值法,double,C++,插值逼近,alpha
来源: https://blog.csdn.net/onion23/article/details/121781560

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有