面向对象的模拟退火编程技术.cpp
上传用户:bonzan
上传日期:2007-04-15
资源大小:4k
文件大小:13k
开发平台:

Visual C++

  1. //***********引入库函数
  2. #include "iostream.h"
  3. #include "math.h"
  4. #include "stdlib.h"
  5. #include "iomanip.h"
  6. #include "time.h"
  7. #include "fstream.h"
  8. //*************定义常量
  9. const int TRUE=1;
  10. const int FALSE=0;
  11. const int MarkovLengh=10000;
  12. const int MaxInnerLoop=10000;
  13. const int MaxOuterLoop=60;
  14. const double CO=0.1;
  15. const double DeclineRate=0.95;
  16. const long MAX=100000;
  17. const int AcceptRate=1;
  18. const double ForceDecline=0.9;
  19. //************定义全局变量
  20. int DataNum;               //聚类样本数目
  21. int Dimension;             //样本维数
  22. int K;                     //分类数
  23. double *DataSet;            //指向浮点型的指针
  24. int HALT=0;
  25. int Row=3;
  26. //***************************************************************
  27. //  类 GETDATA: 设定全局变量,维数,样本数,和类别数等         ***  
  28. //               随机生成样本或手工输入样本的类               ***
  29. //***************************************************************
  30. class GETDATA{
  31. public:
  32. GETDATA();
  33. void Display();
  34. void Initial();
  35. void Input();
  36. double FRand(double,double);
  37.     double rand1,rand2;          //随机数的高低值
  38. };
  39. GETDATA::GETDATA()
  40. {
  41. int i,j;
  42. Dimension=2;
  43. DataNum=50;
  44. K=4;
  45. DataSet=new double[Dimension*DataNum];
  46. for(i=0;i<DataNum;i++)
  47. {
  48. for(j=0;j<Dimension;j++)
  49. DataSet[i*Dimension+j]=(((double)rand()/(double)RAND_MAX)*100);
  50. }
  51. //*****************显示当前待聚类的样本(维数,个数,类别数等)
  52. void GETDATA::Display()
  53. {
  54. int i,j;
  55. cout<<" 当前样本集如下:"<<endl<<" {"<<endl;
  56. for(i=0;i<DataNum;i++)
  57. {
  58. cout<<" [";
  59. for(j=0;j<Dimension;j++)
  60. {
  61.     cout<<" "<<setw(8)<<DataSet[i*Dimension+j];
  62. }
  63. cout<<" ]  ";
  64. if((i+1)%Row==0)
  65. cout<<endl;
  66. }
  67.     cout<<endl<<" }"<<endl;
  68. cout<<endl<<" 以上实数样本集由计算机在1---100之间随机产,其中:"<<endl;
  69. cout<<endl<<" 样本维数 Dimension= "<<Dimension<<endl;
  70. cout<<" 样本数   DataNum= "<<DataNum<<endl;
  71. cout<<" 类别数   K= "<<K<<endl;
  72. }
  73. //****************输入待聚类样本,包括维数,个数,类别数等
  74. void GETDATA::Input()
  75. {
  76. char flag;
  77. int i,j;
  78. double s=0;
  79. cout<<endl<<" 请依次输入: 维数  样本数目  类别数"<<endl;
  80. cout<<endl<<" 维数 Dimension: ";
  81. cin>>Dimension;
  82. cout<<endl<<" 样本数目 DataNum: ";
  83. cin>>DataNum;
  84. cout<<endl<<" 类别数 K:";
  85. cin>>K;
  86. cout<<endl<<" 随机生成数据输入R  人工输入按B: "<<endl; delete[]DataSet;
  87. DataSet=new double[Dimension*DataNum];
  88. cin>>flag;
  89. if(flag=='R'||flag=='r')
  90. {
  91. cout<<" 输入随机数生成范围(最小值和最大值):"
  92. <<endl<<" 最小值:";
  93. cin>>rand1;
  94. cout<<endl<<" 最大值:";
  95. cin>>rand2;
  96. for(i=0;i<DataNum;i++)
  97. {
  98. for(j=0;j<Dimension;j++)
  99. DataSet[i*Dimension+j]=FRand(rand1,rand2);
  100. }
  101. }
  102. else
  103. if(flag=='H'||flag=='h')
  104. {
  105. for(i=0;i<DataNum;i++)
  106. {
  107. cout<<endl<<" 请输入第"<<i+1<<" 个样本的"<<Dimension<<" 个分量";
  108. for(j=0;j<Dimension;j++)
  109. cin>>DataSet[i*Dimension+j];
  110. }
  111. }
  112. else 
  113. cout<<endl<<" 非法数据! ";
  114. }
  115. //****************初始化聚类样本
  116. void GETDATA::Initial()
  117. {
  118. char ch;
  119. GETDATA::Display();
  120. cout<<endl<<" 重新录入样本输入A  开始聚类B: ";
  121. cin>>ch;
  122. while(!(ch=='A'||ch=='a')&&!(ch=='B'||ch=='b'))
  123. {
  124. cout<<endl<<" 重新录入样本输入A  开始聚类B: ";
  125. cin>>ch;
  126. }
  127. if(ch=='A'||ch=='a')  
  128. GETDATA::Input();
  129. }
  130. double GETDATA::FRand(double rand1,double rand2)
  131. {
  132. return rand1+(double)(((double)rand()/(double)RAND_MAX)*(rand2-rand1));
  133. }
  134. //***********************************************************
  135. // 类SSA:    K-均值算法的实现                           ***  
  136. //           功能:根据设定的K,DataNum,Dimension等聚类    ***
  137. //***********************************************************
  138. class SAA
  139. {
  140. public:
  141. struct DataType
  142. {
  143. double *data;
  144. int father;
  145. double *uncle;
  146. };
  147. struct ClusterType
  148. {
  149. double *center;
  150. int sonnum;
  151. };
  152. SAA();
  153. void Initialize();
  154. void KMeans();
  155. void SA( );
  156. void DisPlay();
  157. void GetDataset(DataType *p1,double *p2,int datanum,int dim);
  158. void GetValue(double *str1,double *str2,int dim);
  159. int  FindFather(double *p,int k);
  160. double SquareDistance(double *str1,double *str2,int dim);
  161. int Compare(double *p1,double *p2,int dim);
  162. void NewCenterPlus(ClusterType *p1,int t,double *p2,int dim);
  163. void NewCenterReduce(ClusterType *p1,int t,double *p2,int dim);
  164. double MaxFunc();
  165. void Generate(DataType *p1,ClusterType *c1);
  166. double Compare(DataType *p1,ClusterType *c1,DataType *p2,ClusterType *c2);
  167. void CopyStatus(DataType *p1,ClusterType *c1,DataType *p2,ClusterType *c2);
  168. int  SecondFather(DataType *p,int t,int k);
  169. double AimFunction(DataType *q,ClusterType *c);
  170. double FRand(double ,double);
  171. void KMeans1();
  172. protected:
  173. double Temp;
  174. //double CO;
  175. //double DeclineRate;
  176. //int MarkovLengh;
  177. //int MaxInnerLoop;
  178. //int MaxOuterLoop;
  179. double AimFunc;
  180. DataType *DataMember, *KResult,*CurrentStatus,*NewStatus;
  181. ClusterType * ClusterMember,*NewCluster,*CurrentCluster;
  182.  
  183. }; //end of class SAA
  184. //************建立构造函数,初始化保护成员
  185. SAA::SAA()
  186. {
  187. int i;
  188. // DeclineRate=(double)0.9;
  189. // MarkovLengh=1000;
  190. // MaxInnerLoop=200;
  191. // MaxOuterLoop=10;
  192. // CO=1;
  193. DataMember=new DataType[DataNum];
  194. ClusterMember=new ClusterType[K];
  195. for(i=0;i<DataNum;i++)
  196. {
  197. DataMember[i].data=new double[Dimension];
  198. DataMember[i].uncle=new double[K];
  199. }
  200. for(i=0;i<K;i++)
  201. ClusterMember[i].center=new double[Dimension];
  202. GetDataset(DataMember,DataSet,DataNum,Dimension);
  203. }//endSAA
  204. //****************初始化参数,及开始搜索状态
  205. void SAA::Initialize( )
  206. {
  207. //K-均值聚类法建立退火聚类的初始状态
  208. // KMeans();
  209.  
  210. }
  211. //*******************k-均值法进行聚类
  212. //************接口:数据,数量,维数,类别
  213. //逐点聚类方式
  214. void SAA::KMeans()
  215. {
  216. int i,j,M=1;
  217. int pa,pb,fa;
  218. ClusterType *OldCluster;
  219. //初始化聚类中心
  220. OldCluster=new ClusterType[K];
  221. for(i=0;i<K;i++)
  222. {
  223. // cout<<endl<<i+1<<"中心:";
  224. GetValue(ClusterMember[i].center,DataMember[i].data,Dimension);
  225. ClusterMember[i].sonnum=1;
  226. OldCluster[i].center=new double[Dimension];
  227. GetValue(OldCluster[i].center,ClusterMember[i].center,Dimension);
  228. }
  229. for(i=0;i<DataNum;i++)  
  230. {
  231. // cout<<endl<<i+1<<": "<<ClusterMember[0].center[0]<<" "<<ClusterMember[1].center[0]<<" son: "<<ClusterMember[0].sonnum;
  232. for(j=0;j<K;j++)
  233. {
  234. DataMember[i].uncle[j]=SquareDistance(DataMember[i].data,ClusterMember[j].center,Dimension);
  235. // cout<<"   "<<i+1<<"->"<<j+1<<": "<<DataMember[i].uncle[j];   //"类中心 "<<ClusterMember[j].center[0]<<": "<<DataMember[i].uncle[j]<<"  ";
  236. }
  237. pa=DataMember[i].father=FindFather(DataMember[i].uncle,K);
  238. if(i>=K)
  239. {
  240. // cout<<endl<<pa<<" 类样本数:"<<ClusterMember[pa].sonnum;
  241. ClusterMember[pa].sonnum+=1;
  242. // cout<<endl<<pa<<" 类样本数:"<<ClusterMember[pa].sonnum;
  243. NewCenterPlus(ClusterMember,pa,DataMember[i].data,Dimension);
  244. // cout<<endl<<i+1<<"->"<<pa+1<<"类  :"<<ClusterMember[pa].center[0];
  245. GetValue(OldCluster[pa].center,ClusterMember[pa].center,Dimension);
  246. }
  247. //开始聚类,直到聚类中心不再发生变化。××逐个修改法××
  248. while(!HALT)
  249. {
  250. //一次聚类循环:1.重新归类;2.修改类中心
  251. for(i=0;i<DataNum;i++)  
  252. {
  253. // cout<<endl;
  254. for(j=0;j<K;j++)
  255. {
  256. // cout<<"  D "<<DataMember[i].data[0]<<"  "<<ClusterMember[j].center[0]<<"  ";
  257. DataMember[i].uncle[j]=SquareDistance(DataMember[i].data,ClusterMember[j].center,Dimension);
  258. //              cout<<DataMember[i].data[0]<<"->"<<ClusterMember[0l].center[0]<<" : "<<DataMember[i].uncle[0]<<endl;
  259. // cout<<i+1<<"->"<<j+1<<" "<<DataMember[i].uncle[j];
  260. }
  261. fa=DataMember[i].father;
  262.     if(fa!=FindFather(DataMember[i].uncle,K)&&ClusterMember[fa].sonnum>1)
  263. {
  264. pa=DataMember[i].father;
  265. ClusterMember[pa].sonnum-=1;
  266. pb=DataMember[i].father=FindFather(DataMember[i].uncle,K);
  267. ClusterMember[pb].sonnum+=1;
  268. NewCenterReduce(ClusterMember,pa,DataMember[i].data,Dimension);
  269. NewCenterPlus(ClusterMember,pb,DataMember[i].data,Dimension);
  270. /* cout<<endl<<"*********************"<<M<<" 次聚类:*****************";  //聚一次类输出一次结果
  271. cout<<endl<<DataMember[i].data[0]<<" in "<<pa+1<<"类 -> "<<pb+1<<"类: ";
  272. for(t=0;t<K;t++)
  273. {
  274. cout<<endl<<" 第 "<<t+1 <<"类中心: "<<ClusterMember[t].center[0]<<"  样本个数:"<<ClusterMember[t].sonnum;
  275. }
  276. DisPlay();
  277. M=M+1;
  278. */
  279. }
  280. }//endfor 
  281. //判断聚类是否完成,HALT=1,停止聚类
  282. HALT=0;
  283. for(j=0;j<K;j++)
  284. if(Compare(OldCluster[j].center,ClusterMember[j].center,Dimension))
  285. break;
  286. if(j==K)
  287. HALT=1;
  288. for(j=0;j<K;j++)
  289. GetValue(OldCluster[j].center,ClusterMember[j].center,Dimension);
  290. }//endwhile
  291. }//end of KMeans
  292. //批聚类方式
  293. void SAA::KMeans1()
  294. {
  295. int i,j,M=1;
  296. int pa,pb,fa;
  297. ClusterType *OldCluster;
  298. //初始化聚类中心
  299. OldCluster=new ClusterType[K];
  300. for(i=0;i<K;i++)
  301. OldCluster[i].center=new double[Dimension];
  302. for(j=0;j<K;j++)
  303. GetValue(OldCluster[j].center,ClusterMember[j].center,Dimension);
  304. //开始聚类,直到聚类中心不再发生变化。××逐个修改法××
  305. while(!HALT)
  306. {
  307. //一次聚类循环:1.重新归类;2.修改类中心
  308. for(i=0;i<DataNum;i++)  
  309. {
  310. for(j=0;j<K;j++)
  311. DataMember[i].uncle[j]=SquareDistance(DataMember[i].data,ClusterMember[j].center,Dimension);
  312. fa=DataMember[i].father;
  313.     if(fa!=FindFather(DataMember[i].uncle,K)&&ClusterMember[fa].sonnum>1)
  314. {
  315. pa=DataMember[i].father;
  316. ClusterMember[pa].sonnum-=1;
  317. pb=DataMember[i].father=FindFather(DataMember[i].uncle,K);
  318. ClusterMember[pb].sonnum+=1;
  319. NewCenterReduce(ClusterMember,pa,DataMember[i].data,Dimension);
  320. NewCenterPlus(ClusterMember,pb,DataMember[i].data,Dimension);
  321. }
  322. }//endfor 
  323. //判断聚类是否完成,HALT=1,停止聚类
  324. HALT=0;
  325. for(j=0;j<K;j++)
  326. if(Compare(OldCluster[j].center,ClusterMember[j].center,Dimension))
  327. break;
  328. if(j==K)
  329. HALT=1;
  330. for(j=0;j<K;j++)
  331. GetValue(OldCluster[j].center,ClusterMember[j].center,Dimension);
  332. }//endwhile
  333. }
  334. //几个经常需要调用的小函数
  335. void SAA::NewCenterPlus(ClusterType *p1,int t,double *p2,int dim)
  336. {
  337. int i;
  338. for(i=0;i<dim;i++)
  339. p1[t].center[i]=p1[t].center[i]+(p2[i]-p1[t].center[i])/(p1[t].sonnum);
  340. }
  341. void SAA::NewCenterReduce(ClusterType *p1,int t,double *p2,int dim)
  342. {
  343. int i;
  344. for(i=0;i<dim;i++)
  345. p1[t].center[i]=p1[t].center[i]+(p1[t].center[i]-p2[i])/(p1[t].sonnum);
  346. }
  347. void SAA::GetDataset(DataType *p1,double *p2,int datanum,int dim)
  348. {
  349. int i,j;
  350. for(i=0;i<datanum;i++)
  351. {
  352. for(j=0;j<dim;j++)
  353. p1[i].data[j]=p2[i*dim+j];
  354. }
  355. }
  356. void SAA::GetValue(double *str1,double *str2,int dim)
  357. {
  358. int i;
  359. for(i=0;i<dim;i++)
  360. str1[i]=str2[i];
  361. }
  362. int  SAA::FindFather(double *p,int k)
  363. {
  364. int i,N=0;
  365. double min=30000;
  366. for(i=0;i<k;i++)
  367. if(p[i]<min)
  368. {
  369. min=p[i];
  370. N=i;
  371. }
  372. return N;
  373. }
  374. double SAA::SquareDistance(double *str1,double *str2,int dim)
  375. {
  376. double dis=0;
  377. int i;
  378. for(i=0;i<dim;i++)
  379. dis=dis+(double)(str1[i]-str2[i])*(str1[i]-str2[i]);
  380. return dis;
  381. }
  382. int SAA::Compare(double *p1,double *p2,int dim)
  383. {
  384. int i;
  385. for(i=0;i<dim;i++)
  386. if(p1[i]!=p2[i])
  387. return 1;
  388. return 0;
  389. }
  390. double SAA::FRand(double a,double b)
  391. {
  392. return a+(double)(((double)rand()/(double)RAND_MAX)*(b-a));
  393. }
  394. void SAA::DisPlay()
  395. {
  396. int i,N,j,t;
  397. ofstream  result("聚类过程结果显示.txt",ios::ate);
  398. for(i=0;i<K;i++)
  399. {
  400. N=0;
  401. cout<<endl<<endl<<"******************** 第 "<<i+1<<" 类样本:*******************"<<endl;
  402. result<<endl<<endl<<"******************** 第 "<<i+1<<" 类样本:*******************"<<endl;
  403. for(j=0;j<DataNum;j++)
  404. if(DataMember[j].father==i)
  405. {
  406. cout<<" [";
  407. for(t=0;t<Dimension;t++)
  408. cout<<" "<<setw(5)<<DataMember[j].data[t];
  409. cout<<" ]  ";
  410. if((N+1)%Row==0)
  411. cout<<endl;
  412. result<<" [";
  413. for(t=0;t<Dimension;t++)
  414. result<<" "<<setw(5)<<DataMember[j].data[t];
  415. result<<" ]  ";
  416. if((N+1)%Row==0)
  417. result<<endl;
  418. N=N+1;
  419. }
  420. }//end for
  421. cout<<endl<<endl<<"  聚类结果,总体误差准则函数:"<<AimFunction(DataMember,ClusterMember)<<endl;
  422. result<<endl<<"  聚类结果,总体误差准则函数:"<<AimFunction(DataMember,ClusterMember)<<endl;
  423.   
  424. result.close();
  425. }//end of Display
  426. double SAA::AimFunction(DataType *q,ClusterType *c)
  427. {
  428. int i,j;
  429. double *p;
  430. p=new double[K];
  431. for(i=0;i<K;i++)
  432. p[i]=0;
  433. for(i=0;i<K;i++)
  434. {
  435. for(j=0;j<DataNum;j++)
  436. if(q[j].father==i)
  437. {
  438. p[i]=p[i]+SquareDistance(c[i].center,q[j].data,Dimension);
  439. }
  440. }
  441. AimFunc=0;
  442. for(i=0;i<K;i++)
  443. AimFunc=AimFunc+p[i];
  444. return AimFunc;
  445. }
  446. //************************************
  447. //            主函数入口          ****   
  448. //************************************
  449. void main()
  450. {
  451. //用户输入数据
  452. srand((unsigned)time(NULL));
  453. GETDATA getdata;
  454. getdata.Initial();
  455. ofstream file("聚类过程结果显示.txt",ios::trunc);   //聚类结果存入“聚类结果显示.txt”文件中
  456. //k-均值聚类方法聚类
  457. SAA saa;    //****此行不可与上行互换。
  458. saa.KMeans();    //逐个样本聚类
  459. // saa.KMeans1();   //批处理方式聚类,可以比较saa.KMeans()的区别
  460. cout<<endl<<"***********************K-均值聚类结果:**********************";
  461. file<<endl<<"***********************K-均值聚类结果:**********************"<<endl;
  462. file.close();
  463. saa.DisPlay(); 
  464. cout<<endl<<"  程序运行结束!"<<endl;
  465. }