Griewank函数单纯形法实现c++
时间: 2023-12-25 14:04:21 浏览: 165
单纯形法的C++实现
以下是 Griewank 函数的单纯形法实现(C语言):
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define DIM 10 // 变量的维度
#define MAX_ITER 10000 // 最大迭代次数
#define ALPHA 1.0 // 反射系数
#define BETA 0.5 // 收缩系数
#define GAMMA 2.0 // 扩展系数
double f(double x[]);
void simplex(double p[][DIM+1], double y[], int *imin, int *imax);
int main()
{
double p[DIM+1][DIM+1]; // 单纯形的顶点
double y[DIM+1]; // 每个顶点的函数值
double x[DIM]; // 最优解
double delta; // 两个最差顶点的距离
int iter; // 当前迭代次数
int i, j, imin, imax;
// 初始化单纯形的顶点
for (i = 0; i <= DIM; i++) {
for (j = 0; j < DIM; j++) {
if (i == j+1) p[i][j] = 1.0;
else p[i][j] = 0.0;
}
y[i] = f(p[i]);
}
// 迭代
for (iter = 0; iter < MAX_ITER; iter++) {
// 找到最差和次差的顶点
imin = 0;
imax = 1;
if (y[1] > y[0]) {
imax = 0;
imin = 1;
}
for (i = 2; i <= DIM; i++) {
if (y[i] < y[imin]) imin = i;
if (y[i] > y[imax]) imax = i;
}
// 计算两个最差顶点之间的距离
delta = 0.0;
for (j = 0; j < DIM; j++) {
delta += (p[imax][j] - p[imin][j]) * (p[imax][j] - p[imin][j]);
}
delta = sqrt(delta);
// 如果最差顶点和次差顶点之间的距离小于阈值,则结束迭代
if (delta < 1e-6) break;
// 计算反射点
double xr[DIM];
for (j = 0; j < DIM; j++) {
xr[j] = (1.0 + ALPHA) * p[imax][j] - ALPHA * p[imin][j];
}
double yr = f(xr);
// 如果反射点比最差但比次差点好,则替换最差点
if (yr < y[imax] && yr >= y[imin]) {
for (j = 0; j < DIM; j++) {
p[imax][j] = xr[j];
}
y[imax] = yr;
}
// 如果反射点比次差点还要好,则计算扩展点
else if (yr < y[imin]) {
double xe[DIM];
for (j = 0; j < DIM; j++) {
xe[j] = GAMMA * xr[j] + (1.0 - GAMMA) * p[imax][j];
}
double ye = f(xe);
// 如果扩展点比反射点更好,则替换最差点
if (ye < yr) {
for (j = 0; j < DIM; j++) {
p[imax][j] = xe[j];
}
y[imax] = ye;
}
// 否则替换最差点
else {
for (j = 0; j < DIM; j++) {
p[imax][j] = xr[j];
}
y[imax] = yr;
}
}
// 如果反射点比最差点还要差,则计算收缩点
else {
double xc[DIM];
for (j = 0; j < DIM; j++) {
xc[j] = BETA * p[imax][j] + (1.0 - BETA) * p[imin][j];
}
double yc = f(xc);
// 如果收缩点比最差点更好,则替换最差点
if (yc < y[imax]) {
for (j = 0; j < DIM; j++) {
p[imax][j] = xc[j];
}
y[imax] = yc;
}
// 否则缩小整个单纯形
else {
simplex(p, y, &imin, &imax);
}
}
}
// 打印最优解和函数值
for (j = 0; j < DIM; j++) {
x[j] = p[imin][j];
}
printf("x = [ ");
for (j = 0; j < DIM; j++) {
printf("%f ", x[j]);
}
printf("], f(x) = %f\n", y[imin]);
return 0;
}
// Griewank 函数
double f(double x[])
{
double sum1 = 0.0;
double sum2 = 1.0;
int i;
for (i = 0; i < DIM; i++) {
sum1 += x[i] * x[i];
sum2 *= cos(x[i] / sqrt(i+1));
}
return 1.0 + sum1 / 4000.0 - sum2;
}
// 缩小整个单纯形
void simplex(double p[][DIM+1], double y[], int *imin, int *imax)
{
int i, j;
*imin = 0;
*imax = 1;
for (i = 2; i <= DIM; i++) {
if (y[i] < y[*imin]) *imin = i;
if (y[i] > y[*imax]) *imax = i;
}
double xc[DIM];
for (i = 0; i < DIM; i++) {
xc[i] = 0.0;
for (j = 0; j <= DIM; j++) {
if (j != *imax) {
xc[i] += p[j][i];
}
}
xc[i] /= DIM;
}
double yc = f(xc);
for (i = 0; i <= DIM; i++) {
for (j = 0; j < DIM; j++) {
p[i][j] = 0.5 * (p[i][j] + p[*imax][j]);
}
y[i] = f(p[i]);
}
}
```
需要注意的是,上述代码中的 Griewank 函数的维度为 10,可以根据需要进行修改。同时,反射、扩展和收缩系数的取值也可以根据需要进行调整。
阅读全文