天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 65|回复: 0

C++算法之遗传算法及实现

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
[code]/****************************************/
//功能:使用遗传算法求解y = -x^2 + 5的最大值
//遗传算法细节:
//编码:二进制
//选择:轮转赌轮
//交叉:单点交叉,交叉概率固定
//变异:平均随机变异,变异概率固定
//具体参数可以事先给定

/****************************************/
#include <stdio.h>  
#include <conio.h>  
#include <stdlib.h>  
#include <time.h>  
#include <iostream>  

using namespace std;

/*****初始化一些参数*****/
const int Population_size = 100;        //种群规模
const int Chromosome_length = 6;    //假定有64个网络节点,用64位表示每一个节点
double rate_crossover = 0.5;                //交叉率
double rate_mutation = 0.001;           //变异率
int iteration_num = 50;                     //进化50代                                    
/****************************************/

//将染色体定义为结构体类型
typedef struct Chromosome                          
{   
    short int bit[Chromosome_length];           //染色体二进制码串
    double value;                                           //二进制代码对应的实际值
    double fitness;                                     //适应值  
    double rate_fit;                                        //相对的fit值,即所占的百分比
    double cumu_fit;                                    //积累概率  
}chromosome;


/*****函数声明*****/
//初始化得到个体的二进制字符串
void population_initialize(chromosome (&population_current)[Population_size]);
//对染色体进行解码
void decode(chromosome &population_current) ;   
//计算染色体的适应度值
double objective_function(double x);
//更新种群内个体的属性值
void fresh_property(chromosome(&population_current)[Population_size]);
//基于旋转赌轮的选择操作    proportional roulette wheel selection
void seletc_prw(chromosome(&population_current)[Population_size], chromosome(&population_next_generation)[Population_size], chromosome &best_individual);
//交叉操作
void crossover(chromosome (&population_next_generation)[Population_size]);  
//突变操作
void mutation(chromosome (&population_next_generation)[Population_size]);
/****************************************/

// 主函数
void main()                                   
{
    /*****初始化定义的种群和个体*****/
    clock_t start, end;//开始计时,精确到秒
    start = clock();
    /****************************************/


    /*****初始化定义的种群和个体*****/
    chromosome population_current[Population_size];                    //当前种群  
    chromosome population_next_generation[Population_size];       //产生的下一代的种群                        
    chromosome best_individual;                                                 //记录适应度的最大值
    chromosome zeros_chromosome;                                                //定义一个全为0的个体,用于群体中某个个体的重置
    /****************************************/

    int i = 0,j = 0;//循环变量

    //*****初始化定义的种群和个体*****
    //首先初始化zeros_chromosome,后使用之初始化其他个体
    for (i = 0; i < Chromosome_length; i++)
        zeros_chromosome.bit[i] = 0;
    zeros_chromosome.fitness = 0.0;
    zeros_chromosome.value = 0.0;
    zeros_chromosome.rate_fit = 0.0;
    zeros_chromosome.cumu_fit = 0.0;

    best_individual = zeros_chromosome;
    for (i = 0; i < Population_size; i++)
    {
        population_current[i] = zeros_chromosome;
        population_next_generation[i] = zeros_chromosome;
    }
    /****************************************/


    printf("\nWelcome to the Genetic Algorithm!\n");  //   
    printf("The Algorithm is based on the function y = -x^2 + 5 to find the maximum value of the function.\n");

enter:printf("\nPlease enter the no. of iterations\n请输入您要设定的迭代数 : ");
    // 输入迭代次数,传送给参数 iteration_num
    scanf_s("%d", &iteration_num);                           

    // 判断输入的迭代次数是否为负或零,是的话重新输入
    if (iteration_num <1)
        goto enter;


    //种群初始化,得到个体的二进制字符串
    population_initialize(population_current);
    //更新种群内个体的属性值
    fresh_property(population_current);
    // 开始迭代
    for (i = 0; i< iteration_num; i++)                           
    {
        // 输出当前迭代次数
        //printf("\ni = %d\n", i);
        //挑选优秀个体组成新的种群
        seletc_prw(population_current,population_next_generation,best_individual);                 
        //对选择后的种群进行交叉操作
        crossover(population_next_generation);              
        //对交叉后的种群进行变异操作
        mutation(population_next_generation);                     
        //更新种群内个体的属性值
        fresh_property(population_next_generation);
        //将population_next_generation的值赋给population_current,并清除population_next_generation的值
        for (i = 0; i < Population_size; i++)
        {
            population_current[i] = population_next_generation[i];
            population_next_generation[i] = zeros_chromosome;
        }
        //检验时间是否到90s
        end = clock();
        if (double(end - start) / CLK_TCK> 89)
            break;
    }
    //输出所用时间
    printf("\n 迭代%d次所用时间为: %f\n", iteration_num, double(end - start) / CLK_TCK);

    //输出结果
    printf("\n 函数得到最大值为: %f ,适应度为:%f \n", best_individual.value, best_individual.fitness);

    for (i = 0; i<Population_size; i++)
    {
        printf(" population_current[%d]=", i);
        for (j = 0; j < Chromosome_length; j++)
            printf(" %d", population_current[i].bit[j]);
        printf("        value=%f    fitness = %f\n", population_current[i].value, population_current[i].fitness);
    }
    printf("\nPress any key to end ! ");


    // 清除所有缓冲区
//  flushall();                                   
    system("pause");
}


//函数:种群初始化  
//输入是数组的引用
//调用时,只需输入数组名
void population_initialize(chromosome (&population_current)[Population_size])   
{
    int i = 0, j = 0;

    //产生随机数种子
    srand((unsigned)time(NULL));
    //遍历种群中的每个染色体
    for (j = 0; j<Population_size; j++)                              
    {
        //随机初始化染色体的每一位
        for (i = 0; i<Chromosome_length; i++)                       
        {
            // 随机产生染色体上每一个基因位的值,0或1
            population_current[j].bit[i] = rand()% 2;         
        }

    }

}


// 函数:将二进制换算为十进制
void decode(chromosome &population_current)   
{//此处的染色体长度为,其中个表示符号位  
    int i = 0;
    population_current.value = 0;
    //地位在前,高位再后
    for( i = 0 ; i < Chromosome_length -1; i++ )
        population_current.value += (double)pow(2, i) * (double)population_current.bit[i];    //遍历染色体二进制编码,
    //最高位为符号位,如果是1代表负数
    if (population_current.bit[Chromosome_length - 1] == 1)
        population_current.value = 0 - population_current.value;

}

//函数:计算适应度
double objective_function(double x)
{
    double y;
    // 目标函数:y= - ( (x-1)^ 2 ) +5
    y = -((x - 1) *(x - 1)) + 5;                                
    return(y);
}

//函数:更新种群内个体的属性值
//说明:当种群中个体的二进制串确定后,就可以计算每个个体fitness、value、rate_fit 、cumu_fit
//输入:
//chromosome (&population_current)[Population_size] 当前代种群的引用
void fresh_property(chromosome (&population_current)[Population_size])
{
    int j = 0;
    double sum = 0;

    for (j = 0; j < Population_size; j++)
    {

    //染色体解码,将二进制换算为十进制,得到一个整数值
        //计算二进制串对应的10进制数值
        decode(population_current[j]);                 
        //计算染色体的适应度
        population_current[j].fitness = objective_function(population_current[j].value);
        sum = sum + population_current[j].fitness;

    }


    //计算每条染色体的适应值百分比及累计适应度值的百分比,在轮盘赌选择法时用它选择染色体  
    population_current[0].rate_fit = population_current[0].fitness / sum;
    population_current[0].cumu_fit = population_current[0].rate_fit;
    for (j = 1; j < Population_size; j++)
    {
        population_current[j].rate_fit = population_current[j].fitness / sum;
        population_current[j].cumu_fit = population_current[j].rate_fit + population_current[j-1].cumu_fit;
    }


}

//函数:基于轮盘赌选择方法,对种群中的染色体进行选择  
//输入:
//chromosome (&population_current)[Population_size] 当前代种群的引用
//chromosome (&population_next_generation)[Population_size] 选择出的下一代种群的引用
//chromosome &best_individual 当前代种群中的最优个体
void seletc_prw(chromosome (&population_current)[Population_size],chromosome (&population_next_generation)[Population_size],chromosome &best_individual)
{

    int i = 0, j = 0;
    double rate_rand = 0.0;
    best_individual = population_current[0];
    //产生随机数种子
    srand((unsigned)time(NULL));
    for (i = 0; i < Population_size; i++)
    {
        rate_rand = (float)rand() / (RAND_MAX);
        if (rate_rand < population_current[0].cumu_fit)
            population_next_generation[i] = population_current[0];      
        else
        {
            for (j = 0; j < Population_size; j++)
            {
                if (population_current[j].cumu_fit <= rate_rand && rate_rand < population_current[j + 1].cumu_fit)
                {
                    population_next_generation[i] = population_current[j + 1];
                    break;
                }
            }
        }

        //如果当前个体比目前的最有个体还要优秀,则将当前个体设为最优个体
        if(population_current[i].fitness > best_individual.fitness)
            best_individual = population_current[i];
    }

}


// 函数:交叉操作
void crossover(chromosome (&population_next_generation)[Population_size])         
{   
    int i = 0,j = 0;
    double rate_rand = 0.0;
    short int bit_temp = 0;
    int num1_rand = 0, num2_rand = 0, position_rand = 0;
    //产生随机数种子
    srand((unsigned)time(NULL));
    //应当交叉变异多少次呢?先设定为种群数量
    for (j = 0; j<Population_size; j++)
    {
        rate_rand = (float)rand()/(RAND_MAX);
        //如果大于交叉概率就进行交叉操作
        if(rate_rand <= rate_crossover)
        {
            //随机产生两个染色体
            num1_rand = (int)rand()%(Population_size);
            num2_rand = (int)rand()%(Population_size);
            //随机产生两个染色体的交叉位置
            position_rand = (int)rand()%(Chromosome_length - 1);
            //采用单点交叉,交叉点之后的位数交换
            for (i = position_rand; i<Chromosome_length; i++)
            {
                bit_temp = population_next_generation[num1_rand].bit[i];
                population_next_generation[num1_rand].bit[i] = population_next_generation[num2_rand].bit[i];     
                population_next_generation[num2_rand].bit[i] = bit_temp;     
            }

        }
    }

}

// 函数:变异操作
void mutation(chromosome (&population_next_generation)[Population_size])               
{
    int position_rand = 0;
    int i = 0;
    double rate_rand = 0.0;
    //产生随机数种子
    srand((unsigned)time(NULL));
    //变异次数设定为种群数量
    for (i = 0; i<Population_size; i++)
    {
        rate_rand = (float)rand()/(RAND_MAX);
        //如果大于交叉概率就进行变异操作
        if(rate_rand <= rate_mutation)
        {
            //随机产生突变位置
            position_rand = (int)rand()%(Chromosome_length);
            //突变
            if (population_next_generation[i].bit[position_rand] == 0)
                population_next_generation[i].bit[position_rand] = 1;
            else
                population_next_generation[i].bit[position_rand] = 0;

        }

    }
}[/code]

 

 

 

 

C++算法之遗传算法及实现
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 11:39 , Processed in 0.155479 second(s), 27 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表