ea-neurons.c

来自「一个在unix下运行的neurons EA小程序」· C语言 代码 · 共 272 行

C
272
字号
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define Example        16 /* number of examples               */
#define Input          5  /* the last input is always -1      */
#define Output         1  /* number of output neurons         */
#define MaxHidden      20 /* maximum number of hidden neurons */

#define Generation     1000
#define PopSize        100
#define BitPerWeight   16
#define GeneLength     2040 /* (BitPerWeight+1)*MaxHidden*(Input+Output) */

#define Rc             0.8
#define Rm             0.001
#define DesiredFitness 0.99
#define lambda         10.0
#define A              20.0
#define B              -10.0
#define Used           1

#define sigmoid(x)    (1.0/(1.0+exp(-lambda*x)))
#define frand()       (rand()%10000/10001.0)
#define randomize()   srand((unsigned int)time(NULL))

typedef struct {
  unsigned char genotype[GeneLength];
  double        fitness;
  int           size; /* the number of hidden neurons actually used */
} Individual;

Individual net[PopSize];
Individual new_net[PopSize];
Individual best_net;

double x[Example][Input]={
  {0,0,0,0,-1},{0,0,0,1,-1},{0,0,1,0,-1},{0,0,1,1,-1},
  {0,1,0,0,-1},{0,1,0,1,-1},{0,1,1,0,-1},{0,1,1,1,-1},
  {1,0,0,0,-1},{1,0,0,1,-1},{1,0,1,0,-1},{1,0,1,1,-1},
  {1,1,0,0,-1},{1,1,0,1,-1},{1,1,1,0,-1},{1,1,1,1,-1},
};
double d[Example][Output]={0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};

double v[MaxHidden][Input];
double w[Output][MaxHidden];

double y[MaxHidden];
double o[Output];

void Initialization(void);
void Reconstruction(int);
int CheckNeuron(int);
double GetWeight(int,int);
void Evaluation(int);
void Reproduction(void);
void Crossover(int, int);
void Mutation(int);
void PrintResult(int);
/**************************************************************/
/* The main program                                           */
/**************************************************************/
main(){
  int i,i0,g=0;

  Initialization();
  for(g=1;g<Generation;g++){
    i0=0;
    for(i=1;i<PopSize;i++){
      Evaluation(i);
      if(net[i].fitness>net[i0].fitness) i0=i;
    }
    best_net=net[i0];

    printf("Highest fitness [%d] = %f\n",g, best_net.fitness);
    printf("Size of the best net [%d] = %d\n\n",g, best_net.size);
    if(best_net.fitness>DesiredFitness) break;
    Reproduction();
  } 
  PrintResult(i0);
}

/**************************************************************/
/* Initialization of all individuals                          */
/**************************************************************/
void Initialization(void){
  int i,j;

  randomize();
  for(i=0;i<PopSize;i++){
    for(j=0;j<GeneLength;j++){
      net[i].genotype[j]=rand()%2;
    }
  }
}

/**************************************************************/
/* Reconstruction of the individual from its genotype         */
/* Return the number of hidden neurons actually used          */
/**************************************************************/
void Reconstruction(int p){
  int i,j,k;
  int tag[MaxHidden];

  net[p].size=0;
  for(j=0;j<MaxHidden;j++){
    if((tag[j]=CheckNeuron(p))==Used) net[p].size++;
    for(i=0;i<Input;i++){
      v[j][i]=GetWeight(p,tag[j]);
    }
  }

  for(k=0;k<Output;k++){
    for(j=0;j<MaxHidden;j++){
      w[k][j]=GetWeight(p,tag[j]);
    }
  }
}

/**************************************************************/
/* Check if the current hidden neuron is used or not          */
/**************************************************************/
int CheckNeuron(int p){
  static int current_individual=0;
  static int start=0;
  int i;

  if(current_individual!=p){
    start=0;
    current_individual=p;
  }
  
  i=start;
  start=i+BitPerWeight*Input;
  return net[p].genotype[i];
}

/**************************************************************/
/* Return a weight from the genotype of the p-th individual   */
/**************************************************************/
double GetWeight(int p,int tag){
  static int start=0;
  double tmp1=0.5,tmp2=0,result=0;
  int i;

  if(tag==Used){
    for(i=start;i<start+BitPerWeight;i++){
      tmp2+=net[p].genotype[i]*tmp1;
      tmp1*=0.5;
    }
    result=tmp2*A+B;
  }
  start+=BitPerWeight;
  if(start>=GeneLength) start=0;
  return result;
}

/**************************************************************/
/* Find the fitness of the p-th individual                    */
/**************************************************************/
void Evaluation(int p){
  int i,j,k,q;
  double Error;
  double temp;

  Reconstruction(p);
  Error=0;
  for(q=0; q<Example; q++){
    for(j=0;j<MaxHidden-1;j++){
      temp=0;
      for(i=0;i<Input;i++)
	temp+=v[j][i]*x[q][i];
      y[j]=sigmoid(temp);
    }

    y[MaxHidden-1]=-1;
    for(k=0; k<Output; k++){
      temp=0;
      for(j=0;j<MaxHidden;j++)
	temp+=w[k][j]*y[j];
      o[k]=sigmoid(temp);
      Error+=0.5*pow(d[q][k]-o[k],2.0);
    }
  }
  net[p].fitness=1/(1+Error);
}

/**************************************************************/
/* Reproduction of the individuals                            */
/**************************************************************/
void Reproduction(void){
  int i,i0;
  double total_fitness=0;
  double r,sum;
    
  for(i=0;i<PopSize;i++)
    total_fitness+=net[i].fitness;

  for(i=0;i<PopSize;i++){
    r=total_fitness*frand();
    i0=0;
    sum=0;
    while((sum+=net[i0].fitness)<r) i0++;
    new_net[i]=net[i0];
  }
  
  for(i=0;i<PopSize;i+=2){
    Crossover(i,i+1);
    Mutation(i);
    Mutation(i+1);
  }
  net[0]=best_net;
}

/**************************************************************/
/* Producing two sons from two parents using cross-over       */
/**************************************************************/
void Crossover(int i1,int i2){
  int i;
  int crossover_point;

  if(frand()<Rc){
    crossover_point=rand()%(GeneLength-2)+1;
    for(i=0;i<GeneLength;i++){
      if(i<crossover_point){
	net[i1].genotype[i]=new_net[i1].genotype[i];
	net[i2].genotype[i]=new_net[i2].genotype[i];
      }
      else{
	net[i1].genotype[i]=new_net[i2].genotype[i];
	net[i2].genotype[i]=new_net[i1].genotype[i];
      }
    }
  }
}

/**************************************************************/
/* Mutation of a given individual                                   */
/**************************************************************/
void Mutation(int s){
  int i;

  for(i=0;i<GeneLength;i++){
    if(frand()<Rm) net[s].genotype[i]=(net[s].genotype[i]+1)%2;
  }
}

/**************************************************************/
/* Print out the final result                                 */
/**************************************************************/
void PrintResult(int best){ 
  int i,j,k;

  Reconstruction(best);
  printf("\n\n");
  printf("The connection weights in the output layer:\n");
  for(k=0;k<Output;k++){
    for(j=0;j<MaxHidden;j++)
      printf("%5f ",w[k][j]);
    printf("\n");
  }

  printf("\n\n");
  printf("The connection weights in the hidden layer:\n");
  for(j=0; j<MaxHidden-1; j++){
    for(i=0; i<Input; i++)
      printf("%5f ",v[j][i]);
    printf("\n");
  }
  printf("\n\n");
}

⌨️ 快捷键说明

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