 ## Author: M. Turhan ÇOBAN
## Created: 2021-11-07
## Genetic optimisation using binary genes 0010011100101000111..
## genetic_opt

function [BestX BestY] =genetic_opt(iPOPSIZE,iMAXGENS,iNVARS,iPXOVER,iPMUTATION,fx,xmin,xmax)
# Maximizing a function
POPSIZE=iPOPSIZE;      ## population size
MAXGENS=iMAXGENS;      ## maximum number of generations;
NVARS=iNVARS  ;        ## number of independent variables of function
N=64;                  ## number of genes in each variable, number of variables
PXOVER=iPXOVER;        ## probability of crossover;
PMUTATION=iPMUTATION;  ## proportion of mutated variables
Generation=i;          ## Current generation number
NBreeder=0;            ## Number of survivors in a generation
Best=1;                ## The best genotype in the population
nBest=2;               ## next to  best genotype in the population
    ## fx : function to be aveluated
    ## xmin: minimum values of variables
    ## xmax: maximum values of variables
ngene=NVARS; ## number of genes(number of x) in each variable y(x)
##============= INITIAL ==================
## set initial population
total=0.0;
biggest=-realmax('double');
max=biggest;
min=-biggest;
# set initial population, find Best and next to best
for i=1:POPSIZE
 genotype(i)= set_random_genotype(fx,xmin,xmax,ngene,i);
 genotype1(i)= genotype(i);
 x1=genotype(i).y;
 if x1>max
   max=x1;
 endif
 if x1<min
   min=x1;
 endif
 if x1>biggest
   nBest=genotype(Best).no;
   Best=i;
   biggest=x1;
 endif
 total=total+genotype(i).y;
endfor
# set normalised RFitness (0-1 ) each
# set cumulative normalised (0-1) total
for i=1:POPSIZE
 xx=genotype(i).y;
 genotype(i).RFitness= (xx-min)/(max-min);
 if i==1
   genotype(i).RCFitness= xx/total;
 else
   genotype(i).RCFitness=genotype(i-1).RCFitness+xx/total;
 endif
endfor
## printf('original pupulation \n');
## for i=1:POPSIZE
##  printf('%i %d %d %d \n',i,xx,genotype(i).y);
## endfor 
##================= GENERATIONS ================================
## initial population set is finished
## now iterate for MAXGENS maximum number of generations
for mng=1:MAXGENS
## create new generations
    ##  retain BEst and second best in the list
genotype1(1)=genotype(Best);
genotype1(2)=genotype(nBest);
for w=3:POPSIZE
    ## get parent # 1
    while 1
       n1=int8(POPSIZE*rand);
       if n1==0  
         n1=1;
       endif
       xxx=genotype(n1).RFitness;
       if xxx>PXOVER
         break;
       endif
    endwhile
    ## get parent # 2
    while 1 
       n2=int8(POPSIZE*rand);
       if n2==0  
         n2=1; 
       endif
       xxx=genotype(n2).RFitness;
       if xxx>PXOVER
         break;
       endif
    endwhile
    ## now cross corrolate parents to create a child
    for k=1:NVARS
      bb1=cross_over(genotype(n1).b(k,:),genotype(n2).b(k,:));
      ## There are some mutation possibility in here
      if rand<PMUTATION
        bb2=mutate(bb1);
      else
        bb2=bb1;
      end
      b3(k,:)=bb2;
    endfor
    x3=binary_to_double(b3,xmin,xmax);
    x3(1,:);
    x4=x3(1,:);
    genotype1(w).x=x4;
    genotype1(w).b=b3;
    y4=genotype1(w).y=fx(x4);
endfor 
## new generation is created now replace old generation with he new ones

total=0.0;
biggest=-realmax('double');
max=biggest;
min=-biggest;
# set population, find Best and next to best
for i=1:POPSIZE
 genotype(i).x= genotype1(i).x;
 genotype(i).y= genotype1(i).y;
 genotype(i).no= genotype1(i).no;
 genotype(i).xmin= genotype1(i).xmin;
 genotype(i).xmax= genotype1(i).xmax;
 genotype(i).f= genotype1(i).f;
 x1=genotype(i).y;
 if x1>max
   max=x1;
 endif
 if x1<min
   min=x1;
 endif
 if x1>biggest
   nBest=genotype(Best).no;
   Best=i;
   biggest=x1;
 endif
 total=total+genotype(i).y;
endfor
# set normalised RFitness (0-1 ) each
# set cumulative normalised (0-1) total
for i=1:POPSIZE
 xx=genotype(i).y;
 genotype(i).RFitness= (xx-min)/(max-min);
 if i==1
   genotype(i).RCFitness= xx/total;
 else
   genotype(i).RCFitness=genotype(i-1).RCFitness+xx/total;
 endif

endfor # for i=1:POPSIZE
## printf('%i generation %i population \n',mng);
##  for i=1:POPSIZE
##  printf('%i %d %d %d \n',i,xx ,genotype(i).y);
## endfor 

endfor # for mng=1:MAXGENS 
BestX=genotype(Best).x;
BestY=genotype(Best).y;  
endfunction
