liegeneticreduct1.cpp

来自「某个实验事编写粗糙集智能信息处理的程序」· C++ 代码 · 共 401 行

CPP
401
字号
// LieGeneticReduct1.cpp : implementation file
//

#include "stdafx.h"
#include "../rset.h"
#include "LieGeneticReduct1.h"

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

/////////////////////////////////////////////////////////////////////////////
// CLieGeneticReduct1
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cmath>

CLieGeneticReduct1::CLieGeneticReduct1()
{
	srand((unsigned)time(0));
	mutate_probability=0.05;		//变异概率. 原先为0.1
	crossover_probability=0.7;		//交叉概率. 原先为0.5
	m_nMaxGen=50;//进化代数最大值
}

CLieGeneticReduct1::~CLieGeneticReduct1()
{
}

////// InitTable,从CTable继承
//读入文件,初始化相关变量
bool CLieGeneticReduct1::InitTable(CString txtname)
{
	if (! CTable::InitTable(txtname) )
		return false;
//	if (m_nConAttrNum<=5)
//		m_nPopNum=4;
//	else
//		m_nPopNum=10;
	//初始群体规模为 power(
	m_nPopNum=pow(2,m_nConAttrNum/2>6?6:m_nConAttrNum/2);
	return true;
}

/*--------------------------------------------------
	创建可辨识矩阵,存入m_matrix中.
	m_matirx 类型见本类声明部分的头部.

----------------------------------------------------*/
bool CLieGeneticReduct1::CreateMatrix()
{
	TRACE("CreateMatrix;\n");
	try
	{
		deleteDup();						//删除重复记录
		CLieBitArray array(m_nConAttrNum);	//一个bitarray
		for(int i=0;i<m_nCount-1;i++)
		{
			if(!m_bObj[i]) continue;		//has been deleted
			for(int j=i+1;j<m_nCount;j++)
			{
				if(!m_bObj[j]) continue;	//has been deleted
				array.ClearAll();	//set all bits to '0'
				//	TRACE("object %d,%d :",i,j);
				//  决策不同
				if( m_Record[i][m_nConAttrNum] != m_Record[j][m_nConAttrNum] )
				{//决策不同,构建决策矩阵
					bool bCollision=true;
					for(int m=0;m<m_nConAttrNum;m++)
						if( m_Record[i][m] != m_Record[j][m] )
						{
							bCollision=false;
							//TRACE(" %d",m);
							array.SetBit(m);//对应位置为1
						}
					if(bCollision)		//产生冲突,条件属性相同,决策不同...
					{
						TRACE("collision\n");
						//AfxMessageBox("collision");
						continue;
					}
				}
				else //  the decision  value is equal
					continue;				
				m_matrix.push_back(array);
			} //end of for
		}	// end of for
	}// end of try
	catch(...)
	{
		return false;
	}
	if(!m_matrix.empty())
	   return true;
	else return false; 
}

/*------------------------------------------------------------
private function
名称: 
	ComputeFitness
功能描述:
	计算 一个约简结果的适应度 (fitness)
参数说明:
	[in] reduct 一个约简结果
返回值:
	double类型, reduct的适应度

------------------------------------------------------------*/
double CLieGeneticReduct1::ComputeFitness(const CLieBitArray &reduct)
{
	TRACE("compute fitness;");
	ASSERT( m_nConAttrNum == reduct.GetBitLength());

	int _1s=reduct.Get1s();	//约简结果(染色体)中1的个数
	if( _1s == 0)
		return 0;//约简结果为空
//		return 1;
	int rows_covered=RowsCoveredByReductInDescMatrix(reduct);
							//约简结果(染色体)覆盖的记录数
	int rows_total=m_matrix.size();	 
	double ret;
	ret =   ( (double)m_nConAttrNum - _1s)/(double)m_nConAttrNum +
		 (double)rows_covered/ (double)rows_total;//适应度

	if (rows_covered == rows_total)
		ret+= 0.5;

	TRACE(" bitarray: %x",reduct.GetULAt(0));
	TRACE(" num of 1s: %d,rows_covered: %d,rows_total:%d ,ret: %f\n",
		_1s,rows_covered,rows_total,ret);
	return ret;
}


/*-----------------------------------------------------------
 private function
 名称: 
	RowsCoveredByReductInDescMatrix()
 功能描述:
	获得约简reduct在可辨识矩阵中所覆盖的条数
 参数:
	[in] reduct ,约简结果
 返回值:
	int类型,记录数
 其它:
	m_matrix :类成员,记录可辨识矩阵
------------------------------------------------*/
int CLieGeneticReduct1::RowsCoveredByReductInDescMatrix(const CLieBitArray &reduct)
{
	int rows_covered=0;;
	for( TABLE::const_iterator it_i=m_matrix.begin();it_i!=m_matrix.end();it_i++)
	{
		if ( ((*it_i) & reduct).Get1s()>0) //能覆盖!
			rows_covered++;
	}

	return rows_covered;
	
}

////////////////////////////////////////////
/*
	函数名: InitPopulation
	功能描述:
		随机初始化population(群体,即一个约简集合). 并把
		初始fitness设置为0.0
	参数:
		[in] initnum 初始群体中个体数
	返回值:
*/
void CLieGeneticReduct1::InitPopulation(int initnum)
{
	TRACE("init population;\n");
	TRACE("init population number :%d\n",m_nPopNum);
	// num: the number of randam number needed.
	while(initnum--)		//生成m_nPopNum个个体,作为初始群体
	{
		CLieBitArray array(m_nConAttrNum);
		int num= m_nConAttrNum / 32 + (m_nConAttrNum % 32 != 0);//32是什么意思?
		for(int i=0;i<num;i++)
		{
			unsigned long temp=static_cast<unsigned long> (rand() );
			for(int j=0;j<32 && j<array.GetBitLength();j++)
			{
				if ( 1<< j & temp )
					array.SetBit( j+i*32 );
			}
		}
/*
		for(int i=0;i<array.GetULLength();i++)
		{
			unsigned long temp=static_cast<unsigned long> (rand() );
			array.SetULAt(i,temp);

		}
*/
		m_population.push_back( Chromosome_Fitness_Pair(array,ComputeFitness(array)));
	}
}

/*--------------------------------------------------------

下面的函数供调试使用.
向Output窗口输出.测试各函数的正确性
慎重考虑之前不要使用该接口.

-----------------------------*/

#ifdef _DEBUG
void CLieGeneticReduct1::Output()
{
//	InitPopulation(10);
	for( Population::iterator it_i=m_population.begin();it_i!=m_population.end();it_i++)
	  TRACE("indivadul: %x\n",it_i->first.getdata());
}
#endif //_DEBUG

bool CLieGeneticReduct1::reduct()
{
	//-----------time count
    double duration;
	CString str;
    clock_t  finish	,start;
	start = clock();
	///-------------end of time count
	try
	{
		if(!CreateMatrix())
		{
			AfxMessageBox("差别矩阵为空,不能进行本算法");
			return false;
		}
	}
	catch(...)
	{
		return false;
	}
	InitPopulation(m_nPopNum);		//初始群体设定
	Population temp_population;
	int times=0;
	do
	{	
#ifdef _DEBUG
		TRACE("on reduct : %d\n",times);
		TRACE(" population nums: %d\n",m_population.size());
		TRACE(" fist chromosome : %d  fitness: %f\n",m_population.begin()->first.getdata(),m_population.begin()->second);
#endif//_debug

		PerformSelect();
		PerformCrossOver();
		PerformMutate();

	}while(++times <m_nMaxGen);

//---------- time count----------
    finish = clock();
	duration = (double)(finish - start) / CLOCKS_PER_SEC;
	str.Format (" 约简运行时间:%f 秒",duration);
	AfxMessageBox(str);  
//--------------end of time count----------
	return true;
}

bool CLieGeneticReduct1::WriteFile(CString name)
{
	//排序
	std::sort(m_population.begin(),m_population.end(),CLieGeneticReduct1::pair_fitness_greater);
	CLieBitArray& result_bitarray=m_population.begin()->first;

	ASSERT(result_bitarray.GetBitLength()==m_nConAttrNum);

	for(int i=0;i<m_nConAttrNum;/*result_bitarray->GetBitLength()*/i++)
	{
		m_bAttr[i]= static_cast<bool>(result_bitarray[i]);
	}
	return CTable::WriteFile(name);	
}


void CLieGeneticReduct1::PerformSelect()
{
	ASSERT(m_population.size()== m_nPopNum);
	int *NF=new int[m_population.size()];
	int i;
	double total=0;
	double maxfitness=-1;
	double maxIndex=-1;
	Population temp_population;	//临时群体

	//找到群体中适应度最好的个体,保存下来。
	//若使用最佳个体保存方法进行选择时,需要本个体。

	for(i=0;i<m_population.size();i++)
	{
		total+=m_population[i].second;
		if(maxfitness<m_population[i].second)
		{
			maxfitness=m_population[i].second;
			maxIndex=i;
		}
	}
	
	OptimumChromosome=
	Chromosome_Fitness_Pair(m_population[maxIndex].first,
								maxfitness);


	//NF中存储 对应个体的正规化适应度*1000
	NF[0]=(int)(m_population[0].second/total *1000);
	for(i=1;i<m_population.size();i++)
		NF[i]=NF[i-1]+(int)(m_population[i].second/total *1000);

	//赌轮法构造新群体
	temp_population=m_population;
	m_population.clear();
	for(i=0;i<temp_population.size();i++)
	{
		int j;
		int randnum;
		if(NF[m_nPopNum-1]>0)//适应度有可能为0
		{
			randnum=rand()%NF[m_nPopNum-1];
			for(j=0;j<m_population.size()-1;j++)
			  if( randnum<NF[j]) break;
		}
		//now j is the index of selected indivadual
		m_population.push_back(temp_population[j]);
	}
	delete[] NF;
}

void CLieGeneticReduct1::PerformCrossOver()
{
	//m_population的顺序是select的顺序,已经具有随机性.
	//故随机配对省略,从前到后,每两个个体进行配对.
	for(int i=0;i<m_population.size()-1;i+=2)
	{
		//个体i和个体i+1以概率crossover_probability进行交叉
		if( (rand()%1000) > int(1000*crossover_probability) ) 
			continue;
		//crossover position
		int cp=rand() % (m_population.size()-1);
		CLieBitArray tmpBA=m_population[i].first;
		for(int j=0;j<=cp;j++)
		{
			if(m_population[i+1].first[j])
				m_population[i].first.SetBit(j);
			else
				m_population[i].first.ClearBit(j);

			if(tmpBA[j])
				m_population[i+1].first.SetBit(j);
			else
				m_population[i+1].first.ClearBit(j);
		}

	}
}
void CLieGeneticReduct1::PerformMutate()
{
	int i;
	int minIndex;			//最小适应度索引
	double minFitness=1000; //对应的最小适应度
	for(i=0;i<m_population.size();i++)
	{
		for( int j=0;j<m_population[i].first.GetBitLength();j++)
		{
			if( (rand() %1000) < int(1000*mutate_probability) )
				m_population[i].first.Flip(j);//j位取反
		}
		m_population[i].second=ComputeFitness(m_population[i].first);
		if(minFitness>m_population[i].second)
		{
			minFitness=m_population[i].second;
			minIndex=i;
		}
	}
	//若使用最佳个体保留方法,则
	//mutation完成之后,查看最佳个体是否仍然在群体中,
	//若不在,则把最佳个体加入群体
	for(i=0;i<m_population.size();i++)
	{
		if(m_population[i].first == OptimumChromosome.first)
			return;	//发现最佳个体
	}
	TRACE("保留最佳个体!替换掉个体%d - %f \n",minIndex,minFitness);

	//从大到小排序.(按fitness排序)
//	std::sort(m_population.begin(),m_population.end(),CLieGeneticReduct1::pair_fitness_greater);

	//没有发现最佳个体,则替换适应度最小的个体,
	//以维持群体规模
	
	//m_population.push_back(OptimumChromosome);
	m_population[minIndex]=OptimumChromosome;
}

⌨️ 快捷键说明

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