⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fcmdlg.cpp

📁 一个用VC++开发的采用模糊C均值聚类算法.
💻 CPP
字号:
// FCMDlg.cpp : implementation file
//

#include "stdafx.h"
#include "FCM.h"
#include "FCMDlg.h"
#include <time.h>
#include <math.h>
#include <stdlib.h>
//#include <stdio.h>
#include <string.h>
#include <memory.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

//const MAX_NUM=5000;
const MAX_RAND=0x7fff;
//const double PI=3.1415926;
//const MAX_PATTERN=1000;
//const MAX_CATA=10;
//const MAX_DIMENSION=10;
const SIZE1=10;
#define FILE_PARAMS_IN  "paramOut.txt";
#define FILE_DATA_IN  "datain.txt";
#define FILE_MATRIX  "matrix.txt";
#define FILE_CENTER  "center.txt";
#define FILE_PARAMS_OUT  "process.txt";


/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
double objectfun(double *,double *,double *,int,int,int,float);

inline double distance(double v1[],double v2[],double dimension)
//这个函数计算欧氏距离
{
   int i;
   double result;
   result=0;
   for(i=0;i<dimension;i++){
      result+=(v1[i]-v2[i])*(v1[i]-v2[i]);
   }
   result=sqrt(result);
   return result;
}
class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFCMDlg dialog

CFCMDlg::CFCMDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CFCMDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CFCMDlg)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
	nProcess=0;
	dDelta=1000;
	
}

void CFCMDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFCMDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CFCMDlg, CDialog)
	//{{AFX_MSG_MAP(CFCMDlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_TIMER()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFCMDlg message handlers

BOOL CFCMDlg::OnInitDialog()
{
	CDialog::OnInitDialog();
	SetTimer(1,100,NULL);
	BeginFCM();
	KillTimer(1);
	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	
	// TODO: Add extra initialization here
	CDialog::OnOK();
	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CFCMDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CFCMDlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CFCMDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}


int CFCMDlg::funfcm(double adi_pattern[],int n_dimension,int n_numpattern,int n_catacount,float f_weightm,int n_maxcycle,double d_threshold,double ado_matrixu[],double ado_center[],double d_funj)
// 本函数完成FCM聚类算法
//参数分为三组:基本聚类样本的信息、算法的参数信息、算法控制信息、输出信息。
//其中:
//adi_pattern[]为样本点向量  指标为:样本指标*维数+维数指标
//n_dimension是每个样本的维数
//n_numpattern是样本的个数


//***************关于上面三个参数的说明***********
//adi_pattern[]为一维数组,它的数目由n_dimension*n_numpattern确定
//************************************************
  
//n_catacount是要分类的数目
//f_weightm是fcm的重要控制参数m
//n_maxcycle是最大循环次数
//d_threshold为算法结束迭代的阈值
//ado_matrixu[]为输出的划分矩阵   指标为:聚类指标*样本数+样本指标
//ado_center[]为输出的样本的聚类中心向量  指标为:据类指标*维数+维数指标
//d_funj为目标函数的值
{
    int j,i,k,t,count;
	int n_cycle;
	int n_selnum;
	int flagtemp;
	double f_temp,lastv,delta,t_temp;
	double v1[SIZE1];
	double v2[SIZE1];
	double min_dis=0.001;//距离的最小值
    //验证输入参数的有效性:
    if(n_catacount>=n_numpattern||f_weightm<=1){
		return 1;
	}
	srand( (unsigned)time( NULL ) );
	//随机的选取初始迭代点作为初始的聚类中心。
   for(j=0;j<n_catacount;j++){
	   t_temp=rand();
	   t_temp/=MAX_RAND;
	   //ado_center[j]=t_temp;
	   n_selnum=int(rand()*n_numpattern/(n_catacount*MAX_RAND)+j*int(n_numpattern/n_catacount));
	   n_selnum=j*int(n_numpattern/n_catacount);
	   while(n_selnum*n_dimension>n_numpattern*n_dimension){
		   n_selnum-=n_numpattern;
	   }
	   for(i=0;i<n_dimension;i++){
		   ado_center[j*n_dimension+i]=adi_pattern[n_selnum*n_dimension+i];
	   }
   }
   //ado_center[0]=0;ado_center[1]=1;
   //ado_center[2]=2;ado_center[3]=2;
   //开始主循环
   n_cycle=0;
   lastv=0;
   
	do{
      //计算划分矩阵
      for(i=0;i<n_numpattern;i++){
		  flagtemp=0;
		  count=0;
		  for(j=0;j<n_catacount;j++){
    			  f_temp=0;
				for(t=0;t<n_catacount;t++){
					for(k=0;k<n_dimension;k++){
					  v1[k]=adi_pattern[i*n_dimension+k];
					  v2[k]=ado_center[t*n_dimension+k];
					}
					if (distance(v1,v2,n_dimension)>min_dis){
					  f_temp+=pow(distance(v1,v2,n_dimension),-2/(f_weightm-1));
					}else{
					  flagtemp=1;
					}
				}
				for(k=0;k<n_dimension;k++){
					     v1[k]=adi_pattern[i*n_dimension+k];
						 v2[k]=ado_center[j*n_dimension+k];
				}
				if(flagtemp==1){
                   ado_matrixu[j*n_numpattern+i]=0;
				   flagtemp=0;
				}
				//如果存在使得||Xk-Vi||=0的点置标志-1
				if(distance(v1,v2,n_dimension)>min_dis){
						double shit1=distance(v1,v2,n_dimension);
						double shit2=pow(shit1,-2/(f_weightm-1))/f_temp;
						int shit3=j*n_numpattern+i;
						ado_matrixu[shit3]=shit2;
				}else{
					  count++;
                      ado_matrixu[j*n_numpattern+i]=-1;
				}
		  }//end for j
		 // 如果存在使得||Xk-Vi||=0就让所有的与Xk不为零的类的隶属度为零。
		if(count>0){
		  for(j=0;j<n_catacount;j++){
			  if(ado_matrixu[j*n_numpattern+i]==-1){
                       ado_matrixu[j*n_numpattern+i]=1/double(count);
			  }else{
                       ado_matrixu[j*n_numpattern+i]=0;
			  }
		  }
		}
	  }//end for i
	  f_temp=objectfun(ado_matrixu,ado_center,adi_pattern,n_catacount,n_numpattern,n_dimension,f_weightm);
      delta=fabs(f_temp-lastv);
	  lastv=f_temp;

	  //计算聚类中心的坐标
	  for(i=0;i<n_catacount;i++){
          for(j=0;j<n_dimension;j++){
			  f_temp=0;
			  for(k=0;k<n_numpattern;k++){
				  f_temp+=pow(ado_matrixu[i*n_numpattern+k],f_weightm)*adi_pattern[k*n_dimension+j];
			  }
			  ado_center[i*n_dimension+j]=f_temp;
			  f_temp=0;
              for(k=0;k<n_numpattern;k++){
				  f_temp+=pow(ado_matrixu[i*n_numpattern+k],f_weightm);
			  }
              ado_center[i*n_dimension+j]/=f_temp;
		  }
	  }
      n_cycle++;
	  nProcess=n_cycle;
	  dDelta=delta;
   }while(n_cycle<n_maxcycle&&delta>d_threshold);

   return 0;
}
double objectfun(double u[],double v[],double x[],int c,int pattern,int dimension,float m){
//此函数计算优化的目标函数
  int i,j,k;
  double v1[SIZE1];
  double v2[SIZE1];
  double object;
  object=0;
  for(i=0;i<c;i++){
	  for(j=0;j<pattern;j++){
		  for(k=0;k<dimension;k++){
              v1[k]=x[j*dimension+k];
	          v2[k]=v[i*dimension+k];
		  }
		  object+=pow(u[i*pattern+j],m)*distance(v1,v2,dimension)*distance(v1,v2,dimension);
	  }
  }
  return object;
}

void CFCMDlg::BeginFCM()
{
	double result=0;
	double * pattern;
	float m,limit;
	int numpattern,dimension,cata,maxcycle;
	float readdata;
	FILE * stream;
	FILE * parafile;
	double* umatrix;
	double* rescenter;
	//获得程序的当前路径
	char strCurPath[200];
	//memset(pattern,0,MAX_PATTERN*MAX_DIMENSION);
	//memset(umatrix,0,MAX_CATA*MAX_DIMENSION);
	DWORD dwSize = ::GetModuleFileName(AfxGetApp()->m_hInstance,strCurPath,200);
	strCurPath[dwSize] = 0;
	char* p = strrchr(strCurPath,'\\');
	*p = 0;
	sCurPath=CString(strCurPath);
	//设定参数的初值
	numpattern=0;		//样本点个数
	dimension=0;		//每个样本点的维数
	cata=8;				//要聚类的数目
	maxcycle=1000;	//最大的跌代次数
	m=2;				//参数m
	limit=float(0.1);	//误差限

	//从参数文件中读取参数的值
	
	CString filePath=CString(strCurPath)+"\\"+FILE_PARAMS_IN;
	char read[20];
	if((parafile=fopen(filePath,"r"))!=NULL){
		fscanf(parafile,"%s\n",&read);
		numpattern=atoi(read);
		fscanf(parafile,"%s\n",&read);
		dimension=atoi(read);
		fscanf(parafile,"%s\n",&read);
		cata=atoi(read);
		fscanf(parafile,"%s\n",&read);
		m=float(atof(read));
		fscanf(parafile,"%s\n",&read);
		maxcycle=atoi(read);
		fscanf(parafile,"%s\n",&read);
		limit=float(atof(read));
		fclose(parafile);
	}
	
	pattern=new double[numpattern*dimension];
	umatrix=new double[numpattern*cata];
	rescenter=new double[cata*dimension];
	if(pattern==0||umatrix==0||rescenter==0){
		return;
	}

	//从文件中读出原始数据pattern为样本点的坐标
	filePath=CString(strCurPath)+"\\"+FILE_DATA_IN;
	int t;
	if((stream=fopen(filePath,"r"))!=NULL){
	    fseek(stream,0L,SEEK_SET);	
	    for(t=0;t<numpattern*dimension;t++){
			fscanf(stream,"%f,",&readdata);
			//printf("%f\n",readdata);
			pattern[t]=readdata;
		}
		fclose(stream);
	}
	
	funfcm(pattern,dimension,numpattern,cata,m,maxcycle,limit,umatrix,rescenter,result);
	delete [numpattern*dimension] pattern;
	filePath=CString(strCurPath)+"\\"+FILE_MATRIX;
	if((stream=fopen(filePath,"w"))!=NULL){
		for(int j=0;j<numpattern;j++){
			for(int i=0;i<cata;i++){
				fprintf(stream,"%4f,",umatrix[i*numpattern+j]);
			}
			fprintf(stream,"\n");
		}
		fclose(stream);
	}

	filePath=CString(strCurPath)+"\\"+FILE_CENTER;
	if((stream=fopen(filePath,"w"))!=NULL){
		for(int i=0;i<cata;i++){
			for(int j=0;j<dimension;j++){
				fprintf(stream,"%4f,",rescenter[i*dimension+j]);
			}
			fprintf(stream,"\n");
		}
		fclose(stream);
	}

}

//DEL int CFCMDlg::OnCreate(LPCREATESTRUCT lpCreateStruct) 
//DEL {
//DEL 	if (CDialog::OnCreate(lpCreateStruct) == -1)
//DEL 		return -1;
//DEL 	
//DEL 	// TODO: Add your specialized creation code here
//DEL 	return 0;
//DEL }

void CFCMDlg::OnOK() 
{
	// TODO: Add extra validation here

	CDialog::OnOK();
}




void CFCMDlg::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	FILE *stream;
	CString filePath=sCurPath+"\\"+FILE_PARAMS_OUT;
	if((stream=fopen(filePath,"w"))!=NULL){
		fprintf(stream,"%i\n",nProcess);
		fprintf(stream,"%4f\n",dDelta);
		fclose(stream);
	}
	CDialog::OnTimer(nIDEvent);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -