def test_complexe_creation(): g = Arbre(None, None, None, None, None) f1 = g.racine f2 = Feuille() sA = f1.ajoutFils(f2, forme="serie") f3 = Feuille() sA.ajoutFils(f3, index=0) f4 = Feuille() pB = f1.ajoutFils(f4, forme="parallele") f5 = Feuille() pB.ajoutFils(f5, index=1) f6 = Feuille() sC = f2.ajoutFils(f6, forme="serie") # Tests de généalogie assert g.forme == [1, 3, 5] assert g.racine is sA assert sA.parent is None assert sA.fils == [f3, pB, sC] assert pB.parent is sA assert f3.parent is sA assert sC.parent is sA assert pB.fils == [f1, f5, f4] assert f1.parent is pB assert f5.parent is pB assert f4.parent is pB assert sC.fils == [f2, f6] assert f2.parent is sC assert f6.parent is sC # Tests sur les capacités assert len(sA.capacites) == 2 assert len(sC.capacites) == 1 assert g.nbCondensateurs == 4 return g
def test_ajout_parallele_existant(): g, p = test_ajout_fils_feuille_parallele() f1, f2 = p.fils f3 = Feuille() p.ajoutFils(f3, index=1) assert g.forme == [1, 3] assert f3.arbre is g assert f3.parent is p assert p.fils == [f1, f3, f2] return g, p
def test_creationSimulation_parallele_simple(): Cint = 0.5 T = list(range(10)) Text = [1 for i in range(10)] Tint = list(range(10)) Pint = [0 for i in range(10)] g = Arbre(0.5, T, Text, Tint, Pint) f1 = g.racine f2 = Feuille() p = f1.ajoutFils(f2, forme="parallele") f3 = Feuille() p.ajoutFils(f3, index=2) A, B, C = g.creationSimulation() assert np.shape(A) == (1, 1) assert A[0, 0] == f1.H + f2.H + f3.H assert np.shape(C) == (1, 1) assert C[0, 0] == 2 assert np.shape(B) == (1, 2) assert B[0, 0] == -(f1.H + f2.H + f3.H) assert B[0, 1] == 1 return g
def test_ajout_serie_existant(): g, p = test_ajout_fils_feuille_serie() f1, f2 = p.fils f3 = Feuille() p.ajoutFils(f3, index=1) assert g.forme == [1, 3] assert f3.arbre is g assert f3.parent is p assert p.fils == [f1, f3, f2] assert len(p.capacites) == 2 assert g.nbCondensateurs == 3 return g, p
def test_ajout_parallele_existant_rang_superieur(): g, p = test_ajout_parallele_existant() f1, f2, f3 = p.fils f4 = Feuille() p2 = f3.ajoutFils(f4, forme="parallele") assert type(p2) == Parallele assert p2.fils == [f3, f4] assert p2.arbre is g assert f3.parent is p2 assert f4.parent is p2 assert p2.parent is p assert g.forme == [1, 3, 2] return g, p, p2
def test_ajout_fils_feuille_parallele(): g, f1 = test_creation_arbre_minimal() f2 = Feuille() p = f1.ajoutFils(f2, forme="parallele") assert p.fils == [f1, f2] assert p.parent is None assert f1.parent == p assert f2.parent == p assert p.profondeur == 0 assert f1.profondeur == 1 assert f2.profondeur == 1 assert g.forme == [1, 2] assert g.racine is p return g, p
def test_creationSimulation_serie_simple(): cInt = 0.5 T = np.array(list(range(10))) tExt = np.array([1 for i in range(10)]) tInt = np.array(list(range(10))) pInt = np.array([0 for i in range(10)]) g = Arbre(cInt, T, tExt, tInt, pInt) f1 = g.racine f2 = Feuille() p = f1.ajoutFils(f2, forme="serie") f3 = Feuille() p.ajoutFils(f3, index=2) c1, c2 = p.capacites A, B, C = g.creationSimulation() assert (A == np.array([ [f3.H, 0, -f3.H], [0, f1.H + f2.H, -f2.H], [-f3.H, -f2.H, f2.H + f3.H], ])).all() assert (C == np.array([[1 / cInt, 0, 0], [0, 1 / c1, 0], [0, 0, 1 / c2]])).all() print(B) assert (B == np.array([[0, 1], [-f1.H, 0], [0, 0]])).all() return g
def test_ajout_parallele_sur_serie(): g, p = test_ajout_serie_existant() f1, f2, f3 = p.fils f4 = Feuille() p2 = f3.ajoutFils(f4, forme="parallele") assert type(p2) == Parallele assert p2.fils == [f3, f4] assert p2.arbre is g assert len(p.capacites) == 2 assert type(p) is Serie assert g.nbCondensateurs == 3 assert f3.parent is p2 assert f4.parent is p2 assert p2.parent is p assert g.forme == [1, 3, 2] return g, p, p2
def test_ajout_serie_existant_rang_superieur(): g, p = test_ajout_serie_existant() f1, f2, f3 = p.fils f4 = Feuille() p2 = f3.ajoutFils(f4, forme="serie") assert type(p2) == Serie assert p2.fils == [f3, f4] assert p2.arbre is g assert len(p2.capacites) == 1 assert len(p.capacites) == 2 assert g.nbCondensateurs == 4 assert f3.parent is p2 assert f4.parent is p2 assert p2.parent is p assert g.forme == [1, 3, 2] return g, p, p2
def test_ajout_fils_feuille_serie(): g, f1 = test_creation_arbre_minimal() f2 = Feuille() p = f1.ajoutFils(f2, forme="serie") assert type(p) is Serie assert p.fils == [f1, f2] assert p.parent is None assert f1.parent == p assert f2.parent == p assert len(p.capacites) == 1 assert g.nbCondensateurs == 2 assert p.profondeur == 0 assert f1.profondeur == 1 assert f2.profondeur == 1 assert g.forme == [1, 2] assert g.racine is p return g, p
def individuAleatoire(self): """Génère un individu aléatoire. Notes ----- graineAlternance : float `graineAlternance` est une graine qui détermine si l'alternance devrait commencer par des liaisons séries ou parallèles. `graineAlternance` peut prendre les valeurs -Genetique.BIAIS_ALTERNANCE ou Genetique.BIAIS_ALTERNANCE. hasard : bool `hasard` a 50% de chances d'être vrai et 50% d'être faux et nous permet de choisir entre ajouter un fils en série et en parallèle. `graineAlternance` permet de favoriser tantôt les liaisons séries, tantôt les liaisons parallèles. largeurAutorisee : int Pour éviter des configurations absurdes, on force l'arbre à avoir une forme un peu conique (c'est-à-dire à n'avoir pas trop de fils sur les premières générations). """ graineAlternance = ( GenerateurArbres.BIAIS_ALTERNANCE + 2 * (random.random() > 0.5) * GenerateurArbres.BIAIS_ALTERNANCE) # On initialise l'individu que l'on va créer. individu = Arbre(self.Cint, self.T, self.Text, self.Tint, self.Pint) # On tire aléatoirement la profondeur qu'aura notre individu. profondeur = random.randint(1, GenerateurArbres.PROFONDEUR_MAX_ARBRE) # On crée itérativement tous les niveaux de notre arbre. for i in range(profondeur - 1): # cf. docstring pour `largeurAutorisee`. # Notez que la largeur réelle d'une couche de l'arbre dépasse # souvent la largeur maximale autorisée. En effet, lorsque l'on # ajoute un fils a une feuille, cette dernière descend dans la # nouvelle profondeur. On se retrouve donc avec deux noeuds de plus # à la nouvelle profondeur au lieu d'un. largeurAutorisee = min(GenerateurArbres.LARGEUR_MAX_ARBRE, 3 * (i + 1)) # On détermine au hasard la largeur de la profondeur i+1. largeur = random.randint(1, largeurAutorisee) # On choisit (avec remise) les noeuds de la génération i qui # accueilleront des enfants à la génération i+1. indicesChoisis = random.choices(population=range( individu.forme[i]), k=largeur) # On ajoute les enfants aux parents désignés. for k in indicesChoisis: # Le noeud auquel on doit ajouter un enfant. Un même indice peut # être tiré plusieurs fois. parent = individu.inspecter(i, k) enfant = Feuille() if type(parent) is Feuille: # cf. docstring pour `hasard`. hasard = random.random() > (0.5 + graineAlternance) if hasard: parent.ajoutFils(enfant, forme="serie") else: parent.ajoutFils(enfant, forme="parallele") else: # On tire aléatoirement l'index où l'on va insérer le nouvel # enfant parmi les enfants préexistants du parent. Le +1 # correspond au fait que l'on peut insérer un enfant tout à # la fin de la liste des descendants du parent. indexAleatoire = random.randrange(len(parent.fils) + 1) # On insère le nouvel enfant. parent.ajoutFils(enfant, index=indexAleatoire) # On alterne le biais entre liaisons séries et parallèle. graineAlternance *= -1 # Si on a demandé un élaguage automatique, alors on tronque l'individu # pour qu'il soit représentable sous forme d'image. if self.elaguageForce: individu.elaguer(largeur=self.imageLargeur, hauteur=self.imageHauteur) # On renvoie la liste ainsi formée. return individu
def mutation(self): """Affecte des mutations à certains individus de la population. Pour l'instant, on utilise un taux de mutation constant. """ for individu in self.population: # On note si l'individu a été muté, auquel cas il faudra l'élaguer # si cela est demandé pour qu'il reste représentable sous forme # d'image. besoinElaguage = False # On peut muter un même individu plusieurs fois si le hasard le veut while random.random() < Genetique.CHANCE_DE_MUTATION: besoinElaguage = True profondeur = len(individu.forme) # On tire une profondeur à laquelle faire la mutation. choixProfondeur = random.randrange(profondeur) # Le nombre de noeuds à la profondeur donnée. largeur = individu.forme[choixProfondeur] # On choisit un individu au hasard parmi ceux à cette profondeur. choixLargeur = random.randrange(largeur) # On récupère l'individu tiré au hasard. noeud = individu.inspecter(choixProfondeur, choixLargeur) # On tire aléatoirement entre True et False avec équiprobabilité. action = random.random() > 0.5 # L'action sera différente si le noeud tiré est une `Feuille` ou # non. if type(noeud) is Feuille: # On va ajouter une feuille à ce noeud. fils = Feuille() if action: # 50% de chances d'ajouter en série noeud.ajoutFils(fils, forme="serie") else: # 50% de chances d'ajouter en parallèle noeud.ajoutFils(fils, forme="parallele") else: nombreFils = len(noeud.fils) if action: # 50% de chances d'ajouter un enfant. # On tire un indice sur le lequel faire notre action # dans 0, `nombreFils` inclu. choixIndex = random.randrange(nombreFils + 1) fils = Feuille() noeud.ajoutFils(fils, index=choixIndex) else: # 50% de chances de supprimer un fils. # On tire un indice sur le lequel faire notre action # dans 0, `nombreFils` exclu. choixIndex = random.randrange(nombreFils) noeud.suppressionFils(index=choixIndex) if besoinElaguage: # On remet l'indicateur à 0 pour le prochain individu. besoinElaguage = False if Genetique.ELAGUAGE_FORCE: # Si besoin, on élague l'individu obtenu individu.elaguer( largeur=self.imageLargeur, hauteur=self.imageHauteur )
def test_creationSimulation_complexe(): cInt = 0.5 T = [float(i) for i in range(10)] tExt = [1 for i in range(10)] tInt = list(range(10)) pInt = [0 for i in range(10)] g = Arbre(cInt, T, tExt, tInt, pInt) f1 = g.racine f2 = Feuille() sA = f1.ajoutFils(f2, forme="serie") f3 = Feuille() sA.ajoutFils(f3, index=2) f4 = Feuille() pB = f3.ajoutFils(f4, forme="parallele") f5 = Feuille() sC = f3.ajoutFils(f5, forme="serie") f6 = Feuille() sC.ajoutFils(f6, index=0) f7 = Feuille() sD = f2.ajoutFils(f7, forme="serie") f8 = Feuille() pE = f2.ajoutFils(f8, forme="parallele") f9 = Feuille() pE.ajoutFils(f9, index=2) # Oui, c'est un exemple assez compliqué, c'est parce que j'essaie de tester # l'implémentation de curseur, qui n'intervient que dans des cas assez # importants. cA, cB = sA.capacites cC = sD.capacites[0] cD, cE = sC.capacites # Pour proposer les solutions qui suivent j'ai suivi l'algorithme à la main # sur un tableau. solA = np.array([ [f4.H + f5.H, 0, -f4.H, 0, 0, -f5.H], [0, f1.H + f2.H + f8.H + f9.H, 0, -f2.H - f8.H - f9.H, 0, 0], [-f4.H, 0, f4.H + f6.H + f7.H, -f7.H, -f6.H, 0], [0, -f2.H - f8.H - f9.H, -f7.H, f2.H + f7.H + f8.H + f9.H, 0, 0], [0, 0, -f6.H, 0, f3.H + f6.H, -f3.H], [-f5.H, 0, 0, 0, -f3.H, f3.H + f5.H], ]) solB = np.array([[0, 1], [-f1.H, 0], [0, 0], [0, 0], [0, 0], [0, 0]]) solC = np.diag([1 / cInt, 1 / cA, 1 / cB, 1 / cC, 1 / cD, 1 / cE]) A, B, C = g.creationSimulation() assert (A == solA).all() assert (B == solB).all() assert (C == solC).all() return g
def test_simulation_score(): cInt = 0.5 T = list(range(10)) tExt = [1 for i in range(10)] tInt = list(range(10)) pInt = [0 for i in range(10)] g = Arbre(cInt, T, tExt, tInt, pInt) f1 = g.racine f2 = Feuille() sA = f1.ajoutFils(f2, forme="serie") f3 = Feuille() sA.ajoutFils(f3, index=2) f4 = Feuille() pB = f3.ajoutFils(f4, forme="parallele") f5 = Feuille() sC = f3.ajoutFils(f5, forme="serie") f6 = Feuille() sC.ajoutFils(f6, index=0) f7 = Feuille() sD = f2.ajoutFils(f7, forme="serie") f8 = Feuille() pE = f2.ajoutFils(f8, forme="parallele") f9 = Feuille() pE.ajoutFils(f9, index=2) s = g.score() assert s < 0 # Il n'y a rien d'autre à tester pour score, le code est transparent. return g
def test_simulation_coherence(): cInt = 0.5 T = list(range(10)) tExt = [1 for i in range(10)] tInt = list(range(10)) pInt = [0 for i in range(10)] g = Arbre(cInt, T, tExt, tInt, pInt) f1 = g.racine f2 = Feuille() sA = f1.ajoutFils(f2, forme="serie") f3 = Feuille() sA.ajoutFils(f3, index=2) f4 = Feuille() pB = f3.ajoutFils(f4, forme="parallele") f5 = Feuille() sC = f3.ajoutFils(f5, forme="serie") f6 = Feuille() sC.ajoutFils(f6, index=0) f7 = Feuille() sD = f2.ajoutFils(f7, forme="serie") f8 = Feuille() pE = f2.ajoutFils(f8, forme="parallele") f9 = Feuille() pE.ajoutFils(f9, index=2) sol = g.simulation() x, y = sol.t, sol.y[0] assert sol.success assert (x == np.array(T)).all() for temperature in sol.y: assert temperature[0] == tExt[0] assert len(x) == len(y) # C'est à peu près tout ce que l'on peut vérifier simplement sur la # cohérence de la simulation... return g
def test_representation_image_complexe(): len = 30 Cint = Coefficients.muC T = list(range(len)) Text = list(range(len)) Tint = [-1.4 * (i / len) for i in range(len)] Pint = [0 for i in range(len)] # scores = [] iterations = 100 # compteur = 0 # for i in range(iterations): # try: # g = Arbre(Cint, T, Text, Tint, Pint) # f1 = g.racine # f2 = Feuille() # sA = f1.ajoutFils(f2, forme="serie") # f3 = Feuille() # sA.ajoutFils(f3, index=0) # f4 = Feuille() # pB = f1.ajoutFils(f4, forme="parallele") # f5 = Feuille() # pB.ajoutFils(f5, index=1) # f6 = Feuille() # sC = f2.ajoutFils(f6, forme="serie") # scores.append(g.score()) # compteur+=1 # print("score=", scores[-1]) # except SimulationException as e: # print(str(e)) # plt.plot(range(50), sorted(scores)[-50:]) # plt.show() # dist = [] for i in range(iterations): g = Arbre(Cint, T, Text, Tint, Pint) f1 = g.racine f2 = Feuille() sA = f1.ajoutFils(f2, forme="serie") f3 = Feuille() sA.ajoutFils(f3, index=0) f4 = Feuille() pB = f1.ajoutFils(f4, forme="parallele") f5 = Feuille() pB.ajoutFils(f5, index=1) f6 = Feuille() sC = f2.ajoutFils(f6, forme="serie") image = g.ecritureImage(largeur=100, hauteur=100) print("(1) score=", g.score()) ancienneImage = image.copy() # R, V, B = image[:,:,0], image[:,:,1], image[:,:,2] # plt.imshow(image) # plt.show() # plt.imshow(R) # plt.colorbar() # plt.show() # plt.imshow(V) # plt.colorbar() # plt.show() # plt.imshow(B) # plt.colorbar() # plt.show() g.lectureImage(image) # print(i) print("(2) score=", g.score()) print()