libfgen  0.1.15
Library for optimization using a genetic algorithm or particle swarm optimization
mutation.c
00001 
00002 /*
00003     mutation.c -- Genetic algorithm mutation implementation.
00004 
00005     fgen -- Library for optimization using a genetic algorithm or particle swarm optimization.
00006     Copyright 2012, Harm Hanemaaijer
00007 
00008     This file is part of fgen.
00009 
00010     fgen is free software: you can redistribute it and/or modify it
00011     under the terms of the GNU Lesser General Public License as published
00012     by the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     fgen is distributed in the hope that it will be useful, but WITHOUT
00016     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00017     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00018     License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public
00021     License along with fgen.  If not, see <http://www.gnu.org/licenses/>.
00022 
00023 */
00024 
00025 
00026 #include <stdlib.h>
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <math.h>
00030 #include <float.h>
00031 #include <pthread.h>
00032 #include "fgen.h"               /* General includes. */
00033 #include "parameters.h"
00034 #include "population.h"         /* Module includes. */
00035 #include "bitstring.h"
00036 #include "random.h"
00037 #include "win32_compat.h"
00038 
00039 #ifndef __GNUC__
00040 
00041 // Log-gamma code was taken from the following source:
00042 // Visit http://www.johndcook.com/stand_alone_code.html for the source of this code and more like it.
00043 
00044 double LogGamma(double x);
00045 
00046 static double Gamma
00047 (
00048     double x    // We require x > 0
00049 )
00050 {
00051 
00052     // Split the function domain into three intervals:
00053     // (0, 0.001), [0.001, 12), and (12, infinity)
00054 
00056     // First interval: (0, 0.001)
00057         //
00058         // For small x, 1/Gamma(x) has power series x + gamma x^2  - ...
00059         // So in this range, 1/Gamma(x) = x + gamma x^2 with error on the order of x^3.
00060         // The relative error over this interval is less than 6e-7.
00061 
00062         const double gamma = 0.577215664901532860606512090; // Euler's gamma constant
00063 
00064     if (x < 0.001)
00065         return 1.0/(x*(1.0 + gamma*x));
00066 
00068     // Second interval: [0.001, 12)
00069     
00070         if (x < 12.0)
00071     {
00072         // The algorithm directly approximates gamma over (1,2) and uses
00073         // reduction identities to reduce other arguments to this interval.
00074                 
00075                 double y = x;
00076         int n = 0;
00077         bool arg_was_less_than_one = (y < 1.0);
00078 
00079         // Add or subtract integers as necessary to bring y into (1,2)
00080         // Will correct for this below
00081         if (arg_was_less_than_one)
00082         {
00083             y += 1.0;
00084         }
00085         else
00086         {
00087             n = static_cast<int> (floor(y)) - 1;  // will use n later
00088             y -= n;
00089         }
00090 
00091         // numerator coefficients for approximation over the interval (1,2)
00092         static const double p[] =
00093         {
00094             -1.71618513886549492533811E+0,
00095              2.47656508055759199108314E+1,
00096             -3.79804256470945635097577E+2,
00097              6.29331155312818442661052E+2,
00098              8.66966202790413211295064E+2,
00099             -3.14512729688483675254357E+4,
00100             -3.61444134186911729807069E+4,
00101              6.64561438202405440627855E+4
00102         };
00103 
00104         // denominator coefficients for approximation over the interval (1,2)
00105         static const double q[] =
00106         {
00107             -3.08402300119738975254353E+1,
00108              3.15350626979604161529144E+2,
00109             -1.01515636749021914166146E+3,
00110             -3.10777167157231109440444E+3,
00111              2.25381184209801510330112E+4,
00112              4.75584627752788110767815E+3,
00113             -1.34659959864969306392456E+5,
00114             -1.15132259675553483497211E+5
00115         };
00116 
00117         double num = 0.0;
00118         double den = 1.0;
00119         int i;
00120 
00121         double z = y - 1;
00122         for (i = 0; i < 8; i++)
00123         {
00124             num = (num + p[i])*z;
00125             den = den*z + q[i];
00126         }
00127         double result = num/den + 1.0;
00128 
00129         // Apply correction if argument was not initially in (1,2)
00130         if (arg_was_less_than_one)
00131         {
00132             // Use identity gamma(z) = gamma(z+1)/z
00133             // The variable "result" now holds gamma of the original y + 1
00134             // Thus we use y-1 to get back the orginal y.
00135             result /= (y-1.0);
00136         }
00137         else
00138         {
00139             // Use the identity gamma(z+n) = z*(z+1)* ... *(z+n-1)*gamma(z)
00140             for (i = 0; i < n; i++)
00141                 result *= y++;
00142         }
00143 
00144                 return result;
00145     }
00146 
00148     // Third interval: [12, infinity)
00149 
00150     if (x > 171.624)
00151     {
00152                 // Correct answer too large to display. Force +infinity.
00153                 double temp = DBL_MAX;
00154 //              return temp*2.0;
00155                 return temp;
00156     }
00157 
00158     return exp(LogGamma(x));
00159 }
00160 
00161 static double LogGamma
00162 (
00163     double x    // x must be positive
00164 )
00165 {
00166 
00167     if (x < 12.0)
00168     {
00169         return log(fabs(Gamma(x)));
00170     }
00171 
00172         // Abramowitz and Stegun 6.1.41
00173     // Asymptotic series should be good to at least 11 or 12 figures
00174     // For error analysis, see Whittiker and Watson
00175     // A Course in Modern Analysis (1927), page 252
00176 
00177     static const double c[8] =
00178     {
00179                  1.0/12.0,
00180                 -1.0/360.0,
00181                 1.0/1260.0,
00182                 -1.0/1680.0,
00183                 1.0/1188.0,
00184                 -691.0/360360.0,
00185                 1.0/156.0,
00186                 -3617.0/122400.0
00187     };
00188     double z = 1.0/(x*x);
00189     double sum = c[7];
00190     for (int i=6; i >= 0; i--)
00191     {
00192         sum *= z;
00193         sum += c[i];
00194     }
00195     double series = sum/x;
00196 
00197     static const double halfLogTwoPi = 0.91893853320467274178032973640562;
00198     double logGamma = (x - 0.5)*log(x) - x + halfLogTwoPi + series;    
00199         return logGamma;
00200 }
00201 
00202 #define lgamma(x) LogGamma(x)
00203 
00204 #endif
00205 
00206 /* Avoid function calls to fgen_mutate_bit. */
00207 #define mutate_bit(bitstring, bitnumber) bitstring[bitnumber / 8] ^= 1 << (bitnumber & 7);
00208 
00209 static double BinomialCoefficient(int n, int k) {
00210         return exp(lgamma(n + 1) - lgamma(k + 1) - lgamma(n - k + 1));
00211 }
00212 
00213 /*
00214  * This function is called at the beginning of fgen_run and variants. It sets up an array of probabilities of
00215  * how many bits in an individual will be mutated.
00216  */
00217 
00218 void SetupFastMutationCumulativeChanceArray(FgenPopulation *pop) {
00219         if (pop->fast_mutation_cumulative_chance != NULL) {
00220                 // There is already a table present.
00221                 if (pop->mutation_probability_float == pop->fast_mutation_probability)
00222                         // We have already calculated the table for the right probability.
00223                         return;
00224                 // Otherwise, overwrite the existing table.
00225         }
00226         else
00227                 // There was no table yet.
00228                 pop->fast_mutation_cumulative_chance = (float *)malloc(pop->individual_size_in_bits * sizeof(float));
00229         /* Calculate the chance that one or more bits are mutated in an individual. Equal to one minus the */
00230         /* minus the chance that no bits are mutated. */
00231         pop->fast_mutation_cumulative_chance[0] =
00232                 1.0 - pow(1.0 - pop->mutation_probability_float, pop->individual_size_in_bits);
00233 //      printf("Probability %d bits or more mutated: %lf\n", 1, pop->fast_mutation_cumulative_chance[0]);
00234         for (int i = 1; i < pop->individual_size_in_bits; i++) {
00235                 /* Calculate the chance that exactly i bits are mutated in an individual. */
00236                 float f = BinomialCoefficient(pop->individual_size_in_bits, i) *
00237                         pow(pop->mutation_probability_float, i) *
00238                         pow(1.0 - pop->mutation_probability_float, pop->individual_size_in_bits - i);
00239                 if (isnan(f))
00240                         pop->fast_mutation_cumulative_chance[i] = 0;
00241                 else
00242                         /* Assign the chance that more than i bits are mutated. */
00243                         pop->fast_mutation_cumulative_chance[i] = pop->fast_mutation_cumulative_chance[i - 1] - f;
00244 //              printf("Probability %d bits or more mutated: %lf\n", i + 1, pop->fast_mutation_cumulative_chance[i]);
00245                 if (pop->fast_mutation_cumulative_chance[i] <= 0.000001) {
00246                         if (i < pop->individual_size_in_bits - 1)
00247                                 pop->fast_mutation_cumulative_chance[i + 1]  = 0;
00248 //                      printf("Probability %d bits or more mutated: %lf\n", i + 2,
00249 //                              pop->fast_mutation_cumulative_chance[i + 1]);
00250                         break;
00251                 }
00252         }
00253         pop->fast_mutation_probability = pop->mutation_probability_float;
00254 }
00255 
00256 static int NumberOfBitsToMutate(FgenPopulation *pop) {
00257         float f = fgen_random_f(pop->rng, 1.0);
00258         int n = 0;
00259         while (f < pop->fast_mutation_cumulative_chance[n])
00260                 n++;
00261         return n;
00262 }
00263 
00264 /*
00265  * This function performs the Mutation step of the genetic algorithm.
00266  */
00267 
00268 void DoMutation(FgenPopulation *pop) {
00269         int i;
00270         FgenIndividual **ind1 = pop->ind;
00271         FgenIndividual **ind2 = AllocatePopulation(pop);
00272         if (pop->fgen_mutation_func == fgen_mutation_per_bit_fast ||
00273         pop->fgen_mutation_func == fgen_mutation_per_bit_plus_macro_mutation_fast) {
00274                 for (i = 0; i < pop->size; i++) {
00275                         if ((pop->selection_type & FGEN_ELITIST_ELEMENT) && ind1[i]->is_elite) {
00276                                 ind2[i] = ind1[i];
00277                                 /* The following two lines of code have no net effect so can be omitted. */
00278                                 /* ind1[i]->refcount++; */
00279                                 /* FreeIndividual(ind1[i]); */
00280                                 continue;
00281                         }
00282                         int n = NumberOfBitsToMutate(pop);
00283                         if (n == 0 && pop->fgen_mutation_func == fgen_mutation_per_bit_fast)
00284                                 ind2[i] = ind1[i];
00285                         else {
00286                                 ind2[i] = NewIndividual(pop);
00287                                 CopyIndividualBitstring(pop, ind1[i], ind2[i]);
00288                                 pop->fast_mutation_nu_bits_to_mutate = n;
00289                                 pop->fgen_mutation_func(pop, ind1[i]->bitstring, ind2[i]->bitstring);
00290                                 FreeIndividual(ind1[i]);
00291                         }
00292                 }
00293         }
00294         else {
00295                 for (i = 0; i < pop->size; i++) {
00296                         if ((pop->selection_type & FGEN_ELITIST_ELEMENT) && ind1[i]->is_elite) {
00297                                 ind2[i] = ind1[i];
00298                                 /* The following two lines of code have no net effect so can be omitted. */
00299                                 /* ind1[i]->refcount++; */
00300                                 /* FreeIndividual(ind1[i]); */
00301                                 continue;
00302                         }
00303                         ind2[i] = NewIndividual(pop);
00304                         CopyIndividualBitstring(pop, ind1[i], ind2[i]);
00305                         pop->fgen_mutation_func(pop, ind1[i]->bitstring, ind2[i]->bitstring);
00306                         FreeIndividual(ind1[i]);
00307                 }
00308         }
00309         free(ind1);
00310         pop->ind = ind2;
00311 }
00312 
00317 void fgen_mutation_per_bit(FgenPopulation *pop, const unsigned char *parent, unsigned char *child) {
00318         int i;
00319         for (i = 0; i < pop->individual_size_in_bits; i++) {
00320                 int r = fgen_random_16(pop->rng);
00321                 if (r < pop->mutation_probability) {
00322                         /* Mutate the bit. */
00323                         mutate_bit(child, i);
00324                 }
00325         }
00326 }
00327 
00333 void fgen_mutation_per_bit_fast(FgenPopulation *pop, const unsigned char *parent, unsigned char *child) {
00334         int i;
00335         for (i = 0; i < pop->fast_mutation_nu_bits_to_mutate; i++) {
00336                 int r = fgen_random_n(pop->rng, pop->individual_size_in_bits);
00337                 mutate_bit(child, r);           
00338         }
00339 }
00340 
00346 void fgen_mutation_per_bit_plus_macro_mutation(FgenPopulation *pop, const unsigned char *parent,
00347 unsigned char *child) {
00348         fgen_mutation_per_bit(pop, parent, child);
00349         if (pop->macro_mutation_probability > 0) {
00350                 int i;
00351                 /* For each data element. */
00352                 int n = pop->individual_size_in_bits / pop->data_element_size;
00353                 for (i = 0; i < n; i++) {
00354                         int r = fgen_random_16(pop->rng);
00355                         if (r < pop->macro_mutation_probability)
00356                                 /* Mutate the entire data element with a random value */
00357                                 CreateRandomBitstring(pop->rng, child + i * pop->data_element_size / 8,
00358                                         pop->data_element_size / 8);
00359                 }
00360         }
00361 }
00362 
00369 void fgen_mutation_per_bit_plus_macro_mutation_fast(FgenPopulation *pop, const unsigned char *parent,
00370 unsigned char *child) {
00371         fgen_mutation_per_bit_fast(pop, parent, child);
00372         if (pop->macro_mutation_probability > 0) {
00373                 if (pop->data_element_size == 32) {
00374                         int n = pop->individual_size_in_bits / 32;
00375                         for (int i = 0; i < n; i++) {
00376                                 int r = fgen_random_16(pop->rng);
00377                                 if (r < pop->macro_mutation_probability)
00378                                         *(unsigned int *)&child[i * 4] = fgen_random_32(pop->rng);
00379                         }
00380                         return;
00381                 }
00382                 if (pop->data_element_size == 64) {
00383                         int n = pop->individual_size_in_bits / 32;
00384                         for (int i = 0; i < n; i += 2) {
00385                                 int r = fgen_random_16(pop->rng);
00386                                 if (r < pop->macro_mutation_probability) {
00387                                         *(unsigned int *)&child[i * 4] = fgen_random_32(pop->rng);
00388                                         *(unsigned int *)&child[i * 4 + 4] = fgen_random_32(pop->rng);
00389                                 }
00390                         }
00391                         return;
00392                 }
00393                 /* For each data element. */
00394                 int n = pop->individual_size_in_bits / pop->data_element_size;
00395                 for (int i = 0; i < n; i++) {
00396                         int r = fgen_random_16(pop->rng);
00397                         if (r < pop->macro_mutation_probability)
00398                                 /* Mutate the entire data element with a random value */
00399                                 CreateRandomBitstring(pop->rng, child + i * pop->data_element_size / 8,
00400                                         pop->data_element_size / 8);
00401                 }
00402         }
00403 }
00404 
00409 void fgen_mutation_permutation_swap(FgenPopulation *pop, const unsigned char *parent, unsigned char *child) {
00410         int index1, index2;
00411         int r = fgen_random_16(pop->rng);
00412         if (r >= pop->mutation_probability)
00413                 return;
00414         do {
00415                 index1 = fgen_random_n(pop->rng, pop->permutation_size);
00416                 index2 = fgen_random_n(pop->rng, pop->permutation_size);
00417         } while (index1 == index2);
00418         *(int *)&child[index1 * 4] = *(int *)&parent[index2 * 4];
00419         *(int *)&child[index2 * 4] = *(int *)&parent[index1 * 4];
00420 }
00421 
00427 void fgen_mutation_permutation_insert(FgenPopulation *pop, const unsigned char *parent, unsigned char *child) {
00428         int r = fgen_random_16(pop->rng);
00429         if (r >= pop->mutation_probability)
00430                 return;
00431         int index = fgen_random_n(pop->rng, pop->permutation_size);
00432         int index_dest = fgen_random_n(pop->rng, pop->permutation_size);
00433         if (index_dest < index) {
00434                 /* The destination of the element is to the left of its previous position. */
00435                 /* The first, unaltered part of the permutation was already copied into the child. */
00436                 /* The second part is the inserted element. */
00437                 *(int *)&child[index_dest * 4] = *(int *)&parent[index * 4];
00438                 /* The third part is the part of the parent up to the element location. */
00439                 memcpy(child + (index_dest + 1) * 4, parent + index_dest * 4, (index - index_dest) * 4);
00440                 /* The fourth, unaltered part of the permutation was already copied into the child. */
00441         }
00442         if (index_dest > index) {
00443                 /* The destination of the element is to the right of it previous position. */
00444                 /* The first, unaltered part of the permutation was already copied into the child. */
00445                 /* The second part is the part of the parent to the right of the element, up to destination location. */
00446                 memcpy(child + index * 4, parent + (index + 1) * 4, (index_dest - index) * 4);
00447                 /* The third part is the inserted element. */
00448                 *(int *)&child[index_dest * 4] = *(int *)&parent[index * 4];
00449                 /* The fourth, unaltered part of the permutation was already copied into the child. */
00450         }
00451         /* If the destination is the same as the source location, nothing happens (the child already contains a copy). */
00452 }
00453 
00458 void fgen_mutation_permutation_invert(FgenPopulation *pop, const unsigned char *parent, unsigned char *child) {
00459         int r = fgen_random_16(pop->rng);
00460         if (r >= pop->mutation_probability)
00461                 return;
00462         const int *p = (int *)parent;
00463         int *c = (int *)child;
00464         int index = fgen_random_n(pop->rng, pop->permutation_size);
00465         int max_size = pop->permutation_size - index;
00466         int size;
00467         if (max_size > 1)
00468                 size = fgen_random_n(pop->rng, max_size) + 1;
00469         else
00470                 size = 1;
00471         /* Invert the subroute. */
00472         for (int i = index; i < index + size; i++) {
00473                 c[i] = p[index + size - 1 - (i - index)];
00474         }
00475 }
00476 
00477 /*
00478  * Mutation, threaded version.
00479  * It is slower, and may not be safe. Not used at the moment.
00480  */
00481 
00482 typedef struct {
00483         FgenPopulation *pop;
00484         FgenIndividual **ind2;
00485         int start_index;
00486         int end_index;
00487 } ThreadData;
00488 
00489 void *DoMutationPartThread(void *threadarg) {
00490         ThreadData *thread_data = (ThreadData *)threadarg;
00491         FgenPopulation *pop = thread_data->pop;
00492         FgenIndividual **ind2 = thread_data->ind2;
00493         int start_index = thread_data->start_index;
00494         int end_index = thread_data->end_index;
00495         FgenIndividual **ind1 = pop->ind;
00496         int i;
00497         for (i = start_index; i < end_index; i++) {
00498                 if ((pop->selection_type & FGEN_ELITIST_ELEMENT) && ind1[i]->is_elite) {
00499                         ind2[i] = ind1[i];
00500                         ind1[i]->refcount++;    /* Is this safe? */
00501                         continue;
00502                 }
00503                 ind2[i] = NewIndividual(pop);
00504                 CopyIndividualBitstring(pop, ind1[i], ind2[i]);
00505                 pop->fgen_mutation_func(pop, ind1[i]->bitstring, ind2[i]->bitstring);
00506         }
00507         return NULL;
00508 }
00509 
00510 void DoMutationThreaded(FgenPopulation *pop) {
00511         ThreadData *thread_data;
00512         pthread_t *thread;
00513         int max_threads;
00514         FgenIndividual **ind2;
00515         int i;
00516         max_threads = 2;
00517         thread = (pthread_t *)malloc(sizeof(pthread_t) * max_threads);
00518         thread_data = (ThreadData *)malloc(sizeof(ThreadData) * max_threads);
00519         ind2 = AllocatePopulation(pop);
00520         /* Do the first half. */
00521         thread_data[0].pop = pop;
00522         thread_data[0].ind2 = ind2;
00523         thread_data[0].start_index = 0;
00524         thread_data[0].end_index = pop->size / 2;
00525         pthread_create(&thread[0], NULL, DoMutationPartThread, &thread_data[0]);
00526         /* Do the second half. */
00527         thread_data[1].pop = pop;
00528         thread_data[1].ind2 = ind2;
00529         thread_data[1].start_index = pop->size / 2;
00530         thread_data[1].end_index = pop->size;
00531         DoMutationPartThread(&thread_data[1]);
00532         pthread_join(thread[0], NULL);
00533         for (i = 0; i < pop->size; i++)
00534                 FreeIndividual(pop->ind[i]);
00535         free(thread_data);
00536         free(thread);
00537         free(pop->ind);
00538         pop->ind = ind2;
00539 }
00540 
 All Data Structures Functions Variables