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)
-
-
-
-
-
-    
-
-
-
-
-
-
-
-
-
-
-
-
-    
-