基于基本蚁群算法解决连续优化问题
相关链接
基本蚁群算法解决连续优化问题基本流程
用一个蚂蚁代表一个可行解,一个蚂蚁含有的信息包括各变量值;
1、确定迭代周期;
2、确定蚂蚁数;
2.a、随机初始化蚁群,记录蚁群中的最优解;
2.b、进入循环,将已初始化的蚂蚁分为两种;
2.b.a、一种是上一次蚁群中的最优解,搜索在最优解附近搜索;
可行解格式{ 、 、 、 }
X={ 、 、 、 }
或
择优录取吧,每次循环后, 要变小;
2.b.b、另一种是非最优解,有一定概率向最优解进化;
最优解蚂蚁的信息素浓度;
当前蚂蚁的信息素浓度;
2.b.b.a、向最优解移动:
2.b.b.b、自己搜索移动:
2.c、更新信息素
参数设置
最大迭代周期 T = 200;
蚂蚁数量 ant_size = 25;
信息素衰退因子 p = 0.9;
步长系数 = 1,随着迭代的进行变小
步长系数减小因数 wu = 0.5;该数值越大,搜的范围越精细;
最优解搜索步长 dx[max_x]:一般为自变量取值范围的一半;防止局部最优解;
更新信息素系数 k = 1;
更新信息素因子 a;求最小值时a取e;求最大值时a取0.5;
非最优解步长系数 u = 0.7;
非最优解向最优解进化概率 p0 = 0.7;
本算法的fun()函数里包含三个求最小值样例;
三个return分别代表三个函数
函数一:二维分段函数,自变量范围[-5,5]
图像:
10组测试结果:
函数二:二维复杂函数,自变量范围[-5,5]
图像:
10组测试结果:
函数三:三维函数,自变量 范围[-10,10], 范围[-10,10];
图像:
10组测试结果:
算法代码
#include<iostream>
#include<ctime>
#include<cmath>
#include<fstream>
#include<algorithm>
#include<string.h>
#include<iomanip>
using namespace std;
//常量
const int max_x = 10;//自变量规模最大值
const int max_ants = 1000;//蚂蚁规模最大值
//变量
int x_size;//自变量规模
int low_bound[max_x];//自变量下界
int high_bound[max_x];//自变量上界
int ant_size=5;//蚂蚁数量
int T;//迭代周期
double message[max_ants];//信息素
double w;//步长系数,随着迭代的进行变小
double wu;//步长系数减小因数
double dx[max_x];//最优解搜索步长
double k;//更新信息素系数
double a;//更新信息素因子
double u;//非最优解步长系数
double p0;//非最优解向最优解进化概率
double p;//信息素衰减系数
double best_ants[max_x];//最优解对应自变量值
double best;//最优解
double fun(double* num){//求解函数
return num[0] <= 1 ? pow(num[0], 2) : (pow(num[0] - 3, 2) - 3);
//return num[0] + 10 * sin(5 * num[0]) + 7 * cos(4 * num[0]);
//return num[0] / (1 + abs(num[1]));
}
void init() {
x_size=1;//自变量规模
for (int i = 0; i < x_size; ++i) {
low_bound[i] = -5;//自变量下界
high_bound[i]=5;//自变量上界
dx[i]=high_bound[i]-low_bound[i];//最优解搜索步长,,一般为数据范围的一半
}
T = 200;//迭代周期
ant_size = 25;//蚂蚁数量
w=1;//最优解步长系数,随着迭代的进行变小
wu = 0.5;
k=1;//更新信息素系数
//a=exp(1);//更新信息素因子
a = 0.5;///////////////
p0 = 0.7;//非最优解向最优解进化概率
u=0.7;//非最优解步长系数
p=0.9;//信息素衰减系数
//best =1e9;////////////
best = -1e9;
}
double mrand(int l, int r) {//范围在20内
int t = l;
r -= l;
l -= l;
const double v = 1e3;
r *= v;
l *= v;
double temp = rand() % ((r - l) + 1);
//int a = RAND_MAX;
temp += 1 + l;
return temp / v+t;
//return (rand() % ((r - l) + 1) + 1 + l)/1e6;
}
double get_p(int i, int bes) {
return exp(message[bes] - message[i]) / exp(message[bes]);
}
void islegal(double* xi) {
for (int i = 0; i < x_size; ++i) {
if (xi[i] > high_bound[i])
xi[i]=high_bound[i];
else if(xi[i] < low_bound[i])
xi[i] = low_bound[i];
}
}
//max
/*
void moni() {
a = 0.5;///////////////
best = -1e9;
double t_ants[max_ants][max_x];//蚁群
double value[max_ants];//
double ans = best;//
int t_ant;//局部最优解
for (int i = 0; i < ant_size; ++i) {
for (int j = 0; j < x_size; ++j) {
t_ants[i][j] = mrand(low_bound[j], high_bound[j]);
}
value[i] = fun(t_ants[i]);
if (ans < value[i]) {/////////
ans = value[i];
t_ant = i;
}
message[i] = k * pow(a, -fun(t_ants[i]));//信息素初始化
}
int t = T;
double x1[max_x];//构建临时解
double x2[max_x];
while (t--) {//开始迭代循环
for (int i = 0; i<ant_size; ++i) {//更新信息素
//message[i] = (1-p) * message[i] + t_mess[i];
//message[i] = (1 - p) * message[i] + k * pow(a, -fun(t_ants[t_ant]));
message[i] = (1 - p) * message[i];
}
double tw = w;
for (int i = 0; i<ant_size; ++i) {//遍历每只蚂蚁
if (value[i] == ans) {//上次循环最优解
for (int j = 0; j < x_size; ++j) {
x1[j] = t_ants[i][j] + tw * dx;
x2[j] = t_ants[i][j] - tw * dx;
}
tw *= 0.1;
islegal(x1);
if (value[i] < fun(x1)) {//////////////
value[i] = fun(x1);
ans = value[i];
t_ant = i;
for (int j = 0; j < x_size; ++j) {
t_ants[i][j] = x1[j];
}
}
islegal(x2);
if (value[i] < fun(x2)) {///////////////
value[i] = fun(x2);
ans = value[i];
t_ant = i;
for (int j = 0; j < x_size; ++j) {
t_ants[i][j] = x2[j];
}
}
}
else {//非最优解
if (get_p(i, ans)<p0) {//向最优解移动
for (int j = 0; j < x_size; ++j) {
x1[j] = t_ants[i][j] + u * (t_ants[t_ant][j] - t_ants[i][j]);
}
}
else {
for (int j = 0; j < x_size; ++j) {
x1[j] = t_ants[i][j] + dx * mrand(-1, 1);
}
}
islegal(x1);
if (ans < fun(x1)) {//////////////
ans = fun(x1);
value[i] = ans;
t_ant = i;
for (int j = 0; j < x_size; ++j)
t_ants[i][j] = x1[j];
}
}
//t_mess[i] += k * pow(a, -ans);
message[i] += k * pow(a, -fun(t_ants[i]));
}
//
//for (int i = 0; i<ant_size; ++i) {//更新信息素
//message[i] = (1-p) * message[i] + t_mess[i];
//message[i] = (1 - p) * message[i] + k * pow(a, -fun(t_ants[t_ant]));
//}
//ans = min(ans,t_ans);
}
for (int i = 0; i < x_size; ++i) {
best_ants[i] = t_ants[t_ant][i];
}
best = ans;
}
*/
void moni() {//min
a=exp(1);//更新信息素因子
best = 1e9;
double t_ants[max_ants][max_x];//蚁群
double value[max_ants];//
double ans = best;//
int t_ant;//局部最优解
for (int i = 0; i < ant_size; ++i) {
for (int j = 0; j < x_size; ++j) {
t_ants[i][j] = mrand(low_bound[j], high_bound[j]);
}
value[i] = fun(t_ants[i]);
if (ans > value[i]) {/////////
ans = value[i];
t_ant = i;
}
message[i] = k * pow(a, -fun(t_ants[i]));//信息素初始化
}
int t = T;
double x1[max_x];//构建临时解
double x2[max_x];
while (t--) {//开始迭代循环
for (int i = 0; i<ant_size; ++i) {//更新信息素
//message[i] = (1-p) * message[i] + t_mess[i];
//message[i] = (1 - p) * message[i] + k * pow(a, -fun(t_ants[t_ant]));
message[i] = (1 - p) * message[i];
}
double tw = w;
for (int i = 0; i<ant_size; ++i) {//遍历每只蚂蚁
if (value[i] == ans) {//上次循环最优解
for (int j = 0; j < x_size; ++j) {
x1[j] = t_ants[i][j] + tw * dx[j];
x2[j] = t_ants[i][j] - tw * dx[j];
}
tw *= wu;
islegal(x1);
if (value[i] > fun(x1)) {//////////////
value[i] = fun(x1);
ans = value[i];
t_ant = i;
for (int j = 0; j < x_size; ++j) {
t_ants[i][j] = x1[j];
}
}
islegal(x2);
if (value[i] > fun(x2)) {///////////////
value[i] = fun(x2);
ans = value[i];
t_ant = i;
for (int j = 0; j < x_size; ++j) {
t_ants[i][j] = x2[j];
}
}
}
else {//非最优解
if (get_p(i, ans)<p0) {//向最优解移动
for (int j = 0; j < x_size; ++j) {
x1[j] = t_ants[i][j] + u * (t_ants[t_ant][j] - t_ants[i][j]);
}
}
else {
for (int j = 0; j < x_size; ++j) {
x1[j] = t_ants[i][j] + dx[j] * mrand(-1, 1);
}
}
islegal(x1);
if (ans > fun(x1)) {//////////////
ans = fun(x1);
value[i] = ans;
t_ant = i;
for (int j = 0; j < x_size; ++j)
t_ants[i][j] = x1[j];
}
}
//t_mess[i] += k * pow(a, -ans);
message[i] += k * pow(a, -fun(t_ants[i]));
}
//
//for (int i = 0; i<ant_size; ++i) {//更新信息素
//message[i] = (1-p) * message[i] + t_mess[i];
//message[i] = (1 - p) * message[i] + k * pow(a, -fun(t_ants[t_ant]));
//}
//ans = min(ans,t_ans);
}
for (int i = 0; i < x_size; ++i) {
best_ants[i] = t_ants[t_ant][i];
}
best = ans;
}
void output() {
for (int i = 0; i < x_size; ++i) {
cout << "x" << i << " = " << best_ants[i];
if (i != x_size - 1)
cout << " , ";
else
cout << endl;
}
cout <<fixed<< "f() = " << best << endl;
cout.clear();
}
int main() {
srand(time(nullptr));
int t;
while (cin >> t) {//仅作为重启算法开关使用,无意义
//for (int i = 0; i < t; ++i) {
init();//使用程序内置数据使用init()函数,
//test();//使用文件读取数据使用test()函数
moni();//开始算法
output();//输出
//}
}
return 0;
}