Abstract
ccpso2算法是ccpso算法的改进,它吸纳了后者 对相关变量(effectivevariable) 采用的random grouping 技术。
在多峰复杂优化问题上,ccpso2算法的性能要明显优于sep-CMA-ES 、two existing PSO algorithms、cooperativecoevolving differetial evolution algorithm 等 目前最先进的优化算法。即使,它在单峰问题的表现上不尽如人意。
Ⅰ. Introduction
PSO是一种求优化问题满意解的近似算法。然而,它会陷入维度灾难。能求解髙维度优化问题的算法很稀有。
Potter和 Jong 提出了 CCEA 算法(CC:协同演化),采用分治的算法对变量进行decomposite。各组迭代求出最优解后再行组合。每个子分量为一维但是,在解不可分问题 (存在大量相关变量) 的时候,表现较差。
基于CC模型,Van denBergh 和 Engelbrecht 提出了两个模型:CPSO-Sk ,CPSO-Hk。然而,这两个模型只被用于解决30-190维的低维问题。
Yang在他的论文中提出了一个decomposite的技术:random grouping。相关变量更有几率被放在同一个分组当中更新。
有人提出一种adaptive weighting的方案对解进行微调。
ccpso算法吸纳了 ① random grouping ② adaptive weighting 的思想。主要用于解决高维不可分问题,能精确到1000维。
作者的研究表明,相对于①,②简直是鸡肋。结合其他,提出ccpso2。
ccpso2 与 ccpso算法的区别:
新的模型:
① 使用柯西-高斯分布 在 局部最优 和 邻域最优 内取样。
② 使用环形拓扑结构。
③ 使用新方法更新 局部最优 和 全局最优。
④ 抛弃adaptive weighting
⑤ 运行时动态确定每一分组的大小。
⑥ 将ccpso2与sep-CMA-ES,two existing PSO 与 CC DE进行比较。
⑦ 函数优化问题扩展到 2000 维。
优点:
① “柯西-高斯分布”+“ 环形拓扑结构” 提升 搜索能力
② 不必认为指定分组大小,由自适应函数指定。
Ⅱ.Cooperative coevolution
CCGA
Potter 和 Jong 提出的是:CCGA算法,基于GA。 先后创建了2个模型:CCGA1、CCGA2。
CCGA1在可分问题上表现比 GA好,但不可分问题上较差
CCGA2表现均比GA好,但是维度只被测试到30维
FEP
使用CC模型的FEP算法在 标准测试函数 上可扩展到 1000维,但是对于其中一个不可分问题,表现极差。充分暴露了 “Potter 和 Jong 提出的decomposition” 技巧(每个子分量只有一维)的缺陷!
CPSO-Sk & CPSO-Hk
把整个变量分成k部分,每部分不一定是一维。
Random Grouping of Variables
CPSO-Sk,在整个循环体中,被分成k个组,每个组s个一维变量。(n = kxs)。很不好!
è 两个相关变量可能始终都不能在一个组中。
RandomGrouping:
每个循环中动态分组,如:每一个循环就重新分一次组,(也是分成k个组,每个组s个一维变量)。那么两个相关变量,在50次循环中至少在一个组中一次的几率为:
P(x≥1) = p(1) + … +p(50) = 1 –(50,0) [(0.1)^0] * [(1-0.1)^50] = 0.9948
提高了解不可分问题的可靠性 !
Ⅲ. Particle Swarm Optimization
基本pso算法
cpso算法
:CPSO-Sk 、CPSO-Hk
CPSO-Sk,单纯的分治:一个n维种群 -> k个s维种群 (kxs = n)
CPSO-Hk,结合CPSO-Sk 和 basic PSO ,轮换交流 全局最优因子。
Ⅳ. NEW CCPSO2 ALGORITHM
A
(1) 基于高斯分布的PSO算法:
单纯使用高斯分布 -> 搜索空间有限
使用柯西-高斯 联合分布
(2) 基于环形拓扑 的 局部PSO算法,只知邻域的信息->收敛慢,利于解决多峰函数寻优问题。
B
基于柯西和高斯分布的PSO算法
高斯分布->降低搜索能力
柯西分布->提升搜索能力
C
Dynamically changing group size
Pseudocode of CCPSO2:
初始化时,手工选定一个k.( s = n/k )
每迭代一次后,若全局最优被更新了,则继续按这个k值更新下去。否则,在集合S中选择另外一个k进行迭代。 其中,若一个k值,它被用于更新全局最优成功的比重越大,则,在需要选择k值时,它被选择的比重越大。(集合S是需要人为指定的)
理论上,使用randomgrouping 技术越频繁,对于解决高维不可分问题越有好处。
interacting variables 相关变量
D
CCPSO2
Ⅴ. EXPERIMENTAL STUDIES
...
Codes for CCPSO2 (implemented by myself) are released here:
/******************************************************/
/************** CCPSO2 algorithm *******************/
/************** cocurrentcy version *******************/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include "test_funcs.h"
#include "./CEC2010/Benchmarks.h"
#include "./CEC2010/Header.h"
#define randf (double)rand()/RAND_MAX
#include "boost/random.hpp"
#include "boost/random/uniform_real.hpp"
#include "boost/random/cauchy_distribution.hpp"
#include "boost/random/normal_distribution.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace boost;
using namespace std;
// Set generator and C-G distribution
kreutzer1986 engine(randf);
cauchy_distribution <double> distribution1(0,1);
normal_distribution <double> distribution2(0,1);
variate_generator<kreutzer1986& , cauchy_distribution<double> > CAUCHY(engine,distribution1);
variate_generator<kreutzer1986& , normal_distribution<double> > GAUSSIAN(engine,distribution2);
/******************* Variables **********************/
const int MAX_DIM = 2000;
const double Xmax = 500;
const int n = 1000;
const int sw = 30;
int k,s;
int func_num;
bool improved;
const int SIZE = 10;
const int iteration_time = 500;
int S[SIZE] = {5,10,20,25,50,100,200,250,500,1000};
// X -> current pos of particle
// Y -> pbest pos of particle
// N -> lbest pos of particle
// G -> gbest pos of D-dimension swarm
double X[sw][n];
double Y[sw][n];
double N[sw][n];
double G[n];
// array used for shuffle
int list[MAX_DIM];
// functions:
void init ();
int select ();
void shuffle ();
void fly ();
void updatePOS ();
void updateN (int,int,int);
void updateLbest (int,int);
void check (int par_inde,int begin_col,int end_col);
double func (int func_number , int dim , double * x);
double Simple (int dim , double* x);
void assign1 (double*,double*,int,int);
void assign2 (double[][n],double*,int,int,int);
void assign3 (double[][n],double[][n],int,int,int);
void assign4 (double[][n],double[][n],int,int,int,int);
/****************** Function implementation ********************/
void init() {
for(int i = 0 ; i < n ; i ++)
list[i] = i;
double interval = 2*Xmax;
for(int i = 0 ; i < sw ; i ++)
{
for(int j = 0 ; j < n ; j ++)
{
X[i][j] = -Xmax + interval * randf;
N[i][j] = Y[i][j] = X[i][j];
}
}
assign2(X,G,0,0,n-1);
}
// valid inde range: 0 ~ SIZE-1
int select() {
int inde = int(rand()%SIZE);
return S[inde];
}
void check(int par_inde , int begin_col , int end_col) {
for(int j = begin_col ; j <= end_col ; j ++)
{
if(X[par_inde][j] > Xmax)
X[par_inde][j] = Xmax;
if(X[par_inde][j] < -Xmax)
X[par_inde][j] = -Xmax;
}
}
double Simple(int dim , double* x) {
double Sum = 0;
for(int i = 1 ; i <= dim ; i ++) {
Sum += -1 * x[i] * sin(sqrt(fabs(x[i])));
}
return Sum;
}
double func(int func_number , int dim , double * x) {
switch(func_number){
case 1: return Simple(dim,x);
break;
default:
printf("Error : Function number out of range\n");
exit(0);
break;
}
}
// randomly change the matrix use algorithm --- shuffle-fisher yates
double tmp_store[sw][n];
void shuffle() {
int i,j;
int fr = 0, to = n-1;
for(i = fr ; i <= to ; i ++)
{
int select = int(i+ (to-i+1) * randf);
int tmp = list[select];
list[select] = list[i];
list[i] = tmp;
}
// X
for( i = 0 ; i < sw ; i ++)
for( j = 0 ; j < n; j ++)
tmp_store[i][j] = X[i][list[j]];
for( i = 0 ; i < sw ; i ++)
for( j = 0 ; j < n ; j ++)
X[i][j] = tmp_store[i][j];
// Y
for( i = 0 ; i < sw ; i ++)
for( j = 0 ; j < n; j ++)
tmp_store[i][j] = Y[i][list[j]];
for( i = 0 ; i < sw ; i ++)
for( j = 0 ; j < n ; j ++)
Y[i][j] = tmp_store[i][j];
// G
for( j = 0 ; j < n ; j ++)
tmp_store[0][j] = G[list[j]];
for( j = 0 ; j < n ; j ++)
G[j] = tmp_store[0][j];
// N
for( i = 0 ; i < sw ; i ++)
for( j = 0 ; j < n ; j ++)
tmp_store[i][j] = N[i][list[j]];
for( i = 0 ; i < sw ; i ++)
for( j = 0 ; j < n ; j ++)
N[i][j] = tmp_store[i][j];
}
// both 1-dimension arrays
void assign1(double * source , double * dest , int fr , int to ) {
for(int i = fr ; i <= to ; i ++)
dest[i] = source[i];
}
// 1-dimension array and 2-dimension array
void assign2(double source[][n] ,double* dest , int k , int fr , int to ) {
for(int i = fr ; i <= to ; i ++)
dest[i] = source[k][i];
}
// both 2-dimension arrays
void assign3(double source[][n] , double dest[][n] , int k , int fr , int to) {
for(int i = fr ; i <= to ; i ++)
dest[k][i] = source[k][i];
}
void assign4(double source[][n] , double dest[][n] , int source_row , int dest_row , int fr , int to) {
for(int i = fr ; i <= to ; i ++)
dest[dest_row][i] = source[source_row][i];
}
// particles fly
//void fly(Benchmarks *fp) {
void fly() {
int fr,to;
double tmp1[n];
double tmp2[n];
for(int j = 1 ; j <= k ; j ++)
{
//update and record the best particle of the jth swarm
int inde = -1;
double min_f = func(func_num,n,G);
//double min_f = fp->compute(G);
fr = (j-1)*s ; to = fr + s - 1;
double re1,re2;
for(int i = 0 ; i < sw ; i ++)
{
assign1(G,tmp1,0,n-1);
assign1(G,tmp2,0,n-1);
assign2(X,tmp1,k,fr,to);
assign2(Y,tmp2,k,fr,to);
double f1 = func(func_num,n,tmp1);
double f2 = func(func_num,n,tmp2);
//double f1 = fp->compute(tmp1);
//double f2 = fp->compute(tmp2);
if(f1 < f2)
{
assign3(X,Y,k,fr,to);
if(f1 < min_f)
{
min_f = f1;
inde = k;
improved = 1;
}
}
}
//update the gbest of the swarm
if(inde != -1)
{
assign2(X,G,inde,fr,to);
improved = 1;
}
// update the lbest of the swarm
//updateLbest(fr,to,fp);
updateLbest(fr,to);
}
}
void updatePOS() {
int fr,to;
for(int j = 1 ; j <= k ; j ++)
{
for(int i = 0 ; i < sw ; i ++)
{
fr = (j-1)*s; to = fr+s-1;
// Cauchy
if(randf <= 0.5)
for(int t = fr ; t <= to ; t ++)
X[i][t] = Y[i][t] + CAUCHY()* fabs(Y[i][t] - N[i][t]);
// Gaussian
else
for(int t = fr ; t <= to ; t ++)
X[i][t] = N[i][t] + GAUSSIAN()* fabs(Y[i][t] - N[i][t]);
}
}
for(int j = 0 ; j < sw ; j ++)
check(j,0,n-1);
}
// update the lbest of the particles
//void updateLbest(int fr ,int to, Benchmarks *fp){
void updateLbest(int fr, int to) {
int i,j,k,p;
int l_inde, m_inde, r_inde;
int inde = -1;
double tmpL[n];
double tmpM[n];
double tmpR[n];
double fL,fM,fR;
for(k = 0 ; k < sw ; k ++)
{
m_inde = k;
if(m_inde == 0)
{
l_inde = sw-1;
r_inde = m_inde + 1;
}
else if(m_inde == sw-1)
{
l_inde = m_inde-1;
r_inde = 0;
}
else
{
l_inde = m_inde-1;
r_inde = m_inde+1;
}
assign1(G,tmpL,0,n-1);
assign1(G,tmpM,0,n-1);
assign1(G,tmpR,0,n-1);
assign2(Y,tmpL,l_inde,fr,to);
assign2(Y,tmpM,m_inde,fr,to);
assign2(Y,tmpR,r_inde,fr,to);
fL = func(func_num,n,tmpL);
fM = func(func_num,n,tmpM);
fR = func(func_num,n,tmpR);
//fL = fp->compute(tmpL);
//fM = fp->compute(tmpM);
//fR = fp->compute(tmpR);
if(fL < fM)
{
inde = l_inde;
if(fL > fR)
inde = r_inde;
}
else
{
inde = m_inde;
if(fM > fR)
inde = r_inde;
}
assign4(Y,N,inde,m_inde,fr,to);
}
}
/*
int main() {
Benchmarks * fp = NULL;
generateFuncObj(1);
srand((unsigned)time(NULL));
init();
improved = false;
func_num = 1;
for(int t = 0 ; t < iteration_time ; t ++)
{
if(improved == false)
{
s = select();
k = n / s;
}
shuffle();
improved = false;
fly(fp);
updatePOS();
printf("%lg\n",func(1,n,G));
//printf("%lg\n",fp->compute(G));
}
return 0;
}
*/
int main() {
func_num = 1;
srand((unsigned)time(NULL));
init();
improved = false;
for(int t = 0 ; t < iteration_time ; t ++)
{
if(improved == false)
{
s = select();
k = n / s;
}
shuffle();
improved = false;
fly();
updatePOS();
printf("%lg\n",func(1,n,G));
}
return 0;
}
本文详细介绍了CCPSO2算法,它是CCPSO算法的改进版,特别针对高维不可分优化问题进行了优化。通过使用柯西-高斯分布和环形拓扑结构,该算法在多峰复杂优化问题上的性能显著优于其他最先进的优化算法。尽管在单峰问题上表现不佳,但在高维不可分问题上的表现令人印象深刻。
636





