Da due giorni ormai mi sto rompendo la testa per far funzionare tutto in ruby, ma ottengo comportamenti sempre più imprevedibili... Questo dovrebbe essere un algoritmo genetico per evolvere delle funzioni che approssimino relazioni tra ennuple di valori e una loro immagine.
In sostanza, dati a, b, c, d, ..., y approssima f tale che f(a, b, c, d, ...) = y:
Il problema è che nelle 1450 generazioni la soluzione migliore è sempre la stessa, con una fitness orribile. Dopo vari studi, ho notato che compaiono soluzioni con fitness molto bassa, ma, non so perchè, scompaiono dopo poco tempo. Per evitare questo ho anche forzato l'inserimento delle migliori soluzioni nell'array finale:codice:#.... class GeneticEngine attr_accessor :population_size, :crossover_number, :mutation_probability, :max_depth, :elitism attr_accessor :values #array di array attr_reader :population def initialize() end def current_generation() return @current_generation end def generate_population() @population = Array.new() for i in (1..@population_size) do @population[i - 1] = Boid.create_random(@max_depth) @population[i - 1].evaluate_fitness(values) end @current_generation = 0 end def next_generation() @population.sort! { |x, y| x.fitness <=> y.fitness } best = @population[0..(@crossover_number-1)] 0.upto(@crossover_number - 1) do |i| @population.concat(Boid.crossover(@population[i * 2], @population[i * 2 + 1])) end @population.each { |boid| boid.evaluate_fitness(@values) } #@population.each { |boid| puts boid.fitness } #gets tmp_pop = Array.new() 0.upto(@population_size - 1) do |i| if @population[i].fitness >= Float::MAX then tmp_pop[i] = nil else tmp_pop[i] = @population[i] end end tmp_pop.compact! #elimina nil tmp_pop.sort! { |x, y| x.fitness <=> y.fitness } #tmp_pop.each { |boid| puts boid.fitness } #gets if tmp_pop.length > @population_size then tmp_pop = tmp_pop[0..(@population_size-1)] end tmp_pop.each { |boid| boid.attempt_mutation(@mutation_probability) } if tmp_pop.length < @population_size then (tmp_pop.length).upto(@population_size - 1) do |i| tmp_pop[i] = Boid.create_random(@max_depth) end end tmp_pop.each { |boid| boid.evaluate_fitness(@values) } minfit = (tmp_pop.min { |x, y| x.fitness <=> y.fitness }).fitness bestfit = (best.min { |x, y| x.fitness <=> y.fitness}).fitness if bestfit < minfit then tmp_pop[-(@crossover_number)..-1] = best end @population = tmp_pop @current_generation += 1 end def get_best_solution() return (@population.sort { |x, y| x.fitness <=> y.fitness })[0] end end g = GeneticEngine.new() g.population_size = 20 g.crossover_number = 5 g.mutation_probability = 0.7 g.max_depth = 1 g.values = [[1, 2], [2, 3], [3, 4]] g.generate_population() while (g.current_generation < 1450) do g.next_generation() #g.population.each { |x| puts "> " + x.expression.to_s(), " > " + x.fitness.to_s() } best = g.get_best_solution() if best then if best.fitness == 0 then break end if g.current_generation % 50 == 0 then puts "Generation " + g.current_generation.to_s() puts "Best solution: " + best.expression.to_s() puts "Fitness: " + best.fitness.to_s() end end end
Ma anche così le soluzioni con fitness bassa continuano a scomparire, e rimane sempre una funzione stupida che si impone sulle altre... Fino a non poco tempo fa, risultava addirittura che questa funzione rimpiazzasse tutte le altre (non si sa come). Qualcuno mi sa aiutare?codice:tmp_pop.each { |boid| boid.evaluate_fitness(@values) } minfit = (tmp_pop.min { |x, y| x.fitness <=> y.fitness }).fitness bestfit = (best.min { |x, y| x.fitness <=> y.fitness}).fitness if bestfit < minfit then tmp_pop[-(@crossover_number)..-1] = best end

Rispondi quotando