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

📄 knapsack.cpp

📁 用GAlib库实现的解决0/1背包问题的遗传算法程序源代码。
💻 CPP
字号:
/* ----------------------------------------------------------------------------  gaknapsack.cpp by yweiqin in Wuhan University, 2004-05.
  It uses genetic algorithm to solve 0/1knapsack problem on the basis of GAlib.  ---------------------------------------------------------------------------- */#include <stdio.h>#include <iostream.h>#include <fstream.h>#include <ga/ga.h>//定义编译开关
#define GREEDREPAIR               //使用贪婪修复
#define MIXGREEDGENOME            //初始种群带贪心解
//定义常量
#define POPULATION_SIZE 80        //种群大小
#define NUM_GENERATIONS 500       //进化最大代数
#define PROBABILITY_MUTATION 0.01 //变异概率
#define PROBABILITY_CROSSOVER 0.6 //杂交概率
#define NUM_GOODS 50              //物品总共数量
//定义全局变量
static float WeightList[NUM_GOODS]=   //各物品的重量 
{80,82,85,70,72,70,66,50,55,25,50,55,40,48,50,32,22,60,30,32,40,38,35,32,25,28,30,22,50,30,45,30,60,50,20,65,20,25,30,10,20,25,15,10,10,10,4,4,2,1}
;
static float ValueList[NUM_GOODS]=    //各物品的价值
{220,208,198,192,180,180,165,162,160,158,155,130,125,122,120,118,115,110,105,101,100,100,98,96,95,90,88,82,80,77,75,73,72,70,69,66,65,63,60,58,56,50,30,20,15,10,8,5,3,1}
;
static float KnapsackMaxContent=1015; //背包的极限容量
static int DensityQueue[NUM_GOODS];   //各物品按密度的降序队列
//函数声明
float objective(GAGenome & c);        //目标值函数
float WeightSum(GAGenome & c);        //计算个体对应解的物品总重量
void InitDensityQueue();              //把物品按密度从大到小排序,把下标队列写入数组DensityQueue
void RandomRepair(GAGenome & c);      //不可行解的随机修复算子
int SelectRandomBit(GAGenome & c);     //为随机修复选择一个清除物品
void GreedRepair(GAGenome & c);       //不可行解的贪心修复算子
void repair(GAGenome & c);            //总的修复算子
void KnapsackGenomeInitialize(GAGenome & c);            //个体初始化算子
int KnapsackGenomeOnePointCrossover(const GAGenome& p1, const GAGenome& p2,
				GAGenome* c1, GAGenome* c2);            //杂交算子
int KnapsackGenomeFlipMutator(GAGenome & c, float pmut);//变异算子
void CreatKnapsackGreedGenome(GAGenome & c);            //生成贪心解个体
void ShowGenome(GAGenome & c);                          //输出个体的基因编码
//定义解0-1背包问题的遗传算法类
class MyKnapsackGA : public GASimpleGA{ 
public:
	MyKnapsackGA(const GAGenome& c): GASimpleGA(c){};   //构造函数
#ifdef MIXGREEDGENOME                                   
    void initialize(unsigned int seed)                  //重载算法初始化函数
	{	//调用基类的初始化函数
		GASimpleGA::initialize(seed);
		//初始化时种群中最差个体替换为贪心解个体
		GAGenome& genome = pop->worst();
		CreatKnapsackGreedGenome(genome);
		//重新评估种群中的个体
		pop->evaluate(gaTrue);	
		stats.reset(*pop);
		if(!scross) GAErr(GA_LOC, className(), "initialize", gaErrNoSexualMating);
	};
#endif
};
//主函数
int main(int argc, char **argv){
	cout << "应用遗传算法求解0-1背包问题\n";    cout.flush();    //把物品按密度从大到小排序
    InitDensityQueue();    //创建基因组对象,并为其指定编码长度、适应值函数    GA1DBinaryStringGenome genome(NUM_GOODS, (GAGenome::Evaluator) objective);
	//为基因组指定自定义的初始化函数、杂交算子、变异算子
	genome.initializer((GAGenome::Initializer) KnapsackGenomeInitialize);
    genome.crossover((GAGenome::SexualCrossover) KnapsackGenomeOnePointCrossover);    genome.mutator((GAGenome::Mutator) KnapsackGenomeFlipMutator);
    //创建遗传算法对象,并为其指定基因组对象    MyKnapsackGA ga(genome);
    //为遗传算法类指定各控制参数    ga.populationSize(POPULATION_SIZE);         //种群大小     ga.nGenerations(NUM_GENERATIONS);           //进化代数
	ga.pCrossover(PROBABILITY_CROSSOVER);       //变异概率    ga.pMutation(PROBABILITY_MUTATION);         //杂交概率    ga.scoreFilename("score.dat");              //记录跟踪信息的文件    ga.scoreFrequency(50);                      //记录跟踪信息的频率    ga.flushFrequency(100);                     //输出跟踪信息到文件的频率
	//开始进化     ga.evolve();    //输出求解结果     genome = ga.statistics().bestIndividual();
    cout << "the best individual: "; ShowGenome(genome);  
    cout << "\nthe total value: "<<objective(genome)<< "\n";
    cout << "the total weight: "<<WeightSum(genome) << "\n";
    cout << "best of each generation data are in '" << ga.scoreFilename() << "'\n";
    return 0;}float objective(GAGenome & c)          //目标值函数
{
    int i, genomelength;
	float sum=0;
    GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
	genomelength=genome.length();
    for(i=0;i<genomelength;i++)
		if(genome.gene(i)!=0) sum += ValueList[i];
    return sum;
}
float WeightSum(GAGenome & c)          //个体对应解的包中物品总重量
{
    int i, genomelength;
	float sum=0;
    GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
    genomelength=genome.length();
    for(i=0;i<genomelength;i++)
		if(genome.gene(i)!=0) sum += WeightList[i];
    return sum;
}
void InitDensityQueue()                //把物品按密度从大到小排序,把下标队列写入数组DensityQueue
{
	int i,j,no;
	float FixDensity,CursorDensity;
	for(i=0;i<NUM_GOODS;i++)
	{
		FixDensity = ValueList[i] / WeightList[i];
		no=0;
		for(j=0;j<NUM_GOODS;j++)
			if(i!=j){
				CursorDensity = ValueList[j] / WeightList[j];
				if((CursorDensity > FixDensity)||((CursorDensity == FixDensity)&&(j < i)))
					   no++;
			}
		DensityQueue[no]=i;
	}
}
void repair(GAGenome & c)              //总的修复算子
{
#ifdef GREEDREPAIR
		GreedRepair(c);
#else
		RandomRepair(c);
#endif
}
int SelectRandomBit(GAGenome & c)      //为随机修复选择一个清除物品
{
	bool foundflag=false;
	int index,rand;
	GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
	rand = GARandomInt(0, NUM_GOODS-1);
	for(index=0; !foundflag && index<NUM_GOODS; index++)
		if(genome.gene(rand)!=0) foundflag=true;
		else rand = (rand+1)%NUM_GOODS;
	return rand;
}
void RandomRepair(GAGenome & c)        //随机修复算子
{
    bool knapsack_overfilled=false;
	float wsum;
	int index;
	GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
	
	wsum = WeightSum(c);
	if(wsum > KnapsackMaxContent) knapsack_overfilled=true;
	while(knapsack_overfilled)
	{
        index=SelectRandomBit(c);
	    genome.gene(index, 0);
        wsum -= WeightList[index];
		if(wsum <= KnapsackMaxContent) knapsack_overfilled=false;
	}
}
void GreedRepair(GAGenome & c)         //贪心修复算子
{
	float wsum,tempwsum;
	int no,index;
	GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
	
	wsum = 0;
	for(no=0;no<NUM_GOODS;no++)
	{
		index = DensityQueue[no];
		if(genome.gene(index)==1)
		{
			tempwsum = wsum + WeightList[index];
			if(tempwsum > KnapsackMaxContent) genome.gene(index, 0);
			else wsum = tempwsum;
		}
	}
}
int KnapsackGenomeOnePointCrossover(const GAGenome& p1,	const GAGenome& p2,
		GAGenome* c1, GAGenome* c2)                     //杂交算子
{
	GAGenome &rc1=*c1, &rc2=*c2;
	int n;
	n = GA1DBinaryStringGenome::OnePointCrossover(p1, p2, c1, c2);
	repair(rc1); repair(rc2);	
	return n;
}
int KnapsackGenomeFlipMutator(GAGenome & c, float pmut) //变异算子
{
	int nMut;
	nMut = GA1DBinaryStringGenome::FlipMutator(c, pmut);
	repair(c);
    return nMut;
}
void KnapsackGenomeInitialize(GAGenome & c)             //个体初始化算子
{
	GA1DBinaryStringGenome::UniformInitializer( c );
	repair(c);
}
void CreatKnapsackGreedGenome(GAGenome & c)             //生成贪心解个体
{
	int index;
	GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
	for(index=0;index<NUM_GOODS;index++) genome.gene(index, 1);
	GreedRepair(genome);
}
void ShowGenome(GAGenome & c)                           //输出个体的基因编码
{
	int i;
	float wsum=0;
	GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;
	for(i=0;i<NUM_GOODS;i++) cout<<genome.gene(i);
}




//debug code
/*
//int popsize  = POPULATION_SIZE;
    //int ngen     = NUM_GENERATIONS;
    //float pmut   = PROBABILITY_MUTATION;
    //float pcross = PROBABILITY_CROSSOVER;
class MyKnapsackGA : public GASimpleGA{ 
public:
	MyKnapsackGA(const GAGenome& c): GASimpleGA(c){};
#ifdef MIXGREEDGENOME//need fix
    void initialize(unsigned int seed)
	{
    pop->initialize();
	GASimpleGA::initialize(seed);

	GAGenome& genome = pop->worst();
	CreatKnapsackGreedGenome(genome);
	//float x = WeightSum(genome);
	//cout << "    CreatKnapsackGreedGenome = "<<x<<"\n";
	//cout << objective(genome)<<"\n";
	//ShowGenome(genome);

    pop->evaluate(gaTrue);	
    stats.reset(*pop);
    if(!scross) 
      GAErr(GA_LOC, className(), "initialize", gaErrNoSexualMating);
	};
#endif
};
  
void writeBestGenome(GAGenome & c)
{
	ofstream ostrm;
	ostrm.open("bogbest.dat");
	ostrm.seekp(0,ios::end);

	int i;
	GA1DBinaryStringGenome & genome = (GA1DBinaryStringGenome &)c;

	for(i=0;i<NUM_GOODS;i++)
	{
		ostrm<<genome.gene(i);
	}
	ostrm<<"\n";
	
	ostrm.close();
}*/

⌨️ 快捷键说明

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