Commit 44049d1d authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files

Les bouquets ne sont plus maximaux, debut de catégorieFleurie

parent b4e3415b
......@@ -11,14 +11,43 @@ if GRAPHVIZ_ENABLED:
class BouquetAbstrait(Morphisme):
nb_viz = 0
def __init__(self,foncteur1, foncteur2, tiges, cat_cones1=None,cat_cones2=None,cat_cocones1=None,cat_cocones2=None):
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
self.tiges = list(tiges) #liste de morphismes de la catégorie cible des foncteurs
self.categorie = self.foncteur1.cat_cible
self.cat_cones1 = cat_cones1
self.cat_cones2 = cat_cones2
self.cat_cocones1 = cat_cocones1
self.cat_cocones2 = cat_cocones2
identite = False
if self.foncteur1 == self.foncteur2:
for tige in self.tiges:
if not tige.is_identite:
break
else:
for objet in self.foncteur1.app_objets.values():
if self.categorie.identites[objet] not in self.tiges:
break
else:
identite = True
Morphisme.__init__(self,self.foncteur1,self.foncteur2,str(self),identite)
def __eq__(self,other):
if issubclass(type(other),BouquetAbstrait):
if len([e for e in self.tiges if e not in other.tiges]) > 0:
return False
if len([e for e in other.tiges if e not in self.tiges]) > 0:
return False
return True
return self.foncteur1 == other.foncteur1 and self.foncteur2 == other.foncteur2
return False
def __str__(self):
return '('+str(self.foncteur1)+','+'/'.join(map(str,self.tiges))+','+str(self.foncteur2)+')'
def __repr__(self):
return str(self)
def verifier_coherence(self):
raise NotImplementedError()
......@@ -31,13 +60,13 @@ class BouquetAbstrait(Morphisme):
Composante bleue foncée : cocones
Composante orange: Bouquet"""
Bouquet.nb_viz += 1
if not hasattr(self,'cat_cones1'):
if self.cat_cones1 == None:
self.cat_cones1 = CategorieCones(self.foncteur1)
if not hasattr(self,'cat_cones2'):
if self.cat_cones2 == None:
self.cat_cones2 = CategorieCones(self.foncteur2)
if not hasattr(self,'cat_cocones1'):
if self.cat_cocones1 == None:
self.cat_cocones1 = CategorieCocones(self.foncteur1)
if not hasattr(self,'cat_cocones2'):
if self.cat_cocones2 == None:
self.cat_cocones2 = CategorieCocones(self.foncteur2)
image1 = self.foncteur1.categorie_image()
image2 = self.foncteur2.categorie_image()
......@@ -96,12 +125,7 @@ class BouquetPerceptif(BouquetAbstrait):
def __init__(self, foncteur1, foncteur2, tiges, cat_cones1=None,cat_cones2=None):
"""On peut fournir cat_cones1 et cat_cones2 pour économiser du temps de calcul."""
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
self.tiges = list(tiges) #liste de morphismes de la catégorie cible des foncteurs
self.categorie = self.foncteur1.cat_cible
self.cat_cones1 = cat_cones1
self.cat_cones2 = cat_cones2
BouquetAbstrait.__init__(self,foncteur1, foncteur2, tiges, cat_cones1,cat_cones2)
if TOUJOURS_VERIFIER_COHERENCE:
BouquetPerceptif.verifier_coherence(self)
......@@ -141,12 +165,7 @@ class BouquetActif(BouquetAbstrait):
def __init__(self, foncteur1, foncteur2, tiges,cat_cocones1=None,cat_cocones2=None):
"""On peut fournir cat_cocones1 et cat_cocones2 pour économiser du temps de calcul."""
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
self.tiges = list(tiges) #liste de morphismes de la catégorie cible des foncteurs
self.categorie = self.foncteur1.cat_cible
self.cat_cocones1 = cat_cocones1
self.cat_cocones2 = cat_cocones2
BouquetAbstrait.__init__(self,foncteur1, foncteur2, tiges,None,None,cat_cocones1,cat_cocones2)
if TOUJOURS_VERIFIER_COHERENCE:
BouquetActif.verifier_coherence(self)
......@@ -189,6 +208,42 @@ class Bouquet(BouquetPerceptif,BouquetActif):
"""On peut fournir cat_cones1, cat_cones2, cat_cocones1 et cat_cocones2 pour économiser du temps de calcul."""
BouquetPerceptif.__init__(self,foncteur1,foncteur2,tiges,cat_cones1,cat_cones2)
BouquetActif.__init__(self,foncteur1,foncteur2,tiges,cat_cocones1,cat_cocones2)
BouquetAbstrait.__init__(self,foncteur1,foncteur2,tiges,cat_cones1,cat_cones2,cat_cocones1,cat_cocones2)
class CompositionBouquets(BouquetAbstrait):
"""Appeler le constructeur de Composition n'instancie pas forcément une nouvelle composition.
Comparer les composée avec les opérateurs == et !=
/!\ si une identité incohérente est placée dans une composition valide, elle sera simplement omise /!\
"""
def __new__(cls,*bouquets):
if len(bouquets) == 0:
raise Exception("Composition de 0 bouquets")
backup = bouquets
bouquets = [m for m in bouquets if not m.is_identite] #on supprime les identités
if len(bouquets) == 0:
for i in range(1,len(backup)):
if backup[i-1] != backup[i]:
raise Exception("Composition d'identites differentes"+str(backup))
return backup[0]
elif len(bouquets) == 1:
return bouquets[0]
else:
for i in range(1,len(bouquets)):
if bouquets[i-1].cible != bouquets[i].source:
raise Exception("Composition de bouquets impossible : "+bouquets.__repr__())
tiges = bouquets[0].tiges
for i in range(1,len(bouquets)):
nouvelles_tiges = []
for t1 in tiges:
for t2 in bouquets[i].tiges:
if t1.cible == t2.source:
nouvelles_tiges += [bouquets[i].categorie.Composee(t1,t2)]
tiges = copy(nouvelles_tiges)
instance = BouquetAbstrait(bouquets[0].source,bouquets[-1].cible,tiges,bouquets[0].cat_cones1,bouquets[-1].cat_cones2,bouquets[0].cat_cocones1,bouquets[-1].cat_cocones2)
return instance
class BouquetsPerceptifs:
def __init__(self, foncteur1, foncteur2, cat_cones1=None, cat_cones2=None):
......@@ -202,45 +257,31 @@ class BouquetsPerceptifs:
self.cat_cones2 = CategorieCones(foncteur2) if cat_cones2 == None else cat_cones2
self.categorie = self.foncteur1.cible
self.bouquets_perceptifs = []
# on énumère les applications possibles des cônes de D1 vers les cônes de même apex de D2
# si on note C1_o les cônes d'apex o de D1 et C2_o les cônes d'apex o de D2
# on cherche toutes les applications (C1_o1 -> C2_o1) x (C1_o2 -> C2_o2) x ... x (C1_oN -> C2_oN)
apices = set([c.apex for c in self.cat_cones1.objets])
applications_cones = []
for apex in apices:
domaine = [e for e in self.cat_cones1.objets if e.apex == apex]
codomaine = [e for e in self.cat_cones2.objets if e.apex == apex]
images = itertools.product(codomaine,repeat=len(domaine))
applications = [dict(zip(domaine,image)) for image in images]
applications_cones += [applications]
# on énumère toutes les flèches de D1 à D2
objets_comma_category = {(i,j):self.categorie.enumerer_composees(self.foncteur1(i),self.foncteur2(j))\
for i in self.foncteur1.source.objets for j in self.foncteur2.source.objets}
#les flèches de D1(i) à D2(j) {(i,j) : [C(D1(i),D2(j))]}
fleches = [e for liste in objets_comma_category.values() for e in liste]
for app_cone in itertools.product(*applications_cones):
fleches_candidates = {cle:copy(objets_comma_category[cle]) for cle in objets_comma_category} #{(i,j) : [C(D1(i),D2(j))]}
ajouter_bouquet = True
for app in app_cone:
#app est une application des cônes d'apex O vers d'autres cônes de même apex
if ajouter_bouquet:
for cone1 in app:
cone2 = app[cone1]
for couple in fleches_candidates:
i,j = couple
fleches_candidates[couple] = [g for g in fleches_candidates[couple] if self.categorie.Composee(cone1.jambes[i],g) in cone2.jambes.values()]# on retire les g qui composés avec une jambe ne donnent pas une jambe du cône image
# on vérifie que toutes les jambes du cône image sont atteintes
jambes_atteintes = [self.categorie.Composee(cone1.jambes[i],g) for i,j in fleches_candidates for g in fleches_candidates[(i,j)]]
jambes_manquees = [jambe for jambe in cone2.jambes.values() if jambe not in jambes_atteintes]
if len(jambes_manquees) > 0:
ajouter_bouquet = False
# on énumère toutes les interactions de D1 à D2
for nb_fleches in range(1,len(objets_comma_category)+1):
for interaction in itertools.combinations(fleches,nb_fleches):
ajouter_bouquet = True
for cone in self.cat_cones1.objets:
fleches_generees = set()
for jambe in cone.jambes.values():
for fleche in interaction:
if fleche.source == jambe.cible:
fleches_generees |= {self.categorie.Composee(jambe,fleche)}
cone_a_l_arrivee = False
for cone2 in self.cat_cones2.objets:
if fleches_generees == set(cone2.jambes.values()):
cone_a_l_arrivee = True
break
if ajouter_bouquet:
self.bouquets_perceptifs += [BouquetPerceptif(self.foncteur1,self.foncteur2,[e for l in fleches_candidates.values() for e in l],\
cat_cones1, cat_cones2)]
if not cone_a_l_arrivee:
ajouter_bouquet = False
break
if ajouter_bouquet:
self.bouquets_perceptifs += [BouquetPerceptif(self.foncteur1,self.foncteur2,interaction,cat_cones1,cat_cones2)]
def transformer_graphviz(self):
......@@ -259,45 +300,31 @@ class BouquetsActifs:
self.cat_cocones2 = CategorieCocones(foncteur2) if cat_cocones2 == None else cat_cocones2
self.categorie = self.foncteur1.cible
self.bouquets_actifs = []
# on énumère les applications possibles des cocônes de D2 vers les cocônes de même nadir de D1
# si on note C2_o les cocônes de nadir o de D2 et C1_o les cocônes de nadir o de D1
# on cherche toutes les applications (C2_o1 -> C1_o1) x (C2_o2 -> C1_o2) x ... x (C2_oN -> C1_oN)
nadirs = set([c.nadir for c in self.cat_cocones2.objets])
applications_cocones = []
for nadir in nadirs:
domaine = [e for e in self.cat_cocones2.objets if e.nadir == nadir]
codomaine = [e for e in self.cat_cocones1.objets if e.nadir == nadir]
images = itertools.product(codomaine,repeat=len(domaine))
applications = [dict(zip(domaine,image)) for image in images]
applications_cocones += [applications]
# on énumère toutes les flèches de D1 à D2
objets_comma_category = {(i,j):self.categorie.enumerer_composees(self.foncteur1(i),self.foncteur2(j))\
for i in self.foncteur1.source.objets for j in self.foncteur2.source.objets}
#les flèches de D1(i) à D2(j) {(i,j) : [C(D1(i),D2(j))]}
fleches = [e for liste in objets_comma_category.values() for e in liste]
for app_cocone in itertools.product(*applications_cocones):
fleches_candidates = {cle:copy(objets_comma_category[cle]) for cle in objets_comma_category} #{(i,j) : [C(D1(i),D2(j))]}
ajouter_bouquet = True
for app in app_cocone:
#app est une application des cocônes de nadir O vers d'autres cocônes de même nadir
if ajouter_bouquet:
for cocone2 in app:
cocone1 = app[cocone2]
for couple in fleches_candidates:
i,j = couple
fleches_candidates[couple] = [g for g in fleches_candidates[couple] if self.categorie.Composee(g,cocone2.jambes[j]) in cocone1.jambes.values()]# on retire les g qui composés avec une jambe ne donnent pas une jambe du cocône image
# on vérifie que toutes les jambes du cocône image sont atteintes
jambes_atteintes = [self.categorie.Composee(g,cocone2.jambes[j]) for i,j in fleches_candidates for g in fleches_candidates[(i,j)]]
jambes_manquees = [jambe for jambe in cocone1.jambes.values() if jambe not in jambes_atteintes]
if len(jambes_manquees) > 0:
ajouter_bouquet = False
# on énumère toutes les interactions de D1 à D2
for nb_fleches in range(1,len(objets_comma_category)+1):
for interaction in itertools.combinations(fleches,nb_fleches):
ajouter_bouquet = True
for cocone in self.cat_cocones2.objets:
fleches_generees = set()
for jambe in cocone.jambes.values():
for fleche in interaction:
if fleche.cible == jambe.source:
fleches_generees |= {self.categorie.Composee(fleche,jambe)}
cocone_au_depart = False
for cocone1 in self.cat_cocones1.objets:
if fleches_generees == set(cocone1.jambes.values()):
cocone_au_depart = True
break
if ajouter_bouquet:
self.bouquets_actifs += [BouquetActif(self.foncteur1,self.foncteur2,[e for l in fleches_candidates.values() for e in l],\
cat_cocones1, cat_cocones2)]
if not cocone_au_depart:
ajouter_bouquet = False
break
if ajouter_bouquet:
self.bouquets_actifs += [BouquetActif(self.foncteur1,self.foncteur2,interaction,cat_cocones1,cat_cocones2)]
def transformer_graphviz(self):
......@@ -380,9 +407,17 @@ def main():
fonct1 = Foncteur(cat_fleche,cat2,{'A':'A','B':'B'},{a:h})
fonct2 = Foncteur(cat_fleche,cat2,{'A':'C','B':'D'},{a:k})
bouquets = BouquetsActifs(fonct1,fonct2)
bouquets = BouquetsPerceptifs(fonct1,fonct1)
bouquets.transformer_graphviz()
for b in bouquets.bouquets_perceptifs:
print(b)
print(b.is_identite)
bouquets2 = BouquetsPerceptifs(fonct1,fonct2)
bouquets2.transformer_graphviz()
bouquet3 = CompositionBouquets(bouquets.bouquets_perceptifs[0],bouquets2.bouquets_perceptifs[0])
bouquet3.transformer_graphviz()
if __name__ == '__main__':
......
......@@ -353,7 +353,7 @@ def main():
fonct1 = Foncteur(cat_fleche,cat2,{'A':'A','B':'B'},{a:h})
fonct2 = Foncteur(cat_fleche,cat2,{'A':'C','B':'D'},{a:k})
bouquets = BouquetsActifs(fonct1,fonct2)
bouquets = BouquetsPerceptifs(fonct1,fonct1)
bouquets.transformer_graphviz()
......
from Categorie import Categorie
from Bouquet import BouquetsPerceptifs, BouquetsActifs, Bouquets
from Diagramme import DiagrammeIdentite, Objets
class CategorieFleurieAbstraite(Categorie):
"""Catégorie dont les objets sont des diagrammes Di d'intérêt d'une catégorie C.
Les flèches entre les diagrammes sont des bouquets perceptifs."""
def __init__(self,categorie)
Categorie.__init__(self,"Categorie fleurie perceptive")
def ajouter_diagramme_interêt
\ No newline at end of file
......@@ -4,5 +4,10 @@
- Problème dans catégorie aléatoire : un morphisme peut avoir deux inverses (voir s'il y a pas d'autres problèmes du genre)
- Corriger catégorie aléatoire isomophisme : il faut faire commuter les composantes isomorphes
- Retirer image objets de Parallele
- Créer deux catégorie, une où toutes les composées sont générées lors de l'enumeration (peu de contrainte de composition) et une plus graphe de composition (bcp de contraintes de composition)
-transformer la liste en tiges en ensemble de tiges
P.5 : InteractC peut être infinie si C est finie ?
\ No newline at end of file
Q : Maximalité des cluster et identité (comment on obtient un cluster identité avec la maximalité ?)
Est-ce que les clusters identités en sont vraiment ?
PB avec les bouquets inter : il faut que les bouquets de D1 vers delta(A) soient des cocônes et les bouquets de delta(A) vers D1 sont des cônes (trop restrictif)
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment