#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <afx.h>
#include <string.h>
#include <math.h>
using namespace std;
#define square(x) ((x)*(x))
#define DIMEN_MAX 20
#define POP_MAX 40 // 粒子群群体规模
#define coe 1 //粒子适应度系数
#define LOOP_MAX 10000 //循环最大次数
#define WU 0.9 //权重系数
#define WB 0.4 //权重系数
#define C1 2.0 //调节参数
#define C2 2.0 //调节参数
#define RANGE 1000.0
#define START -500.0
#define V_MAX 1000 //速度最大值
#define FRAND() (double(rand())/RAND_MAX) //随机的位于0到1之间的数
//二维结构体
struct point2d
{
public: double x,y;
int cluster[POP_MAX]; //所属类号
};
point2d * centroid; //存放中心点
point2d * set; //存放样本点
//int *nb; //纪录类的个数
//粒子结构体
struct particle
{
point2d position[DIMEN_MAX]; //位置,二维的
point2d velocity[DIMEN_MAX]; //速度,二维的
point2d pos_best[DIMEN_MAX]; //最优位置,二维的
double solution; //粒子适应度
double pbest; //经历过的最好位置
int nb[DIMEN_MAX]; //纪录此粒子各类的数目
}pops[POP_MAX];
int gbest_no=0; //位于群体最好位置的粒子的编号
double gbest=pops[0].pbest; // 群体所有微粒经历过的最好位置初始设置为第一个粒子的最好位置
//随机生成点坐标,写入txt文件
void rand_k(int p_count)
{
ofstream fout; //定义一个文件输出流对象
ifstream fin; //定义一个文件输入流对象
double pointx,pointy,xup,xlow,yup,ylow;
cout <<"输入坐标X范围:"<<endl;
cin >>xlow>>xup;
cout <<"输入坐标Y范围:"<<endl;
cin >>ylow>>yup;
cout<<"请稍等..."<<endl;
fout.open("source.txt"); //打开(生成)source.txt作为输出流
//生成随机x,y坐标值
for(int i=1;i<=p_count;i++)
{
pointx=(double)rand()/RAND_MAX;
pointx=xlow+pointx*(xup-xlow);
pointy=(double)rand()/RAND_MAX;
pointy=ylow+pointy*(yup-ylow);
fout << pointx <<'*'<< pointy <<endl; //写出到txt,中间用*隔开
}
fout.close(); //关闭输出流
}
//读入点坐标,存入数组中
void read_k(int p_count,int k,int in){
int i,j,len;
int i_cpy;
set=new point2d[p_count];
centroid=new point2d[k]; //生成二维坐标对象
//nb=new int[k];
CStdioFile file;
CString str;
file.Open("source.txt",CFile::modeRead,NULL); //打开source.txt,准备读数据
for(i_cpy=0;i_cpy<p_count;i_cpy++){
file.ReadString(str); //读出数据,放入str中
len=str.GetLength(); //获得str长度
char *ch = (char *) malloc(len*sizeof(char));
sprintf(ch,"%s",str); //将数据放入数组ch中,便于分割出x,y
for(i=0;i<15;i++){
if(ch[i]=='*') break;
}
char *chf = (char *) malloc(i*sizeof(char));
char *chb = (char *) malloc((len-i-1)*sizeof(char));
strncpy(chf,ch,i); //将数组ch的前半部分即坐标x的部分放入chf
for(i=i+1,j=0;i<=len;i++,j++) chb[j]=ch[i];//将数组ch的后半部分即坐标y的部分放入chb
set[i_cpy].x=atof(chf);
set[i_cpy].y=atof(chb); //分别将x,y转换为double型付给二维结构体的相应部分
set[i_cpy].cluster[in]=(int)((k-1)*FRAND()); //************应该在此随机分给某一类??
}
}
//计算中心点坐标
void KMeansCluster(int p_count,int k,int in)
{
int i,j,cl;
for(j=0;j<k;j++)
{
pops[in].nb[j]=0; //记录此类的个数
centroid[j].x=centroid[j].y=0; //将中心的x,y坐标值设为0
}
for(i=0;i<p_count;i++)
{
cl=set[i].cluster[in];
centroid[cl].x+=set[i].x;
centroid[cl].y+=set[i].y; //实现x,y坐标值的累加
pops[in].nb[cl]++; //类数目自加
}
}
//集合划分,最近邻法则
void KMeansAssign(int p_count,int k,int in)
{
int i,j,winner;
double dist,distmin;
for(i=0;i<p_count;i++)
{
distmin=1.0e8;
for(j=0;j<k;j++)
{
//计算每个点分别到k个聚类中心的距离
//SQRT 函数[数字]. 功能. 返回一个数字的平方根
dist=sqrt(square(set[i].x-pops[in].position[j].x)+square(set[i].y-pops[in].position[j].y));
//如果dist小于最小距离就将dist设为最小距离,且将此类号付给winner
if (dist<distmin) {distmin=dist; winner=j;}
}
set[i].cluster[in]=winner; //将此二维点归为第j类
}
}
//计算粒子的适应度
double Deg_Adapt(int p_count,int k,int in){
int i,j;
double ada,dist,sum,Jc=0;
for(j=0;j<k;j++){
for(i=0;i<p_count;i++){
sum=0;
if(set[i].cluster[in]==j){
dist=sqrt(square(set[i].x-pops[in].position[j].x)+square(set[i].y-pops[in].position[j].y));
sum+=dist;}
}
Jc+=sum;
}
ada=coe/Jc;
return ada;
}
//初始化粒子群
void initial_particle(int p_count,int k,int size){
int i,j;
srand((unsigned)time(NULL));
for (i=0;i<size;i++ ){
cout<<"第"<<i<<"个"<<endl;
read_k(p_count,k,i);
KMeansCluster(p_count,k,i);
for(j=0;j<k;j++){
if (pops[i].nb[j]>0) {centroid[j].x/=pops[i].nb[j];centroid[j].y/=pops[i].nb[j];} //计算新的聚类中心坐标
pops[i].position[j]=centroid[j];
pops[i].velocity[j].x=FRAND()*V_MAX;
pops[i].velocity[j].y=FRAND()*V_MAX;
//cout <<"Class "<<j<<" "<<nb[j]<<" "<<centroid[j].x<<" "<<centroid[j].y<<endl;
cout <<j<<endl;
cout <<pops[i].velocity[j].x<<endl;
cout <<pops[i].velocity[j].y<<endl;
pops[i].nb[j]=0;
}
pops[i].solution=Deg_Adapt(p_count,k,i);
pops[i].pbest=-1e9; //设置粒子初始最好位置
}
}
//更新粒子经历过的最好位置和群体经历过的最好位置
void evaluate(int k,int size)
{
int i,j;
for (j=0;j<size;j++){
if (pops[j].solution>pops[j].pbest){
pops[j].pbest=pops[j].solution;
for(i=0;i<k;i++)
pops[j].pos_best[i]=pops[j].position[i];
}
if (pops[j].pbest>gbest)
{
gbest_no=j;
gbest=pops[j].pbest;
}
}
}
//调整粒子的位置和速度
void move(int loop_no,int k,int size)
{
int i,j;
float weight=WU-(WU-WB)*(loop_no/LOOP_MAX);
for (j=0;j<size;j++){
for (i=0;i<k;i++){
pops[j].velocity[i].x=weight*pops[j].velocity[i].x
+C1*FRAND()*(pops[j].pos_best[i].x-pops[j].position[i].x)
+C2*FRAND()*(pops[gbest_no].pos_best[i].x-pops[j].position[i].x);
pops[j].velocity[i].y=weight*pops[j].velocity[i].y
+C1*FRAND()*(pops[j].pos_best[i].y-pops[j].position[i].y)
+C2*FRAND()*(pops[gbest_no].pos_best[i].y-pops[j].position[i].y);
if (pops[j].velocity[i].x>V_MAX)
pops[j].velocity[i].x=V_MAX;
else if(pops[j].velocity[i].x<-V_MAX)
pops[j].velocity[i].x=-V_MAX;
if (pops[j].velocity[i].y>V_MAX)
pops[j].velocity[i].y=V_MAX;
else if(pops[j].velocity[i].y<-V_MAX)
pops[j].velocity[i].y=-V_MAX;
pops[j].position[i].x+=pops[j].velocity[i].x;
pops[j].position[i].y+=pops[j].velocity[i].y;
if(pops[j].position[i].x<START)
pops[j].position[i].x=START;
else if(pops[j].position[i].x>START+RANGE)
pops[j].position[i].x=START+RANGE;
if(pops[j].position[i].y<START)
pops[j].position[i].y=START;
else if(pops[j].position[i].y>START+RANGE)
pops[j].position[i].y=START+RANGE;
}
}
}
//k均值算法优化新一代粒子
void KMeans(int p_count,int k,int size,int in){
int i,j;
for (i=0;i<size;i++){
KMeansAssign(p_count,k,i);
KMeansCluster(p_count,k,i);
for(j=0;j<k;j++){
if (pops[i].nb[j]>0) {centroid[j].x/=pops[i].nb[j];centroid[j].y/=pops[i].nb[j];} //计算新的聚类中心坐标
pops[i].position[j]=centroid[j];
}
pops[i].solution=Deg_Adapt(p_count,k,i);
}
}
void main(){
int P_count,K,N;
int loop_no=1;
int i,j;
CString xh;
CString lj="result/result";
CString hz=".txt";
ofstream fout; //定义一个文件输出流对象
ifstream fin; //定义一个文件输入流对象
srand((unsigned)time(NULL));