class Object

Public Instance Methods

bestSelection(population) click to toggle source
# File lib/gemetics.rb, line 159
def bestSelection(population)
        return population[0..1]
end
continue?(highestFitness, threshold, currentGen, options) click to toggle source

Internal Logic

# File lib/gemetics.rb, line 103
def continue?(highestFitness, threshold, currentGen, options)
        return false if exceedsThreshold?(options[:greaterBetter], highestFitness, threshold)
        return false if currentGen > options[:genMax]
        return true
end
default_GA_options() click to toggle source
# File lib/gemetics.rb, line 3
def default_GA_options()
  return {
        greaterBetter: true,
        totalPopReplace: true,
        genMax: 1000,
        selectionStyle: 'tournament',
        mutationPercent: 0.05,
        elitism: 0,
        debug: false,
        tournamentSize: 10,
  }
end
dependentOptionsWithinLimits(options, populationSize) click to toggle source
# File lib/gemetics.rb, line 235
def dependentOptionsWithinLimits(options, populationSize)
        if(options[:selectionStyle] == 'tournament')
                return false if !(options[:tournamentSize] > 0 && options[:tournamentSize] <= populationSize)
        end
        return true
end
exceedsThreshold?(greaterBetter, val, threshold) click to toggle source
# File lib/gemetics.rb, line 109
def exceedsThreshold?(greaterBetter, val, threshold)
        if(val == nil)
                return false
        end
        if(greaterBetter)
                return val>=threshold
        else
                return val<=threshold
        end
        return false
end
hasRequiredDependentOptions(options) click to toggle source
# File lib/gemetics.rb, line 213
def hasRequiredDependentOptions(options)
        if(options[:selectionStyle] == 'tournament')
                return false if !options.has_key?(:tournamentSize)
        end
        return true
end
hasRequiredOptions(options) click to toggle source
# File lib/gemetics.rb, line 202
def hasRequiredOptions(options)
        return false if !options.has_key?(:greaterBetter)
        return false if !options.has_key?(:totalPopReplace)
        return false if !options.has_key?(:selectionStyle)
        return false if !options.has_key?(:genMax)
        return false if !options.has_key?(:mutationPercent)
        return false if !options.has_key?(:debug)
        return false if !options.has_key?(:elitism)
        return true
end
mateOrgs(one, two) click to toggle source
# File lib/gemetics.rb, line 188
def mateOrgs(one, two)
        return one.mate(two)
end
rouletteSelection(population) click to toggle source
# File lib/gemetics.rb, line 163
def rouletteSelection(population)
        additiveFitness = 0.0
        for member in population
                additiveFitness += member.fitness
        end

        result = []
        for member in population
                if Random.new.rand() <= (member.fitness/additiveFitness)
                        result.push(member)
                        break
                end
        end
        
        for member in population
                if Random.new.rand() <= (member.fitness/additiveFitness)
                        result.push(member)
                        break
                end
        end

        result.push(population[0]) while result.size() < 2
        return result
end
runGeneticAlgorithm(initialPopulation, eval, threshold, options) click to toggle source
# File lib/gemetics.rb, line 16
def runGeneticAlgorithm(initialPopulation, eval, threshold, options)
        # make sure options is assigned
        if(options == nil)
                options = default_GA_options()
        end
        validOptions(options,initialPopulation.size()) # Raises error if options are not correct
        currentGen = 0
        bestCanidate = initialPopulation[0]
        population = initialPopulation
        while(continue?(bestCanidate.fitness, threshold, currentGen, options)) do
                # evaluate the population
                population = eval.call(population)

            if(options[:greaterBetter])
                        sortedPopulation = population.sort{ |x , y| y.fitness <=> x.fitness }
                else
                        sortedPopulation = population.sort{ |x , y| x.fitness <=> y.fitness }
                end
                bestCanidate = population[0].clone

                if(options[:debug])
               puts 'Best Canidate Soultion:'
               puts bestCanidate.inspect
                puts 'Current Generation:'
               puts currentGen
               puts 'Average Fitness:'
               cumulative = 0
               for org in population
                       cumulative += org.fitness
               end
               puts cumulative/population.size()
            end


                if(options[:totalPopReplace] == false)
                        # Do not replace every organism
                        mates = selection(sortedPopulation.clone(), options)

                        # mate and replace
                        results = mateOrgs(mates[0], mates[1])
                        replaced = []
                        if(options[:elitism] > 0)
                                population = sortedPopulation
                                for i in 0...options[:elitism]
                                  replaced.push(i)
                                end
                        end
                        for i in 0...results.size()
                                results[i].mutate() if Random.new.rand() < options[:mutationPercent]
                                temp = Random.new.rand(population.size())
                                while(replaced.include?(temp)) do
                                        temp = Random.new.rand(population.size())
                                end
                                replaced.push(temp)
                                population[replaced[-1]] = results[i]
                        end
                else
                        # Repalce every single organism
                        needed = population.size()
                        have = 0
                        newPopulation = Array.new(population.size(), GeneticObject.new)
                        if(options[:elitism] > 0)
                                for i in 0...options[:elitism]
                                  newPopulation[i] = sortedPopulation[i]
                                end
                        end
                        while have < needed do
                                mates = selection(sortedPopulation.clone(), options)

                                # mate and put them into new pop
                                results = mateOrgs(mates[0], mates[1])
                                for i in 0...results.size()
                                        results[i].mutate() if Random.new.rand() < options[:mutationPercent]
                                        newPopulation[have+i] = results[i] if (have+i) < needed
                                end
                                have += results.size()
                        end
                        population = newPopulation
                end
    # Increment generations
    currentGen += 1
        end
        return bestCanidate
end
selection(population, options) click to toggle source
# File lib/gemetics.rb, line 121
def selection(population, options)
        # select mates
        if(options[:selectionStyle] == 'tournament')
                return tournamentSelection(population, options[:tournamentSize])
        elsif(options[:selectionStyle] == 'best')
                return bestSelection(population)
        elsif(options[:selectionStyle] == 'roulette')
                return rouletteSelection(population)
        end
        raise 'Problem with selection type'
end
tournamentSelection(population, size) click to toggle source

Selection algorithms are based on population being sorted

# File lib/gemetics.rb, line 135
def tournamentSelection(population, size)
        population = population.shuffle
        subPop = population[0...size]
        additiveFitness = 0
        result = []
        for member in subPop
                additiveFitness += member.fitness
        end
        for member in subPop
                if Random.new.rand() <= (member.fitness/additiveFitness)
                        result.push(member)
                        break
                end
        end
        for member in subPop
                if Random.new.rand() <= (member.fitness/additiveFitness)
                        result.push(member)
                        break
                end
        end
        result.push(subPop[0]) while result.size() < 2
        return result
end
validOptions(options, populationSize) click to toggle source

Validation

# File lib/gemetics.rb, line 194
def validOptions(options, populationSize)
        raise 'Required Option Missing' if !hasRequiredOptions(options)
        raise 'Required Dependent Options Missing' if !hasRequiredDependentOptions(options)
        raise 'Options Not Within Limits' if !withinLimits(options, populationSize)
        raise 'Dependent Options Not Within Limits' if !dependentOptionsWithinLimits(options, populationSize)
        return true
end
withinLimits(options, populationSize) click to toggle source
# File lib/gemetics.rb, line 220
def withinLimits(options, populationSize)
        possibleGreaterBetter = [true, false]
        possibleTotalPopReplace = [true, false]
        possibleDebug = [true, false]
        possibleSelectionStyle = ['tournament', 'best', 'roulette']
        return false if !(possibleGreaterBetter.include?(options[:greaterBetter]))
        return false if !(possibleTotalPopReplace.include?(options[:totalPopReplace]))
        return false if !(options[:genMax]>0)
        return false if !(possibleSelectionStyle.include?(options[:selectionStyle]))
        return false if !(options[:mutationPercent]>0.0)
        return false if !(possibleDebug.include?(options[:debug]))
        return false if !(options[:elitism]>=0 && options[:elitism]<populationSize)
        return true
end