Task: Evolutionary algorithm


C++: #include <string>
#include <cstdlib>
#include <iostream>
#include <cassert>
#include <algorithm>
#include <vector>
#include <ctime>

std::string allowed_chars = " ABCDEFGHIJKLMNOPQRSTUVWXYZ";






class selection
{
public:
  
  
  
  
  static int fitness(std::string candidate)
  {
    assert(target.length() == candidate.length());

    int fitness_so_far = 0;

    for (int i = 0; i < target.length(); ++i)
    {
      int target_pos = allowed_chars.find(target[i]);
      int candidate_pos = allowed_chars.find(candidate[i]);
      int diff = std::abs(target_pos - candidate_pos);
      fitness_so_far -= std::min(diff, int(allowed_chars.length()) - diff);
    }

    return fitness_so_far;
  }

  
  static int target_length() { return target.length(); }
private:
  static std::string target;
};

std::string selection::target = "METHINKS IT IS LIKE A WEASEL";


void move_char(char& c, int distance)
{
  while (distance < 0)
    distance += allowed_chars.length();
  int char_pos = allowed_chars.find(c);
  c = allowed_chars[(char_pos + distance) % allowed_chars.length()];
}



std::string mutate(std::string parent, double mutation_rate)
{
  for (int i = 0; i < parent.length(); ++i)
    if (std::rand()/(RAND_MAX + 1.0) < mutation_rate)
    {
      int distance = std::rand() % 3 + 1;
      if(std::rand()%2 == 0)
        move_char(parent[i], distance);
      else
        move_char(parent[i], -distance);
    }
  return parent;
}



bool less_fit(std::string const& s1, std::string const& s2)
{
  return selection::fitness(s1) < selection::fitness(s2);
}

int main()
{
  int const C = 100;

  std::srand(time(0));

  std::string parent;
  for (int i = 0; i < selection::target_length(); ++i)
  {
    parent += allowed_chars[std::rand() % allowed_chars.length()];
  }

  int const initial_fitness = selection::fitness(parent);

  for(int fitness = initial_fitness;
      fitness < 0;
      fitness = selection::fitness(parent))
  {
    std::cout << parent << ": " << fitness << "\n";
    double const mutation_rate = 0.02 + (0.9*fitness)/initial_fitness;
    std::vector<std::string> childs;
    childs.reserve(C+1);

    childs.push_back(parent);
    for (int i = 0; i < C; ++i)
      childs.push_back(mutate(parent, mutation_rate));

    parent = *std::max_element(childs.begin(), childs.end(), less_fit);
  }
  std::cout << "final string: " << parent << "\n";
}









Fortran:  
 	module evolve_routines
 
 	implicit none
 	
 	
 	character(len=*),parameter :: targ = 'METHINKS IT IS LIKE A WEASEL'
 	
 	contains
 
 	
 
 	pure elemental function fitness(member) result(n)
 
 
 
 
 	
 	implicit none
 	integer :: n
 	character(len=*),intent(in) :: member
 	
 	integer :: i
 	
 	n=0
 	do i=1,len(targ)
 		n = n + abs( ichar(targ(i:i)) - ichar(member(i:i))  )
 	end do
 	
 
 	end function fitness
 
 	
 
 	pure elemental subroutine mutate(member,factor)
 
 
 
 	
 	implicit none
 	character(len=*),intent(inout) :: member   
 	real,intent(in) :: factor                  
 	
 	integer,parameter :: n_chars = 27	
 	character(len=n_chars),parameter :: chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ '
 	
 	real    :: rnd_val
 	integer :: i,j,n
 	
 	n = len(member)
 		
 	do i=1,n
 		rnd_val = rand()
 		if (rnd_val<=factor) then   
 			rnd_val = rand()
 			j = int(rnd_val*n_chars)+1   
 			member(i:i) = chars(j:j)
 		end if
 	end do
 	
 
	end subroutine mutate
 

 
 	end module evolve_routines
 
 
 
 	program evolve
 
 
 
 	use evolve_routines
 	
 	implicit none
 	
 	
 	integer,parameter :: seed = 12345             
 	integer,parameter :: max_iter = 10000         
 	integer,parameter :: population_size = 200    
 	real,parameter    :: factor = 0.04            
 	integer,parameter :: iprint = 5               
 	
 	
 	integer :: i,iter
 	integer,dimension(1) :: i_best
 	character(len=len(targ)),dimension(population_size) :: population
 	
 	
 	call srand(seed)
 	
 	
 	
 	population(1) = 'PACQXJB CQPWEYKSVDCIOUPKUOJY'  
 	iter=0
 		
 	write(*,'(A10,A30,A10)') 'iter','best','fitness'
 	write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
 		
 	do 
 	
 		iter = iter + 1 
 		
  		
 		if (mod(iter,iprint)==0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
		
 		
 		if ( iter>max_iter .or. fitness(population(1))==0 ) exit
 	
 		
 		population = population(1)	
 		do i=2,population_size
 			call mutate(population(i),factor)	
 		end do
 	
 		
 		
 		i_best = minloc(fitness(population))
 		population(1) = population(i_best(1))
 		 	
 	end do
 	
 	
 	if (mod(iter,iprint)/=0) write(*,'(I10,A30,I10)') iter,population(1),fitness(population(1))
 	 	
 	if (iter>max_iter) then
 		write(*,*) 'No solution found.'
 	else
 		write(*,*) 'Solution found.'
 	end if
 	
 
 	end program evolve