diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6ff5f5a98092a23fdd0b88d61529be1f32fa19b0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.pyc +__pycache__/ +*.png \ No newline at end of file diff --git a/RotTable.py b/RotTable.py index 3d9a88fe9f137cfbed43954895bb74eed387bce1..9f841efe35b5e7de98443db1b6948ec1a040ef33 100644 --- a/RotTable.py +++ b/RotTable.py @@ -21,9 +21,40 @@ class RotTable: "TA": [36, 0.9, 0, 1.1, 2, 0],\ "TC": [36.9, 5.3, -120, 0.9, 6, 0],\ "TG": [34.5, 3.5, 64, 0.9, 34, 0],\ - "TT": [35.62, 7.2, -154, 0.06, 0.6, 0]\ + "TT": [35.62, 7.2, 154, 0.06, 0.6, 0]\ } + __CORRESPONDANCE = {\ + "AA": "TT",\ + "AC": "GT",\ + "AG": "CT",\ + "AT": "AT",\ + "CA": "TG",\ + "CC": "GG",\ + "CG": "CG",\ + "CT": "AG",\ + "GA": "TC",\ + "GC": "GC",\ + "GG": "CC",\ + "GT": "AC",\ + "TA": "TA",\ + "TC": "GA",\ + "TG": "CA",\ + "TT": "AA"\ + } + + __SOUS_CORRESPONDANCE = {\ + "AA": "TT",\ + "AC": "GT",\ + "AG": "CT",\ + "AT": "AT",\ + "CA": "TG",\ + "CC": "GG",\ + "CG": "CG",\ + "GA": "TC",\ + "GC": "GC",\ + "TA": "TA"\ + } # get the angles in each axis (x, y, z), considering the deviation def __init__(self): self.rot_table = {} @@ -34,13 +65,18 @@ class RotTable: # get a random deviation, considering the "limits" given in the last 3 columns # of __ORIGINAL_ROT_TABLE def alea(self): - for dinucleotide in RotTable.__ORIGINAL_ROT_TABLE: + for dinucleotide in RotTable.__SOUS_CORRESPONDANCE: for i in range(2): - self.rot_table[dinucleotide][i] += numpy.random.uniform(low = -RotTable.__ORIGINAL_ROT_TABLE[dinucleotide][i+3], high= RotTable.__ORIGINAL_ROT_TABLE[dinucleotide][i+3]) + delta = numpy.random.uniform(low = -RotTable.__ORIGINAL_ROT_TABLE[dinucleotide][i+3], high= RotTable.__ORIGINAL_ROT_TABLE[dinucleotide][i+3]) + self.rot_table[dinucleotide][i] += delta + self.rot_table[RotTable.__SOUS_CORRESPONDANCE[dinucleotide]][i] += delta # return __ORIGINAL_ROT_TABLE def orta(self): return self.__ORIGINAL_ROT_TABLE + + def corr(self): + return self.__CORRESPONDANCE ################### # WRITING METHODS # @@ -66,3 +102,4 @@ class RotTable: #table1 = RotTable() #print(table1.orta()) +# print(table1.rot_table) diff --git a/__pycache__/RotTable.cpython-37.pyc b/__pycache__/RotTable.cpython-37.pyc index 77ac689bc55b7a2da3f537139c1edf0282d17f75..e6bef50c3581cf2f06a53777c7291030d276cecd 100644 Binary files a/__pycache__/RotTable.cpython-37.pyc and b/__pycache__/RotTable.cpython-37.pyc differ diff --git a/__pycache__/Traj3D.cpython-37.pyc b/__pycache__/Traj3D.cpython-37.pyc index f7109d9eed1cccc1d2977773da0f78ab514515c7..865cc612f429be0814ee850289aa455b69755f50 100644 Binary files a/__pycache__/Traj3D.cpython-37.pyc and b/__pycache__/Traj3D.cpython-37.pyc differ diff --git a/algogenetique.py b/algogenetique.py new file mode 100644 index 0000000000000000000000000000000000000000..cbcde6366a75846200845f298aabc3b3588fda1c --- /dev/null +++ b/algogenetique.py @@ -0,0 +1,45 @@ +import mathutils +import math +import numpy +import RotTable +from individu import Individu +from population import Population, afficher +import croisement +from Traj3D import * +from random import random +import matplotlib.pyplot as plt + + + +def main(N,tmax,pmutation, proportion,brin="plasmid_8k.fasta"): + '''lineList = [line.rstrip('\n') for line in open(brin)] + brin = ''.join(lineList[1:])''' + L=[] + People=Population(N) + # afficher(People) + for i in range(tmax): + print("\n \n NOUVELLE GENERATION \n \n") + max=0 + best=None + for individu in People.indiv: + individu.evaluate("AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAA") + People.reproduction(p = proportion, proba_mutation= pmutation) + # for individu in People.indiv: + # individu.mutation(pmutation) + for individu in People.indiv: + individu.evaluate("AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAA") + if individu.score>max: + best=individu + max=individu.score + afficher(People) + L.append(max) + #print(L) + plt.plot([i for i in range(tmax)], L) + plt.show() + return(best) + + +main(10,50,0,5) + + + diff --git a/croisement.py b/croisement.py index a59546f35101170f94063bcc93992754ca4c402a..96f85a8a89e1dcaa97cbed0f06233942ee36f211 100644 --- a/croisement.py +++ b/croisement.py @@ -1,5 +1,6 @@ import numpy from RotTable import RotTable +from individu import Individu ROT_TABLE = {\ "AA": [35.62, 7.2, -154, 0.06, 0.6, 0],\ @@ -22,33 +23,74 @@ ROT_TABLE = {\ def croisement_un_point(parent1, parent2): - enfant1 = RotTable() - enfant2 = RotTable() + enfant1 = Individu(RotTable()) + enfant2 = Individu(RotTable()) comp = 0 - point_crois= numpy.random.random_integers(0,16) + point_crois= numpy.random.random_integers(0,8) for doublet in ROT_TABLE: + if doublet == "GA": + break if comp < point_crois: - enfant1.rot_table[doublet] = parent1.rot_table[doublet] - enfant2.rot_table[doublet] = parent2.rot_table[doublet] + enfant1.table.rot_table[doublet] = parent1.table.rot_table[doublet] + correspondent_doublet1 = enfant1.table.corr()[doublet] + enfant1.table.rot_table[correspondent_doublet1] = parent1.table.rot_table[correspondent_doublet1] + enfant1.table.rot_table[correspondent_doublet1][2] *= -1 + + enfant2.table.rot_table[doublet] = parent2.table.rot_table[doublet] + correspondent_doublet2 = enfant2.table.corr()[doublet] + enfant2.table.rot_table[correspondent_doublet2] = parent2.table.rot_table[correspondent_doublet2] + enfant2.table.rot_table[correspondent_doublet2][2] *= -1 + else : - enfant1.rot_table[doublet] = parent2.rot_table[doublet] - enfant2.rot_table[doublet] = parent1.rot_table[doublet] + enfant1.table.rot_table[doublet] = parent2.table.rot_table[doublet] + correspondent_doublet1 = enfant1.table.corr()[doublet] + enfant1.table.rot_table[correspondent_doublet1] = parent2.table.rot_table[correspondent_doublet1] + enfant1.table.rot_table[correspondent_doublet1][2] *= -1 + + enfant2.table.rot_table[doublet] = parent1.table.rot_table[doublet] + correspondent_doublet2 = enfant2.table.corr()[doublet] + enfant2.table.rot_table[correspondent_doublet2] = parent1.table.rot_table[correspondent_doublet1] + enfant2.table.rot_table[correspondent_doublet2][2] *= -1 + comp += 1 return enfant1, enfant2 def croisement_deux_points(parent1, parent2): - enfant1 = RotTable() - enfant2 = RotTable() + enfant1 = Individu(RotTable()) + enfant2 = Individu(RotTable()) comp = 0 - point_crois1= numpy.random.random_integers(0,16) - point_crois2= numpy.random.random_integers(0,16) + point_crois1= numpy.random.random_integers(0,8) + point_crois2= numpy.random.random_integers(0,8) for doublet in ROT_TABLE: if comp < min(point_crois1,point_crois2) or comp > max(point_crois1,point_crois2): - enfant1.rot_table[doublet] = parent1.rot_table[doublet] - enfant2.rot_table[doublet] = parent2.rot_table[doublet] + enfant1.table.rot_table[doublet] = parent1.table.rot_table[doublet] + correspondent_doublet1 = enfant1.table.corr()[doublet] + enfant1.table.rot_table[correspondent_doublet1] = parent1.table.rot_table[correspondent_doublet1] + enfant1.table.rot_table[correspondent_doublet1][2] *= -1 + + enfant2.table.rot_table[doublet] = parent2.table.rot_table[doublet] + correspondent_doublet2 = enfant2.table.corr()[doublet] + enfant2.table.rot_table[correspondent_doublet2] = parent2.table.rot_table[correspondent_doublet2] + enfant2.table.rot_table[correspondent_doublet2][2] *= -1 + else : - enfant1.rot_table[doublet] = parent2.rot_table[doublet] - enfant2.rot_table[doublet] = parent1.rot_table[doublet] + enfant1.table.rot_table[doublet] = parent2.table.rot_table[doublet] + correspondent_doublet1 = enfant1.table.corr()[doublet] + enfant1.table.rot_table[correspondent_doublet1] = parent2.table.rot_table[correspondent_doublet1] + enfant1.table.rot_table[correspondent_doublet1][2] *= -1 + + enfant2.table.rot_table[doublet] = parent1.table.rot_table[doublet] + correspondent_doublet2 = enfant2.table.corr()[doublet] + enfant2.table.rot_table[correspondent_doublet2] = parent1.table.rot_table[correspondent_doublet1] + enfant2.table.rot_table[correspondent_doublet2][2] *= -1 comp += 1 - return enfant1, enfant2 \ No newline at end of file + return enfant1, enfant2 + +# parent1 = Individu(RotTable()) +# parent2 = Individu(RotTable()) +# print("parent1: ", parent1.table.rot_table) +# print("parent2: ", parent2.table.rot_table) +# enfant1, enfant2 = croisement_un_point(parent1, parent2) +# print("enfant1: ", enfant1.table.rot_table) +# print("enfant2: ", enfant2.table.rot_table) \ No newline at end of file diff --git a/individu.py b/individu.py index 4653a5885ebb8c68d1ee001ce65ef39b2a736954..fbc09a35d5937ef2e9593154befc0f2a22a7f9cc 100644 --- a/individu.py +++ b/individu.py @@ -1,10 +1,15 @@ from RotTable import RotTable -from Traj3D import * +from Traj3D import Traj3D import numpy as np from math import sqrt +from random import random + +P1 = 0.015 class Individu(): + + def __init__(self, table): self.table = table self.score = None @@ -21,15 +26,38 @@ class Individu(): distance = sqrt(sum((first_nucleotide - last_nucleotide) ** 2)) diff_ideal_distance = abs(3.38 - distance) - self.score = 1/(diff_ideal_distance ) - - - def mutation(self): - mutation = 0 - return mutation - -table = RotTable() -test = Individu(table) -test.evaluate("AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAA") -print(table.rot_table) -print(test.score) + first_name = brin[0] + last_name = brin[-1] + + #rot_computed = self.table.rot_table[last_name+first_name] + #rot_traj = first_nucleotide - last_nucleotide + # print(rot_traj) + # print(rot_computed) + #diff_angle = sum(abs(rot_computed - rot_traj)) + + self.score = 1/distance + + + def mutation(self, proba = P1): + table_rotations = self.table.rot_table + for doublet in table_rotations : + for coord in range(3): + tir = random() + if tir < proba : + table_rotations[doublet][coord] =np.random.uniform(low = self.table.orta()[doublet][coord] - self.table.orta()[doublet][coord + 3], high = self.table.orta()[doublet][coord] + self.table.orta()[doublet][coord + 3]) + doublet2 = self.table.corr()[doublet] + if coord == 0 or coord == 1 : + table_rotations[doublet2][coord] = table_rotations[doublet][coord] + else : + #sur l'axe z il y a un moins + table_rotations[doublet2][coord] = - table_rotations[doublet][coord] + + +# individu1 = Individu(RotTable()) +# print(individu1.table.rot_table) +# individu1.mutation() + +# table = RotTable() +# test = Individu(table) +# test.evaluate("AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAA") +# print(test.score) diff --git a/population.py b/population.py new file mode 100644 index 0000000000000000000000000000000000000000..dc51f8c876c286ad1822991da190f5dcf3804b40 --- /dev/null +++ b/population.py @@ -0,0 +1,184 @@ +import random +from random import random, randint, randrange +from individu import Individu +from RotTable import RotTable +from croisement import croisement_un_point, croisement_deux_points + +class Population: + def __init__(self,n): + self.indiv=[Individu(RotTable()) for k in range (n)] + self.n = n + + def modifier_population(self, liste_individus): + """Fonction qui renvoie une nouvelle instance de population a partir d'une liste d'individus""" + self.n = len(liste_individus) + self.indiv = liste_individus + return self + + def selection_duel_pondere(self,p=None): + if p == None : + p = (self.n)//2 + newself=[] + vu=set() + m=randrange(0,self.n) + t=randrange(0,self.n) #méthode des duels pondérée: si x=10 et y=1, y a une chance sur 11 de passer + while len(newself)<p: + while m in vu: + m=randrange(0,self.n) + while t in vu: + t=randrange(0,self.n) + x=self.indiv[m] + y=self.indiv[t] + vu.add(t) + vu.add(m) + p=random() + if p>x.score/(x.score+y.score): + newself.append(y) + else: + newself.append(x) + + self = self.modifier_population(newself) + + def selection_duel(self,p=None): + if p == None : + p = (self.n)//2 + meilleur = self.indiv[0] + for individu in self.indiv : + if meilleur.score < individu.score: + meilleur = individu + newself = [meilleur] + print("\n \n \nmeilleur", meilleur.table.rot_table, "\n \nscore", meilleur.score) + vu=set() + t=randrange(0,self.n) + m=randrange(0,self.n) + while len(newself)<p: + while m in vu: + m=randrange(0,self.n) + while t in vu: + t=randrange(0,self.n) + x=self.indiv[m] + y=self.indiv[t] + vu.add(t) + vu.add(m) + if x.score>=y.score: + newself.append(x) + else: + newself.append(y) + self = self.modifier_population(newself) + + def selection_par_rang(self,p = None): + if p == None : + p = (self.n)//2 + liste_individus = self.indiv + n = self.n + + def echanger(tableau, i, j): + tableau[i], tableau[j] = tableau[j], tableau[i] + + def partitionner(tableau,debut,fin): + echanger(tableau,debut,randint(debut,fin-1)) + partition=debut + for i in range(debut+1,fin): + # if tableau[i] < tableau[debut]: + if tableau[i].score<tableau[debut].score: + partition+=1 + echanger(tableau,i,partition) + echanger(tableau,debut,partition) + return partition + + def tri_rapide_aux(tableau,debut,fin): + if debut < fin-1: + positionPivot=partitionner(tableau,debut,fin) + tri_rapide_aux(tableau,debut,positionPivot) + tri_rapide_aux(tableau,positionPivot+1,fin) + + def tri_rapide(tableau): + tri_rapide_aux(tableau,0,len(tableau)) + + tri_rapide(liste_individus) + individus_selectionnes = [] + + for _ in range(p): + curseur = random()*n*(n+1)/2 + # print("curseur", curseur) + j = 1 + while j*(j+1)/2 < curseur : + j+=1 + #on doit prendre l'individu avec le jème score + # print("individus selectionés", individus_selectionnes) + individus_selectionnes.append(liste_individus[j-1]) + + self = self.modifier_population(individus_selectionnes) + + def selection_proportionelle(self,p= None): + if p == None : + p = (self.n)//2 + newself=[] + somme=0 + for indiv in self.indiv: + somme=somme+indiv.score + while len(newself)<p: + m=m=randrange(0, self.n) + x=self.indiv[m] + p=random() + if p<=x.score/somme: + newself.append(x) + self = self.modifier_population(newself) + + def reproduction(self,proba_mutation = None, selection=None,enfant=croisement_un_point, p = None): + if proba_mutation == None : + proba_mutation = 0.001 + if selection == None : + selection = self.selection_duel + if p == None : + p = (self.n)//2 + vieille_taille = self.n + selection(p) + newself = list(self.indiv) + while len(newself)<vieille_taille: + m=randrange(0,self.n) + t=randrange(0,self.n) + x=newself[m] + y=newself[t] + couple_enfant = enfant(x,y) + for child in couple_enfant : + child.mutation(proba_mutation) + newself.append(couple_enfant[0]) + newself.append(couple_enfant[1]) + self = self.modifier_population(newself) + +def afficher(popu): + for individu in popu.indiv : + print("\n individu \n") + print(individu.table.rot_table) + print ("score", individu.score) + +def test(): + popu = Population(4) + print("\n POPULATION INITIALE \n") + for individu in popu.indiv : + individu.evaluate("AAAGGATCTTCTTGAGATCCTTTTTTTCTGCGCGTAATCTGCTGCCAGTAAACGAAAAAACCGCCTGGGGAGGCGGTTTAGTCGAA") + afficher(popu) + popu.reproduction(selection = popu.selection_duel) + print("\n REPRODUCTION \n") + afficher(popu) + +#test() + + + + + + + + + + + + + + + + + + diff --git a/test.py b/test.py deleted file mode 100644 index c1a1a413240574732ee27affacd13bb894d49c11..0000000000000000000000000000000000000000 --- a/test.py +++ /dev/null @@ -1,138 +0,0 @@ -import random - -class Population: - def __init__(self,n): - self.indiv=[Individu(rot_table.alea) for k in range (n)] - self.n = n - - def selection_duel_pondere(self,p=(self.n)//2): - newself=[] - vu={} - m=None - t=None #méthode des duels pondérée: si x=10 et y=1, y a une chance sur 11 de passer - while len(newself)<p: - while m in vu: - m=random.randrange(0,len(self)) - while t in vu: - t=random.randrange(0,len(self)) - x=self[m] - y=self[t] - vu.add(t) - vu.add(m) - p=uniform(0,1) - if p>x.score/(x.score+y.score): - newself.append(y) - else: - newself.append(x) - - return(newself) - - def selection_duel(self,p=(self.n)//2): - newself=[] - vu={} - t=None - m=None - while len(newself)<p: - while m in vu: - m=random.randrange(0,len(self)) - while t in vu: - t=random.randrange(0,len(self)) - x=self[m] - y=self[t] - vu.add(t) - vu.add(m) - if x.score<=y.score: - newself.append(x) - else: - newself.append(y) - return(newself) - - def selection_par_rang(self, p=(self.n)//2): - liste_individus = self.indiv - n = self.n - - def echanger(tableau, i, j): - tableau[i], tableau[j] = tableau[j], tableau[i] - - def partitionner(tableau,debut,fin): - echanger(tableau,debut,randint(debut,fin-1)) - partition=debut - for i in range(debut+1,fin): - if tableau[i] < tableau[debut]: - if tableau[i].score<tableau[debut].score: - partition+=1 - echanger(tableau,i,partition) - echanger(tableau,debut,partition) - return partition - - def tri_rapide_aux(tableau,debut,fin): - if debut < fin-1: - positionPivot=partitionner(tableau,debut,fin) - tri_rapide_aux(tableau,debut,positionPivot) - tri_rapide_aux(tableau,positionPivot+1,fin) - - def tri_rapide(tableau): - tri_rapide_aux(tableau,0,len(tableau)) - - tri_rapide(liste_individus) - individus_selectionnes = [] - - for _ in range(p): - curseur = random()*n*(n+1)/2 - # print("curseur", curseur) - j = 1 - while j*(j+1)/2 < curseur : - j+=1 - #on doit prendre l'individu avec le jème score - # print("individus selectionés", individus_selectionnes) - individus_selectionnes.append(liste[j-1]) - - def modifier_population(self, liste_individus): - self.n = len(liste_individus) - self.indiv = liste_individus - return self - - self = modifier_population(self, individus_selectionnes) - - def selection_proportionelle(self,p=(self.n)//2): - newself=[] - somme=0 - for indiv in self: - somme=somme+indiv.score - while len(newself)<p: - m=m=random.randrange(0,len(self)) - x=self[m] - p=uniform(0,1) - if p<=x.score/somme: - newself.append(x) - return(newself) - - def reproduction(self,selection=selection_duel,enfant=mixage,p=n//2): - newself=selection(self,p) - while len(newself)<self.n: - m=random.randrange(0,len(newself)) - t=random.randrange(0,len(newself)) - x=newself[m] - y=newself[t] - newself.append(enfant(x,y)) - return(newself) - - - - - - - - - - - - - - - - - - - -