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

📄 semimini.cpp

📁 某个实验事编写粗糙集智能信息处理的程序
💻 CPP
📖 第 1 页 / 共 2 页
字号:
 // SemiMiniDoc4.cpp: implementation of the CSemiMiniDoc class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "String.h"
#include "../RSet.h"
#include "fstream.h"
#include "SemiMini.h"

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

//////////////////////////////////////////////////////////////////////
// iAttNumstruction/Destruction
//////////////////////////////////////////////////////////////////////

CSemiMini::CSemiMini()
{
  Cut=NULL;
  NewTable=NULL;
  MidCut=NULL;
  Wp=NULL;
  pAttName=NULL;
  pDataType=NULL;
  pStringTable=NULL;
  pStringTableResult=NULL; 
  pStrResult=NULL; 
  pNonStringTable=NULL; 
  strCuts=NULL; 
}

CSemiMini::~CSemiMini()
{
  int i;
 if(Cut!=NULL)
 {
	 for(i=0;i<iNonStrAttNum;i++)
		 delete []Cut[i];
	 delete []Cut;
	 Cut=NULL;
 } 
 if(NewTable!=NULL)
 {
	 for(i=0;i<iRecordNum;i++)
	     delete []NewTable[i];
	 delete []NewTable;
	 NewTable=NULL;
 }
 if(MidCut!=NULL)
 {
	 for(i=0;i<iNonStrAttNum;i++)
		 delete []MidCut[i];
	 delete []MidCut;
	 MidCut=NULL;
 }
 if(Wp!=NULL)
 {
	 for(i=0;i<iNonStrAttNum;i++)
		 delete []Wp[i];
	 delete []Wp;
	 Wp=NULL;
 }
	if(pAttName)
	{
		for(i=0;i<iAttNum+1;i++)
			delete []pAttName[i];
		delete[] pAttName;
        pAttName=NULL;
	}

	if(pDataType)
	{
		for(i=0;i<iAttNum+1;i++)
			delete []pDataType[i];
		delete[] pDataType;
		pDataType=NULL;
	}
	if(pStringTable!=NULL)
	{
		for(i=0;i<iRecordNum;i++)
		{
			for(int j=0;j<iStrAttNum;j++)
				delete[] pStringTable[i][j];
			delete[] pStringTable[i];
		}
		delete[] pStringTable;
	}
    if(pStringTableResult!=NULL){ 
        for(i=0;i<iRecordNum;i++) 
            delete[] pStringTableResult[i]; 
        delete[] pStringTableResult; 
        }   
    if(pStrResult){ 
        for(i=0;i<iRecordNum;i++){ 
            for(int j=0;j<iStrAttNum;j++) 
                delete[] pStrResult[i][j]; 
            delete[] pStrResult[i]; 
        } 
        delete[] pStrResult; 
    } 
    if(pNonStringTable){ 
        for(i=0;i<iRecordNum;i++) 
            delete[] pNonStringTable[i]; 
        delete[] pNonStringTable; 
    } 
}

BOOL CSemiMini::OnSemiMinidis()
{//具体实现离散化
       double duration;//计算约简时间的大小
       CString str;
       clock_t  finish	,start;
       start = clock();

	   GetCut();//得到实际选取的断点集
       GetNewTable();// 根据所选取的断点,计算出
	   //离散化后新的决策表并存入NewTable中
	  if(iStrAttNum!=0) 
        doString();
	  
      finish = clock();
      duration = (double)(finish - start) / CLOCKS_PER_SEC;
      str.Format (" 约简运行时间:%f 秒",duration);
 //   AfxMessageBox(str);  
	  return TRUE;
}

void CSemiMini::GetCut()
{//得到实际选取的断点集
  int **X=NULL; //X为等价类的集合
  int N=1; //N 为等价类的个数,初始时未划分等价类,等价类的个数为1
  int i,j;
  int m,n;
  int max=0;

  if(iNonStrAttNum==0)
	  return;
  //下面为初始化等价类,X的每一个元素的值代表的是实例
  X=new int	*[1];
  if((X[0]=new int [iRecordNum+1])==0)
  {
	  AfxMessageBox("分配内存失败!",MB_OK|MB_ICONSTOP);
	  return;
  }
  for(i=1;i<iRecordNum+1;i++)
	  X[0][i]=i-1;
  X[0][0]=iRecordNum;
  //X[0][0]代表的是此等价类中的元素的个数,初始时未划分等价类,
  //所以个数为信息表中的记录数。
  GetMidCut();//计算出所有的候选断点,并存入MidCut中
  while(judge(X,N))   //判断X中的集合是否全部由决策相同的等价类组成,N为等价类的个数
  {   //N为X中的集合的个数 true:return 0,else return 1;
     for(i=0;i<iNonStrAttNum;i++)//属性i    
  	   for(j=1;j<=(int)MidCut[i][0];j++)//i属性断点个数
	   {//得到每个属性每个断点能够区分的实例对的个数
		   if(MidCut[i][j]!=0)//在每个等价类内部计算.不考虑等价类之间.
			   Wp[i][j]=ComputeWp(X,N,MidCut[i][j],i);//根据X,返回midcut断点所能区分
		   //出的实例对个数
	   }
	   max=0;
	   for(m=0;m<iNonStrAttNum;m++)//列
		   for(n=1;n<=Wp[m][0];n++)
		   {//得到所有断点中区分样例对最多的数目,既算法中找出列中1个数最多的断点
			   if(Wp[m][n]>max)
			     max=Wp[m][n];
		   }
	  if(max==0)
		  break;	  
	  int flag=0;
      for(m=0;m<iNonStrAttNum;m++)//第m个属性
	  { 
		  for(n=1;n<=Wp[m][0];n++)//第n个断点值
		   {
			   if(Wp[m][n]==max)//找到区分能力最大的断点值--列
			   {	     
				   Cut[m][n]=MidCut[m][n];//得到断点 Cut初始化为0
				   MidCut[m][n]=0;//对应列清零
				   ++Cut[m][0];//断点个数加一
	//把被MidCut[m][n]划分为两部分的X分为两个等价类 不考虑决策,只考虑断点
                   if(!(X=SplitSet(X,N,Cut[m][n],m)))//相当于去掉了该列为1的行
					   return;//返回等价类
				   flag=1;
				   break;
			   }
		   }//end for(n)
		   if(flag==1)
			   break;
	  }//end for(m)
	  for(m=0;m<iNonStrAttNum;m++)
		  for(n=1;n<=Wp[m][0];n++)
		   Wp[m][n]=0; 
		  //置Wp为0,开始下一个找最大区分值的断点的循环
  }//end while(judge(X,N))
  if(X!=NULL)
  {
	  for(i=0;i<N;i++)
		  delete []X[i];
	  delete []X;
  }
}

void CSemiMini::GetNewTable()
{ // 根据所选取的断点,计算出集散化后新的决策表并存入NewTable中
   int i,j,k;
   int m;
   Cut=GetLastCut();//根据选出的断点集,求得最终的断点集
   if((NewTable=new int *[iRecordNum])==0)
   {
	   AfxMessageBox("Out of Memory!");
	   return ;
   }
   for(i=0;i<iRecordNum;i++)
   {//每个样例
	   if((NewTable[i]=new int[iNonStrAttNum+1])==0)
	   {
	      AfxMessageBox("Out of Memory!");
	      return;
	   } 
       for(j=0;j<iNonStrAttNum;j++)
	   {//对每个属性
		   if((int)Cut[j][0]!=0)
		   {
		    m=0;
			for(k=0;k<(int)Cut[j][0];k++)
			{
				if(pNonStringTable[i][j]<Cut[j][k+1])
				{//得到i样例j属性离散化后的值
					NewTable[i][j]=m;
					break;
				}
				m++;
			}
		    if(pNonStringTable[i][j]>=Cut[j][(int)Cut[j][0]])//大于等于最大的那个断点值
				NewTable[i][j]=(int)Cut[j][0];
		  }  
		 if((int)Cut[j][0]==0)
		    NewTable[i][j]=0;
	  }//end for
	   NewTable[i][iNonStrAttNum]=(int)pNonStringTable[i][iNonStrAttNum];//决策值
   } 
}

void CSemiMini::GetMidCut()
{//计算出所有的候选断点,并存入MidCut中
	int i,j,k;
    int num=0;
	int num1=0;	
    int flag=0;
	if((MidCut=new double*[iNonStrAttNum])==0)
	{
	   AfxMessageBox("Out of Memory!");
	   return ;
   }
    if((Cut=new double*[iNonStrAttNum])==0)
	{	//实际所取的断点的集合
	   AfxMessageBox("Out of Memory!");
	   return ;
   }
	if((Wp=new int*[iNonStrAttNum])==0)
	{
	   AfxMessageBox("Out of Memory!");
	   return;
   }
	//MidCut为侯选的断点集的集合
	//MidCut[i][0]为第i个属性候选断点集的个数
    //MidCut[i][j]为第i个属性的第j个后选断点
	//MidCut[i]是经过排序的,由小到大排列的断点集的集合
	//Wp记录每个断点区分实例值
	//Wp[i][j]记录第i个属性的第j个候选断点的区分实例对的数目值,
	//和MidCut[i][j]是对应的,每一次循环寻找最大的Wp[i][j]值,
	//然后把相应的Cut[i][j]置为MidCut[i][j]的值(断点值),再把相应的MidCut[i][j]置为0;
	//下一次循环就不考虑已经选取的MidCut[i][j];
	//Mid[i]存储属性i的不同属性值
	double **Mid=NULL;
	if((Mid=new double*[iNonStrAttNum])==0)
	{
	   AfxMessageBox("Out of Memory!");
	   return ;
   }
    for(i=0;i<iNonStrAttNum;i++)
	{
        Mid[i]=NULL;
		if((Mid[i]=new double[iRecordNum+1])==0)
		{
	       AfxMessageBox("Out of Memory!");
	        return ;
		} 
	}
	for(i=0;i<iNonStrAttNum;i++)//i为属性
	{
		num=0;
		num1=0;
		flag=0;
	    Mid[i][++num]=pNonStringTable[0][i];
		//num 初始化为0  得到第一行的属性i的值
	    for(j=1;j<iRecordNum;j++)
		{//对后面的记录   对属性i完成不重复属性值的收集
			for(k=1;k<=num;k++)
			{
			  if(pNonStringTable[j][i]==Mid[i][k])
              {//看是否已有属性值重复
				  flag=1;
			      break;
			  }
			}
		   if(flag==0)
		   {//不重复,加入
			   Mid[i][++num]=pNonStringTable[j][i];
			  
		   }
		   flag=0;
		}
		Mid[i][0]=(double)num;//不同属性值个数
		MidCut[i]=NULL;
		if((MidCut[i]=new double[num])==0)
		{//分配断点集
			AfxMessageBox("Out of Memory!");
	        return ;
		} 
		Cut[i]=NULL;
        if((Cut[i]=new double[num])==0)
		{
			AfxMessageBox("Out of Memory!");
	        return ;
		} 
		Wp[i]=NULL;
		if((Wp[i]=new int[num])==0)
		{
	      AfxMessageBox("Out of Memory!");
	      return ;
		} 
		   //指针Wp和指针MidCut结构相同,
		   for(j=0;j<num;j++)
		   {//初始化Cut和Wp
			   Cut[i][j]=0;
		       Wp[i][j]=0;
		   }
		   //开始时把Wp[i][j]和Cut[i][j]的值置0
		   MidCut[i][0]=Mid[i][0]-1;//断点个数为不同属性值个数减一
           Wp[i][0]=num-1;
		   //Wp[i][0]的值是第i个属性的候选断点的个数,
		   //但Cut[i][0]的值却由程序选取的断点决定.
		   //每选取第i个属性的一个断点,则Cut[i][0]加1
           
           SelectSort(Mid[i]);// 对出现的属性值进行排序

			for(j=1;j<num;j++)//得到断点值,从小到大排列
				MidCut[i][++num1]=(Mid[i][j]+Mid[i][j+1])/2;
	}
	for(i=0;i<iNonStrAttNum;i++)
		delete []Mid[i];
	 delete []Mid;
}

int CSemiMini::judge(int **X, int N)
//判断X中的集合是否全部由决策相同的等价类组成
//N为X中的集合的个数 
//如果全部由相同的等价类组成,return 0,else return 1
{
	if(X==NULL)
		return 0;
	int i,j;
	int flag=0;
	for(i=0;i<N;i++)
	{
		for(j=1;j<X[i][0];j++)
		{
			if(pNonStringTable[X[i][j]][iNonStrAttNum]!=pNonStringTable[X[i][j+1]][iNonStrAttNum])
			{//相邻等价类中相邻记录比较决策,不一致时返回1;全部一致是返回0
				flag=1;
			    break;
			}
		}
		if(flag==1)
			break;
	}
		return  flag;
}

int CSemiMini::ComputeWp(int **X, int N, double midcut, int m)
{//X为等价类的集合,N为等价类的个数,midcut为候选断点,
//m为指明后选的断点是第几个条件属性的断点
//根据等价类X,计算并返回断点midcut所能区分出的实例对的个数 失败:return -1;
    int i,i1,j1;
	int num=0;//小于此断点值的实例个数
	int num1=0;//大于此断点值的实例个数
	int DiscernValue=0;
	int mid=0;	
	for(i=0;i<N;i++)
	{	//对每个定价类
	    for(i1=1;i1<=X[i][0];i1++)
		  {//统计此集合中小于大于断点的实例个数
		      if(pNonStringTable[X[i][i1]][m]<midcut)
		       ++num;//小于此断点值的实例个数
		      if(pNonStringTable[X[i][i1]][m]>midcut)
			   ++num1;//大于此断点值的实例个数
		  }
	  if((num>0)&&(num1>0))
	  {//说明存在此断点区分的实例对		  
	    double *DeciSet=NULL;
	    DeciSet=GetDeciSet();//返回一个数组,记录了决策属性的所有出现的值
        int **Set=NULL; 
	    Set=new int*[2];
	    for(i1=0;i1<2;i1++)
		{
			Set[i1]=NULL;
			if((Set[i1]=new int[(int)DeciSet[0]])==0)
			{
				AfxMessageBox("内存分配失败!");
				return -1;
			}
		}
	    //Set[0][i-1]为小于断点集的实例对应的DeciSet[i](为决策值)的个数  
        //Set[1][i-1]为大于断点集的实例对应的DeciSet[i](为决策值)的个数
	    //DeciSet[0]为决策值的种类个数,
	    //DeciSet[i]为对应的决策值.
         for(i1=0;i1<2;i1++)
		  for(j1=0;j1<(int)DeciSet[0];j1++)
			  Set[i1][j1]=0;//初始化为0,后面要用
		int **Mid=NULL;
        Mid=new int*[2];

     	for(i1=0;i1<2;i1++)
		{
			Mid[i1]=NULL;
			if((Mid[i1]=new int[X[i][0]])==0)
			{
				AfxMessageBox("内存分配失败!");
				return -1;
			}
		}
	  //因为此集合被断点分割为两部分,一部分为大于断点值实例
	  //另一部分为小于断点值的实例
      //X[i][0]为要被划分的集合的原始个数
      //Mid[j]为划分后的集合,被分为两部分
	      num=num1=0;
		  for(i1=1;i1<=X[i][0];i1++)
		  {//根据断点将集合划分为两部分
		      if(pNonStringTable[X[i][i1]][m]<midcut)//不可能等于,因为断点取得是中值
		      //把小于此断点值的实例和大于此断点值的实例分开
		         Mid[0][++num]=X[i][i1];//小于此断点值的实例
		      if(pNonStringTable[X[i][i1]][m]>midcut)
			     Mid[1][++num1]=X[i][i1];//大于此断点值的实例
		  }
	      Mid[0][0]=num;//num为小于断点值的实例的个数
	      Mid[1][0]=num1;//num1为大于断点值的实例的个数
	     for(i1=1;i1<=num;i1++)
		    for(j1=1;j1<=DeciSet[0];j1++)
			{//统计小于断点值的实例重复决策值个数
			  if(pNonStringTable[Mid[0][i1]][iNonStrAttNum]==DeciSet[j1])
			  {
				  ++Set[0][j1-1];//自加一. 统计DeciSet[j1]决策出现的次数
				  break;
			  }
			}
	     for(i1=1;i1<=num1;i1++)
		    for(j1=1;j1<=DeciSet[0];j1++)
			{//统计大于断点值的实例重复决策值个数
			  if(pNonStringTable[Mid[1][i1]][iNonStrAttNum]==DeciSet[j1])
			  {
				  ++Set[1][j1-1];
				  break;
			  }
			}
		for(i1=0;i1<(int)DeciSet[0];i1++)
			for(j1=0;j1<(int)DeciSet[0];j1++)
			{ //统计要去除的样例对mid
		      if(i1==j1)//决策相等
			  { 
			     mid=mid+Set[0][i1]*Set[1][j1];//其中如Set不为实际决策,则为0
			     break;//mid统计断点能区分的实例对的个数.Set[0][i1]*Set[1][j1]为小于断点的实例
				 //数目*大于断点的实例数目=>实例对的数目
			  } 
			} 
		DiscernValue=DiscernValue+num*num1-mid;
		try{   
		  for(i1=0;i1<2;i1++)
	        delete []Set[i1];
            delete []Set;

   	      for(i1=0;i1<2;i1++)
		    delete []Mid[i1];
          if(Mid!=NULL)
			  delete  []Mid;	

⌨️ 快捷键说明

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