面向对象的模拟退火编程技术.cpp
上传用户:bonzan
上传日期:2007-04-15
资源大小:4k
文件大小:13k
- //***********引入库函数
- #include "iostream.h"
- #include "math.h"
- #include "stdlib.h"
- #include "iomanip.h"
- #include "time.h"
- #include "fstream.h"
- //*************定义常量
- const int TRUE=1;
- const int FALSE=0;
- const int MarkovLengh=10000;
- const int MaxInnerLoop=10000;
- const int MaxOuterLoop=60;
- const double CO=0.1;
- const double DeclineRate=0.95;
- const long MAX=100000;
- const int AcceptRate=1;
- const double ForceDecline=0.9;
- //************定义全局变量
- int DataNum; //聚类样本数目
- int Dimension; //样本维数
- int K; //分类数
- double *DataSet; //指向浮点型的指针
- int HALT=0;
- int Row=3;
- //***************************************************************
- // 类 GETDATA: 设定全局变量,维数,样本数,和类别数等 ***
- // 随机生成样本或手工输入样本的类 ***
- //***************************************************************
- class GETDATA{
- public:
- GETDATA();
- void Display();
- void Initial();
- void Input();
- double FRand(double,double);
- double rand1,rand2; //随机数的高低值
- };
- GETDATA::GETDATA()
- {
- int i,j;
- Dimension=2;
- DataNum=50;
- K=4;
- DataSet=new double[Dimension*DataNum];
- for(i=0;i<DataNum;i++)
- {
- for(j=0;j<Dimension;j++)
- DataSet[i*Dimension+j]=(((double)rand()/(double)RAND_MAX)*100);
- }
- }
- //*****************显示当前待聚类的样本(维数,个数,类别数等)
- void GETDATA::Display()
- {
- int i,j;
- cout<<" 当前样本集如下:"<<endl<<" {"<<endl;
- for(i=0;i<DataNum;i++)
- {
- cout<<" [";
- for(j=0;j<Dimension;j++)
- {
- cout<<" "<<setw(8)<<DataSet[i*Dimension+j];
- }
- cout<<" ] ";
- if((i+1)%Row==0)
- cout<<endl;
- }
- cout<<endl<<" }"<<endl;
- cout<<endl<<" 以上实数样本集由计算机在1---100之间随机产,其中:"<<endl;
- cout<<endl<<" 样本维数 Dimension= "<<Dimension<<endl;
- cout<<" 样本数 DataNum= "<<DataNum<<endl;
- cout<<" 类别数 K= "<<K<<endl;
- }
- //****************输入待聚类样本,包括维数,个数,类别数等
- void GETDATA::Input()
- {
- char flag;
- int i,j;
- double s=0;
- cout<<endl<<" 请依次输入: 维数 样本数目 类别数"<<endl;
- cout<<endl<<" 维数 Dimension: ";
- cin>>Dimension;
- cout<<endl<<" 样本数目 DataNum: ";
- cin>>DataNum;
- cout<<endl<<" 类别数 K:";
- cin>>K;
- cout<<endl<<" 随机生成数据输入R 人工输入按B: "<<endl; delete[]DataSet;
- DataSet=new double[Dimension*DataNum];
- cin>>flag;
- if(flag=='R'||flag=='r')
- {
- cout<<" 输入随机数生成范围(最小值和最大值):"
- <<endl<<" 最小值:";
- cin>>rand1;
- cout<<endl<<" 最大值:";
- cin>>rand2;
- for(i=0;i<DataNum;i++)
- {
- for(j=0;j<Dimension;j++)
- DataSet[i*Dimension+j]=FRand(rand1,rand2);
- }
- }
- else
- if(flag=='H'||flag=='h')
- {
- for(i=0;i<DataNum;i++)
- {
- cout<<endl<<" 请输入第"<<i+1<<" 个样本的"<<Dimension<<" 个分量";
- for(j=0;j<Dimension;j++)
- cin>>DataSet[i*Dimension+j];
- }
- }
- else
- cout<<endl<<" 非法数据! ";
- }
- //****************初始化聚类样本
- void GETDATA::Initial()
- {
- char ch;
- GETDATA::Display();
- cout<<endl<<" 重新录入样本输入A 开始聚类B: ";
- cin>>ch;
- while(!(ch=='A'||ch=='a')&&!(ch=='B'||ch=='b'))
- {
- cout<<endl<<" 重新录入样本输入A 开始聚类B: ";
- cin>>ch;
- }
- if(ch=='A'||ch=='a')
- GETDATA::Input();
- }
- double GETDATA::FRand(double rand1,double rand2)
- {
- return rand1+(double)(((double)rand()/(double)RAND_MAX)*(rand2-rand1));
- }
- //***********************************************************
- // 类SSA: K-均值算法的实现 ***
- // 功能:根据设定的K,DataNum,Dimension等聚类 ***
- //***********************************************************
- class SAA
- {
- public:
- struct DataType
- {
- double *data;
- int father;
- double *uncle;
- };
- struct ClusterType
- {
- double *center;
- int sonnum;
-
- };
- SAA();
- void Initialize();
- void KMeans();
- void SA( );
- void DisPlay();
- void GetDataset(DataType *p1,double *p2,int datanum,int dim);
- void GetValue(double *str1,double *str2,int dim);
- int FindFather(double *p,int k);
- double SquareDistance(double *str1,double *str2,int dim);
- int Compare(double *p1,double *p2,int dim);
- void NewCenterPlus(ClusterType *p1,int t,double *p2,int dim);
- void NewCenterReduce(ClusterType *p1,int t,double *p2,int dim);
- double MaxFunc();
- void Generate(DataType *p1,ClusterType *c1);
- double Compare(DataType *p1,ClusterType *c1,DataType *p2,ClusterType *c2);
- void CopyStatus(DataType *p1,ClusterType *c1,DataType *p2,ClusterType *c2);
- int SecondFather(DataType *p,int t,int k);
- double AimFunction(DataType *q,ClusterType *c);
- double FRand(double ,double);
- void KMeans1();
- protected:
- double Temp;
- //double CO;
- //double DeclineRate;
- //int MarkovLengh;
- //int MaxInnerLoop;
- //int MaxOuterLoop;
- double AimFunc;
- DataType *DataMember, *KResult,*CurrentStatus,*NewStatus;
- ClusterType * ClusterMember,*NewCluster,*CurrentCluster;
-
- }; //end of class SAA
- //************建立构造函数,初始化保护成员
- SAA::SAA()
- {
- int i;
- // DeclineRate=(double)0.9;
- // MarkovLengh=1000;
- // MaxInnerLoop=200;
- // MaxOuterLoop=10;
- // CO=1;
-
- DataMember=new DataType[DataNum];
- ClusterMember=new ClusterType[K];
- for(i=0;i<DataNum;i++)
- {
- DataMember[i].data=new double[Dimension];
- DataMember[i].uncle=new double[K];
- }
- for(i=0;i<K;i++)
- ClusterMember[i].center=new double[Dimension];
- GetDataset(DataMember,DataSet,DataNum,Dimension);
-
- }//endSAA
- //****************初始化参数,及开始搜索状态
- void SAA::Initialize( )
- {
-
- //K-均值聚类法建立退火聚类的初始状态
- // KMeans();
-
- }
- //*******************k-均值法进行聚类
- //************接口:数据,数量,维数,类别
- //逐点聚类方式
- void SAA::KMeans()
- {
-
- int i,j,M=1;
- int pa,pb,fa;
- ClusterType *OldCluster;
- //初始化聚类中心
- OldCluster=new ClusterType[K];
- for(i=0;i<K;i++)
- {
- // cout<<endl<<i+1<<"中心:";
- GetValue(ClusterMember[i].center,DataMember[i].data,Dimension);
- ClusterMember[i].sonnum=1;
- OldCluster[i].center=new double[Dimension];
- GetValue(OldCluster[i].center,ClusterMember[i].center,Dimension);
- }
- for(i=0;i<DataNum;i++)
- {
- // cout<<endl<<i+1<<": "<<ClusterMember[0].center[0]<<" "<<ClusterMember[1].center[0]<<" son: "<<ClusterMember[0].sonnum;
- for(j=0;j<K;j++)
- {
- DataMember[i].uncle[j]=SquareDistance(DataMember[i].data,ClusterMember[j].center,Dimension);
- // cout<<" "<<i+1<<"->"<<j+1<<": "<<DataMember[i].uncle[j]; //"类中心 "<<ClusterMember[j].center[0]<<": "<<DataMember[i].uncle[j]<<" ";
- }
- pa=DataMember[i].father=FindFather(DataMember[i].uncle,K);
- if(i>=K)
- {
- // cout<<endl<<pa<<" 类样本数:"<<ClusterMember[pa].sonnum;
- ClusterMember[pa].sonnum+=1;
- // cout<<endl<<pa<<" 类样本数:"<<ClusterMember[pa].sonnum;
- NewCenterPlus(ClusterMember,pa,DataMember[i].data,Dimension);
- // cout<<endl<<i+1<<"->"<<pa+1<<"类 :"<<ClusterMember[pa].center[0];
- GetValue(OldCluster[pa].center,ClusterMember[pa].center,Dimension);
- }
- }
- //开始聚类,直到聚类中心不再发生变化。××逐个修改法××
- while(!HALT)
- {
- //一次聚类循环:1.重新归类;2.修改类中心
- for(i=0;i<DataNum;i++)
- {
- // cout<<endl;
- for(j=0;j<K;j++)
- {
- // cout<<" D "<<DataMember[i].data[0]<<" "<<ClusterMember[j].center[0]<<" ";
- DataMember[i].uncle[j]=SquareDistance(DataMember[i].data,ClusterMember[j].center,Dimension);
- // cout<<DataMember[i].data[0]<<"->"<<ClusterMember[0l].center[0]<<" : "<<DataMember[i].uncle[0]<<endl;
- // cout<<i+1<<"->"<<j+1<<" "<<DataMember[i].uncle[j];
- }
-
- fa=DataMember[i].father;
- if(fa!=FindFather(DataMember[i].uncle,K)&&ClusterMember[fa].sonnum>1)
- {
- pa=DataMember[i].father;
- ClusterMember[pa].sonnum-=1;
- pb=DataMember[i].father=FindFather(DataMember[i].uncle,K);
- ClusterMember[pb].sonnum+=1;
- NewCenterReduce(ClusterMember,pa,DataMember[i].data,Dimension);
- NewCenterPlus(ClusterMember,pb,DataMember[i].data,Dimension);
-
-
- /* cout<<endl<<"*********************"<<M<<" 次聚类:*****************"; //聚一次类输出一次结果
- cout<<endl<<DataMember[i].data[0]<<" in "<<pa+1<<"类 -> "<<pb+1<<"类: ";
- for(t=0;t<K;t++)
- {
- cout<<endl<<" 第 "<<t+1 <<"类中心: "<<ClusterMember[t].center[0]<<" 样本个数:"<<ClusterMember[t].sonnum;
- }
- DisPlay();
- M=M+1;
- */
- }
- }//endfor
-
-
- //判断聚类是否完成,HALT=1,停止聚类
- HALT=0;
- for(j=0;j<K;j++)
- if(Compare(OldCluster[j].center,ClusterMember[j].center,Dimension))
- break;
- if(j==K)
- HALT=1;
-
- for(j=0;j<K;j++)
- GetValue(OldCluster[j].center,ClusterMember[j].center,Dimension);
-
- }//endwhile
- }//end of KMeans
- //批聚类方式
- void SAA::KMeans1()
- {
- int i,j,M=1;
- int pa,pb,fa;
- ClusterType *OldCluster;
- //初始化聚类中心
- OldCluster=new ClusterType[K];
- for(i=0;i<K;i++)
- OldCluster[i].center=new double[Dimension];
- for(j=0;j<K;j++)
- GetValue(OldCluster[j].center,ClusterMember[j].center,Dimension);
- //开始聚类,直到聚类中心不再发生变化。××逐个修改法××
- while(!HALT)
- {
- //一次聚类循环:1.重新归类;2.修改类中心
- for(i=0;i<DataNum;i++)
- {
- for(j=0;j<K;j++)
- DataMember[i].uncle[j]=SquareDistance(DataMember[i].data,ClusterMember[j].center,Dimension);
- fa=DataMember[i].father;
- if(fa!=FindFather(DataMember[i].uncle,K)&&ClusterMember[fa].sonnum>1)
- {
- pa=DataMember[i].father;
- ClusterMember[pa].sonnum-=1;
- pb=DataMember[i].father=FindFather(DataMember[i].uncle,K);
- ClusterMember[pb].sonnum+=1;
- NewCenterReduce(ClusterMember,pa,DataMember[i].data,Dimension);
- NewCenterPlus(ClusterMember,pb,DataMember[i].data,Dimension);
- }
- }//endfor
-
-
- //判断聚类是否完成,HALT=1,停止聚类
- HALT=0;
- for(j=0;j<K;j++)
- if(Compare(OldCluster[j].center,ClusterMember[j].center,Dimension))
- break;
- if(j==K)
- HALT=1;
-
- for(j=0;j<K;j++)
- GetValue(OldCluster[j].center,ClusterMember[j].center,Dimension);
-
- }//endwhile
- }
- //几个经常需要调用的小函数
- void SAA::NewCenterPlus(ClusterType *p1,int t,double *p2,int dim)
- {
- int i;
- for(i=0;i<dim;i++)
- p1[t].center[i]=p1[t].center[i]+(p2[i]-p1[t].center[i])/(p1[t].sonnum);
- }
- void SAA::NewCenterReduce(ClusterType *p1,int t,double *p2,int dim)
- {
- int i;
- for(i=0;i<dim;i++)
- p1[t].center[i]=p1[t].center[i]+(p1[t].center[i]-p2[i])/(p1[t].sonnum);
- }
- void SAA::GetDataset(DataType *p1,double *p2,int datanum,int dim)
- {
- int i,j;
- for(i=0;i<datanum;i++)
- {
-
- for(j=0;j<dim;j++)
- p1[i].data[j]=p2[i*dim+j];
- }
- }
- void SAA::GetValue(double *str1,double *str2,int dim)
- {
- int i;
- for(i=0;i<dim;i++)
- str1[i]=str2[i];
- }
- int SAA::FindFather(double *p,int k)
- {
- int i,N=0;
- double min=30000;
- for(i=0;i<k;i++)
- if(p[i]<min)
- {
- min=p[i];
- N=i;
- }
- return N;
- }
- double SAA::SquareDistance(double *str1,double *str2,int dim)
- {
- double dis=0;
- int i;
- for(i=0;i<dim;i++)
- dis=dis+(double)(str1[i]-str2[i])*(str1[i]-str2[i]);
- return dis;
- }
- int SAA::Compare(double *p1,double *p2,int dim)
- {
- int i;
- for(i=0;i<dim;i++)
- if(p1[i]!=p2[i])
- return 1;
- return 0;
- }
- double SAA::FRand(double a,double b)
- {
- return a+(double)(((double)rand()/(double)RAND_MAX)*(b-a));
- }
- void SAA::DisPlay()
- {
- int i,N,j,t;
- ofstream result("聚类过程结果显示.txt",ios::ate);
- for(i=0;i<K;i++)
- {
- N=0;
- cout<<endl<<endl<<"******************** 第 "<<i+1<<" 类样本:*******************"<<endl;
- result<<endl<<endl<<"******************** 第 "<<i+1<<" 类样本:*******************"<<endl;
- for(j=0;j<DataNum;j++)
- if(DataMember[j].father==i)
- {
- cout<<" [";
- for(t=0;t<Dimension;t++)
- cout<<" "<<setw(5)<<DataMember[j].data[t];
- cout<<" ] ";
- if((N+1)%Row==0)
- cout<<endl;
- result<<" [";
- for(t=0;t<Dimension;t++)
- result<<" "<<setw(5)<<DataMember[j].data[t];
- result<<" ] ";
- if((N+1)%Row==0)
- result<<endl;
- N=N+1;
- }
- }//end for
- cout<<endl<<endl<<" 聚类结果,总体误差准则函数:"<<AimFunction(DataMember,ClusterMember)<<endl;
- result<<endl<<" 聚类结果,总体误差准则函数:"<<AimFunction(DataMember,ClusterMember)<<endl;
-
- result.close();
- }//end of Display
- double SAA::AimFunction(DataType *q,ClusterType *c)
- {
- int i,j;
- double *p;
- p=new double[K];
- for(i=0;i<K;i++)
- p[i]=0;
- for(i=0;i<K;i++)
- {
- for(j=0;j<DataNum;j++)
- if(q[j].father==i)
- {
- p[i]=p[i]+SquareDistance(c[i].center,q[j].data,Dimension);
- }
- }
-
- AimFunc=0;
- for(i=0;i<K;i++)
- AimFunc=AimFunc+p[i];
- return AimFunc;
- }
- //************************************
- // 主函数入口 ****
- //************************************
- void main()
- {
- //用户输入数据
- srand((unsigned)time(NULL));
- GETDATA getdata;
- getdata.Initial();
- ofstream file("聚类过程结果显示.txt",ios::trunc); //聚类结果存入“聚类结果显示.txt”文件中
- //k-均值聚类方法聚类
- SAA saa; //****此行不可与上行互换。
-
- saa.KMeans(); //逐个样本聚类
- // saa.KMeans1(); //批处理方式聚类,可以比较saa.KMeans()的区别
- cout<<endl<<"***********************K-均值聚类结果:**********************";
- file<<endl<<"***********************K-均值聚类结果:**********************"<<endl;
- file.close();
- saa.DisPlay();
- cout<<endl<<" 程序运行结束!"<<endl;
-
- }