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

📄 gen_init.c

📁 统计模式识别算法包
💻 C
📖 第 1 页 / 共 2 页
字号:
      if (fit < minfitness)         minfitness = fit ;      }   avgfitness /= (double) popsize ;/*   The second step is to apply a linear transform to these fitnesses to prevent   extraordinarily fit individuals from dominating early on, and at the same   time still favor the most fit later in the run when a large number of   individuals are very fit.      This transform is:  f' = tmult * f + tconst.      The coefficients are chosen so that the transformed maximum fitness is   favor_best times the transformed average, while the average after transform   is equal to that before.  A typical value for favor_best is 2-3.   One problem is that late in the run, when the average is close to the max,   very small fitnesses may map negative.  In this case, map the smallest   to zero and do the best we can for the max.   Note that a common alternative is to use the mapping just described, and   truncate transformed fitnesses at zero.  However, the method shown here   is usually superior, as it preserves genetic diversity.*/   ftemp = maxfitness - avgfitness ;   if (ftemp > 1.e-20) {  // Insurance: average may equal max!      tmult = (favor_best - 1.0) * avgfitness / ftemp ;      tconst = avgfitness * (maxfitness - favor_best * avgfitness) / ftemp ;      }   else {      tmult = 1.0 ;      tconst = 0.0 ;      }/*   The 'ideal' scaling factor was just computed.  Use it to map the minimum   fitness.  If it comes out negative, compute an alternative scaling factor   which will map the minimum to zero and keep the average unchanged.*/   if (tmult * minfitness + tconst < 0.0) { // Do not allow negative fitness      ftemp = avgfitness - minfitness ;      if (ftemp > 1.e-20) {         tmult = avgfitness / ftemp ;         tconst = -minfitness * avgfitness / ftemp ;         }      else {         tmult = 1.0 ;         tconst = 0.0 ;         }      }/*   The scaling factors have been computed.  Do the scaling now.   The truncation at zero is theoretically unnecessary, as we avoided   negatives when we computed the scaling factor above.  However, floating   point problems can sometimes still produce a 'negative zero'.  In deference   to possible user modifications which DEMAND nonnegative fitnesses, it is   good programming practice to enforce this.*/   avgfitness = 0.0 ;   for (individual=0 ; individual<popsize ; individual++) {      fit = tmult * fitness[individual] + tconst ;      if (fit < 0.0)         fit = 0.0 ;      fitness[individual] = fit ;      avgfitness += fit ;      }   avgfitness /= (double) popsize ;/*   The final step is to normalize the fitnesses by dividing each by the   average fitness.  The effect is that then each fitness can be interpreted   as the expected number of times it would be chosen from the population   pool if its probability of selection were proportional to its fitness.*/   for (individual=0 ; individual<popsize ; individual++)      fitness[individual] /= avgfitness ;}/*--------------------------------------------------------------------------------   fitness_to_choices - Convert the array of fitnesses (which contain               expected frequency of selection) into the array of parent               choices.  This will allow random selection of parents               without replacement later, while still insuring that               we select (to within one) the expected number of each.--------------------------------------------------------------------------------*/static void fitness_to_choices (   int popsize ,      // Length of fitness, choices vectors   double *fitness ,  // Input array of expected selection frequencies   int *choices       // Output array of parents   ){   int individual, expected, k ;   double rn ;/*   We build the choices array in two steps.  This, the first step, assigns   parents according to the integer part of their expected frequencies.*/   k = 0 ;  // Will index choices array   for (individual=0 ; individual<popsize ; individual++) {      expected = (int) fitness[individual] ; // Assign this many now      fitness[individual] -= expected ;      // Save fractional remainder      while (expected--)                     // Forcibly use the int expected         choices[k++] = individual ;         // quantity of this individual      }/*   The second step is to take care of the remaining fractional expected   frequencies.  Pass through the population, randomly selecting members   with probability equal to their remaining fractional expectation.   It is tempting to think that the algorithm below could loop excessively   due to a very small fitness.  But recall that the sum of the fitnesses will   be AT LEAST as large as the number remaining to be selected, and generally   much more.  Thus, the ones with very small fitness (likely to cause trouble)   will never become the only remaining possibilities.*/   while (k < popsize) {  // Select until choices is full      individual = unifrand() * popsize ;// Randomly select individual      if (fitness[individual] > 0.0) {   // Try members still having expectation         if (fitness[individual] >= unifrand()) { // Selects with this prob            choices[k++] = individual ;   // Bingo!  Select this individual            fitness[individual] -= 1.0 ;  // and make it ineligable for future            }         }      }}/*--------------------------------------------------------------------------------   pick_parents - Randomly select two parents from 'choices' candidate array--------------------------------------------------------------------------------*/static void pick_parents (   int *nchoices ,  // Number of choices (returned decremented by two)   int *choices ,   // Array (nchoices long) of candidates for parent   int *parent1 ,   // One parent returned here   int *parent2     // and the other here   ){   int k ;   k = unifrand() * *nchoices ;        // Select position in choices array   *parent1 = choices[k] ;             // Then return that parent   choices[k] = choices[--*nchoices] ; // without replacement   k = unifrand() * *nchoices ;   *parent2 = choices[k] ;   choices[k] = choices[--*nchoices] ;}/*--------------------------------------------------------------------------------   reproduce - Create a child from half of each of two parents.      If first_child is true, randomly generate the crossover point.      Else use the supplied crossover point and take other halves.      If the chromosome size is at least 16, use two point crossover      half of the time.  Signal this by returning a negative crosspt.      We implement splitting the chromosome at a bit level (i.e. within      a byte) with the 'split' parameter.  This is in the range 0-7,      and is the bit number where the split takes place.  Like crosspt      it is output for the first child and input for the second.--------------------------------------------------------------------------------*/static void reproduce (   char *p1 ,        // Pointer to one parent   char *p2 ,        // and the other   int first_child , // Is this the first of their 2 children?   int chromsize ,   // Number of genes in chromosome   char *child ,     // Output of a child   int *crosspt ,    // If first_child, output of xover pt, else input it.   int *split        // In/out of within byte splitting point   ){   int i, n1, n2, n3, n4 ;   char left, right, *pa, *pb ;   if (first_child) {      *split = longrand() % 8 ; // We will split boundary bytes here      *crosspt = 1 + unifrand() * chromsize ;  // Randomly select cross pt      if ((chromsize >= 16)  &&  (unifrand() < 0.33333)) // Two point?         *crosspt = -*crosspt ; // flag this for second child      pa = p1 ;      pb = p2 ;      } // If first child   else {                       // Second child      pa = p2 ;                 // so parents reverse roles      pb = p1 ;      } // If second child/*   Prepare for reproduction*/   if (*split) {              // Create left and right splitting masks      right = 1 ;      i = *split ;      while (--i)         right = (right << 1) | 1 ;      left = 255 ^ right ;      }   if (*crosspt > 0) {        // Use one point crossover      n1 = chromsize / 2 ;    // This many genes in first half of child      n2 = chromsize - n1 ;   // and this many in second half      n3 = n4 = 0 ;           // We are using one point crossover      i = *crosspt - 1 ;      // We will start building child here      }   else {                             // Use two point crossover      n1 = n2 = n3 = chromsize / 4 ;  // This many in first three quarters      n4 = chromsize - n1 - n2 - n3 ; // And the last quarter gets the rest      i = -*crosspt - 1 ;             // 2 point method was flagged by neg      }/*   Do reproduction here*/   if (*split) {      i = (i+1) % chromsize ;      child[i] = (left & pa[i])  |  (right & pb[i]) ;      --n1 ;      }   while (n1--) {      i = (i+1) % chromsize ;      child[i] = pb[i] ;      }   if (*split) {      i = (i+1) % chromsize ;      child[i] = (left & pb[i])  |  (right & pa[i]) ;      --n2 ;      }   while (n2--) {      i = (i+1) % chromsize ;      child[i] = pa[i] ;      }   if (n4) {               // Two point crossover?      if (*split) {         i = (i+1) % chromsize ;         child[i] = (left & pa[i])  |  (right & pb[i]) ;         --n3 ;         }      while (n3--) {         i = (i+1) % chromsize ;         child[i] = pb[i] ;         }      if (*split) {         i = (i+1) % chromsize ;         child[i] = (left & pb[i])  |  (right & pa[i]) ;         --n4 ;         }      while (n4--) {         i = (i+1) % chromsize ;         child[i] = pa[i] ;         }      } // If two point crossover}/*--------------------------------------------------------------------------------   mutate - apply the mutation operator to a single child--------------------------------------------------------------------------------*/static void mutate (   char *child ,   // Input/Output of the child   int chromsize , // Number of variables in objective function   double pmutate  // Probability of mutation   ){   while (chromsize--) {      if (unifrand() < pmutate)                          // Mutate this gene?         child[chromsize] ^= (char) 1 << (longrand() % 8) ;  // Flip random bit      }}/*--------------------------------------------------------------------------------   rand_ind - Randomly generate an individual's chromosome--------------------------------------------------------------------------------*/static void rand_ind ( char *popptr , int chromsize ){   while (chromsize--)      *popptr++ = 255 & longrand() ;}/*--------------------------------------------------------------------------------   decode - Decode the genes in this chromosome to the network weights.            In genetic parlance, convert the genotype to the phenotype.--------------------------------------------------------------------------------*/static void decode ( char *popptr , int nin , int nh1 , int nh2 ,                     double *w1 , double *w2 ){   int n ;   unsigned char gray, bit, parity, sum ;   double *wptr ;   if (! gray_initialized) {     // If the translation table has not yet      gray_initialized = 1 ;     // been built, do it now (but just once!)      for (n=0 ; n<256 ; n++) {  // Each gene is a one byte gray code         gray = (unsigned char) n ;         sum =  0 ;         bit = 128 ;         parity = 0 ;         while (bit) {            if (bit & gray)               parity = ! parity ;            if (parity)               sum |= bit ;            bit = bit >> 1 ;            }         gray_code_table[n] = sum ;         }      }   n = nh1 * (nin+1) ; // Do hid layer 1 first.  It has this many weights.   wptr = w1 ;         // Point to its weights   while (n--) {      gray = (unsigned char) *popptr++ ;  // The gene is a one byte gray code      *wptr++ = ((double) gray_code_table[gray] - 127.5) * .0392 ; // -5 to 5      }   if (nh2) {              // Do second hidden layer if any      n = nh2 * (nh1+1) ;      wptr = w2 ;      while (n--) {         gray = (unsigned char) *popptr++ ;         *wptr++ = ((double) gray_code_table[gray] - 127.5) * .0392 ;         }      }}

⌨️ 快捷键说明

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