Genetic Algorithm Example from Igor Book

I post this example here, because several people wrote to me that it is a bit lengthy and that it takes a long time to copy it from the book. So, here it is.... Because this example is implemented as a module, you have to copy it to a new, separate procedure window. If you try to use it in Igor's standard procedure window, the #pragma moduleName statement will give you trouble. Try various combinations of mutation rate and population size and see how long it takes until the genetic routine has solved the puzzle. The first argument gives the maximum number of generations after which the program terminates. Compare for example:

  • FindSecret#main(600)
  • FindSecret#main(600,mutationProb=0.1,individuals=100)

to explore how a deviation from the standard values changes the ability of the algorithm to solve the puzzle and find the secret word. More information can be found here.

#pragma moduleName = FindSecret

//----
//--There are other (better) methods for solving the task of
//--getting a 'secret' word. The genetic approach
//--is, however, very instructive from a
//--programmer's point of view. That is why it is done here.

static function main(generations,[mutationProb,individuals])

    variable generations
    variable mutationProb
    variable individuals
   
    mutationProb = (ParamIsDefault(mutationProb) ? 0.05 : mutationProb)
    individuals = (ParamIsDefault(individuals) ? 1000 : individuals)
     
    string secret = "Santa Claus is coming!"
    variable lengthSecret = strlen(secret)
    variable i,k,j
    variable parentIndex
    string gene =""
    string parentGenes = ""
   
    // make a two-dimensional text-wave to store the "genepool"
    // the first column stores a string with the individual's genes,
    // the second column stores the number of correct characters
    // "Santa Clerx" "8"
    // if the number of correct characters == lengthSecret
    // the solution was found!
       
    print "----------------------------------- Starting search!"
    print " "  
   
    //set up a genepool as a free (transient) 2D-textwave
   
    make /FREE /T /N=(individuals,2) GenePool
    wave /T gP = GenePool
   
    //
    // make the first generation
    //

    for (i=0; i<individuals; i++)
        gP[i][0]=""
        gP[i][1]="0"
        for (k=0; k<lengthSecret; k++)
           
            //get a random number between 30 and 127
            //and interpret it as ASCII code by using num2char
            //(0.5 + enoise(0.5)) generates a random number between 0 and 1
            //use floor for rounding to integer values
   
            gene = num2char(floor(30+97*(0.5+enoise(0.5))))
            gP[i][0] += gene
           
            //test if this newest gene is correct, if yes: increase score by one
            if(char2num(gene) == char2num(secret[k]))
                gP[i][1] = num2str( str2num( gP[i][1] ) + 1 )
            endif  
        endfor
    endfor
    SortColumns /A /R /KNDX=1 sortWaves=gP
   
    //sort by score, i.e., sort by number of correct characters
    //without '/A' 1,13,9 is sorted as 9,13,1
    //(sorting by the first character)
   
    //
    //now do the further generations
    //
   
    for (j=0; j<generations; j++)
   
        //leave the best 10% of the previous generation untouched
        //start the for loop at a higher i
       
        for (i=floor(0.1*individuals); i<individuals; i++)  
            gP[i][0]=""
            gP[i][1]="0"
           
            for (k=0; k<lengthSecret; k++)
               
                //allow a mutation with a certain probability
               
                if ( (0.5+enoise(0.5)) < mutationProb)
                    //draw again a random ASCII character
                    gene = num2char(floor(30+97*(0.5+enoise(0.5))))
                    gP[i][0] += gene
                   
                    if (GrepString(gene,secret[k]))
                        gP[i][1] = num2str( str2num( gP[i][1] ) + 1 )
                    endif  
                   
                else //no mutation
                    //pick a random individual from the best 10%
                    parentIndex = floor(0.1*individuals*(0.5+enoise(0.5)))
                    parentGenes = gP[parentIndex][0]
                    gP[i][0] += parentGenes[k]
                   
                    if (char2num(parentGenes[k])==char2num(secret[k]))
                        gP[i][1] = num2str(str2num(gP[i][1])+1)
                    endif  
                                       
                endif  //end mutation-choice

            endfor  //end loop over individual letters (genes)
        endfor //end loop over individuals (rows in genePool)


        SortColumns /A /R /KNDX=1 sortWaves=gP
       
        print "Generation",j+1,":", gP[0][0]   
       
        if (str2num(gP[0][1])==lengthSecret)
                print " "
                print "Puzzle solved! "
                break
        endif
    endfor  //end loop over further generations

end

Forum

Support

Gallery

Igor Pro 8

Learn More

Igor XOP Toolkit

Learn More

Igor NIDAQ Tools MX

Learn More