Commit d37adedd authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files

Suppression des morphismes de la classe abstraite Categorie

parent 1feb2b01
......@@ -25,8 +25,8 @@ class Categorie:
Pour récapituler :
- abs(C) opérateur pour obtenir les objets
- C(_,_) opérateur pour obtenir des morphismes
- += opérateur pour ajouter des objets et des morphismes
- -= opérateur pour supprimer des objets et morphismes
- |= opérateur pour ajouter des objets
- -= opérateur pour supprimer des objets
Pour toutes les catégories on peut :
- vérifier sa cohérence avec la méthode verifier_coherence
......@@ -38,7 +38,6 @@ class Categorie:
def __init__(self,nom: str = "Catégorie"):
self.nom = nom
self.objets = frozenset()
self.__morphismes = frozenset()
def __call__(self, source: any, cible: any) -> set:
"""
......@@ -60,10 +59,10 @@ class Categorie:
NotImplementedError("Les categories filles doivent implementer cette methode.")
def __eq__(self,other: 'Categorie') -> bool:
return self.nom == other.nom and self.objets == other.objets and self.__morphismes == other.__morphismes
return self.nom == other.nom and self.objets == other.objets
def __hash__(self) -> int:
return hash((self.nom,self.objets,self.__morphismes))
return hash((self.nom,self.objets))
def __str__(self) -> str:
return self.nom
......@@ -75,79 +74,32 @@ class Categorie:
"""
return self.objets
def __iadd__(self,other:any):
def __ior__(self,other:set):
"""
Soit C une catégorie.
C += a_i ajoute l'objet a_i à la catégorie C
C += {a_1,a_2,...} ajoute les objets a_i à la catégorie C
C += f_i ajoute le morphisme f_i à la catégorie C
C += {f_1,f_2,...} ajoute les morphismes f_i à la catégorie C
Si on doit ajouter un objet a_i qui hérite de Morphisme, alors on va l'ajouter en tant que morphisme.
Si on veut ajouter une objet descendant d'un Morphisme en tant qu'objet, il faut utiliser la méthode ajouter_objet.
C |= {a_1,a_2,...} ajoute les objets a_i à la catégorie C.
"""
if issubclass(type(other),Morphisme):
self.ajouter_morphisme(other)
elif type(other) in {frozenset,set,list,tuple}:
for elem in other:
self += elem
else:
self.ajouter_objet(other)
self.objets |= other
return self
def __isub__(self,other:any):
"""
Soit C une catégorie.
C -= a_i supprime l'objet a_i de la catégorie C
C -= {a_1,a_2,...} supprime les objets a_i de la catégorie C
C -= f_i supprime le morphisme f_i de la catégorie C
C -= {f_1,f_2,...} supprime les morphismes f_i de la catégorie C
C -= {a_1,a_2,...} supprime les objets a_i de la catégorie C.
"""
if other in self.objets:
self.supprimer_objet(other)
elif other in self.__morphismes:
self.supprimer_morphisme(other)
elif type(other) in {frozenset,set,list,tuple}:
for elem in other:
self -= elem
else:
raise Exception("Erreur : tentative de retirer "+str(other)+" qui n'appartient pas a la categorie")
self -= other
return self
def ajouter_objet(self,objet:any):
self.objets |= {objet}
def ajouter_morphisme(self,morphisme: Morphisme):
self.__morphismes |= {morphisme}
def supprimer_objet(self, objet: any):
self -= {morph for morph in self(objet,self.objets)}
self -= {morph for morph in self(self.objets,objet)}
self.objets -= {objet} # on supprime l'objet
def supprimer_morphisme(self, morphisme: Morphisme):
self.__morphismes -= {morphisme} # on supprime le morphisme
def verifier_coherence(self):
"""Vérifie la cohérence de la structure (tous les axiomes des catégories sont vérifiés)."""
## On vérifie que les objets et les morphismes sont des ensembles disjoints (un objet ne peut pas être un morphisme en même temps)
if len(self.objets&self.__morphismes) > 0:
raise Exception("Incoherence Categorie : objets et morphismes pas distincts "+str(self.objets&self.__morphismes))
## On vérifie que les sources et les cibles des morphismes sont bien des objets de la catégorie
for morphisme in self.__morphismes:
if morphisme.source not in self.objets:
raise Exception("Incoherence Categorie : le morphisme "+str(morphisme)+" a pour source un objet qui n'est pas dans la categorie")
if morphisme.cible not in self.objets:
raise Exception("Incoherence Categorie : le morphisme "+str(morphisme)+" a pour cible un objet qui n'est pas dans la categorie")
## On vérifie que les identités sont neutres
for morphisme in self.__morphismes:
for morphisme in self(self.objets,self.objets):
if not (morphisme@self.identite(morphisme.source) == self.identite(morphisme.cible)@morphisme == morphisme):
raise Exception("Incoherence Categorie : le morphisme "+str(morphisme)+" est modifie par une identite.")
## On vérifie l'associativité
for m1,m2,m3 in itertools.product(sorted(self.__morphismes),repeat=3):
for m1,m2,m3 in itertools.product(sorted(self(self.objets,self.objets)),repeat=3):
if m1.source == m2.cible and m2.source == m3.cible:
if (m1@m2)@m3 != m1@(m2@m3):
raise Exception("Incoherence Categorie : associativite pas respectee pour "+str(m1)+", "+str(m2)+", "+str(m3)+\
......@@ -215,9 +167,9 @@ class Categorie:
def test_Categorie():
from GrapheDeComposition import GC,MGC
GC = GC()
GC += {'A','B','C'}
GC |= {'A','B','C'}
morphismes = [MGC('A','B','f'),MGC('B','C','g')]
GC += morphismes
GC |= morphismes
GC.transformer_graphviz()
GC.loi_de_composition_to_csv()
......@@ -231,8 +183,7 @@ class SousCategoriePleine(Categorie):
def __init__(self, categorie_originelle:Categorie, objets:set):
"""On construit la sous-catégorie pleine de `categorie_originelle` qui contient l'ensemble des `objets`."""
Categorie.__init__(self,"Sous-catégorie pleine de "+str(categorie_originelle)+ " ayant pour objets "+str(objets))
self += objets
self += categorie_originelle(objets,objets)
self |= objets
self.categorie_originelle = categorie_originelle
def __call__(self, source:any, cible:any) -> set:
......@@ -244,9 +195,9 @@ class SousCategoriePleine(Categorie):
def test_SousCategoriePleine():
from GrapheDeComposition import GC,MGC
GC = GC()
GC += set("ABCDE")
GC |= set("ABCDE")
morphismes = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','E','i'),MGC('C','E','j')]
GC += morphismes
GC |= morphismes
GC.transformer_graphviz()
sous_cat_pleine = SousCategoriePleine(GC,set("ADE"))
......@@ -294,7 +245,7 @@ class CategorieDiscrete(Categorie):
def test_CategorieDiscrete():
cat_discrete = CategorieDiscrete()
cat_discrete += set("ABCDE")
cat_discrete |= set("ABCDE")
cat_discrete.transformer_graphviz(afficher_identites=True)
......
......@@ -22,11 +22,11 @@ class GrapheCompositionAleatoire(GC):
print("Création d'une catégorie avec "+str(nb_objets)+" objets et "+str(nb_morph)+" morphismes")
for i in range(nb_objets): #ajout des objets
self += i
self |= i
for i in range(nb_morph): # ajout des morphismes
source = random.randint(0,nb_objets-1)
cible = random.randint(0,nb_objets-1)
self += MGC(source,cible)
self |= MGC(source,cible)
## on définit la loi de composition pour les cycles
for obj in sorted(self.objets):
......
......@@ -126,7 +126,7 @@ class CategorieLibre(Categorie):
return cycles|{self.identite(objet)}
return cycles-{self.identite(objet)}
def enumerer_cycles(self, objet:any, limite_profondeur:int = 6) -> frozenset:
def enumerer_cycles(self, objet:any, limite_profondeur:int = 3) -> frozenset:
"""Enumère toutes les compositions de `objet` à `objet`.
Si f et g sont des cycles minimaux, on doit énumérer tous les mots d'alphabet {f,g}.
Pour ça on s'intéresse aux compositions qui se réduisent en composition déjà générées.
......
......@@ -43,11 +43,11 @@ class CategoriePreordre(Categorie):
def test_CategoriePreordre():
cat = CategoriePreordre()
cat += set("ABCDEF")
cat |= set("ABCDEF")
MPO = MorphismePreordre
f,g,h,i,j,k,l,m = [MPO('A','B','f'),MPO('C','D','g'),MPO('D','E','h'),MPO('E','A','i'),
MPO('F','D','j'),MPO('F','E','k'),MPO('D','B','l'),MPO('B','E','m')]
cat += {f,g,h,i,j,k,l,m}
cat |= {f,g,h,i,j,k,l,m}
cat.transformer_graphviz()
cat.transformer_graphviz()
......
......@@ -57,6 +57,12 @@ class FlecheCommaCategorie(Morphisme):
def __matmul__(self,other:'FlecheCommaCategorie') -> 'FlecheCommaCategorie':
return FlecheCommaCategorie(other.source,self.cible,self.k@other.k,self.h@other.h)
def __eq__(self,other:'FlecheCommaCategorie') -> bool:
return self.k == other.k and self.h == other.h
def __hash__(self) -> int:
return hash((self.k,self.h))
class CommaCategorie(Categorie):
"""
......@@ -70,13 +76,19 @@ class CommaCategorie(Categorie):
if T.cible != S.cible:
raise Exception("Incoherence CommaCategorie : T et S de cibles differentes : "+str(T)+" vs "+str(S))
self.__C = T.cible
self.__T = T
self.__S = S
self += {ObjetCommaCategorie(e,f,d) for e in T.source.objets for d in S.source.objets for f in self.__C(T(e),S(d))} # on ajoute tous les objets
self._T = T
self._S = S
self |= {ObjetCommaCategorie(e,f,d) for e in T.source.objets for d in S.source.objets for f in self.__C(T(e),S(d))} # on ajoute tous les objets
def __eq__(self, other:'CommaCategorie') -> bool:
return self._T == other._T and self._S == other._S
def __hash__(self) -> int:
return hash((self._T,self._S))
def identite(self, objet:ObjetCommaCategorie) -> FlecheCommaCategorie:
'''L'identité pour un objet (e,f,d) est la paire d'identité de T(e) et S(d).'''
return FlecheCommaCategorie(objet,objet,self.__C.identite(self.__T(objet.e)),self.__C.identite(self.__S(objet.d)))
return FlecheCommaCategorie(objet,objet,self.__C.identite(self._T(objet.e)),self.__C.identite(self._S(objet.d)))
def __call__(self, source:ObjetCommaCategorie, cible:ObjetCommaCategorie) -> set:
if source in self.objets:
......@@ -89,9 +101,9 @@ class CommaCategorie(Categorie):
result = set()
for a in source:
for b in cible:
for k in self.__T.source(a.e,b.e):
for h in self.__S.source(a.d,b.d):
if b.f@self.__T(k) == self.__S(h)@a.f:
for k in self._T.source(a.e,b.e):
for h in self._S.source(a.d,b.d):
if b.f@self._T(k) == self._S(h)@a.f:
result |= {FlecheCommaCategorie(a,b,k,h)}
return result
......@@ -131,26 +143,23 @@ SliceCategorie = CategorieSur
def test_CategorieFleches():
from GrapheDeComposition import GC,MGC
from Diagramme import DiagrammeIdentite
cat = GC('C')
cat += {'A','B','C'}
cat |= {'A','B','C'}
morphismes = [MGC('A','B','f'),MGC('B','C','g')]
cat += morphismes
cat |= morphismes
cat.transformer_graphviz()
cat_fleches = CategorieFleches(cat)
cat_fleches.transformer_graphviz()
def test_CategorieSous():
from GrapheDeComposition import GC,MGC
from Diagramme import DiagrammeIdentite
cat = GC('C')
cat += {'A','B','C','D','E'}
cat |= {'A','B','C','D','E'}
morphismes = [MGC('A','B','f'),MGC('B','C','g'),MGC('C','D','h'),MGC('E','C','i'),MGC('E','A','j')]
cat += morphismes
cat |= morphismes
cat.transformer_graphviz()
cat_sous = CategorieSous(cat,'B')
......@@ -159,12 +168,11 @@ def test_CategorieSous():
def test_CategorieSur():
from GrapheDeComposition import GC,MGC
from Diagramme import DiagrammeIdentite
cat = GC('C')
cat += {'A','B','C','D','E'}
cat |= {'A','B','C','D','E'}
morphismes = [MGC('A','B','f'),MGC('B','C','g'),MGC('C','D','h'),MGC('E','C','i'),MGC('E','A','j')]
cat += morphismes
cat |= morphismes
cat.transformer_graphviz()
cat_sur = CategorieSur(cat,'B')
......
......@@ -18,6 +18,7 @@ class Diagramme(Foncteur):
application_objets:dict, application_morphismes:dict, representant:any = None):
Foncteur.__init__(self,categorie_indexante,categorie_indexee, application_objets,
application_morphismes,representant=representant if representant != None else "Diagramme "+str(Morphisme._id))
def faire_commuter(self):
"""
Change la loi de composition de `MorphismeGrapheDeComposition` pour que le diagramme commute.
......@@ -63,12 +64,10 @@ class Diagramme(Foncteur):
raise Exception("Appel d'implementation sur un diagramme dont la cible n'est pas un graphe de composition.")
result = GrapheDeComposition("Implementation de "+str(self))
for obj in self._app_objets:
result += self(obj)
for morph in self._app_morph:
if not morph.is_identite:
result += self(morph)
result |= self(obj)
return result
def champ_perceptif(self):
import CategorieCones
return CategorieCones.CategorieCones(self)
......@@ -263,14 +262,14 @@ class Diagramme(Foncteur):
def test_Diagramme():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
paralelle = GC()
paralelle += set("12")
paralelle |= set("12")
a,b = [MGC('1','2','a'),MGC('1','2','b')]
paralelle += {a,b}
paralelle |= {a,b}
diagramme = Diagramme(paralelle,cat,{'1':'A','2':'C'},{a:g@f,b:i@h})
diagramme.transformer_graphviz()
......@@ -285,33 +284,33 @@ class DiagrammeObjets(Diagramme):
def __init__(self, categorie_indexee:Categorie, objets_a_selectionner:set):
"""`objets_a_selectionner` est une listes d'objets à selectionner dans la catégorie."""
cat = CategorieDiscrete("Objets")
cat += set(range(len(objets_a_selectionner)))
cat |= set(range(len(objets_a_selectionner)))
objets_a_selectionner = list(objets_a_selectionner)
Diagramme.__init__(self,cat,categorie_indexee,{i:objets_a_selectionner[i] for i in range(len(objets_a_selectionner))},dict(),representant="O("+','.join(map(str,objets_a_selectionner))+")")
def test_DiagrammeObjets():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
diag = DiagrammeObjets(cat,"ABCA")
diag.transformer_graphviz()
class Fleche(Diagramme):
"""Permet de selectionner deux objets réliés par une flèche"""
_cat = GrapheDeComposition("1 Flèche")
_cat += {1,2}
_cat |= {1,2}
_f = MorphismeGrapheDeComposition(1,2,'f')
_cat += _f
_cat |= _f
def __init__(self, categorie_indexee:Categorie, fleche_a_selectionner:Morphisme):
Diagramme.__init__(self,Fleche._cat,categorie_indexee,{1:fleche_a_selectionner.source,2:fleche_a_selectionner.cible},{Fleche._f:fleche_a_selectionner},representant="Fleche "+str(fleche_a_selectionner))
def test_Fleche():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
diag = Fleche(cat,h)
diag.transformer_graphviz()
......@@ -320,28 +319,28 @@ class Chemins(Diagramme):
def __init__(self,categorie_indexee:Categorie, source:any, cible:any):
cat = GrapheDeComposition('Chemins')
cat += {1,2}
cat |= {1,2}
chemins = list(categorie_indexee(source,cible))
morphismes = list(map(lambda x:MorphismeGrapheDeComposition(1,2,x),range(len(chemins))))
cat += morphismes
cat |= morphismes
Diagramme.__init__(self,cat,categorie_indexee,{1:source,2:cible},
{morphismes[i]:chemins[i] for i in range(len(chemins))}, 'Chemins de '+str(source)+' vers '+str(cible))
def test_Chemins():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
diag = Chemins(cat,'A','C')
diag.transformer_graphviz()
class Parallele(Diagramme):
_cat = GrapheDeComposition("Parallele")
_cat += {1,2}
_cat |= {1,2}
f = MorphismeGrapheDeComposition(1,2,'f')
g = MorphismeGrapheDeComposition(1,2,'g')
morphismes = [f,g]
_cat += morphismes
_cat |= morphismes
def __init__(self, categorie_indexee:Categorie, image_objets:list, image_morphismes:list):
""" 1 ---> 2
......@@ -356,21 +355,21 @@ class Parallele(Diagramme):
def test_Parallele():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
diag = Parallele(cat,['A','C'],[g@f,i@h])
diag.transformer_graphviz()
class Triangle(Diagramme):
_cat = GrapheDeComposition("Triangle")
_cat += {1,2,3}
_cat |= {1,2,3}
f = MorphismeGrapheDeComposition(1,2,'f')
g = MorphismeGrapheDeComposition(2,3,'g')
h = MorphismeGrapheDeComposition(1,3,'h')
morphismes = [f,g,h]
_cat += morphismes
_cat |= morphismes
def __init__(self, categorie_indexee:Categorie, image_objets:list, image_morphismes:list):
""" h
......@@ -387,23 +386,23 @@ class Triangle(Diagramme):
def test_Triangle():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
diag = Triangle(cat,['A','B','C'],[f,g,g@f])
diag.transformer_graphviz()
class Carre(Diagramme):
_cat = GrapheDeComposition("Carre")
_cat += {1,2,3,4}
_cat |= {1,2,3,4}
f = MorphismeGrapheDeComposition(1,2,'f')
g = MorphismeGrapheDeComposition(2,4,'g')
h = MorphismeGrapheDeComposition(1,3,'h')
i = MorphismeGrapheDeComposition(3,4,'i')
morphismes = [f,g,h,i]
_cat += morphismes
_cat |= morphismes
def __init__(self, categorie_indexee:Categorie, image_objets:list, image_morphismes:list):
""" h
......@@ -421,9 +420,9 @@ class Carre(Diagramme):
def test_Carre():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
diag = Carre(cat,['A','B','D','C'],[f,g,h,i])
diag.transformer_graphviz()
......@@ -436,9 +435,9 @@ class DiagrammeIdentite(Diagramme):
def test_DiagrammeIdentite():
cat = GC()
cat += set("ABCD")
cat |= set("ABCD")
f,g,h,i = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','D','h'),MGC('D','C','i')]
cat += {f,g,h,i}
cat |= {f,g,h,i}
diag = DiagrammeIdentite(cat)
diag.transformer_graphviz()
diag.faire_commuter()
......
......@@ -203,22 +203,22 @@ class Foncteur(Morphisme):
def test_Foncteur():
from GrapheDeComposition import GC,MGC
triangle = GC()
triangle+= {'A','B','C'}
triangle|= {'A','B','C'}
f1,g1= [MGC('A','B','f'),MGC('B','C','g')]
triangle += {f1,g1}
triangle |= {f1,g1}
carre = GC()
carre += {1,2,3,4}
carre |= {1,2,3,4}
f,g,h,i = [MGC(1,2,'f'),MGC(2,4,'g'),MGC(1,3,'h'),MGC(3,4,'i')]
morphismes_carre = {f,g,h,i}
carre += morphismes_carre
carre |= morphismes_carre
pentagone = GC()
pentagone += set("VWXYZ")
pentagone |= set("VWXYZ")
a,b,c,d,e = [MGC('X','Y','a'),MGC('Y','Z','b'),MGC('W','V','c'),MGC('W','X','d'),MGC('V','Z','e')]
pentagone += {a,b,c,d,e}
pentagone |= {a,b,c,d,e}
pentagone.transformer_graphviz()
app_obj = {'A':1,'B':2,'C':4}
......
......@@ -120,7 +120,7 @@ class GrapheDeComposition(CategorieLibre):
Un modèle de graphe de composition est la catégorie libre engendrée par ce graphe de composition.
Cette classe implémente les deux concepts ci-dessus, on peut modifier le graphe de composition et obtenir les morphismes du modèle.
Concrètement, pour un modèle de graphe de composition, on peut :
- ajouter un objet ou un morphisme
- ajouter un objet ou un morphisme avec |=
- faire commuter un diagramme qui a pour cible ce modèle pour identifier des flèches
"""
......@@ -130,6 +130,11 @@ class GrapheDeComposition(CategorieLibre):
self.__morph_entrants = defaultdict(frozenset)
self.__morph_sortants = defaultdict(frozenset)
def verifier_coherence(self):
CategorieLibre.verifier_coherence(self)
if self.objets != set(self.__identites.keys()):
raise Exception("Incohérence GrapheDeComposition : il n'y a pas correspondance entre identités et objets : "+str(self.objets)+"\n"+str(self.__identites))
def __eq__(self,other:'GrapheDeComposition') -> bool:
return CategorieLibre.__eq__(self,other) and self.__identites == other.__identites and\
self.__morph_entrants == other.__morph_entrants and self.__morph_sortants == other.__morph_sortants
......@@ -139,42 +144,50 @@ class GrapheDeComposition(CategorieLibre):
frozenset(self.__morph_entrants.items()),frozenset(self.__morph_sortants.items())))
def identite(self,objet:any) -> MorphismeGrapheDeComposition:
if objet not in self.__identites:
print(objet)
print(self.__identites)
return self.__identites[objet]
def ajouter_objet(self,objet:any):
def __ior__(self,ensemble_objet_ou_morphisme:set):
"""
`objet_ou_morphisme` est considéré comme un morphisme s'il hérite de MorphismeGrapheDeComposition, c'est un objet sinon.
Si on veut ajouter un morphisme en tant qu'objet, appeler Categorie.__ior__(cat,morphisme).
Si le `morphisme` n'appartient pas déjà à la catégorie :
on met à jour le graphe de composition en mettant à jour les dictionnaires morph_entrants et morph_sortants.
Si l'`objet` n'appartient pas déjà à la catégorie :
on ajoute l'`objet`,
on créé une identité,
on met à jour le graphe de composition en mettant à jour les dictionnaires morph_entrants et morph_sortants.
"""
if objet not in self.objets:
Categorie.ajouter_objet(self,objet)
self.__identites[objet] = MorphismeGrapheDeComposition(objet,objet,'Id'+str(objet),True)
self.__morph_entrants[objet] |= {self.__identites[objet]}
self.__morph_sortants[objet] |= {self.__identites[objet]}
for objet_ou_morphisme in ensemble_objet_ou_morphisme:
if issubclass(type(objet_ou_morphisme), MorphismeGrapheDeComposition):
if not objet_ou_morphisme.is_identite:
self.__morph_entrants[objet_ou_morphisme.cible] |= {objet_ou_morphisme}
self.__morph_sortants[objet_ou_morphisme.source] |= {objet_ou_morphisme}
elif objet_ou_morphisme not in self.objets:
self.objets |= {objet_ou_morphisme}
self.__identites[objet_ou_morphisme] = MorphismeGrapheDeComposition(objet_ou_morphisme,objet_ou_morphisme,'Id'+str(objet_ou_morphisme),True)
self.__morph_entrants[objet_ou_morphisme] |= {self.__identites[objet_ou_morphisme]}
self.__morph_sortants[objet_ou_morphisme] |= {self.__identites[objet_ou_morphisme]}
if TOUJOURS_VERIFIER_COHERENCE:
self.verifier_coherence()
return self
def ajouter_morphisme(self,morphisme:MorphismeGrapheDeComposition):
"""
Si le `morphisme` n'appartient pas déjà à la catégorie :
on ajoute le `morphisme`,
on met à jour le graphe de composition en mettant à jour les dictionnaires morph_entrants et morph_sortants.
"""
Categorie.ajouter_morphisme(self,morphisme)
if not morphisme.is_identite:
self.__morph_entrants[morphisme.cible] |= {morphisme}
self.__morph_sortants[morphisme.source] |= {morphisme}
def supprimer_objet(self, objet:any):
'''On supprime l'`objet` et son identité.'''
Categorie.supprimer_objet(self,objet)
def __isub__(self, ensemble_objet_ou_morphisme:set):
'''
On supprime l'`objet` et son identité.