## Author: M. Turhan ÇOBAN
## Created: 2021-06-20
## genetic algorithm

function retval = genetic(fx,xmin,xmax,POPSIZE,MAXGENS,ngene,PXOVER,PMUTATION)
  N=64;
  N1 = 9223372036854775807;
  #    POPSIZE; //population size
	#    MAXGENS; //maximum number of generations;
	#    NVARS;   //number of independent variables of function
  #    ngene;        //number of genes in each variable
	#    PXOVER; probability of crossover;
  #    PMUTATION; proportion of mutated variables
  #    NBreeder; Number of survivors in a generation
  #    Best;  The best genotype1 in the population
  #    iBest   array no of the best
  #    Worst  The worst genotype1 in the population
  #    iWorst  array no of the worst
  #    Population[];
  g1=set_genetic(fx,xmin,xmax,POPSIZE,MAXGENS,ngene,PXOVER,PMUTATION);
  g2=set_genetic(fx,xmin,xmax,POPSIZE,MAXGENS,ngene,PXOVER,PMUTATION);
  # assume contant population size in each generation
  i1=1;
  i2=2;
    ## ======initilization    
  for i=1:g1.POPSIZE   ## ref 2
    for j=1:g1.POPSIZE  ## ref 3
      rand1=rand;
      rand2=rand;
      bool1=g1.genotype(i).RFitness>PXOVER;
      bool2=g1.genotype(i).RCFitness>rand1;
      bool3=g1.genotype(i).RCFitness>rand2;
      bool4=i~=i1;
      if  bool1 && bool2 
        i1=i;
        continue;
      endif
      if bool1 && bool3 && bool4
        i2=i;
        break;
      endif
     endfor  # j=1:g1.POPSIZE ref 3
     endfor   # i=1:g1.POPSIZE   ## ref 2
  ##================== external generation loop

  for ix=1:MAXGENS ## ref 1
    for i=1:g1.POPSIZE   ## ref 2
    for j=1:g1.POPSIZE   ## ref 3
   # fprintf("bool1 %i rand1 %i PXOVER %i RFitness %i RCFitness %i\n",bool1,rand1,PXOVER,g1.genotype(i).RFitness,g1.genotype(i).RCFitness);
   # cross correlation ==============
   b1= g1.genotype(i1).b;
   b2=g1.genotype(i2).b;
   # x1= binary_to_double(b1,xmin,xmax);
   # x2= binary_to_double(b2,xmin,xmax);
   for j=1:g1.ngene ##ref 4
     b3(j,:)=cross_over(b1(j,:),b2(j,:));
   endfor ## ref 4
   b4=b3;
   rand3=rand;
   # mutation ==================
   if rand3<PMUTATION
     b4=mutate(b3);
   endif
   for j=1:g1.ngene ##ref 4
     x4(1,j)=binary_to_double(b4(j,:),g1.xmin(1,j),g1.xmax(1,j));
   endfor ## ref 4
   g2.genotype(i).x=x4;
   for j=1:g2.ngene
     xx=double_to_binary(g2.genotype(i).x(1,j),g2.xmin(1,j),g2.xmax(1,j));
     g2.genotype(i).b(j,:)=xx;
   endfor
   g2.genotype(i).y=g2.f(g2.genotype(i).x);
   g2.genotype(i).RFitness=g2.genotype(i).y;
   g2.genotype(i).RCFitness=g2.genotype(i).y;  
  endfor    # i=1:g1.POPSIZE
  ## calculate RFitness and RCFitness ===========
    for i=1:POPSIZE
    maximum=-realmax;
    minimum=realmax;
     if g2.genotype(i).y>maximum
            maximum=g2.genotype(i).y;
            genetic1.Fbest=g2.genotype(i).y;
            genetic1.ibest=i;
     endif
     if g2.genotype(i).y<minimum
            minimum=g2.genotype(i).y;
            g2.Fworst=g2.genotype(i).y;
            g2.iworst=i;
     endif
    endfor    # i=1:g2.POPSIZE
  for i=1:POPSIZE
    g2.genotype(i).RFitness=(g2.genotype(i).y- g2.Fworst)/(g2.Fbest-g2.Fworst);
  endfor  # i=1:POPSIZE
    total=0.0;
   for i=1:POPSIZE
    g2.genotype(i).RFitness=(g2.genotype(i).y- g2.Fworst)/(g2.Fbest-g2.Fworst);
      total+=g2.genotype(i).RFitness;
    endfor  # i=1:POPSIZE 
    for i=1:POPSIZE
        if i==1 
        g2.genotype(i).RCFitness=g2.genotype(i).RFitness/total;
        else
        g2.genotype(i).RCFitness=g2.genotype(i-1).RCFitness+g2.genotype(i).RFitness/total;
      endif 
    endfor     
  g2.RFbest=g2.genotype( g2.ibest).RFitness;
  g2.RFworst=g2.genotype( g2.iworst).RFitness;
  ## Find best and worst
  g1=g2;
  [ix g1.genotype(g1.ibest).x g1.Fbest]

   endfor  # j=1:g1.POPSIZE ref 3
   endfor   # i=1:g1.POPSIZE   ## ref 2
   #endfor # ix=1:MAXGENS
  xx=g1.genotype(g1.ibest).x
  yy=g1.Fbest
  ##retval = [xx yy];  
endfunction