@TangWill
2019-06-29T21:51:03.000000Z
字数 47280
阅读 662
cpp
目标函数优化问题可以描述为:
这里为搜索空间,为目标函数。(1)式描述的优化问题称为极大化问题,(2)式描述的称为极小化问题。
粒子群优化算法PSO(Particle Swarm Optimization)是一种基于群体的自适应的搜索优化方法。PSO 中,每个优化问题的潜在解都是搜索空间中的一只鸟,称之为粒子。所有的粒子都有一个由被优化的函数决定的适值( fitness value) ,每个粒子还有一个速度决定它们飞翔的方向和距离。然后粒子们就追随当前的最优粒子在解空间中搜索。
PSO初始化为一群随机粒子(随机解),然后通过迭代找到最优解。在每一次迭代中,粒子通过跟踪两个极值来更新自己;第一个就是粒子本身所找到的最优解,这个解称为个体极值;另一个极值是整个种群目前找到的最优解,这个极值是全局极值。另外也可以不用整个种群而只是用其中一部分作为粒子的邻居,那么在所有邻居中的极值就是局部极值。
假设在一个 维的目标搜索空间中,有 个粒子组成一个群落,其中第 个粒子表示为一个维的向量
第个粒子的“飞行”速度也是一个维的向量,记为
第个粒子迄今为止搜索到的最优位置称为个体极值,记为
整个粒子群迄今为止搜索到的最优位置为全局极值,记为
在找到这两个最优值时,粒子根据如下的公式(1.1)和( 1.2)来更新自己的速度和位置:
其中:和 为学习因子,也称加速常数(acceleration constant), 和 为[0,1]范围内的均匀随机数。式(3)右边由三部分组成,第一部分为“惯性(inertia)”或“动量(momentum)”部分,反映了粒子的运动“习惯(habit)”,代表粒子有维持自己先前速度的趋势;第二部分为“认知(cognition)”部分,反映了粒子对自身历史经验的记忆(memory)或回忆(remembrance),代表粒子有向自身历史最佳位置逼近的趋势;第三部分为“社会(social)”部分,反映了粒子间协同合作与知识共享的群体历史经验。
这部分内容主要是针对本文主要研究问题的类型确定粒子群算法具体实现过程和一些参数的选择。
算法流程框图
算法实现
算法的流程如下:
算法的构成要素
对于构成粒子群算法的各个参数进行设定。本算法中主要的参数变量为惯性权值 ,学习因子 , ,群体的大小 ,迭代次数 ,粒子维数 。
(1)群体大小
通常,群体太小则不能提供足够的采样点,以致算法性能很差,容易陷入局部最优;群体太大尽管可以增加优化信息,阻止早熟收敛的发生,但无疑会增加计算量,造成收敛时间太长,表现为收敛速度缓慢。本文对函数的优化选择种群规模为40000。
(2)最大迭代次数
迭代次数越多能保证解的收敛性,但是影响运算速度,本文对函数的优化选最大迭代次数为80次,利用大量的种群和较少的迭代次数,优化效果明显。
(3)惯性权值
惯性权重 表示在多大程度上保留原来的速度。 较大,全局收敛能力强,局部收敛能力弱; 较小,局部收敛能力强,全局收敛能力弱。
(4)学习因子
加速常数 和 分别用于控制粒子指向自身或邻域最佳位置的运动。建议 ,并通常取 。本文中取 。
(5)粒子维数
粒子维数取决于待优化函数的维数。
(6)粒子空间的初始化
较好的选择粒子初始化空间,将大大缩短收敛的时间。在本文中我们主要是选用随机对粒子进行初始化。
测试函数
编号 | 函数 | 取值范围 | 维度 |
---|---|---|---|
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
10 | |||
2 | |||
4 |
class Particle
封装了单个粒子的类;
Particle.h
//
// Created by tq on 2019/6/18.
//
#ifndef _PARTICLE_H_
#define _PARTICLE_H_
/*
Particle:封装了单个粒子的类;
该类的数据成员,包括粒子的:
坐标维度:in_dims,坐标,适应值,位置上下限,速度上下限,惯性系数,
全局速度因子,局部速度因子,速度上下限,速度范围因子,局部最优解,全局最优解,
方法: 随机初始化、计算适应值、更新全局最优、更新局部最优
*/
class Particle {
public:
float *velocity; //速度
float fitness; //粒子的适应值
float *position; //粒子的坐标
float fitness_pbest; //粒子的历史最优适应值
float *position_pbest; //粒子的历史最优坐标
float fitness_gbest; //粒子的全局最优适应值
float *position_gbest; //粒子的全局最优坐标
Particle(int dims, float *inmax, float *inmin, float *vmax, float *vmin, float _w, float _c1, float _c2,
int _index); //Particle:构造函数
void init();//init:随机初始化粒子的速度和位置
void get_fitness();//get_fitness:计算当前坐标的适应值
void init_pbest();//init_pbest:初始化历史最优
void updata_pbest();//updata_pbest:更新历史最优
void get_gbest(float *_in_gbest, float _fitness_gbest);//get_gbest: 更新全局最优
void updata_v();//updata_v::更新速度
void updata_in();//updata_in:更新坐标
private:
int index; //函数索引
int dimension; //坐标维度
float *position_max, *position_min; //位置上下限
float *velocity_max, *velocity_min; //速度上下限
float w, c1, c2; //惯性系数,局部速度因子、全局速度因子
};
#endif // _PARTICLE_H_
particle.cpp
//
// Created by tq on 2019/6/18.
//
#include <iostream>
#include<algorithm>
#include"Particle.h"
#include"funs.h"
using namespace std;
Particle::Particle(int dims, float *inmax, float *inmin, float *vmax, float *vmin, float _w, float _c1,float _c2, int _index) {
index = _index;
dimension = dims; //坐标维度
fitness = 0.0; //粒子的适应值
position = new float[dimension]; //粒子的坐标
velocity = new float[dimension]; //速度
fitness_pbest = 0.0; //粒子的历史最优适应值
position_pbest = new float[dimension]; //粒子的历史最优坐标
fitness_gbest = 0.0; //粒子的全局最优适应值
position_gbest = new float[dimension]; //粒子的全局最优坐标
position_max = inmax; //位置上限
position_min = inmin; //位置下限
velocity_max = vmax; //速度上限
velocity_min = vmin; //速度下限
w = _w; //惯性系数,
c1 = _c1; //历史速度因子
c2 = _c2; //全局速度因子
}
void Particle::init() { // 随机初始化坐标
position = random_array(dimension, position_max, position_min);
// 随机初始化速度
velocity = random_array(dimension, velocity_max, velocity_min);
}
void Particle::get_fitness() {
//计算适应值
fitness = fitness_fun(position, index, dimension);
}
void Particle::init_pbest() {
//将坐标值和适应值,直接拷贝
copy_(position, position_pbest, dimension);
fitness_pbest = fitness;
}
void Particle::updata_pbest() { //如果当前粒子的适应值大于历史最优值pbest,重新拷贝
if (fitness <= fitness_pbest)
copy_(position, position_pbest, dimension);
fitness_pbest = fitness;
}
void Particle::get_gbest(float *_in_gbest, float _fitness_gbest) { //将传入的全局最优,赋值给当前粒子的全局最优
//全局最优需要比较所有粒子的适应值,
//所以先在外部对所有粒子进行比较。然后再传入。
copy_(_in_gbest, position_gbest, dimension);
fitness_gbest = _fitness_gbest;
}
void Particle::updata_v() {
//根据如下公式更新速度
//v=v*w + (pbestin-in)*c1 + (gbestin-in)*c2
//速度不得超过上限、下限
for (int i = 0; i < dimension; i++) {
velocity[i] = velocity[i] * w + (position_pbest[i] - position[i]) * c1 + (position_gbest[i] - position[i]) * c2;
if (velocity[i] > velocity_max[i]) { velocity[i] = velocity_max[i]; }
if (velocity[i] < velocity_min[i]) { velocity[i] = velocity_min[i]; }
}
}
void Particle::updata_in() {
//更新位置。位置不得超过上限、下限
for (int i = 0; i < dimension; i++) {
position[i] = position[i] + velocity[i];
if (position[i] > position_max[i]) { position[i] = position_max[i]; }
if (position[i] < position_min[i]) { position[i] = position_min[i]; }
}
}
class Pso
标准粒子群算法
成员:多个Particle,速度因子、惯性因子等
Pso.h
//
// Created by tq on 2019/6/18.
//
#ifndef _PSO_H_
#define _PSO_H_
#include "Particle.h"
#include <vector>
using namespace std;
/*
Pso类:标准粒子群算法
成员:多个Particle,速度因子、惯性因子等
*/
class Pso {
protected:
int index;
int swarm_amount; //粒子群数量
int in_dim; //粒子坐标的维度
float w, c1, c2;
float *max_in;
float *min_in;
float *max_v;
float *min_v;
float *fitness_list;
float v_scale = 0.1; //速度范围因子。建议0.05<v_scale<0.2
float w_col = 1.0; // 惯性衰减因子,建议0.96<w_col<1.0
float v_col = 1.0; //速度衰减因子,建议0.96<v_col<1.0
vector<Particle> vector_pso; //存储所有粒子的容器
public:
float *in_gbest_final; //存放最终的最优坐标
float fitness_gbest_final; //最优坐标对应的最优适应值
Pso(int _swarm_amount, int dim, float _w, float *_max, float *_min, float v_scale_, int _index);//Pso:构造函数
void set_w_col(float w_col); //set_w_col:设置惯性衰减因子
void set_v_col(float v_col);//set_v_col:设置速度衰减因子
void gbest(int flag);//gbest:计算全局最优gbest
void initialize(); //initialize:初始化每个粒子的坐标值、速度、适应值、局部最优、全局最优、
void update();//update:更新坐标值、速度、适应值、局部最优、全局最优、
void pso_iteration(int circle_);//pso_iteration:循环迭代。circle_表示迭代次数
};
#endif // _PSO_H_
Pso.cpp
//
// Created by tq on 2019/6/18.
//
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <time.h>
#include<algorithm>
#include "Pso.h"
#include"funs.h"
using namespace std;
//构造函数:初始化参数
Pso::Pso(int _swarm_amount, int dim, float _w, float *_max, float *_min, float v_scale_, int _index) {
index = _index;
in_dim = dim;
in_gbest_final = new float[in_dim];
swarm_amount = _swarm_amount;
fitness_list = new float[swarm_amount];
w = _w;
c1 = (1 - w) / 2;
c2 = (1 - w) / 2;
min_in = new float[in_dim];
max_in = new float[in_dim];
min_v = new float[in_dim];
max_v = new float[in_dim];
max_in = _max;
min_in = _min;
v_scale = v_scale_;
for (int i = 0; i < in_dim; i++) {
max_v[i] = (_max[i] - _min[i]) * v_scale;
min_v[i] = -(_max[i] - _min[i]) * v_scale;
}
}
//设置惯性衰减系数
void Pso::set_w_col(float w_col_) {
w_col = w_col_;
}
//设置速度范围的衰减系数
void Pso::set_v_col(float v_col_) {
v_col = v_col_;
}
//更新粒子群的全局最优解gbest
void Pso::gbest(int init_flag) {
float *in_gbest_temp = new float[in_dim]; //存放每轮的最优粒子坐标
float fitness_gbest_temp; //每一轮最优适应值
get_min(swarm_amount, vector_pso, in_gbest_temp, &fitness_gbest_temp, in_dim);
for (int i = 0; i < swarm_amount; i++) {
//如果是处于第一轮迭代,或者fitness_gbest_temp优于粒子的gbest
//将粒子的gbest替换为fitness_gbest_temp和in_gbest_temp
if (init_flag == 0 || fitness_gbest_temp < vector_pso[i].fitness_gbest) {
vector_pso[i].get_gbest(in_gbest_temp, fitness_gbest_temp);
}
}
}
//初始化粒子群的坐标、速度、历史最优、全局最优
void Pso::initialize() {
for (int i = 0; i < swarm_amount; i++) {
Particle single(in_dim, max_in, min_in, max_v, min_v, w, c1, c2, index);
single.init();
single.get_fitness();
single.init_pbest();
vector_pso.push_back(single);
}
gbest(0);
}
//更新粒子群的速度、坐标、历史最优、全局最优
void Pso::update() {
if (w_col != 1.0) {
w = w * w_col; //衰减w
c1 = (1 - w) / 2; //增加c1
c2 = (1 - w) / 2; //增加c2
}
if (v_col != 1.0) {
v_scale = v_scale * v_col; //衰减v_scale
}
for (int i = 0; i < swarm_amount; i++) {
vector_pso[i].updata_v();
vector_pso[i].updata_in();
vector_pso[i].get_fitness();
vector_pso[i].updata_pbest();
}
gbest(1);
}
//初始化,并且反复进行circle_轮的迭代
void Pso::pso_iteration(int circle_) {
this->initialize();
for (int i = 0; i < circle_; i++) {
if (i % 5 == 0) {
cout << i << "nd iteration ..." << endl;
}
this->update();
}
//get_final_gbest:计算最终的最优粒子
get_final_gbest(swarm_amount, vector_pso, in_gbest_final, &fitness_gbest_final, in_dim);
}
function
提供了适应度函数的计算等方法
functions.h
//
// Created by tq on 2019/6/18.
//
#ifndef FUNS_H_
#define FUNS_H_
#include <vector>
#include "Particle.h"
using namespace std;
//random_single:生成0-1的浮点数
float random_single();
//random_array:随机生成dims维度的数组
float *random_array(int dims, float *max_, float *min_);
//fitness_fun:生成适应值的函数
float fitness_fun(float *x, int mode, int dimension);
//copy_:数组 深拷贝
void copy_(float src[], float dst[], int dims);
//get_min:通过计算,得到适应值最小的粒子
void get_min(int mount, vector<Particle> temp_pso, float *max_in, float *max_fit, int in_dims_);
//get_final_gbest:通过计算,得到最终的最优解
void get_final_gbest(int mount, vector<Particle> temp_pso, float *final_in, float *final_fit, int in_dims_);
#endif // FUNS_H_
functions.cpp
//
// Created by tq on 2019/6/18.
//
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <math.h>
#include "Particle.h"
#include "functions.h"
using namespace std;
//生成随机数
float random_single() {
return ((float) (rand() % 1000)) / 1000.0;
}
//生成维度为dims的随机数组
float *random_array(int dims, float *max_, float *min_) {
float *temp = new float[dims];
for (int i = 0; i < dims; i++) {
float random_ = random_single();
temp[i] = (max_[i] - min_[i]) * random_ + min_[i];
}
return temp;
}
//fitness_fun:适应度函数使用
float fitness_fun(float *x, int index, int dimension) {
float sum = 0;
switch (index) {
case 1: {
for (auto i = 0; i < dimension; i++) {
sum += pow(x[i], 2);
}
break;
}
case 2: {
double temp = 1;
for (auto i = 0; i < dimension; i++) {
temp *= abs(x[i]);
}
for (auto i = 0; i < dimension; i++) {
sum += abs(x[i]);
}
sum = sum + temp;
break;
}
case 3: {
double temp = 0;
for (auto i = 0; i < dimension; i++) {
for (auto j = 0; j < i; j++) {
temp += x[i];
}
sum += pow(temp, 2);
}
break;
}
case 4: {
sum = abs(x[0]);
for (auto i = 1; i < dimension; i++) {
if (abs(x[i]) > sum)
sum = abs(x[i]);
}
break;
}
case 5: {
sum = 10 * (100 * pow((x[1] - pow(x[0], 2)), 2) + pow(x[0] - 1, 2));
break;
}
case 6: {
for (auto i = 0; i < dimension; i++) {
sum += pow(floor(x[i] + 0.5), 2);
}
break;
}
case 7: {
for (auto i = 0; i < dimension; i++) {
sum += ((i + 1) * pow(x[i], 4) + (rand() % (1 - 0)) + 0);
}
break;
}
case 8: {
sum = 10 * (-x[0] * sin(sqrt(abs(x[0]))));
break;
}
case 9: {
sum = 10 * (pow(x[0], 2) - 10 * cos(2 * M_PI * x[0]) + 10);
break;
}
case 10: {
double e = 1.0;
int n = 0;
double u = 1.0;
do {
n++;
u = u / n;
e = e + u;
} while (u >= 1.0E-6);
float temp1 = 0, temp2 = 0;
for (auto i = 0; i < dimension; i++) {
temp1 += pow(x[i], 2);
temp2 += cos(2 * M_PI * x[i]);
}
sum += (-20 * exp(-0.2 * sqrt(temp1 / dimension)) - exp(temp2 / dimension) + 20 + e);
break;
}
case 11: {
float temp1 = 0, temp2 = 1;
for (auto i = 0; i < dimension; i++) {
temp1 += pow(x[i], 2);
temp2 *= cos(x[i] / sqrt(i + 1));
}
sum = temp1 / 4000 - temp2 + 1;
break;
}
case 12: {
float y[10] = {0};
for (auto i = 0; i < dimension; i++) {
y[i] = 1 + (x[i] + 1) / 4;
}
float temp = 0;
for (auto i = 0; i < dimension - 1; i++) {
temp += pow(y[i] - 1, 2) * (1 + 10 * pow(sin(M_PI * y[i + 1]), 2));
}
sum = (10 * pow(sin(M_PI * y[0]), 2) + temp + pow(y[dimension - 1], 2)) * M_PI / dimension;
for (auto i = 0; i < dimension; i++) {
sum +=
(x[i] > 10 ? 100 * pow((x[i] - 10), 4) : x[i] < -10 ? 100 * pow((-x[i] - 10), 4)
: 0);
}
break;
}
case 13: {
float temp = 0;
for (auto i = 0; i < dimension; i++) {
temp += pow(x[i] - 1, 2) * (1 + pow(sin(3 * M_PI * x[i]) + 1, 2));
}
sum = 0.1 * (pow(sin(3 * M_PI * x[0]), 2) + temp +
pow(x[dimension - 1] - 1, 2) * (1 + pow(sin(2 * M_PI * x[dimension - 1]), 2)));
for (auto i = 0; i < dimension; i++) {
sum +=
(x[i] > 5 ? 100 * pow((x[i] - 5), 4) : x[i] < -5 ? 100 * pow((-x[i] - 5), 4)
: 0);
}
break;
}
case 14: {
float temp = 0;
int matrix[2][25] = {{-32, 16, 0, 16, 32, -32, -16, 0, 16, 32, -32, -16, 0, 16, 32, -32, -16, 0, 16, 32, -32, -16, 0, 16, 32},
{-32, -32, -32, -32, -32, -16, -16, -16, -16, -16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32}};
for (auto j = 0; j < 25; j++) {
float _temp = 0;
for (auto i = 0; i < dimension; i++) {
_temp += pow(x[i] - matrix[i][j], 6);
}
temp += (1 / (j + 1 + _temp));
}
sum = pow(1 / 500 + temp, -1);
break;
}
case 15: {
float a[11] = {0.1957, 0.1947, 0.1735, 0.16, 0.0844, 0.0627, 0.0456, 0.0342, 0.0323, 0.0235, 0.0246};
float b[11] = {0.25, 0.5, 1, 2, 4, 6, 8, 10, 12, 14, 16};
for (auto i = 0; i < 11; i++) {
sum += pow(a[i] - (x[0] * (pow(1 / b[i], 2) + 1 / b[i] * x[1])) /
(pow(1 / b[i], 2) + 1 / b[i] * x[2] + x[3]), 2);
}
break;
}
}
return sum;
}
//数组复制
void copy_(float src[], float dst[], int dims) {
for (int i = 0; i < dims; i++) {
dst[i] = src[i];
}
}
//通过计算,得到vector中的最小适应值和对应的坐标
void get_min(int mount, vector<Particle> temp_pso, float *min_in, float *min_fit, int in_dims_) {
for (int i = 0; i < mount; i++) {
if (i == 0 || temp_pso[i].fitness < *min_fit) {
*min_fit = temp_pso[i].fitness;
copy_(temp_pso[i].position, min_in, in_dims_);
}
}
}
//通过计算,得到最终的最优解
void get_final_gbest(int mount, vector<Particle> temp_pso, float *final_in, float *final_fit, int in_dims_) {
for (int i = 0; i < mount; i++) {
if (i == 0 || temp_pso[i].fitness < *final_fit) {
*final_fit = temp_pso[i].fitness_gbest;
copy_(temp_pso[i].position, final_in, in_dims_);
}
}
}
main
//
// Created by tq on 2019/6/18.
//
#include <iostream>
#include <stdlib.h>
#include <vector>
#include <time.h>
#include <math.h>
#include "Particle.h"
#include "Pso.h"
#include "functions.h"
#include <iomanip>
using namespace std;
int main() {
srand(time(0)); //随机种子
int amout_ = 40000; //粒子数
float w_ = 0.8; // 惯性权重
// 通常情况下,全局加速因子 c1、历史加速因子c2 ,等于 (1-w)/2
float v_scale_ = 0.1; //速度比例因子。最大速度、最小速度的范围
int iteration = 80;//迭代次数
//本适应度函数是两维。网友可以根据自身需要更改适应度函数、
int index, in_dims_, up_low;
cout << "*********选择函数********" << endl;
cout << "1. Sphere Model " << endl;
cout << "2. Schwefel’s Problem 2.22 " << endl;
cout << "3. Schwefel’s Problem 1.2 " << endl;
cout << "4. Schwefel’s Problem 2.21 " << endl;
cout << "5. Generalized Rosenbrock’s Function " << endl;
cout << "6. Step Function " << endl;
cout << "7. Quartic Function i.e. Niose " << endl;
cout << "8. Generalized Schwefel’s Problem 2.26 " << endl;
cout << "9. Generalized Rastrigin’s Function " << endl;
cout << "10. Ackley’s Function " << endl;
cout << "11. Generalized Griewank Function " << endl;
cout << "12. Generalized Penalized Function " << endl;
cout << "13. Generalized Penalized Function " << endl;
cout << "14. Shekel’s Foxholes Function " << endl;
cout << "15. Kowalik’s Function " << endl;
cout << "*************************" << endl;
cout << "Please input the function index: " << endl;
cin >> index;
cout << "Please input the dimension: " << endl;
cin >> in_dims_;
cout << "Please input the up and low: " << endl;
cin >> up_low;;
float max_in[10]; //输入参数的上限
for (auto i = 0; i < in_dims_; i++) {
max_in[i] = up_low;;
}
float min_in[10]; //输入参数的下限
for (auto i = 0; i < in_dims_; i++) {
min_in[i] = -up_low;;
}
Pso pso_(amout_, in_dims_, w_, max_in, min_in, v_scale_, index);
pso_.set_w_col(0.99); //设置惯性衰减系数。惯性系数每次迭代乘以0.99。c1和c2相应增加
pso_.set_v_col(0.99); //设置速度衰减因子。速度的上限和下限。随着迭代衰减
pso_.pso_iteration(iteration); //执行
cout << "********* Complete Iteration ********" << endl;
cout << "*****final_gbest fitness:" << setiosflags(ios::fixed) << setprecision(4) << pso_.fitness_gbest_final
<< endl;
cout << "********* Complete Iteration ********" << endl;
}
在实现PSO算法对15个函数的测试后,尝试用Qt对PSO优化过程进行可视化,如图。
代码如下:
psoparameters.h
#ifndef PSOPARAMETERS_H
#define PSOPARAMETERS_H
#include <QWidget>
#include <map>
namespace Ui {
class PSOParameters;
}
class PSOParameters : public QWidget
{
Q_OBJECT
public:
explicit PSOParameters(QWidget *parent = 0);
~PSOParameters();
void setResult(double result);
void setProgress(const double &ratio);
void showParameters( std::map<QString,double> &pso);
signals:
void changeParameter(QString target, double value, bool type);
void beginToProcess(bool type);
private slots:
void on_LineEditGroup_textChanged(const QString &arg1);
void on_LineEditGroup_textEdited(const QString &arg1);
void on_LineEditGroup_editingFinished();
void on_LineEditGeneration_editingFinished();
void on_LineEditSpeed1_editingFinished();
void on_LineEditSpeed2_editingFinished();
void on_LineEditUp_editingFinished();
void on_LineEditDown_cursorPositionChanged(int arg1, int arg2);
void on_LineEditDown_editingFinished();
void on_LineEditGroup_D_editingFinished();
void on_LineEditGeneration_D_editingFinished();
void on_LineEditUp_D_editingFinished();
void on_LineEditDown_D_editingFinished();
void on_horizontalSliderWeight_valueChanged(int value);
void on_ComboBoxDimension_currentTextChanged(const QString &arg1);
void on_horizontalSliderFactor_D_valueChanged(int value);
void on_horizontalSliderCR_D_valueChanged(int value);
void on_ComboBoxDimension_D_currentTextChanged(const QString &arg1);
void on_pushButtonProcess_clicked();
void on_comboBoxFunction_currentIndexChanged(int index);
private:
Ui::PSOParameters *ui;
};
#endif // PSOPARAMETERS_H
psoparameters.cpp
#include "psoparameters.h"
#include "ui_psoparameters.h"
#include <QDebug>
PSOParameters::PSOParameters(QWidget *parent) :
QWidget(parent),
ui(new Ui::PSOParameters)
{
ui->setupUi(this);
//设置输入限制
ui->LineEditGroup->setValidator(new QIntValidator(10, 300));
ui->LineEditGeneration->setValidator(new QIntValidator());
ui->LineEditSpeed1->setValidator(new QDoubleValidator(0.0,10.0,10));
ui->LineEditSpeed2->setValidator(new QDoubleValidator(0.0, 10.0,10));
ui->LineEditUp->setValidator(new QDoubleValidator());
ui->LineEditDown->setValidator(new QDoubleValidator());
ui->LineEditGroup_D->setValidator(new QIntValidator());
ui->LineEditGeneration_D->setValidator(new QIntValidator());
ui->LineEditUp_D->setValidator(new QDoubleValidator());
ui->LineEditDown_D->setValidator(new QDoubleValidator());
ui->lineEditResult->setReadOnly(true);
}
PSOParameters::~PSOParameters()
{
delete ui;
}
void PSOParameters::setResult(double result)
{
ui->lineEditResult->setText(QString::number(result,10,3));
ui->lineEditResult->repaint();
}
void PSOParameters::setProgress(const double &ratio)
{
double tmp = ratio + 0.01;
ui->progressBar->setValue(tmp*100);
ui->progressBar->repaint();
}
void PSOParameters::showParameters( std::map<QString,double> &pso)
{
//设置pso的参数
ui->LineEditGroup->setText(QString::number(static_cast<int>(pso["population"]),10));
ui->LineEditGeneration->setText(QString::number(static_cast<int>(pso["generation"]),10));
double ratio = pso["w"];
ui->horizontalSliderWeight->setValue(static_cast<int>(ratio*100));
ui->LineEditSpeed1->setText(QString::number(pso["c1"],10,2));
ui->LineEditSpeed2->setText(QString::number(pso["c1"],10,2));
ui->ComboBoxDimension->setCurrentText(QString::number(static_cast<int>(pso["dimension"])));
ui->LineEditUp->setText(QString::number(pso["upbounding"],10,2));
ui->LineEditDown->setText(QString::number(pso["lowbounding"],10,2));
}
void PSOParameters::on_LineEditGroup_textChanged(const QString &arg1)
{
Q_UNUSED(arg1);
}
void PSOParameters::on_LineEditGroup_textEdited(const QString &arg1)
{
Q_UNUSED(arg1);
}
void PSOParameters::on_LineEditGroup_editingFinished()
{
double value = ui->LineEditGroup->text().toDouble();
emit changeParameter(tr("population"),value, false);
}
void PSOParameters::on_LineEditGeneration_editingFinished()
{
double value = ui->LineEditGeneration->text().toDouble();
emit changeParameter(tr("generation"),value, false);
}
void PSOParameters::on_LineEditSpeed1_editingFinished()
{
double value = ui->LineEditSpeed1->text().toDouble();
emit changeParameter(tr("c1"),value, false);
}
void PSOParameters::on_LineEditSpeed2_editingFinished()
{
double value = ui->LineEditSpeed2->text().toDouble();
emit changeParameter(tr("c2"),value, false);
}
void PSOParameters::on_LineEditUp_editingFinished()
{
double value = ui->LineEditUp->text().toDouble();
emit changeParameter(tr("upbounding"),value, false);
}
void PSOParameters::on_LineEditDown_cursorPositionChanged(int arg1, int arg2)
{
Q_UNUSED(arg1);
Q_UNUSED(arg2);
}
void PSOParameters::on_LineEditDown_editingFinished()
{
double value = ui->LineEditDown->text().toDouble();
emit changeParameter(tr("lowbounding"),value, false);
}
void PSOParameters::on_LineEditGroup_D_editingFinished()
{
double value = ui->LineEditGroup_D->text().toDouble();
emit changeParameter(tr("population"),value, true);
}
void PSOParameters::on_LineEditGeneration_D_editingFinished()
{
double value = ui->LineEditGeneration_D->text().toDouble();
emit changeParameter(tr("generation"),value, true);
}
void PSOParameters::on_LineEditUp_D_editingFinished()
{
double value = ui->LineEditUp_D->text().toDouble();
emit changeParameter(tr("upbounding"),value, true);
}
void PSOParameters::on_LineEditDown_D_editingFinished()
{
double value = ui->LineEditDown_D->text().toDouble();
emit changeParameter(tr("lowbounding"),value, true);
}
void PSOParameters::on_horizontalSliderWeight_valueChanged(int value)
{
double ratio = value/100.0;
ui->labelWeight->setText(QString::number(ratio,10,1));
emit changeParameter(tr("w"),ratio,false);
}
void PSOParameters::on_ComboBoxDimension_currentTextChanged(const QString &arg1)
{
int value = arg1.toInt();
emit changeParameter(tr("dimension"),static_cast<double>(value),false);
}
void PSOParameters::on_horizontalSliderFactor_D_valueChanged(int value)
{
double ratio = value/200.0;
ui->labelFactor_D->setText(QString::number(ratio,10,1));
emit changeParameter(tr("F"),ratio,true);
}
void PSOParameters::on_horizontalSliderCR_D_valueChanged(int value)
{
double ratio = value/100.0;
ui->labelCR_D->setText(QString::number(ratio,10,1));
emit changeParameter(tr("CR"),ratio,true);
}
void PSOParameters::on_ComboBoxDimension_D_currentTextChanged(const QString &arg1)
{
int value = arg1.toInt();
emit changeParameter(tr("dimension"),static_cast<double>(value),true);
}
void PSOParameters::on_pushButtonProcess_clicked()
{
emit beginToProcess(true);
}
void PSOParameters::on_comboBoxFunction_currentIndexChanged(int index)
{
int value = index + 1;
emit changeParameter(tr("function"),value, false);
emit changeParameter(tr("function"),value, true);
}
algorithm.h
#ifndef ALGORITHM_H
#define ALGORITHM_H
#include <map>
#include <QString>
#include <QObject>
#include <vector>
class Algorithm : public QObject
{
Q_OBJECT
public:
//double result;//存储结果
static void dataInitialization(int func_num, int dimension);
Algorithm():minY(0.0),maxY(10000000000.0){}
void setParameters(const QString &target, double value){
parameters[target] = value;
}
double getParameters(const QString &target){
return parameters[target];
}
void resetParameters(std::vector<std::pair<QString,double> > &parm);//设置参数
virtual void initial();
virtual void process(){
return;
}
double getResult(std::vector<double> ans);
std::map<QString,double>& getParameterList(){
return parameters;
}
signals:
void processFinished(double result);
void frameUpdate(double midret,const std::vector<double>& target,
const double &ymin,const double &ymax,
const int &curGen,const int &totalGen,
const std::pair<int,double> &bestValue);//运行过程中的动态更新
protected:
std::vector<std::vector<std::vector<double> > > group;//群体
std::vector<double> currentValue;
std::pair<int,double> bestValue;
double minY,maxY,avgValue;
void calcCurrentValue(const std::vector<std::vector<double> > &target);
private:
std::map<QString, double> parameters;//参数列表
};
class PSOAlgorithm : public Algorithm{//粒子群算法
Q_OBJECT
public:
std::vector<double> gBest; //全局最优解
PSOAlgorithm(){}
virtual void initial();
virtual void process();
void update(int curGeneration);//更新速度和位置
void curAndgloBest(int curGeneration);//计算全局最优与当前最优
private:
std::vector<std::vector<double> >velocity;//速度
std::vector<std::vector<double> >pBest;//当前每个的最优解
};
#endif // ALGORITHM_H
algorithm.cpp
#include <ctime>
#include <cmath>
#include <cstdlib>
#include "algorithm.h"
#include "MyFunction.cpp"
#include <QDebug>
#include <iostream>
#include <float.h>
void Algorithm::dataInitialization(int func_num, int dimension)
{
initialization(func_num, dimension);
}
void Algorithm::resetParameters(std::vector<std::pair<QString, double> > &parm)
{
for(auto it = parm.begin();it != parm.end();++it){
this->setParameters(it->first,it->second);
}
}
void Algorithm::initial()
{
//初始化
minY = DBL_MAX;
maxY = -11000000;
srand((unsigned)time(nullptr));
int population = static_cast<int>(getParameters(tr("population")));//种群大小
int dimension = static_cast<int>(getParameters(tr("dimension")));//维度
int generation = static_cast<int>(getParameters(tr("generation")));//迭代次数
double lowbounding = getParameters(tr("lowbounding"));
double upbounding = getParameters(tr("upbounding"));
group.clear();
group.resize(generation,std::vector<std::vector<double> >(population,
std::vector<double>(dimension,0.0)));
for (int i = 0; i < population; i++) {
for (int j = 0; j < dimension; j++) {
group[0][i][j] = lowbounding +
(double)(rand() / (double)RAND_MAX) * (upbounding - lowbounding);
}
}
currentValue.clear();
currentValue.resize(population,0.0);
}
double Algorithm::getResult(std::vector<double> ans)
{
int dimension = static_cast<int>(getParameters(tr("dimension")));
int func_num = static_cast<int>(getParameters(tr("function")));//函数编号
return functions(ans,func_num,dimension);
}
void Algorithm::calcCurrentValue(const std::vector<std::vector<double> > &target)
{
minY = DBL_MAX;
maxY = -11000000;
avgValue = 0;
int dimension = static_cast<int>(getParameters(tr("dimension")));
int func_num = static_cast<int>(getParameters(tr("function")));//函数编号
for(uint x = 0;x < target.size();++x){
currentValue[x] = functions(target[x],func_num,dimension);
avgValue += currentValue[x];
minY = std::min(minY,currentValue[x]);
maxY = std::max(maxY,currentValue[x]);
}
avgValue /= target.size();
}
//以下为粒子群算法
void PSOAlgorithm::initial()
{
Algorithm::initial();
int population = static_cast<int>(getParameters(tr("population")));//种群大小
int dimension = static_cast<int>(getParameters(tr("dimension")));//维度
gBest.clear();
pBest.clear();
velocity.clear();
gBest.resize(dimension, 0.0);
pBest.resize(population,std::vector<double>(dimension, 0.0));
velocity.resize(population,std::vector<double>(dimension,0.0));
bestValue.first = 0;
bestValue.second = DBL_MAX;
}
void PSOAlgorithm::process()
{
curAndgloBest(0);//计算初始代最优解
int generation = static_cast<int>(getParameters(tr("generation")));//迭代次数
for (auto current = 1; current < generation; ++current) {
update(current);
curAndgloBest(current);
calcCurrentValue(pBest);
if(generation <= 100 || (generation > 100 && generation % 2 == 0))
emit frameUpdate(avgValue,currentValue,minY,maxY,current,generation,bestValue);
}
emit processFinished(bestValue.second);
}
void PSOAlgorithm::update(int curGeneration)
{//更新速度和位置
int dimension = static_cast<int>(getParameters(tr("dimension")));
int population = static_cast<int>(getParameters(tr("population")));
double w = getParameters(tr("w"));//惯性权重
double c1 = getParameters(tr("c1"));//加速系数
double c2 = getParameters(tr("c2"));//加速系数
double upbounding = getParameters(tr("upbounding"));//上界
double lowbounding = getParameters(tr("lowbounding"));//下界
for(auto i = 0;i < population;++i){
for(auto j = 0;j < dimension;++j){
double pre = velocity[i][j];
//更新速度
velocity[i][j] = w*pre +
c1*(double)(rand()/(double)RAND_MAX)*
(pBest[i][j] - group[curGeneration - 1][i][j])
+
c2*(double)(rand()/(double)RAND_MAX)*
(gBest[j] - group[curGeneration - 1][i][j]);
if(velocity[i][j] > 200)velocity[i][j] = 200;
//位置更新
group[curGeneration][i][j] = group[curGeneration-1][i][j] + velocity[i][j];
//边界处理
if(group[curGeneration][i][j] > upbounding)
group[curGeneration][i][j] = upbounding;
if(group[curGeneration][i][j] < lowbounding)
group[curGeneration][i][j] = lowbounding;
}
}
}
void PSOAlgorithm::curAndgloBest(int curGeneration)
{//计算当前最优解和全局最优解
int population = static_cast<int>(getParameters(tr("population")));
int dimension = static_cast<int>(getParameters(tr("dimension")));
int func_num = static_cast<int>(getParameters(tr("function")));//函数编号
for (auto i = 0; i < population; ++i) {
double value = functions(group[curGeneration][i], func_num, dimension);
if (value < functions(pBest[i], func_num, dimension))
pBest[i] = group[curGeneration][i];
if (functions(pBest[i], func_num, dimension) < functions(gBest, func_num, dimension)){
gBest = pBest[i];
bestValue.first = i;
bestValue.second = functions(pBest[i], func_num, dimension);
}
}
}
curvedialog.h
#ifndef CURVEDIALOG_H
#define CURVEDIALOG_H
#include <QDialog>
namespace Ui {
class CurveDialog;
}
class PSOParameters;
class CurveDialog : public QDialog
{
Q_OBJECT
public:
explicit CurveDialog(QWidget *parent = 0);
~CurveDialog();
PSOParameters *setting;
private:
Ui::CurveDialog *ui;
};
#endif // CURVEDIALOG_H
curvedialog.cpp
#include "curvedialog.h"
#include "ui_curvedialog.h"
#include "psoparameters.h"
#include <QHBoxLayout>
#include <QDebug>
CurveDialog::CurveDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CurveDialog)
{
ui->setupUi(this);
//非模态对话框
this->setModal(false);
//布局
setting = new PSOParameters(this);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(setting);
this->setLayout(layout);
}
CurveDialog::~CurveDialog()
{
delete ui;
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QLineSeries>
#include <QString>
namespace Ui {
class MainWindow;
}
class PSOParameters;
class PSOAlgorithm;
class CurveDialog;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void addPoint(int x,double y);//曲线点
void reset();//曲线重置
void loadStyleSheet(const QString &styleSheetFile);
protected slots:
void setParameters(QString target, double value);
void beginProcess();//开始运行
void setResult(double result);//设置结果数值
void frameUpdate(double midret,const std::vector<double>& target,
const double &ymin,const double &ymax,
const int &curGen,const int &totalGen,
const std::pair<int,double> &bestValue);//运行过程中的动态设置
private:
bool begin;
Ui::MainWindow *ui;
PSOAlgorithm* pso_algo;
QtCharts::QScatterSeries *series;
QtCharts::QScatterSeries *bestSol;
QtCharts::QLineSeries *seriesCurve;
QtCharts::QChartView *chartView;
QtCharts::QChartView *chartViewCurve;
CurveDialog *curveDlg;
double maxY;
//参数列表
std::vector<std::pair<QString,double> > psoParm;
void createChart();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "psoparameters.h"
#include "curvedialog.h"
#include "algorithm.h"
#include <QtCharts/QChart>
#include <QMessageBox>
#include <QHBoxLayout>
#include <float.h>
#include <QDebug>
using namespace QtCharts;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
begin(false), ui(new Ui::MainWindow)
{
ui->setupUi(this);
QWidget *centeral = new QWidget(this);
this->setCentralWidget(centeral);
this->setWindowTitle("PSO");
this->loadStyleSheet(":/qss/new.qss");
//创建图表
createChart();
//布局
QHBoxLayout *layout = new QHBoxLayout();
layout->addWidget(chartView);
layout->addWidget(chartViewCurve);
centeral->setLayout(layout);
curveDlg = new CurveDialog(this);
connect(curveDlg->setting,&PSOParameters::changeParameter,this,&MainWindow::setParameters);
connect(curveDlg->setting,&PSOParameters::beginToProcess,this,&MainWindow::beginProcess);
//算法处理部分
pso_algo = new PSOAlgorithm();
connect(pso_algo,&PSOAlgorithm::processFinished,this,&MainWindow::setResult);
connect(pso_algo,&PSOAlgorithm::frameUpdate,this,&MainWindow::frameUpdate);
psoParm = {
std::pair<QString,double>("population",100.0),
std::pair<QString,double>("dimension",10.0),
std::pair<QString,double>("function",1.0),
std::pair<QString,double>("generation",500),
std::pair<QString,double>("w",0.5),
std::pair<QString,double>("c1",2.0),
std::pair<QString,double>("c2",2.0),
std::pair<QString,double>("upbounding",100.0),
std::pair<QString,double>("lowbounding",-100.0)
};
pso_algo->resetParameters(psoParm);
curveDlg->setting->showParameters(pso_algo->getParameterList());
curveDlg->show();
}
MainWindow::~MainWindow()
{
delete ui;
delete pso_algo;
}
void MainWindow::addPoint(int x, double y)
{
chartViewCurve->chart()->axisX()->setRange(1,x+1);
if(y > maxY){
maxY = y;
double lowb = 100.0*pso_algo->getParameters(tr("function"));
chartViewCurve->chart()->axisY()->setRange(lowb-100.0,maxY);
}
seriesCurve->append(QPointF(x,y));
chartViewCurve->repaint();
}
void MainWindow::reset()
{
seriesCurve->clear();
maxY = DBL_MIN;
}
void MainWindow::setParameters(QString target, double value)
{
for(auto it = psoParm.begin();it != psoParm.end();++it){
if(it->first == target){
it->second = value;
pso_algo->setParameters(target,value);
break;
}
}
}
void MainWindow::beginProcess()
{
//检查当前的函数是否有对应的维度
if(begin){
QMessageBox::warning(this,tr(u8"警告"),
tr(u8"当前算法任务尚未完成!"));
return;
}
begin = true;
reset();//曲线重置
int func_num = pso_algo->getParameters("function");
int dimension = pso_algo->getParameters("dimension");
Algorithm::dataInitialization(func_num,dimension);
pso_algo->initial();
pso_algo->process();
}
void MainWindow::setResult(double result)
{
curveDlg->setting->setResult(result);
begin = false;
}
void MainWindow::frameUpdate(double midret,const std::vector<double> &target,
const double &ymin,const double &ymax,
const int &curGen,const int &totalGen,
const std::pair<int,double> &bestValue)
{
//设置显示结果
curveDlg->setting->setResult(bestValue.second);
//设置显示图表
chartView->chart()->axisX()->setRange(0,target.size()+2);
chartView->chart()->axisY()->setRange(ymin-10,ymax+10);
series->clear();
for(uint x = 0;x < target.size();++x){
series->append(x+1,target[x]);
}
chartView->repaint();
//设置显示最优解
bestSol->clear();
bestSol->append(bestValue.first,bestValue.second);
//设置显示进度
double ratio = static_cast<double>(curGen)/totalGen;
curveDlg->setting->setProgress(ratio);
//设置显示收敛曲线
addPoint(curGen,midret);
//防止未响应
qApp->processEvents();
}
void MainWindow::createChart()
{
// 构建图表,种群个体是适应值
QChart *chart = new QChart();
chart->legend()->hide(); // 隐藏图例
// 构建 series,作为图表的数据源
series = new QtCharts::QScatterSeries(chart);
series->setMarkerSize(10.0);
bestSol = new QScatterSeries(chart);
bestSol->setMarkerSize(25.0);
chart->addSeries(series); // 将 series 添加至图表中
chart->addSeries(new QScatterSeries(chart));
chart->addSeries(bestSol); //将bestSol 添加至图表中
chart->createDefaultAxes(); // 基于已添加到图表的 series 来创轴
chart->setTitle(tr(u8"种群个体函数值")); // 设置图表的标题
// 构建 QChartView,并设置抗锯齿、标题、大小
chartView = new QChartView(this);
chartView->setChart(chart);
chartView->setRenderHint(QPainter::Antialiasing);
QChart::ChartTheme theme = static_cast<QChart::ChartTheme>(2);
chartView->chart()->setTheme(theme);
QChart *chart2 = new QChart();
chart2->legend()->hide(); // 隐藏图例
seriesCurve = new QLineSeries(chart);
chart2->addSeries(seriesCurve); // 将 series 添加至图表中
chart2->createDefaultAxes(); // 基于已添加到图表的 series 来创轴
chart2->setTitle(tr(u8"收敛曲线")); // 设置图表的标题
chartViewCurve = new QChartView(this);
chartViewCurve->setChart(chart2);
chartViewCurve->setRenderHint(QPainter::Antialiasing);
chartViewCurve->chart()->setTheme(theme);
chartViewCurve->chart()->axisX()->gridVisibleChanged(false);
chartViewCurve->chart()->axisY()->gridVisibleChanged(false);
}
/*load qss style*/
void MainWindow::loadStyleSheet(const QString &styleSheetFile)
{
QFile file(styleSheetFile);
file.open(QFile::ReadOnly);
if (file.isOpen())
{
QString styleSheet = this->styleSheet();
styleSheet += QLatin1String(file.readAll());//读取样式表文件
this->setStyleSheet(styleSheet);//把文件内容传参
file.close();
}
else
{
QMessageBox::information(this,"tip","cannot find qss file");
}
}
main.cpp
#include <QApplication>
#include "algorithm.h"
#include "mainwindow.h"
int main(int argc, char* argv[])
{
QApplication app(argc,argv);
MainWindow window;
window.show();
return app.exec();
}
MyFunction.cpp
//#include <WINDOWS.H>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <malloc.h>
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
#include <QDebug>
using namespace std;
#define INF 1.0e99
#define EPS 1.0e-14
#define E 2.7182818284590452353602874713526625
#define PI 3.1415926535897932384626433832795029
void initialization(int func_num, int dimension);
double functions(vector<double> x, int func_name,int dimension);
void F1(double *, double *, int, double *, double *, int, int); /* Sphere */
void F2(double *, double *, int, double *, double *, int, int);
void F3(double *, double *, int, double *, double *, int, int);
void F4(double *, double *, int, double *, double *, int, int);
void F5(double *, double *, int, double *, double *, int, int);
void F6(double *, double *, int, double *, double *, int, int);
void F7(double *, double *, int, double *, double *, int, int);
void F8(double *, double *, int, double *, double *, int, int);
void F9(double *, double *, int, double *, double *, int, int);
void F10(double *, double *, int, double *, double *, int, int);
void F11(double *, double *, int, double *, double *, int, int);
void F12(double *, double *, int, double *, double *, int, int);
void F13(double *, double *, int, double *, double *, int, int);
void F14(double *, double *, int, double *, double *, int, int);
void F15(double *, double *, int, double *, double *, int, int);
void shiftfunc(double*, double*, int, double*);
void rotatefunc(double*, double*, int, double*);
void sr_func(double *, double *, int, double*, double*, double, int, int); /* shift and rotate */
double *OShift, *M, *y, *z, *x_bound;
int ini_flag = 0, n_flag, func_flag, *SS;
void initialization(int func_num, int dimension) {
int cf_num = 10, i, j;
fstream infile;
char FileName[256];
int nx = dimension;
free(M);
free(OShift);
free(y);
free(z);
free(x_bound);
y = (double *)malloc(sizeof(double) * nx);
z = (double *)malloc(sizeof(double) * nx);
x_bound = (double *)malloc(sizeof(double) * nx);
for (i = 0; i<nx; i++) {
x_bound[i] = 100.0;
}
if (!(nx == 2 || nx == 10 || nx == 20 || nx == 30 || nx == 50 || nx == 100))
{
printf("\nError: Test functions are only defined for D=2,10,20,30,50,100.\n");
}
if (nx == 2 && ((func_num >= 17 && func_num <= 22) || (func_num >= 29 && func_num <= 30)))
{
printf("\nError: hf01,hf02,hf03,hf04,hf05,hf06,cf07&cf08 are NOT defined for D=2.\n");
}
/* Load Matrix M*/
sprintf(FileName, "D:/BJTU/CPP/Pso/AILearning-master/SingleObjectiveOpt/input_data/M_%d_D%d.txt", func_num, nx);
infile.open(FileName);
//std::cout << FileName << "\n";
//fpt = fopen(FileName, "r");
if (!infile)
{
printf("\n Error: Cannot open input file %s for reading \n", FileName);
}
if (func_num<20)
{
M = (double*)malloc(nx*nx * sizeof(double));
if (M == NULL)
printf("\nError: there is insufficient memory available!\n");
for (i = 0; i<nx*nx; i++)
{
infile >> M[i];
//cout << M[i] << endl;
//fscanf(fpt, "%Lf", &M[i]);
}
}
else
{
M = (double*)malloc(cf_num*nx*nx * sizeof(double));
if (M == NULL)
printf("\nError: there is insufficient memory available!\n");
for (i = 0; i<cf_num*nx*nx; i++)
{
infile >> M[i];
//fscanf(fpt, "%Lf", &M[i]);
}
}
infile.close();
//fclose(fpt);
/* Load shift_data */
sprintf(FileName, "D:/BJTU/CPP/Pso/AILearning-master/SingleObjectiveOpt/input_data/shift_data_%d.txt", func_num);
//std::cout << "fileName->" << FileName << std::endl;
infile.open(FileName);
//fpt = fopen(FileName, "r");
if (!infile)
{
printf("\n Error: Cannot open input file for reading \n");
}
if (func_num<20)
{
OShift = (double *)malloc(nx * sizeof(double));
if (OShift == NULL)
printf("\nError: there is insufficient memory available!\n");
for (i = 0; i<nx; i++)
{
infile >> OShift[i];
//fscanf(fpt, "%Lf", &OShift[i]);
}
}
else
{
OShift = (double *)malloc(nx*cf_num * sizeof(double));
if (OShift == NULL)
printf("\nError: there is insufficient memory available!\n");
for (i = 0; i<cf_num - 1; i++)
{
for (j = 0; j<nx; j++)
{
infile >> OShift[i*nx + j];
//fscanf(fpt, "%Lf", &OShift[i*nx + j]);
}
//fscanf(fpt, "%*[^\n]%*c");
}
for (j = 0; j<nx; j++)
{
infile >> OShift[(cf_num - 1)*nx + j];
//fscanf(fpt, "%Lf", &OShift[(cf_num - 1)*nx + j]);
}
}
infile.close();
//fclose(fpt);
/* Load Shuffle_data */
if (func_num >= 11 && func_num <= 20)
{
sprintf(FileName, "D:/BJTU/CPP/Pso/AILearning-master/SingleObjectiveOpt/input_data/shuffle_data_%d_D%d.txt", func_num, nx);
infile.open(FileName);
//fpt = fopen(FileName, "r");
if (!infile)
{
printf("\n Error: Cannot open input file for reading \n");
}
SS = (int *)malloc(nx * sizeof(int));
if (SS == NULL)
printf("\nError: there is insufficient memory available!\n");
for (i = 0; i<nx; i++)
{
infile >> SS[i];
cout << "Shuffle->" << SS[i];
//fscanf(fpt, "%d", &SS[i]);
}
infile.close();
//fclose(fpt);
}
else if (func_num == 29 || func_num == 30)
{
sprintf(FileName, "D:/BJTU/CPP/Pso/AILearning-master/SingleObjectiveOpt/input_data/shuffle_data_%d_D%d.txt", func_num, nx);
infile.open(FileName);
//fpt = fopen(FileName, "r");
if (!infile)
{
printf("\n Error: Cannot open input file for reading \n");
}
SS = (int *)malloc(nx*cf_num * sizeof(int));
if (SS == NULL)
printf("\nError: there is insufficient memory available!\n");
for (i = 0; i<nx*cf_num; i++)
{
infile >> SS[i];
//fscanf(fpt, "%d", &SS[i]);
}
infile.close();
//fclose(fpt);
}
n_flag = nx;
func_flag = func_num;
ini_flag = 1;
}
double functions(vector<double> v, int func_num,int dimension) {
double* x = (double *)malloc(dimension * sizeof(double));
for (int i = 0; i<dimension; i++)
x[i] = v[i];
int nx = dimension;
//qDebug()<<nx;
double result = 0;
if (func_num>0 && func_num <= 30)
{
switch (func_num)
{
case 1:
F1(x, &result, nx, OShift, M, 1, 1);
break;
case 2:
F2(x, &result, nx, OShift, M, 1, 1);
break;
case 3:
F3(x, &result, nx, OShift, M, 1, 1);
break;
case 4:
F4(x, &result, nx, OShift, M, 1, 1);
break;
case 5:
F5(x, &result, nx, OShift, M, 1, 1);
break;
case 6:
F6(x, &result, nx, OShift, M, 1, 1);
break;
case 7:
F7(x, &result, nx, OShift, M, 1, 1);
break;
case 8:
F8(x, &result, nx, OShift, M, 1, 1);
break;
case 9:
F9(x, &result, nx, OShift, M, 1, 1);
break;
case 10:
F10(x, &result, nx, OShift, M, 1, 1);
break;
case 11:
F11(x, &result, nx, OShift, M, 1, 1);
break;
case 12:
F12(x, &result, nx, OShift, M, 1, 1);
break;
case 13:
F13(x, &result, nx, OShift, M, 1, 1);
break;
case 14:
F14(x, &result, nx, OShift, M, 1, 1);
break;
case 15:
F15(x, &result, nx, OShift, M, 1, 1);
break;
default:
printf("\nError: There are only 30 test functions in this test suite!\n");
result = 0.0;
break;
}
return result;
}
}
void F1(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag) /* Sphere */
{
int i;
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
for (i = 0; i<nx; i++)
{
f[0] += z[i] * z[i];
}
}
void F2(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
int i;
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
double temp = 1;
for (i = 0; i < nx; i++) {
temp *= fabs(z[i]);
}
for (auto i = 0; i < nx; i++) {
f[0] += fabs(z[i]);
}
f[0] = f[0] + temp;
}
void F3(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
double temp = 0;
for (auto i = 0; i < nx; i++) {
for (auto j = 0; j < i; j++) {
temp += z[i];
}
f[0]+= pow(temp, 2);
}
}
void F4(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
f[0] = abs(z[0]);
for (auto i = 1; i < nx; i++) {
if (abs(z[i]) > f[0] )
f[0] = abs(z[i]);
}
}
void F5(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
f[0] = 10 * (100 * pow((z[1] - pow(z[0], 2)), 2) + pow(z[0] - 1, 2));
}
void F6(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
for (auto i = 0; i <nx; i++) {
f[0] += pow(floor(z[i] + 0.5), 2);
}
}
void F7(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
for (auto i = 0; i < nx; i++) {
f[0] += ((i + 1) * pow(z[i], 4) + (rand() % (1 - 0)) + 0);
}
}
void F8(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
for(auto i=0;i<nx;i++)
{
f[0]+=(z[i] * sin(sqrt(abs(z[i]))));
}
f[0]=-f[0];
}
void F9(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
f[0] = 10 * (pow(z[0], 2) - 10 * cos(2 * PI *z[0]) + 10);
}
void F10(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
float temp1 = 0, temp2 = 0;
for (auto i = 0; i < nx; i++) {
temp1 += pow(z[i], 2);
temp2 += cos(2 * PI * z[i]);
}
f[0] += (-20 * exp(-0.2 * sqrt(temp1 / nx)) - exp(temp2 / nx) + 20 + E);
}
void F11(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
float temp1 = 0, temp2 = 1;
for (auto i = 0; i < nx; i++) {
temp1 += pow(z[i], 2);
temp2 *= cos(z[i] / sqrt(i + 1));
}
f[0]= temp1 / 4000 - temp2 + 1;
}
void F12(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
float y[10] = {0};
for (auto i = 0; i < nx; i++) {
y[i] = 1 + (z[i] + 1) / 4;
}
float temp = 0;
for (auto i = 0; i < nx - 1; i++) {
temp += pow(y[i] - 1, 2) * (1 + 10 * pow(sin(PI * y[i + 1]), 2));
}
f[0] = (10 * pow(sin(PI * y[0]), 2) + temp + pow(y[nx - 1], 2)) * PI / nx;
for (auto i = 0; i < nx; i++) {
f[0] +=(z[i] > 10 ? 100 * pow((z[i] - 10), 4) : z[i] < -10 ? 100 * pow((-z[i] - 10), 4): 0);
}
}
void F13(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
float temp = 0;
for (auto i = 0; i < nx; i++) {
temp += pow(z[i] - 1, 2) * (1 + pow(sin(3 * PI *z[i]) + 1, 2));
}
f[0] = 0.1 * (pow(sin(3 * PI * z[0]), 2) + temp +
pow(z[nx - 1] - 1, 2) * (1 + pow(sin(2 * PI * z[nx - 1]), 2)));
for (auto i = 0; i < nx; i++) {
f[0] +=
(z[i] > 5 ? 100 * pow((z[i] - 5), 4) : z[i] < -5 ? 100 * pow((-z[i] - 5), 4)
: 0);
}
}
void F14(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
float temp = 0;
int matrix[2][25] = {{-32, 16, 0, 16, 32, -32, -16, 0, 16, 32, -32, -16, 0, 16, 32, -32, -16, 0, 16, 32, -32, -16, 0, 16, 32},
{-32, -32, -32, -32, -32, -16, -16, -16, -16, -16, 0, 0, 0, 0, 0, 16, 16, 16, 16, 16, 32, 32, 32, 32, 32}};
for (auto j = 0; j < 25; j++) {
float _temp = 0;
for (auto i = 0; i < nx; i++) {
_temp += pow(z[i] - matrix[i][j], 6);
}
temp += (1 / (j + 1 + _temp));
}
f[0] = pow(1 / 500 + temp, -1);
}
void F15(double *x, double *f, int nx, double *Os, double *Mr, int s_flag, int r_flag)
{
f[0] = 0.0;
sr_func(x, z, nx, Os, Mr, 1.0, s_flag, r_flag); /* shift and rotate */
float a[11] = {0.1957, 0.1947, 0.1735, 0.16, 0.0844, 0.0627, 0.0456, 0.0342, 0.0323, 0.0235, 0.0246};
float b[11] = {0.25, 0.5, 1, 2, 4, 6, 8, 10, 12, 14, 16};
for (auto i = 0; i < 11; i++) {
f[0] += pow(a[i] - (z[0] * (pow(1 / b[i], 2) + 1 / b[i] * z[1])) /
(pow(1 / b[i], 2) + 1 / b[i] * z[2] + z[3]), 2);
}
}
void shiftfunc(double *x, double *xshift, int nx, double *Os)
{
int i;
for (i = 0; i<nx; i++)
{
xshift[i] = x[i] - Os[i];
}
}
void rotatefunc(double *x, double *xrot, int nx, double *Mr)
{
int i, j;
for(i=0;i<nx;i++)xrot[i] = 0;
for (i = 0; i<nx; i++)
{
for (j = 0; j<nx; j++)
{
xrot[i] = xrot[i] + x[j] * Mr[i*nx + j];
}
}
}
void sr_func(double *x, double *sr_x, int nx, double *Os, double *Mr, double sh_rate, int s_flag, int r_flag) /* shift and rotate */
{
int i;
if (s_flag == 1)
{
if (r_flag == 1)
{
shiftfunc(x, y, nx, Os);
for (i = 0; i<nx; i++)//shrink to the original search range
{
y[i] = y[i] * sh_rate;
}
rotatefunc(y, sr_x, nx, Mr);
}
else
{
shiftfunc(x, sr_x, nx, Os);
for (i = 0; i<nx; i++)//shrink to the original search range
{
sr_x[i] = sr_x[i] * sh_rate;
}
}
}
else
{
if (r_flag == 1)
{
for (i = 0; i<nx; i++)//shrink to the original search range
{
y[i] = x[i] * sh_rate;
}
rotatefunc(y, sr_x, nx, Mr);
}
else
for (i = 0; i<nx; i++)//shrink to the original search range
{
sr_x[i] = x[i] * sh_rate;
}
}
}