Les algorithmes génétiques démystifiés 43: Économie, la population
Après avoir vu dernièrement l’énoncé du problème d’investissement que je me propose de résoudre à l’aide d’un algorithme génétique, on peut maintenant créer la population initiale.
Je me base sur le programme développé pour le problème du sac à dos disponible sur Github. Par contre, le code nécessite la version 2.1 de Ruby (disponible en preview2 à l’heure où j’écris ces lignes).
Tout d’abord la classe Individual, qui recueille toutes les informations
sur nos individus: chromosome, score et fitness.
class Individual
class << self
def random(items)
new(nil, items)
end
def from_chromosome(chromosome)
new(chromosome)
end
def listing(chromosome:, items:)
chromosome.map.with_index do |gene, index|
"#{gene} #{items[index].name}"
end.join("\n")
end
end
attr_accessor :score, :fitness
attr_reader :chromosome
def initialize(chromosome = nil, items = nil)
if chromosome
@chromosome = chromosome
else
@chromosome = []
items.each_with_index do |item, index|
@chromosome << rand(0..item.number)
end
end
end
private_class_method :new
def >(other)
return true if other.nil?
score > other.score
end
endJ’ai ajouté une méthode de classe listing:
def listing(chromosome:, items:)
chromosome.map.with_index do |gene, index|
"#{gene} #{items[index].name}"
end.join("\n")
endElle utilise les arguments nommés requis de Ruby 2.1 et prend en
paramêtre un chromosome et la liste des actions (Knapsack::ITEMS,
voir l’article précédent). Elle servira à afficher la liste des actions,
avec le nombre retenu pour chacune d’entres elles à la fin de l’algorithme.
Dans la méthode initialize, on peut voir comment je crée les chromosomes
de la population initiale:
else
@chromosome = []
items.each_with_index do |item, index|
@chromosome << rand(0..item.number)
end
enditems se réfère à la liste des actions (Knapsack::ITEMS). Un chromosome est
une liste de la même taille que items. Chaque gène (ou emplacement dans
la liste) est un nombre compris entre zéro et le nombre maximum d’actions
pour cette action particulière (voir encore une fois Knapsack::ITEMS).
Maintenant, pour la création de la population proprement dite, il n’y a rien de nouveau:
class Population < Array
def initialize(items, population_size)
population_size.times { self << Individual.random(items) }
end
def best
self.sort_by{|individual| individual.score}.last
end
endLa prochaine fois on verra l’évaluation…
À demain.