Commit 11922fac authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files

Création de CategorieMiseEnCache, avorté car pas trouvé de fonctionnement...

Création de CategorieMiseEnCache, avorté car pas trouvé de fonctionnement élégant pour accéder aux morphismes mis en cache, ou alors il faut appeler la méthode call des classes filles depuis la classe mère
parent 61358527
from Categorie import Categorie
from Foncteur import Foncteur
class CatFinies(Categorie):
"""Catégorie des catégories finies, les morphismes sont des foncteurs.
Cette catégorie est infinie, par défaut il n'y a aucune catégorie dedans, il faut rajouter les catégories d'intérêt."""
def __call__(self, source:set, cible:set) -> set:
for a in source:
for b in cible:
# a et b sont des catégories, on cherche tous les foncteurs de a vers b
\ No newline at end of file
......@@ -103,7 +103,13 @@ class Categorie:
raise Exception("Incoherence Categorie : associativite pas respectee pour "+str(m1)+", "+str(m2)+", "+str(m3)+\
"\n(m1@m2)@m3 = "+str((m1@m2)@m3)+" m1@(m2@m3) = "+str(m1@(m2@m3))+
"\nm1@m2 = "+str(m1@m2)+" m2@m3 = "+str(m2@m3))#+"\nm2@m1 = "+str(m2@m1)+" m3@m2 = "+str(m3@m2))
def est_isomorphe_a(self, objet1:any, objet2:any) -> set:
"""Trouve les isomorphismes entre `objet1` et `objet2`.
Renvoie un ensemble de couple (f,g) tels que gof = Id1 et fog = Id2.
"""
return {(f,g) for f in self({objet1},{objet2}) for g in self({objet2},{objet1}) if (f@g).is_identite and (g@f).is_identite}
def table_loi_de_composition(self):
"""
Renvoie un dico de dico tel que table[f][g] = f o g, table[f][g] = None si f et g ne sont pas composables.
......
from CategorieCones import CategorieCones
from Categorie import Categorie
from Foncteur import Foncteur
from Diagramme import Triangle
from Morphisme import Morphisme,Composition
from collections import defaultdict
from itertools import product
from config import *
class CategorieCocones(Categorie):
def __init__(self, foncteur):
Categorie.__init__(self,"Categorie de cocones de "+str(foncteur))
self.foncteur = foncteur
cocones = [e for nadir in foncteur.cat_cible.objets for e in foncteur.enumerer_cocones(nadir)]
self.ajouter_objets(cocones)
self.app_morph_fleche_cocone = dict() #associe à chaque nouvelle flèche dans la cat_cocone la flèche de laquelle elle vient
for cocone1,cocone2 in product(cocones,repeat=2):
fleches_potentielles = self.foncteur.cat_cible.fleches_elem(cocone1.nadir,cocone2.nadir)
for obj in self.foncteur.cat_source.objets:
fleches_potentielles = [fleche for fleche in fleches_potentielles if self.foncteur.cat_cible.Composee(cocone1.jambes[obj],fleche) == cocone2.jambes[obj]]
for fleche in fleches_potentielles:
f = Morphisme(cocone1,cocone2,str(fleche.representant)+"*")
self.app_morph_fleche_cocone[f] = fleche
self.ajouter_morphisme(f)
for cocone in self.objets:
cycles_nouvelle_cat = self.trouver_cycles_elementaires(cocone)
cycles_ancienne_cat = self.foncteur.cat_cible.trouver_cycles_elementaires(cocone.nadir)
#on veut établir une correspondance entre les anciens cycles et les nouveaux
nouveau_ancien = {c1:self.foncteur.cat_cible.Composee(*[self.app_morph_fleche_cocone[e] for e in c1]) for c1 in cycles_nouvelle_cat}
ancien_nouveau = defaultdict(list)
for cle,valeur in nouveau_ancien.items():
ancien_nouveau[valeur] += [cle]
# Si le cycle est une identite il faut le faire commuter dès le début
for cycle_nouveau in nouveau_ancien:
if nouveau_ancien[cycle_nouveau].is_identite:
t = Triangle(self,[cocone]*3,[cycle_nouveau,self.identites[cocone],self.identites[cocone]])
t.faire_commuter()
# Pour les autres cycles on fait commuter que la frontière de l'arbre de composition
cycles = sorted(self.foncteur.cat_cible.enumerer_cycles(cocone.nadir),key=len)
for debut_antecedant_ancien,fin_antecedant_ancien in product(cycles, cycles+[self.foncteur.cat_cible.identites[cocone.nadir]]):
# pour chaque simplification des cycles originels, on fait la même pour les nouveaux cycles
# on peut avoir l'identite dans fin_antecedant_ancien car un cycle simple peut être simplificateur
antecedant_ancien = Composition(debut_antecedant_ancien,fin_antecedant_ancien)
im = self.foncteur.cat_cible.Composee(*antecedant_ancien)
if antecedant_ancien != im: #il y a simplification
for antecedant_nouveau in product(*[ancien_nouveau[e] for e in antecedant_ancien]):
for image_nouveau in product(*[ancien_nouveau[e] for e in im]):
# if self.Composee(*antecedant_nouveau) != self.Composee(*image_nouveau):
# raise Exception("Modification en double de la loi de composition du cycle "+str(self.Composee(*antecedant_nouveau))+" : "+str(self.Composee(*image_nouveau)))
if self.Composee(*antecedant_nouveau) != self.Composee(*image_nouveau):
t = Triangle(self,[cocone]*3,[self.Composee(*antecedant_nouveau),self.identites[cocone],self.Composee(*image_nouveau)])
t.faire_commuter()
else:
# print("CategorieCocones l.48 : On a echappe a la creation du diagramme superflu "+str(self.Composee(*antecedant_nouveau))+" => "+str(self.Composee(*image_nouveau)))
pass
# On retire ensuite les chemins en double
composees = self.enumerer_toutes_composees()
for cocone1,cocone2 in composees:
comp = sorted([e for e in composees[(cocone1,cocone2)] if not e.is_identite],key=len)
for c in comp:
antecedant_ancien = Composition(*[self.app_morph_fleche_cocone[e] for e in c.composee])
image_ancien = self.foncteur.cat_cible.Composee(*[self.app_morph_fleche_cocone[e] for e in c.composee])
if antecedant_ancien != image_ancien:
#il y a simplification
antecedant_nouveau = c
image_nouveau = []
for f in image_ancien:
im_nouveau = []
for f1,f2 in self.app_morph_fleche_cocone.items():
if f2 == f:
im_nouveau += [f1]
if len(im_nouveau) == 0:
raise Exception("Pas d'image a la fleche "+str(f)+"\n"+'\n'.join(map(lambda x:':'.join(map(str,x)),self.app_morph_fleche_cocone.items())))
image_nouveau += [im_nouveau]
for im in product(*image_nouveau):
if im[0].source == antecedant_nouveau[0].source and im[-1].cible == antecedant_nouveau[-1].cible: #on vérifie que ça part et ça arrive au bon endroit
#on vérifie que c'est composable
composable = True
for i in range(len(im)-1):
if im[i].cible != im[i+1].source:
composable = False
break
if not composable:
# print("Warning, on a tente de composer "+' , '.join(map(str,im)))
continue
if self.Composee(*antecedant_nouveau) != self.Composee(*im):
t = Triangle(self,[cocone1,cocone2,cocone2],[self.Composee(*antecedant_nouveau),self.identites[cocone2],self.Composee(*im)])
t.faire_commuter()
else:
# print("CategorieCocones l.70 : On a echappe a la creation du diagramme superflu "+str(self.Composee(*antecedant_nouveau))+" => "+str(self.Composee(*im)))
pass
else:
# print("Warning : on a pas identifie "+' , '.join(map(str,im))+ " et "+' , '.join(map(str,antecedant_nouveau)))
pass
def colimites(self):
"""Trouve la/les colimite(s) si elle(s) existe(nt), renvoie une liste vide si aucune colimite trouvée
une liste de cocônes isomorphes sinon"""
if len(self.objets) > 0:
graphe = defaultdict(list)
for cle,val in self.morph_entrants.items():
graphe[cle] = list(map(lambda x:x.source,val))
noeuds_visites = []
noeud_courant = self.objets[0]
while len(graphe[noeud_courant]) > 0:
noeuds_visites += [noeud_courant]
if graphe[noeud_courant][0] in noeuds_visites:
while noeuds_visites[0] != graphe[noeud_courant][0]:
noeuds_visites.pop(0)
nouveau_noeud = tuple(noeuds_visites)
graphe[nouveau_noeud]
for cle,val in graphe.items():
if cle in noeuds_visites:
graphe[nouveau_noeud] += [e for e in val if e not in noeuds_visites]
else:
noeuds_a_del = [cible for cible in val if cible in noeuds_visites]
if len(noeuds_a_del) > 0:
graphe[cle] += [nouveau_noeud]
graphe[cle] = [e for e in graphe[cle] if e not in noeuds_a_del]
for noeud in noeuds_visites:
del graphe[noeud]
noeuds_visites = []
noeud_courant = nouveau_noeud
continue
noeud_courant = graphe[noeud_courant][0]
while type(noeud_courant) == tuple:
noeud_courant = noeud_courant[0]
noeud_initial = noeud_courant
#on est arrivé au bout du chemin
for cocone in self.objets:
fleches = self.enumerer_composees(noeud_initial,cocone)
if len(fleches) != 1:
break
else:
result = [cocone for cocone in self.objets if len(self.enumerer_composees(cocone,noeud_initial)) > 0]
if TOUJOURS_VERIFIER_COHERENCE:
for colim in result:
for cocone in self.objets:
fleches = self.enumerer_composees(colim,cocone)
if len(fleches) != 1:
raise Exception("Incoherence Colimite : Une colimite n'a pas de fleche unique vers un autre cone : "+str(colim)+" , "+str(cocone))
return result
return []
def main():
# from Diagramme import DiagrammeIdentite
# cat1 = Categorie('Catégorie à 1 flèche')
# cat1.ajouter_objets("AB")
# f = Morphisme('A','B','f')
# cat1.ajouter_morphismes([f])
# cat2 = Categorie('Catégorie double cône')
# cat2.ajouter_objets("ABCD")
# f1,f2,f3,f4,f5,f6,f7 = [Morphisme('A','B',1),Morphisme('A','C',2),Morphisme('D','B',3),Morphisme('D','C',4),
# Morphisme('B','C',5),Morphisme('A','D',6),Morphisme('A','A',7)]
# cat2.ajouter_morphismes([f1,f2,f3,f4,f5,f6])
# d = DiagrammeIdentite(cat2)
# d.faire_commuter()
# cat2.ajouter_morphisme(f7)
# d = Triangle(cat2,"AAA",[cat2.Composee(f7,f7),cat2.identites['A'],f7])
# d.faire_commuter()
# cat2.transformer_graphviz()
# F = Foncteur(cat1,cat2,{'A':'B','B':'C'},{f:f5})
# F.transformer_graphviz()
# cat3 = CategorieCones(F)
# for d in cat3.diagrammes:
# Foncteur.transformer_graphviz(d)
# cat3.transformer_graphviz()
# for cone in cat3.objets:
# cone.transformer_graphviz()
from CategorieAleatoire import CategorieAleaPreOrdre
from Diagramme import DiagrammeAlea
import random
random.seed(811)
c = CategorieAleaPreOrdre(12,0.3)
print("fin gen cat")
# c.transformer_graphviz()
diag = DiagrammeAlea(c,3)
diag.transformer_graphviz()
print("fin gen diag")
cat3 = CategorieCocones(diag)
cat3.transformer_graphviz(complet=False)
cat3.transformer_graphviz()
lim = cat3.colimites()
for l in lim:
l.transformer_graphviz(destination="graphviz/colimite"+str(lim.index(l)))
for o in cat3.objets:
o.transformer_graphviz()
if __name__ =='__main__':
main()
from Categorie import Categorie
from Foncteur import Foncteur
from Diagramme import Triangle
from Morphisme import Morphisme,Composition
from collections import defaultdict
from itertools import product
from config import *
class CategorieCones(Categorie):
def __init__(self,foncteur):
Categorie.__init__(self,"Categorie de cones de "+str(foncteur))
self.foncteur = foncteur
cones = [e for apex in foncteur.cat_cible.objets for e in foncteur.enumerer_cones(apex)]
self.ajouter_objets(cones)
self.app_morph_fleche_cone = dict() #associe à chaque nouvelle flèche dans la cat_cone la flèche de laquelle elle vient
for cone1,cone2 in product(cones,repeat=2):
fleches_potentielles = self.foncteur.cat_cible.fleches_elem(cone1.apex,cone2.apex)
for obj in self.foncteur.cat_source.objets:
fleches_potentielles = [fleche for fleche in fleches_potentielles if cone1.jambes[obj] == self.foncteur.cat_cible.Composee(fleche,cone2.jambes[obj])]
for fleche in fleches_potentielles:
f = Morphisme(cone1,cone2,str(fleche.representant)+"*")
self.app_morph_fleche_cone[f] = fleche
self.ajouter_morphisme(f)
for cone in self.objets:
cycles_nouvelle_cat = self.trouver_cycles_elementaires(cone)
cycles_ancienne_cat = self.foncteur.cat_cible.trouver_cycles_elementaires(cone.apex)
#on veut établir une correspondance entre les anciens cycles et les nouveaux
nouveau_ancien = {c1:self.foncteur.cat_cible.Composee(*[self.app_morph_fleche_cone[e] for e in c1]) for c1 in cycles_nouvelle_cat}
ancien_nouveau = defaultdict(list)
for cle,valeur in nouveau_ancien.items():
ancien_nouveau[valeur] += [cle]
# Si le cycle est une identite il faut le faire commuter dès le début
for cycle_nouveau in nouveau_ancien:
if nouveau_ancien[cycle_nouveau].is_identite:
t = Triangle(self,[cone]*3,[cycle_nouveau,self.identites[cone],self.identites[cone]])
t.faire_commuter()
# Pour les autres cycles on fait commuter que la frontière de l'arbre de composition
cycles = sorted(self.foncteur.cat_cible.enumerer_cycles(cone.apex),key=len)
for debut_antecedant_ancien,fin_antecedant_ancien in product(cycles, cycles+[self.foncteur.cat_cible.identites[cone.apex]]):
# pour chaque simplification des cycles originels, on fait la même pour les nouveaux cycles
# on peut avoir l'identite dans fin_antecedant_ancien car un cycle simple peut être simplificateur
antecedant_ancien = Composition(debut_antecedant_ancien,fin_antecedant_ancien)
im = self.foncteur.cat_cible.Composee(*antecedant_ancien)
if antecedant_ancien != im: #il y a simplification
for antecedant_nouveau in product(*[ancien_nouveau[e] for e in antecedant_ancien]):
for image_nouveau in product(*[ancien_nouveau[e] for e in im]):
# if self.Composee(*antecedant_nouveau) != self.Composee(*image_nouveau):
# raise Exception("Modification en double de la loi de composition du cycle "+str(self.Composee(*antecedant_nouveau))+" : "+str(self.Composee(*image_nouveau)))
if self.Composee(*antecedant_nouveau) != self.Composee(*image_nouveau):
t = Triangle(self,[cone]*3,[self.Composee(*antecedant_nouveau),self.identites[cone],self.Composee(*image_nouveau)])
t.faire_commuter()
else:
# print("CategorieCones l.48 : On a echappe a la creation du diagramme superflu "+str(self.Composee(*antecedant_nouveau))+" => "+str(self.Composee(*image_nouveau)))
pass
# On retire ensuite les chemins en double
composees = self.enumerer_toutes_composees()
for cone1,cone2 in composees:
comp = sorted([e for e in composees[(cone1,cone2)] if not e.is_identite],key=len)
for c in comp:
antecedant_ancien = Composition(*[self.app_morph_fleche_cone[e] for e in c.composee])
image_ancien = self.foncteur.cat_cible.Composee(*[self.app_morph_fleche_cone[e] for e in c.composee])
if antecedant_ancien != image_ancien:
#il y a simplification
antecedant_nouveau = c
image_nouveau = []
for f in image_ancien:
im_nouveau = []
for f1,f2 in self.app_morph_fleche_cone.items():
if f2 == f:
im_nouveau += [f1]
if len(im_nouveau) == 0:
raise Exception("Pas d'image a la fleche "+str(f))
image_nouveau += [im_nouveau]
for im in product(*image_nouveau):
if im[0].source == antecedant_nouveau[0].source and im[-1].cible == antecedant_nouveau[-1].cible: #on vérifie que ça part et ça arrive au bon endroit
#on vérifie que c'est composable
composable = True
for i in range(len(im)-1):
if im[i].cible != im[i+1].source:
composable = False
break
if not composable:
# print("Warning, on a tente de composer "+' , '.join(map(str,im)))
continue
if self.Composee(*antecedant_nouveau) != self.Composee(*im):
t = Triangle(self,[cone1,cone2,cone2],[self.Composee(*antecedant_nouveau),self.identites[cone2],self.Composee(*im)])
t.faire_commuter()
else:
# print("CategorieCones l.70 : On a echappe a la creation du diagramme superflu "+str(self.Composee(*antecedant_nouveau))+" => "+str(self.Composee(*im)))
pass
else:
# print("Warning : on a pas identifie "+' , '.join(map(str,im))+ " et "+' , '.join(map(str,antecedant_nouveau)))
pass
def limites(self):
"""Trouve la/les limite(s) si elle(s) existe(nt), renvoie une liste vide si aucune limite trouvée
une liste de cônes isomorphes sinon"""
if len(self.objets) > 0:
# On essaie d'aller au bout du graphe, si on boucle, on a trouvé un cycle qu'on doit condenser en un seul noeud
graphe = defaultdict(list)
for cle,val in self.morph_sortants.items():
graphe[cle] = list(map(lambda x:x.cible,val))
noeuds_visites = []
noeud_courant = self.objets[0]
while len(graphe[noeud_courant]) > 0:
noeuds_visites += [noeud_courant]
if graphe[noeud_courant][0] in noeuds_visites:
while noeuds_visites[0] != graphe[noeud_courant][0]:
noeuds_visites.pop(0)
nouveau_noeud = tuple(noeuds_visites)
graphe[nouveau_noeud]
for cle,val in graphe.items():
if cle in noeuds_visites:
graphe[nouveau_noeud] += [e for e in val if e not in noeuds_visites]
else:
noeuds_a_del = [cible for cible in val if cible in noeuds_visites]
if len(noeuds_a_del) > 0:
graphe[cle] += [nouveau_noeud]
graphe[cle] = [e for e in graphe[cle] if e not in noeuds_a_del]
for noeud in noeuds_visites:
del graphe[noeud]
noeuds_visites = []
noeud_courant = nouveau_noeud
continue
noeud_courant = graphe[noeud_courant][0]
while type(noeud_courant) == tuple:
noeud_courant = noeud_courant[0]
noeud_final = noeud_courant
#on est arrivé au bout du chemin
for cone in self.objets:
fleches = self.enumerer_composees(cone,noeud_final)
if len(fleches) != 1:
print(cone)
print()
for f in fleches:
print(f.pretty_print())
print(self.Composee(*f))
print(self.enumerer_cycles(cone))
break
else:
result = [cone for cone in self.objets if len(self.enumerer_composees(noeud_final,cone)) > 0]
if TOUJOURS_VERIFIER_COHERENCE:
for lim in result:
for cone in self.objets:
fleches = self.enumerer_composees(cone,lim)
if len(fleches) != 1:
raise Exception("Incoherence Limite : Une limite n'a pas de fleche unique depuis un autre cone : "+str(lim)+" , "+str(cone))
return result
return []
def main():
# from Diagramme import DiagrammeIdentite
# cat1 = Categorie('Catégorie à 1 flèche')
# cat1.ajouter_objets("AB")
# f = Morphisme('A','B','f')
# cat1.ajouter_morphismes([f])
# cat2 = Categorie('Catégorie double cône')
# cat2.ajouter_objets("ABCD")
# f1,f2,f3,f4,f5,f6,f7 = [Morphisme('A','B',1),Morphisme('A','C',2),Morphisme('D','B',3),Morphisme('D','C',4),
# Morphisme('B','C',5),Morphisme('A','D',6),Morphisme('A','A',7)]
# cat2.ajouter_morphismes([f1,f2,f3,f4,f5,f6])
# d = DiagrammeIdentite(cat2)
# d.faire_commuter()
# cat2.ajouter_morphisme(f7)
# d = Triangle(cat2,"AAA",[cat2.Composee(f7,f7),cat2.identites['A'],f7])
# d.faire_commuter()
# cat2.transformer_graphviz()
# F = Foncteur(cat1,cat2,{'A':'B','B':'C'},{f:f5})
# F.transformer_graphviz()
# cat3 = CategorieCones(F)
# for d in cat3.diagrammes:
# Foncteur.transformer_graphviz(d)
# cat3.transformer_graphviz()
# for cone in cat3.objets:
# cone.transformer_graphviz()
# from CategorieAleatoire import CategorieAleaPreOrdre
# c = CategorieAleaPreOrdre(7,0.3)
# c.transformer_graphviz()
# cat1 = Categorie('Catégorie à 1 flèche')
# cat1.ajouter_objets("AB")
# f = Morphisme('A','B','f')
# cat1.ajouter_morphismes([f])
# F = Foncteur(cat1,c,{'A':c.morphismes[7].source,'B':c.morphismes[7].cible},{f:c.morphismes[7]})
# cat3 = CategorieCones(F)
# cat3.transformer_graphviz()
# lim = cat3.limites()
# for l in lim:
# l.transformer_graphviz(destination="graphviz/limite"+str(lim.index(l)))
# for o in cat3.objets:
# o.transformer_graphviz()
from CategorieAleatoire import CategorieAleaPreOrdre
from Diagramme import DiagrammeAlea
import random
random.seed(811)
c = CategorieAleaPreOrdre(12,0.3)
print("fin gen cat")
c.transformer_graphviz()
diag = DiagrammeAlea(c,3)
diag.transformer_graphviz()
print("fin gen diag")
cat3 = CategorieCones(diag)
cat3.transformer_graphviz(complet=False)
cat3.transformer_graphviz()
lim = cat3.limites()
for l in lim:
l.transformer_graphviz(destination="graphviz/limite"+str(lim.index(l)))
for o in cat3.objets:
o.transformer_graphviz()
if __name__ =='__main__':
main()
......@@ -2,34 +2,26 @@ from Categorie import Categorie
from Morphisme import Morphisme
class MorphismePreordre(Morphisme):
class CategorieMiseEnCache(Categorie):
"""
Il n'y a qu'un seul morphisme pré-ordre entre deux objets d'une catégorie pré-ordre.
Lorsqu'il est coûteux de calculer les morphismes entre deux objets, la catégorie mise en cache permet de ne pas recalculer deux fois ces morphismes.
Lors de l'appel de __call__, les morphismes entre deux objets sont mis en cache,
on empêche aussi la modification ultérieure de la catégorie en supprimant les méthodes __iadd__ et __idel__.
"""
def __init__(self, source:any, cible:any, representant:any=None):
Morphisme.__init__(self,source,cible,representant,source==cible)
def __init__(self, objets:set = set(), nom:str = "Catégorie"):
Categorie.__init__(self,objets,nom)
self._call = dict() # (source,cible) : {Morphismes} dictionnaire qui associe à un couple d'objets un ensemble de morphismes
def __eq__(self,other:'MorphismePreordre') -> bool:
return issubclass(type(self),type(other)) and self.source == other.source and self.cible == other.cible
def __hash__(self) -> int:
return hash((self.source,self.cible))
def __matmul__(self,other:'MorphismePreordre') -> 'MorphismePreordre':
"""
`self` @ `other` <=> `self` o `other`
La composée de deux morphisme pré-ordre est le seul morphisme qui va de la source du premier à la cible du deuxième.
"""
if not issubclass(type(other),MorphismePreordre):
raise Exception("Composition d'un morphisme pre-ordre avec un morphisme de type different : "+str(self)+" o "+str(other))
return MorphismePreordre(other.source,self.cible,str(self)+'o'+str(other))
class CategoriePreordre(Categorie):
"""
Il n'y a qu'un seul morphisme pré-ordre entre deux objets d'une catégorie pré-ordre.
"""
def __call__(self,source:set,cible:set) -> set:
return {MorphismePreordre(a,b) for a in source for b in cible}
def methode_supprimee(self):
raise Exception("Cette methode a ete supprimee lors de la mise en cache par la methode __call__.")
self.__iadd__ = methode_supprimee
self.__idel__ = methode_supprimee
for a in source:
for b in cible:
if (a,b) in self._call:
return self._call[(a,b)]
return self
def identite(self,objet:any) -> MorphismePreordre:
return MorphismePreordre(objet,objet,'Id'+str(objet))
......
from Categorie import Categorie
from Morphisme import Morphisme
from Diagramme import Diagramme
class CategorieOpposee(Categorie):
def __init__(self, cat):
Categorie.__init__(self, "Categorie opoosee de " + str(cat.nom))
for obj in cat.objets:
self.ajouter_objet(obj)
self.app_morph = {cat.identites[o]: self.identites[o] for o in
self.objets} # associe à chaque ancien morphisme son nouveau morphisme opposé
for morph in cat.morphismes:
if not morph.is_identite:
nouveau_morph = Morphisme(morph.cible, morph.source, morph.representant)
self.ajouter_morphisme(nouveau_morph)
self.app_morph[morph] = nouveau_morph
for diag in cat.diagrammes:
nouvelle_cat_source = CategorieOpposee(diag.cat_source)
nouveau_diag = Diagramme(nouvelle_cat_source, self, diag.app_objets,
{nouvelle_cat_source.app_morph[morph]: self.Composee(
*[self.app_morph[m] for m in diag(morph)]) for morph in
diag.cat_source.morphismes if not morph.is_identite})
nouveau_diag.faire_commuter()
self.verifier_coherence()
def main():
from Diagramme import DiagrammeIdentite, Triangle
cat = Categorie('Catégorie double cône')
cat.ajouter_objets("ABCD")
f1, f2, f3, f4, f5, f6, f7 = [Morphisme('A', 'B', 1), Morphisme('A', 'C', 2), Morphisme('D', 'B', 3),
Morphisme('D', 'C', 4),
Morphisme('B', 'C', 5), Morphisme('A', 'D', 6), Morphisme('A', 'A', 7)]
cat.ajouter_morphismes([f1, f2, f3, f4, f5, f6])
cat.transformer_graphviz(destination="graphviz/test")
d = DiagrammeIdentite(cat)
d.transformer_graphviz()
d.faire_commuter()
cat.ajouter_morphisme(f7)
d = Triangle(cat, "AAA", [cat.Composee(f7, f7), cat.identites['A'], f7])
d.faire_commuter()
cat.transformer_graphviz()
cat2 = CategorieOpposee(cat)
cat2.transformer_graphviz()
if __name__ == '__main__':
main()
import Categorie
from Morphisme import Morphisme
import Diagramme
from GrapheDeComposition import GC,MGC
from Diagramme import Triangle,DiagrammeIdentite
gc1 = GC()
gc1 |= set("ABCDEF")
f,g,h,i,j,k,l = [MGC('A','B','f'),MGC('B','C','g'),MGC('D','E','h'),MGC('E','F','i'),MGC('A','D','j'),MGC('B','E','k'),MGC('C','F','l')]
gc1 |= {f,g,h,i,j,k,l}
cat = Categorie.Categorie("Catégorie acyclique")
cat.ajouter_objets("ABCDEF")
f,g,h,i,j,k = [Morphisme('A','B','f'),Morphisme('A','C','g'),Morphisme('B','D','h'),Morphisme('B','E','i'),
Morphisme('C','E','j'),Morphisme('C','F','k')]
cat.ajouter_morphismes([f,g,h,i,j,k])
cat.transformer_graphviz()
diag = Diagramme.Carre(cat,"ABCE",[f,i,g,j])
diag.transformer_graphviz()
\ No newline at end of file
diag_identite = DiagrammeIdentite(gc1)
diag_identite.faire_commuter()
\ No newline at end of file
......@@ -69,18 +69,25 @@ class Foncteur(Morphisme):
if o not in self._app_objets:
raise Exception("Incoherence foncteur : l'application d'objet n'est pas une application, "+str(o)+" n'a pas d'image")
##respect de l'identite
## Respect de l'identite
for objet in self.source.objets:
if self._app_morph[self.source.identite(objet)] != self.cible.identite(self._app_objets[objet]):