from individual_interface import * from random import * from math import * def distance(ville_1, ville_2) : return sqrt((ville_1[1]-ville_2[1])**2 + (ville_1[2]-ville_2[2])**2) class Ville(Individual_Interface): def __init__(self, villes): ''' create an Individual object, its genome value is randomly built. Initially score is not set. :param size: size of the genome :type size: int ''' self.__villes = villes.copy() super().__init__(len(villes)) def copy(self): ''' build a copy of self, the genome is a copy of self's genome :return: a new Individual which is a "clone" of self :rtype: an Individual object ''' copy = Ville(self.__size) copy.set_value(self.get_value()) return copy def init_value(self): ''' randomly initialize the genome value of self ''' alea = self.__villes shuffle(alea) return alea def cross_with(self, other): ''' perform a 1 point crossover between self and other, two new built individuals are returned :param other: the individual to croww with :type other: an Idnividual object :return: the two new Individuals built by 1 point crossover operation :rtype: 2-uple of individuals ''' value = self.get_value() other_value = other.get_value() pivot = randint (0, self.get_size()) test_1, test_2 = Ville(self.__villes), Ville(self.__villes) test_1.set_value(value[:pivot] + other_value[pivot:]) test_2.set_value(other_value[:pivot] + value[pivot:]) test_1.eliminer_doublons() test_2.eliminer_doublons() return (test_1, test_2) def mutate(self, probability): ''' apply mutation operation to self : each element of the geome sequence is randomly changed with given probabiliy side effect : self's genome is modified :param probability: the probability of mutation for every gene :type probability: float :UC: probability in [0,1[ ''' for gene in range(len(self.get_value())): proba = uniform(0, 1) if proba < probability : self.mutate_gene(gene) def mutate_gene(self, gene): temp = self.get_value() self.set_value(temp[:gene] + [choice(self.__villes)] + temp [gene+1:]) self.eliminer_doublons() def eliminer_doublons(self): dico = {} redondantes = self.get_value() liste_finale = [] for ville in redondantes : if ville[0] not in dico: liste_finale.append(ville) dico[ville[0]] = ville for el in self.__villes: if el[0] not in dico: liste_finale.append(el) self.set_value(liste_finale) def distance_totale(self): i = 0 total = 0 while i < self.get_size()-1 : total = total + distance(self.get_value()[i],self.get_value()[i+1]) i+=1 total = total + distance(self.get_value()[0],self.get_value()[-1]) return total