C-language implementation of genetic Algorithm (a): an example of solving the extremum with nonlinear function

Source: Internet
Author: User
Tags sin

Before the mathematical modeling, research (in fact, not a research, but probably understand) some artificial intelligence algorithms, such as the previously mentioned particle swarm optimization (PSO), but also the famous genetic algorithm (GA), simulated annealing algorithm (SA), Ant colony Algorithm (ACA) and so on. At that time know very shallow, only copy other people's code (usually matlab), change a value and parameters, patchwork took over, and did not understand the underlying principle of what it is. This period of time, I re-turned the then bought the "MATLAB Intelligent algorithm 30 Case analysis", reread again, found that this book is still very good, not only has the algorithm of the MATLAB implementation, and each algorithm of the implementation principle is basically clear, I look at the time, I didn't understand it before (maybe it was too quick) and now it's almost all figured out. It really makes me feel very happy ~ ~ ~ So I had an impulse to use now I am familiar with the C language, the book on the case of re-realization, thoroughly understand the principle of each algorithm. I'm going to update a few regularly to introduce some of these common intelligent algorithms and their applications (I will not only read this book, but also refer to other books and papers), as much as possible to understand the principles of each algorithm, but also as a summary of my exposure to these intelligent algorithms.

Today the genetic algorithm (genetic algorithm,ga) is introduced first.

Genetic algorithm is an evolutionary algorithm, the basic principle is to imitate the nature of the biological "natural selection, survival of the fittest" evolutionary law, the problem parameters encoded as chromosomes, and then use the iterative method of selection, crossover, mutation and other algorithms to exchange the information of chromosomes in the population, Eventually, the chromosomes that match the optimized target are generated.

In genetic algorithms, chromosomes correspond to data or arrays, usually represented by one-dimensional string structure data, and the values of the corresponding genes in each position of the string. A string of genes is a chromosome, or a genetic entity . A certain number of individuals constitute a population , the size of the population is called the size of the population, also known as the size of the population, and individual adaptation to the environment is called the degree of Fitness .

The steps of the standard genetic algorithm are as follows:

(1) Coding: Genetic algorithm before searching the solution space needs to represent the solution data into the genetic space of the genotype string structure data, the different combinations of these string structure data constitute a different chromosome.

(2) Initialization: The initial population is generated. The practice is to randomly generate n initial chromosomes (the solution of the solution space), each chromosome is actually equivalent to an individual, n individuals constitute an initial population. The genetic algorithm begins to evolve with these n individuals as initial values.

(3) Fitness Evaluation: Adaptability indicates the merits and demerits of individual or solution. Different problems, the way to define fitness functions is also different. For example, if the maximum value of a function is obtained, the greater the function value of a solution, the higher the fitness of the individual (solution).

(4) selection : The purpose of the selection is to select good individuals from the current population, so that they can become the parents of the next generation of children to reproduce. The genetic algorithm embodies this idea through the selection process, and the principle of selection is that the adaptable individual contributes one or more offspring to the next generation with great probability. This embodies Darwin's principle of survival of the fittest.

(5) Crossover: crossover operation is the most important genetic operation in genetic algorithm. A new generation of individuals can be obtained by crossing, and the individual characteristics of their parents are combined. The intersection embodies the idea of exchanging information.

(6) mutation : Mutation first randomly selects an individual in a group, for the selected individual with a certain probability (usually a relatively small probability, which is consistent with nature, nature's mutation is a small probability event) randomly changing the value of a gene in a chromosome.

Sometimes, in addition to choosing, crossing , and mutating These three operations, we also add other operations (such as reversals ) to specific issues, but select , Cross , mutation is a genetic operation in which all genetic algorithms are common.

In this paper, a common application of genetic algorithm-solving complex nonlinear function extremum problem as an example to illustrate how to use the code (here is the C language, of course, you can change any other language) to implement the above-mentioned genetic algorithm operation. The function of solving is from 30 case analysis of MATLAB intelligent algorithm, namely:

f = -5*sin (x1) *sin (x2) *sin (x3) *sin (x4) *sin (X5)-Sin (5*x1) *sin (5*x2) *sin (5*x3) *sin (5*x4) *sin (5*x5) + 8

Where x1,x2,x3,x4,x5 is the real number between 0~0.9*pi. The minimum value of the function is 2, which is obtained when the x1,x2,x3,x4,x5 is PI/2.

The solution code for the genetic algorithm using C language is as follows:

/* * Genetic algorithm to solve the optimal value problem of the function * Reference from the MATLAB intelligent Algorithm 30 Case Study * * The optimization function of this example is: F = -5*sin (x1) *sin (x2) *sin (x3) *sin (x4) *sin (X5)-Sin (5*x1) *sin (5 *X2) *sin (5*x3) *sin (5*x4) *sin (5*X5) + 8 * Where x1,x2,x3,x4,x5 is the real number between 0~0.9*pi. The minimum value of the function is 2, which is obtained when the x1,x2,x3,x4,x5 is PI/2. * Update in 16/12/3 * Author:lyrichu * email:[email protected] * * #include <stdio.h> #include <stdlib.h># include<math.h> #include <time.h> #define PI 3.1415926//PI # Sizepop 50//Population number # Maxgen 500//Evolutionary algebra #define PCROSS 0.6//crossover probability # Pmutation 0.1//mutation probability # define LENCHROM 5//Chromosome length # Bound_down 0//variable lower bound, because it's all the same, so Instead of a single value, if each variable has a different upper and lower bounds, it may be necessary to define a # define BOUND_UP (0.9*3.1415926)//upper bound double Chrom[sizepop][lenchrom] with an array. Population array double Fitness[sizepop]; The fitness of each individual of the population is double fitness_prob[sizepop]; The probability of each individual being selected (determined using the Roulette method) double Bestfitness[maxgen]; Optimal value per generation double Gbest_pos[lenchrom]; The position of the optimal value double average_best[maxgen+1]; Average optimal value per generation double gbest; All evolutionary optimal values of int gbest_index; Number of iterations to get the optimal value ordinal//target function double fit_func (double * arr) {   Double x1 = *arr;    Double x2 = * (arr+1);    Double x3 = * (arr+2);    Double x4 = * (arr+3);    Double x5 = * (arr+4); Double Func_result = -5*sin (x1) *sin (x2) *sin (x3) *sin (x4) *sin (X5)-Sin (5*x1) *sin (5*x2) *sin (5*x3) *sin (5*x4) *sin (5*x5)    + 8; return func_result;}    Sum function double sum (double * fitness) {double sum_fit = 0;    for (int i=0;i<sizepop;i++) Sum_fit + = * (fitness+i); return sum_fit;}    Minimum function double * min (double * fitness) {double min_fit = *fitness;    Double min_index = 0;    static double arr[2];            for (int i=1;i<sizepop;i++) {if (* (Fitness+i) < Min_fit) {min_fit = * (fitness+i);        Min_index = i;    }} arr[0] = Min_index;    ARR[1] = Min_fit; return arr;}            Population initialization void Init_chrom () {for (int. i=0;i<sizepop;i++) {for (int j=0;j<lenchrom;j++) {        CHROM[I][J] = bound_up* ((double) rand ())/rand_max); } Fitness[i] = Fit_func (Chrom[i]); Initialization fitness}}//Select operation VoiD Select (double Chrom[sizepop][lenchrom]) {int index[sizepop];        for (int i=0;i<sizepop;i++) {double * arr = chrom[i]; Fitness[i] = 1/(Fit_func (arr));    This example is to find the minimum value, the fitness is the reciprocal of the objective function, that is, the smaller the function value, the greater the degree of adaptability} double sum_fitness = 0;        for (int i=0;i<sizepop;i++) {sum_fitness + = fitness[i];//Fit sum} for (int i=0;i<sizepop;i++) {    Fitness_prob[i] = fitness[i]/sum_fitness; } for (int i=0;i<sizepop;i++) {Fitness[i] = 1/fitness[i];//restore function value} for (int i=0;i<sizepop;i++)/        /Sizepop Roulette {Double pick = (double) rand ())/rand_max;        while (pick < 0.0001) pick = (double) rand ())/rand_max;            for (int j=0;j<sizepop;j++) {pick = Pick-fitness_prob[j];                if (pick<=0) {index[i] = j;            Break }}} for (int i=0;i<sizepop;i++) {for (int j=0;j<lenchrom;j++) {ch rom[I][J] = Chrom[index[i]][j];    } Fitness[i] = Fitness[index[i]];        }}//crossover operation Void Cross (double chrom[sizepop][lenchrom]) {for (int i=0;i<sizepop;i++) {//randomly select two chromosomes to cross        Double pick1 = ((double) rand ())/rand_max;        Double Pick2 = ((double) rand ())/rand_max; int choice1 = (int) (pick1*sizepop);//The first randomly selected chromosome ordinal int choice2 = (int) (pick2*sizepop);//second chromosome ordinal while (Cho            Ice1 > Sizepop-1) {pick1 = (double) rand ())/rand_max; Choice1 = (int) (PICK1*SIZEPOP);            Prevents selection of locations over bounds} while (Choice2 > sizepop-1) {pick2 = (double) rand ())/rand_max;        Choice2 = (int) (PICK2*SIZEPOP);        The Double pick = ((double) rand ())/rand_max;//is used to determine whether to cross-operate if (Pick>pcross) continue; int flag = 0;            Determines whether the cross is valid for the token while (flag = = 0) {Double pick = (double) rand ())/rand_max;            int pos = (int) (PICK*LENCHROM); while (POS> lenchrom-1) {Double pick = (double) rand ())/rand_max; int pos = (int) (PICK*LENCHROM);            Processing out of Bounds}//crossover begins Double R = ((double) rand ())/rand_max;            Double v1 = Chrom[choice1][pos];            Double v2 = Chrom[choice2][pos];            Chrom[choice1][pos] = R*v2 + (1-r) *v1; Chrom[choice2][pos] = r*v1 + (1-r) *v2; Cross over if (Chrom[choice1][pos] >=bound_down && chrom[choice1][pos]<=bound_up && Chrom[cho Ice2][pos] >=bound_down && chrom[choice2][pos]<=bound_up) flag = 1; Cross valid, exit cross, otherwise continue next cross}}}//mutation operation void Mutation (double chrom[sizepop][lenchrom]) {for (int i=0;i<sizepop;i+        +) {Double pick = ((double) rand ())/rand_max;//Randomly select a chromosome to mutate int choice = (int) (PICK*SIZEPOP);            while (Choice > sizepop-1) {pick = (double) rand ())/rand_max; int choice = (int) (PICK*SIZEPOP); Handle subscript out of bounds} pick = (double) rand ())/rand_max;        Used to determine if the wheel is mutating if (pick>pmutation) continue;        Pick = (double) rand ())/rand_max;        int pos = (int) (PICK*LENCHROM);            while (pos > lenchrom-1) {pick = (double) rand ())/rand_max;        pos = (int) (PICK*LENCHROM);        } double v = chrom[i][pos];        Double V1 = v-bound_up;        Double v2 = bound_down-v;        Double R = ((double) rand ())/rand_max;        Double r1 = ((double) rand ())/rand_max;        if (r >= 0.5) Chrom[i][pos] = v-v1*r1* (* (double) i)/maxgen) * (n (double) i)/maxgen); else Chrom[i][pos] = v + v2*r1* ((double) i)/maxgen) * (n (double) i)/maxgen);    Note that the wording here does not cross the border, so only one mutation can be}}//main function int main (void) {time_t start,finish; start = Clock (); The program starts Timing srand ((unsigned) time (NULL)); Initializes a random number seed init_chrom ();    Initializes a population of double * best_fit_index = min (fitness); int best_index = (int) (*best_fit_index); gbest = * (best_fit_index+1);    Optimal value Gbest_index = 0; Average_best[0] = SUM (fitness)/sizepop;    Initial average optimal value for (int i=0;i<lenchrom;i++) gbest_pos[i] = Chrom[best_index][i];  Evolution begins for (int i=0;i<maxgen;i++) {select (Chrom);//Choose Cross (Chrom);//Crossover Mutation (Chrom);        Variant for (int j=0;j<sizepop;j++) {Fitness[j] = Fit_func (Chrom[j]);        } Double sum_fit = SUM (fitness); AVERAGE_BEST[I+1] = Sum_fit/sizepop;        Average optimal value double * arr = min (fitness);        Double new_best = * (arr+1); int new_best_index = (int) (*ARR);            New optimal value Sequence if (New_best < gbest) {gbest = New_best;            for (int j=0;j<lenchrom;j++) {Gbest_pos[j] = chrom[new_best_index][j];        } Gbest_index = i+1; }} finish = Clock ();    The program calculates the end of double duration = ((double) (Finish-start))/clocks_per_sec; printf ("Program Calculation time:%lf sec \ n.", DuratiON);    printf ("Genetic algorithm has evolved%d times, the optimal value is:%LF, the optimal value was obtained in%d generation, the average optimal value of this generation is%lf.\n", Maxgen,gbest,gbest_index,average_best[gbest_index]);    printf ("Where the best value is obtained (%LF,%LF,%LF,%LF,%LF). \ n", gbest_pos[0],gbest_pos[1],gbest_pos[2],gbest_pos[3],gbest_pos[4]); return 0;}

Description

(1) Here is the minimum value of the function, the smaller the number of individual fitness, so the reciprocal transformation is used here, that is, the fitness function f (x) is defined as the "F (x)" (x) is the target function value), so that the fitness function f (x), the greater the individual is better. (Of course we have guaranteed that f (x) is always a positive number)

(2) The choice operation is the classical roulette method, that is, each individual is selected as the parent's probability and fitness is proportional, the higher the degree of adaptability, the probability of being selected, set pi for the first individual is selected probability, then

pi=fi/(∑FI), Fi is a fitness function for the first individual.

(3) Cross operation: because the individual uses the real number coding, therefore the cross operation also uses the real number intersection method, the K chromosome AK and the first L chromosome AL in the first J position cross operation method is:

Akj=aij (1-b) +aijb; Alj=alj (1-b) +AKJB, where B is a random number between [0,1]. K,l,j are randomly generated, that is randomly selected two parents, and then randomly select a gene, according to the formula to complete the cross-operation.

(4) mutation Operation: the first of the individuals of the first J gene for mutation operation method is:

r>=0.5, aij=aij+ (Amax-aij) *f (g)

r<0.5, aij=aij+ (Amin-aij) *f (g)

Where Amax is the upper bound of the gene AIJ, Amin is the nether of AIJ, F (g) =r2* (1-g/gmax) 2,R2 is a random number between [0,1], G is the current number of iterations, Gmax is the maximum number of evolutions, and R is the random number between [0,1].

As you can see, when r>=0.5, AIJ change between AIJ and Amax; r<0.5, AIJ changes from Amin to AIJ. Such a function can actually construct more than one, to complete the operation of the mutation. As long as the randomness is met and the gene is guaranteed to be within the range of effective change.

I run the results under ubuntu16.04 using the GCC compiler as follows:

From the results, the number of population is 50, the evolutionary algebra is 500, The obtained optimal solution for 2.014102 is already very close to the actual optimal solution 2, of course, if the number of population is larger, such as 500, evolutionary algebra, such as 1000 generations, then the resulting results will be more accurate, the number of population is 500, the evolutionary algebra is 1000 when the optimal solution is as follows:

It can be seen that, after increasing the number of populations and increasing the evolutionary algebra, the optimal value changes from 2.014102 to 2.000189, which increases the two-bit compared to the original accuracy, but correspondingly, the program's running time increases significantly (from 0.08 seconds to about 2 seconds). Therefore, in the specific solution of complex problems (such as sometimes encountered dozens of of the function parameters), we must consider the optimal solution of the accuracy and complexity (operation time) These two aspects, after the trade-off, take the appropriate parameters to solve the problem.

Of course, this is just to solve the extremum problem of multivariate nonlinear function as an example to illustrate the specific implementation steps of genetic algorithm, the practical application of genetic algorithm is very extensive, not only can solve the complex function extremum, but also in the field of operations research and many other fields have a very wide range of applications, It is often combined with other intelligent algorithms or optimization algorithms to solve problems. I will discuss this later in more detail.

C-language implementation of genetic Algorithm (a): an example of solving the extremum with nonlinear function

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.