| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 487 人关注过本帖
标题:关于遗传算法
取消只看楼主 加入收藏
iceberg0
Rank: 1
等 级:新手上路
帖 子:37
专家分:9
注 册:2012-3-2
结帖率:0
收藏
 问题点数:0 回复次数:1 
关于遗传算法
程序代码:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define SUM 20              //定义群体的染色体数量
#define MAXloop 1200        //最大循环次数
#define error 0.01          //若两次最优值之差小于次数则认为结果没有改变
#define crossp 0.7          //交叉概率,所选中的双亲按此概率进行交叉
#define mp 0.04             //变异概率
struct gen                  //定义染色体
{
    int info;               //染色体结构,用一整型数的后14位作为染色体编码
    float suitability;      //此染色体所对应的适应度函数值,即表达式的值
};
struct gen gen_group[SUM];  //定义含有20个染色体的种群
struct gen gen_new[SUM];    //定义含有20个染色体的种群,记录交叉产生的子代染色体
struct gen gen_result;      //记录上一轮循环中得到的最优的染色体
int result_unchange_time;   //当相邻两轮得到的最优值对应的适应度
                            //之差小于error时其值增1,反之清零
struct  log                 //形成链表,记录每次循环所产生的最优的适应度
{
    float suitability;
    struct log *next;
}llog, *head, *end;
int log_num;                // 链表长度

void initiate(void);            //初始化函数,负责产生初始种群
void evaluation(int flag);  //评估染色体的适应度,进行排序
void cross(void);               //交叉函数
void selection(void);           //选择函数
int record(void);               //记录每次循环所产生的最优解并判断循环是否终止
void mutation(void);            //编译函数
void showresult(int);          //显示结果
int randsign(float p);          //按概率p随机产生0、1其值为的概率为p
int randbit(int i, int j);      //随机产生一个在i,j两个数之间的整数
int randnum(void);              //随机产生一个14个基因组成的染色体
int createmask(int a);          //用于交叉操作
int convertionD2B(float x);     //对现实解空间的可能解x进行二进制编码
float convertionB2D(int x);     //将二进制编码x转化为现实解空间的值

void main()
{
    int i,flag;
    flag = 0;
    initiate();
    evaluation(0);
    for(i=0; i<MAXloop; i++)
    {
        cross();
        evaluation(1);
        selection();
        if(record()==1)
        {
            flag == 1;
            break;
        }
        mutation();
    }
    showresult(flag);
}
/*函数三个功能:1.初始化随机列表 2.建立规模SUM的初始种群 3.建立log链表头,
  其中指针head记录链表头的位置,end始终指向链表的尾部*/
void initiate(void)
{
    int i, stime;
    long ltime;
    ltime = time(NULL);
    stime = (unsigned)ltime/2;
    srand(stime);
    for(i=0; i<SUM; i++)
        gen_group[i].info = randnum();
    gen_result.suitability = 1000;
    result_unchange_time = 0;
    head = end = (struct log *)malloc(sizeof(llog));
    if(head == NULL)
    {
        printf("\n内存不够");
        exit(1);
    }
    end->next = NULL;
    log_num = 1;
}
void evaluation(int flag)
{
    int i, j;
    struct gen *genp;
    int gentinfo;
    float gentsuitability;
    float x;
    if(flag == 0)
        genp = gen_group;
    else
        genp = gen_new;
    for(i=0; i<SUM; i++)
    {
        x = convertionB2D(genp[i].info);
        genp[i].suitability = x*(x*(x*(x*(x*(x-10)-26)+344)+193)-1846)-1680;
    }
    for(i=0; i<SUM-1; i++)
    {
        for(j=i+1; j<SUM; j++)
        {
            if(genp[i].suitability > genp[j].suitability)
            {
                gentinfo = genp[i].info;
                genp[i].info = genp[j].info;
                genp[j].info = gentinfo;
                gentsuitability = genp[i].suitability;
                genp[i].suitability = genp[j].suitability;
                genp[j].suitability = gentsuitability;
            }
        }
    }
}
/*cross由三部分组成:1.随机选择将要进行交叉的染色体对,保证种群中的每一个
染色体都有唯一一次交叉的机会,2.按crossp的概率对选择的染色体对进行交叉操作
3.为进行交叉的染色体直接复制作为子染色体。  首先由ranbit()进行交叉位
createmask()返回一个交叉位以右皆为1的二进制数,赋值给mask1,mask2为交叉
以左皆为1的二进制数,它们分别与父染色体gen_group[i].info gen_group[j].info
进行操作,所得的结果的和即为交叉的结果*/
void cross(void)
{
    int i, j, k;
    int mask1, mask2;
    int a[SUM];
    for(i=0; i<SUM; i++)
        a[i] = 0;
    k = 0;
    for(i=0; i<SUM; i++)
    {
        if(a[i]==0)
        {
            for(;;)
            {
                j = randbit(i+1, SUM-1);
                if(a[j] == 0)
                    break;
            }
            if(randsign(crossp)==1)
            {
                mask1 = createmask(randbit(0, 14));
                mask2 = -mask1;
                gen_new[k].info = (gen_group[i].info) & mask1 +
                (gen_group[j].info) & mask2;
                gen_new[k+1].info = (gen_group[i].info) & mask2 +
                (gen_group[j].info) & mask1;
                k = k + 2;
            }
            else
            {
                gen_new[k].info = gen_group[i].info;
                gen_new[k+1].info = gen_group[j].info;
                k = k + 2;
            }
            a[i] = a[j] = 1;
        }
    }
}
/*函数从父代种群和子代种群中选择最优的染色体组成新的父代种群。由于两个种群
都已进行了排序,因此只需找到子代种群中的第t个个体使其适应度函数值满足:
大于父代中种群中的第NUM-t个个体,并小于父代的第NUM-t+1个个体,然后用子代种群中
的前t个个体代替父代种群的后t个个体即可。*/
void selection(void)
{
    int i, j, k;
    j = 0;
    i = SUM/2 - 1;
    if(gen_group[i].suitability < gen_new[i].suitability)
    {
        for(j=1; j<SUM/2; j++)
        {
            if(gen_group[i+j].suitability > gen_new[i-j].suitability)
                break;
        }
    }
    else
        if(gen_group[i].suitability > gen_new[i].suitability)
        {
            for(j = -1; j>-SUM/2; j--)
            {
                if(gen_group[i+j].suitability<=gen_new[i-j].suitability)
                    break;
            }
        }
    for(k=j; k<SUM/2+1; k++)
    {
        gen_group[i+k].info = gen_new[i-k].info;
        gen_group[i+k].suitability = gen_new[i-k].suitability;
    }
}
/*两个任务:1.用链表记录各轮循环中的最优值,2.判断是否满足循环停止条件,
    当两次循环的适应度的差小于error时,result——unchange-time的值加1,
    若result——unchange-time达到20时表示已经搜索到最优值,返回1,若适应度
    差大于等于error则将result——unchange——time清零,并记录本轮最优,函数返回0*/
int record(void)
{
    float x;
    struct log *r;
    r = (struct log*)malloc(sizeof(llog));
    if(r==NULL)
    {
        printf("\n内存不够!\n");
        exit(1);
    }
    r->next = NULL;
    end->suitability = gen_group[0].suitability;
    end->next = r;
    end = r;
    log_num++;
    x = gen_result.suitability - gen_group[0].suitability;
    if(x < 0)
        x = -x;
    if(x < error)
    {
        result_unchange_time++;
        if(result_unchange_time >= 20)
            return 1;
    }
    else
    {
        gen_result.info = gen_group[0].info;
        gen_result.suitability = gen_group[0].suitability;
        result_unchange_time = 0;
    }
    return 0;
}
void mutation(void)
{
    int i, j, m;
    int gentinfo;
    float x;
    float cmp;
    float gentsuitablitity;
    cmp = 1 - pow(i-mp, 11);
    for(i=0; i<SUM; i++)
    {
        if(randsign(cmp)==1)
        {
            j = randbit(0, 14);
            m = 1<< j;
            gen_group[i].info = gen_group[i].info^m;
            x = convertionB2D(gen_group[i].info);
            x = x*(x*(x*(x*(x*(x-10)-26)+344)+193)-1846)-1680;
            gen_group[i].suitability = x;
        }
    }
    for(i=0; i<SUM-1; i++)
    {
        for(j=i+1; j<SUM; j++)
        {
            if(gen_group[i].suitability > gen_group[j].suitability)
            {
                gentinfo = gen_group[i].info;
                gen_group[i].info = gen_group[j].info;
                gen_group[j].info = gentinfo;
                gentsuitablitity = gen_group[i].suitability;
                gen_group[i].suitability = gen_group[j].suitability;
                gen_group[j].suitability = gentsuitablitity;
            }
        }
    }
}
void showresult(int flag)
{
    int i, j;
    struct log *logfree;
    struct log *logprint;
    logprint = (struct log *)malloc(sizeof(llog));
    if(logprint==NULL)
    {
        printf("分配内存");
        exit(1);
    }
    logprint = head;
    FILE *logf;
    if(flag == 0)
        printf("\n已到最大搜索次数,搜索失败!\n");
    else
    {
        printf("当取值%f时表达式达到最小值为%f\n",
               convertionB2D(gen_result.info), gen_result.suitability);
        printf("收敛过程记录与文件log.txt");
        if((logf = fopen("log.txt", "w+"))==NULL)
        {
            printf("Cannot creat/open file");
            exit(1);
        }
        for(i=0; i<log_num; i=i+5)
        {
            for(j=0; (j<5) & ((i+j)<log_num-1); j++)
            {
                fprintf(logf, "%20f", logprint->suitability);
                logprint = logprint->next;
            }
            fprintf(logf, "\n \n");
        }
    }
    for(i=0; i<log_num; i++)
    {
        logfree = head;
        head = head->next;
        free(logfree);
        fclose(logf);
    }
    getchar();
}
int randsign(float p)
{
    if(rand()>(p*32768))
        return 0;
    else
        return 1;
}

int randbit(int i, int j)
{
    int a, l;
    l = j - i + 1;
    a = i + rand() * l/32768;
    return a;
}
int randnum(void)
{
    int x;
    x = rand()/2;
    return x;
}
float convertionB2D(int x)
{
    float y;
    y = x;
    y = (y - 8192)/1000;
    return y;
}
int convertionD2B(float x)
{
    int g;
    g = (x*1000) + 8192;
    return g;
}
int createmask(int a)
{
    int mask;
    mask = (1<<(a+1)) - 1;
    return mask;
}
高手们帮我看看这个遗传算法哪里出错了???
谢谢!!!
搜索更多相关主题的帖子: color 算法 
2012-09-07 10:22
iceberg0
Rank: 1
等 级:新手上路
帖 子:37
专家分:9
注 册:2012-3-2
收藏
得分:0 
自己的错误已经找到了。
2012-09-07 15:16
快速回复:关于遗传算法
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.085544 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved