- main.cpp
#include <iostream>
#include <cmath>
#include "Search.h"
using namespace std;
double fun(double x){
return 0.05 * (x*x + 10 * sin(x));
}
int main()
{
double min_x, min_y;
int k;
int number;
do
{
std::cout << "Please chose a search method : \n";
std::cout << "1.Violent search" << endl;
std::cout << "2.Interval elimination search" << endl;
std::cout << "3.Golden section search" << endl;
std::cout << "4.Fibonacci search" << endl;
std::cout << "5.Exit" << endl;
std::cin >> number; //输入number的数值
std::cout << "You entered: " << number << std::endl;
switch (number)
{
case 1:
std::tie(min_x, min_y, k) = violent_search(fun, -5, 0, 0.1);
std::cout << "Minimum x: " << min_x << std::endl;
std::cout << "Minimum y: " << min_y << std::endl;
std::cout << "Iterations: " << k << std::endl;
break;
case 2:
std::tie(min_x, min_y, k) = interval_elimination_search(fun, -5, 0, 0.1);
std::cout << "Minimum x: " << min_x << std::endl;
std::cout << "Minimum y: " << min_y << std::endl;
std::cout << "Iterations: " << k << std::endl;
break;
case 3:
std::tie(min_x, min_y, k) = golden_section_search(fun, -5, 0, 0.1);
std::cout << "Minimum x: " << min_x << std::endl;
std::cout << "Minimum y: " << min_y << std::endl;
std::cout << "Iterations: " << k << std::endl;
break;
case 4:
std::tie(min_x, min_y, k) = fibonacci_search(fun, -5, 0, 0.1);
std::cout << "Minimum x: " << min_x << std::endl;
std::cout << "Minimum y: " << min_y << std::endl;
std::cout << "Iterations: " << k << std::endl;
break;
}
} while (number!=5);
return 0;
}
- Search.h
#ifndef SEARCH_H
#define SEARCH_H
#include <functional>
#include <tuple>
#include <chrono>
#include <iostream>
#include <vector>
std::tuple<double, double, int> violent_search(std::function<double(double)> fun_input, double x_min,double x_max,double epsilon);
std::tuple <double, double, int> interval_elimination_search(std::function<double(double)> fun_input, double x_min, double x_max, double epsilon);
std::tuple <double, double, int> golden_section_search(std::function<double(double)> fun_input, double x_min, double x_max, double epsilon);
std::tuple <double, double, int> fibonacci_search(std::function<double(double)> fun_input, double x_min, double x_max, double epsilon);
#endif // !SEARCH_H
- violent_search.cpp(暴力搜索)
#include "Search.h"
std::tuple<double, double, int> violent_search(std::function<double(double)> fun_input, double x_min, double x_max, double epsilon) {
auto start = std::chrono::high_resolution_clock::now();//获取当前时间,以获得该算法的耗时
double num = std::ceil((x_max - x_min) / epsilon);//将区间分为num份
double min_x = x_min;
double min_y = 1.0e10;
for (int i = 0; i <= num; ++i) {
double x_temp = x_min + i * epsilon;//x的增量
double y_temp = fun_input(x_temp);
if (y_temp < min_y) {//更新min_x,与min_y。
min_x = x_temp;
min_y = y_temp;
}
}
int k = num + 1;
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Algorithm took: " << duration.count() << " microseconds" << std::endl;
return std::make_tuple(min_x, min_y, k);//返回make_tuple类型的数
}
- golden_section_search.cpp(黄金分割)
#include "Search.h"
std::tuple <double, double, int> golden_section_search (std::function<double(double)> fun_input, double x_min, double x_max, double epsilon) {
auto start = std::chrono::high_resolution_clock::now();
double ruo = (3 - std::sqrt(5)) * 0.5;//这个数是0.381966
//和区间消去一样
double x_left_side = x_min;
double x_right_side = x_max;
double x_left_center = x_left_side + ruo * (x_right_side - x_left_side);
double x_right_center = x_right_side - ruo * (x_right_side - x_left_side);
double y_left_center = fun_input(x_left_center);
double y_right_center = fun_input(x_right_center);
int num = 0;
while (true) {
num++;
if (y_left_center >= y_right_center) {
x_left_side = x_left_center;
x_right_side = x_right_side;
x_left_center = x_right_center;//这里是原来的右边界成为新的左边界
//只更新右边界,提高算法效率
x_right_center = x_right_side - ruo * (x_right_side - x_left_side);
y_left_center = y_right_center;
y_right_center = fun_input(x_right_center);
}
else {
x_left_side = x_left_side;
x_right_side = x_right_center;
x_right_center = x_left_center;
x_left_center = x_left_side + ruo * (x_right_side - x_left_side);
y_right_center = y_left_center;//同理
y_left_center = fun_input(x_left_center);
}
if (x_right_side - x_left_side <= epsilon) {
break;
}
}
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Algorithm took: " << duration.count() << " microseconds" << std::endl;
double min_x = (x_left_side + x_right_side) * 0.5;
double min_y = fun_input(min_x);
int k = num;
return std::make_tuple(min_x, min_y, num);
}
- fibonacci_search.cpp
#include "Search.h"
//std::tuple <double, double, int> fibonacci_search(std::function<double(double)> fun_input, double x_min, double x_max, double epsilon) {
//
//
// double Fibonacci_up = (x_max - x_min) / epsilon;
// std::vector<int> Fibonacci_set = { 1, 2 };
// int Fibonacci_num = 1; // 初始斐波那契数列索引为 1
// while (true) {
// int next_fibonacci = Fibonacci_set[Fibonacci_num] + Fibonacci_set[Fibonacci_num - 1];
// if (next_fibonacci >= Fibonacci_up) {
// break;
// }
// Fibonacci_set.push_back(next_fibonacci);
// Fibonacci_num++;
// }
// int N = Fibonacci_num - 1;
// std::vector<double> ruo(N);
// double x_left_side = x_min;
// double x_right_side = x_max;
// double x_left_center = x_left_side + ruo[0] * (x_right_side - x_left_side);
// double x_right_center = x_right_side - ruo[0] * (x_right_side - x_left_side);
// double y_left_center = fun_input(x_left_center);
// double y_right_center = fun_input(x_right_center);
// for (int i = 2; i <= N; ++i) {
// if (N == i) {
// ruo[i] = 0.5 - 0.1 * epsilon;
// }
// else {
// ruo[i] = 1.0 - static_cast<double>(Fibonacci_set[N - i + 1]) / Fibonacci_set[N - i + 2];
// }
//
// if (y_left_center >= y_right_center) {
// x_left_side = x_left_center;
// x_right_side = x_right_side;
// x_left_center = x_right_center;
// x_right_center = x_right_side - ruo[i] * (x_right_side - x_left_side);
// y_left_center = y_right_center;
// y_right_center = fun_input(x_right_center);
// }
// else {
// x_left_side = x_left_side;
// x_right_side = x_right_center;
// x_right_center = x_left_center;
// x_left_center = x_left_side + ruo[i] * (x_right_side - x_left_side);
// y_right_center = y_left_center;
// y_left_center = fun_input(x_left_center);
// }
// }
// double min_x = (x_left_side + x_right_side) * 0.5;
// double min_y = fun_input(min_x);
// int k = N - 1;
//
// return std::make_tuple(min_x, min_y, k);
//}
std::tuple<double, double, int> fibonacci_search(std::function<double(double)> fun_input, double x_min, double x_max, double epsilon) {
// 计算斐波那契数列
auto start = std::chrono::high_resolution_clock::now();
double Fibonacci_up = (x_max - x_min) / epsilon;
int Fibonacci_set[100];
Fibonacci_set[0] = 1;
Fibonacci_set[1] = 2;
int Fibonacci_num = 2;
while (true) {
Fibonacci_set[Fibonacci_num] = Fibonacci_set[Fibonacci_num - 1] + Fibonacci_set[Fibonacci_num - 2];
if (Fibonacci_set[Fibonacci_num] >= Fibonacci_up)
break;
Fibonacci_num++;
}
int N = Fibonacci_num - 1;
double ruo[100];
ruo[0] = 1 - Fibonacci_set[N] / (double)Fibonacci_set[N + 1];
// 初始化
double x_left_side = x_min;
double x_right_side = x_max;
double x_left_center = x_left_side + ruo[0] * (x_right_side - x_left_side);
double x_right_center = x_right_side - ruo[0] * (x_right_side - x_left_side);
double y_left_center = fun_input(x_left_center);
double y_right_center = fun_input(x_right_center);
// 循环搜索
for (int i = 1; i < N; ++i) {
if (N == i + 1)
ruo[i] = 1 / 2 - 0.1 * epsilon;
else
ruo[i] = 1 - Fibonacci_set[N - i] / (double)Fibonacci_set[N - i + 1];
if (y_left_center >= y_right_center) {
// 更新区间,继续计算
x_left_side = x_left_center;
x_left_center = x_right_center;
x_right_center = x_right_side - ruo[i] * (x_right_side - x_left_side);
y_left_center = y_right_center;
y_right_center = fun_input(x_right_center);
}
else {
// 更新区间,继续计算
x_right_side = x_right_center;
x_right_center = x_left_center;
x_left_center = x_left_side + ruo[i] * (x_right_side - x_left_side);
y_right_center = y_left_center;
y_left_center = fun_input(x_left_center);
}
}
// 输出最近点和迭代步长
double min_x = (x_left_side + x_right_side) * 0.5;
double min_y = fun_input(min_x);
int k = N;
auto end = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
std::cout << "Algorithm took: " << duration.count() << " microseconds" << std::endl;
return std::make_tuple(min_x, min_y, k);
}