C语言实现penna模型

  一年前写的代码,偶然翻出来。发现自己当时水平还不赖吗。

  1 # include <stdio.h>
  2 # include <stdlib.h>
  3 # include <time.h>
  4 # include <stdbool.h>
  5 # include <windows.h>
  6 
  7 # define N0 1000    //初始时刻种群数量为1000
  8 # define Nmax 100000    //种群最大数量为100000
  9 # define R 6    //最低繁殖年龄为8
 10 # define B 32   //老死年龄即位串长度为32
 11 # define b 1    //每次繁殖子代个数为1
 12 # define T 4    //最大疾病次数为2
 13 # define M 2    //突变强度为2
 14 # define LEN sizeof(GENE)   //宏替换一个结构体的大小
 15 clock_t start, finish;
 16 double duration;
 17 int t;
 18 typedef struct Gene
 19 {
 20     bool Gene[B];   //用布尔类型数组表示位串
 21     int Age;    //年龄
 22     int SickNum;    //患病次数
 23     struct Gene *next;  //存放一个连接链表的节点指针
 24 }GENE;
 25 int Nt = N0;    //定义一个全局变量,表示t时刻种群的数量
 26 double M_rate = (double)M/B;    //M_rate表示基因遗传突变率
 27 GENE *pHead = NULL, *pFore = NULL, *pNext = NULL, *p = NULL, *pTail = NULL;
 28 //定义五个指针:pHead指向头节点pFore为节点的前驱指针,pNext建立新节点,p游标指针,pTail尾节点指针
 29 GENE Gene_Str;  //定义一个GENE类型的结构体Gene_Str
 30 
 31 void Initialize(void)   //构造链表及种群初始状态
 32 {
 33     pHead = (GENE *)malloc(LEN);//为头节点指针分配空间
 34     p = pHead;  //头节点指针赋值给游标指针
 35     for (int i=1; i<N0; i++)
 36     {
 37         p->Age = 0; //初始时刻年龄为0(t=0)
 38         p->SickNum = 0; //患病次数为0
 39         for (int j=0; j<B; j++)
 40         {
 41             p->Gene[j] = (rand()%2);    //  对第一代个体基因随机规定
 42         }
 43         pNext = (GENE *)malloc(LEN);    //为新节点开辟存储空间
 44         p->next = pNext;    //将前驱节点指向下一结构体地址
 45         p = pNext;  //将新节点赋值给游标指针
 46     }
 47     pTail = p;
 48     pNext = p = NULL;
 49     pTail->next = NULL; //尾节点下一指向为空
 50 }
 51 void Aging(void)    //执行年龄增长机制,每次调用,所有个体年龄加一
 52 {
 53     p = pHead;  //游标指针指向头指针
 54     while (p != NULL)   //遍历每个个体
 55     {
 56         if (p->Gene[p->Age] == 1)
 57         {
 58             p->SickNum++;
 59         }   //如果该年龄位置为坏基因,则患病次数加一
 60         p->Age++;   //每个个体年龄加一
 61         p = p->next;    //游标指针指向下一个体
 62     }
 63 }
 64 void Die(void)  //执行死亡机制,每次调用,满足条件的个体死去,链表节点删除
 65 {
 66     pFore = p = pHead;  //游标指针指向头指针,并创建一个和游标指针同步的前驱指针
 67     while (p != NULL)   //遍历每个个体
 68     {
 69         double RandOfLive = (double)rand()/(double)RAND_MAX;    //构造一个随机概率
 70         if (p->SickNum>=T || p->Age>=(B-1) || RandOfLive>=(1-(double)Nt/Nmax))
 71         //满足三种情况之一即死亡:年龄到达老死年龄,达到最大患病次数,因环境压力随机死亡
 72         {
 73             Nt--;   //每次死亡导致种群数量减一          
 74             if (p == pHead)//当p为头节点
 75             {
 76                 pHead = p->next;
 77                 free(p);    //节点删除后释放占用的空间
 78                 pFore = p = pHead;
 79                 p = p->next;    //重新初始化
 80             }
 81             else if (p->next == NULL)//当p为尾节点
 82             {
 83                 pFore->next = NULL; //将前一个节点设置为尾节点
 84                 free(p);    //释放删除后的节点
 85                 p = NULL;
 86             }
 87             else    //既不是头节点又不是尾节点
 88             {
 89                 pFore->next = p->next;  //跳过p节点,前后相连接
 90                 free(p);    //释放删除了的节点
 91                 p = pFore;
 92                 pFore = p;
 93                 p = p->next;    //重新初始化
 94             }
 95         }
 96         else    //如果个体不满足死亡条件
 97         {
 98             pFore = p;
 99             p = p->next;    //指针向下一节点移动并始终存储前一节点以备删除中间节点
100         }
101     }   //结束后p == NULL,是尾节点的节点指针
102     pNext = NULL;
103     pFore = NULL;   //遍历之后将这两个指针置为空,防止错误调用
104 }
105 void RePreduction(void) //执行繁殖机制
106 {
107     p = pHead;  //p指向链表的头指针
108     while (p != NULL)   //遍历每个个体
109     {
110         double RandOfChange = (double)rand()/(double)RAND_MAX;  //构造一个随机数
111         if (p->Age >= R)    //如果年龄达到最低繁殖年龄
112         {
113             pNext = p;  //为了方便操作,将每一个新生个体对应的节点连在尾节点后
114             while (pNext->next != NULL)
115                 pNext = pNext->next;    //此时pNext为尾节点
116             
117             for (int k=0; k<b; k++) //每次繁殖将产生b个新个体
118             {
119                 while (pNext->next != NULL)
120                     pNext = pNext->next;
121                 
122                 pTail = (GENE *)malloc(LEN);    //开辟一个存储空间
123                 pNext->next = pTail;    //尾节点的next指向该存储空间
124                 pTail->next = NULL; //将这个新节点设为尾节点         
125                 for (int i=0; i<B; i++)
126                 {
127                     if (RandOfChange < M_rate)  //达到要求则发生突变
128                         pTail->Gene[i] = !p->Gene[i];
129                     else    //否则执行拷贝复制
130                         pTail->Gene[i] = p->Gene[i];
131                 }
132                 pTail->Age = 0;
133                 pTail->SickNum = 0; //新生个体的这两项也要初始化,开始一直忘了!!!!!!!!
134                 Nt+=1;  //个体数加一
135             }
136             p = p->next;
137         }
138         else
139             p = p->next;    //执行完继续下一个体
140     }
141 }
142 
143 int main(void)
144 {
145     FILE* fp = fopen("resultr6.txt", "w");
146     if (fp == NULL)
147         printf("error
");
148     Sleep(2000);    //挂起两秒钟
149     srand((unsigned)time(NULL));    //随机种子
150     Initialize();   //对初始个体进行初始化操作
151     for (t=0; t<1000; t++)  //种群在该机制下演化一千个时间步
152     {
153         Aging();    //执行年龄增长机制
154         Die();  //执行死亡机制
155         RePreduction(); //执行繁殖机制
156         printf("A");
157         fprintf(fp, "%d	", Nt);
158     }
159     fclose(fp);
160     return 0;
161 }
View Code

  附图

原文地址:https://www.cnblogs.com/zhaoyu1995/p/5557840.html