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

Début catégorie quotient

parent e14734af
from Categorie import Categorie
from Morphisme import Morphisme
from typing import *
class ObjetQuotient(set):
"""Objet d'une catégorie après le passage au quotient.
Un `ObjetQuotient` est donc une classe d'équivalence d'objets de la catégorie initiale."""
pass
class MorphismeQuotient(Morphisme):
"""Morphisme d'une catégorie après le passage au quotient.
Un `MorphismeQuotient` est donc une classe d'équivalence de morphismes de la catégorie initiale.
On peut itérer sur le morphisme pour obtenir tous les morphismes initiaux qui ont généré le `MorphismeQuotient`."""
def __init__(self, source:ObjetQuotient, cible:ObjetQuotient, morphismes:Set[Morphisme], nom:str = None):
Morphisme.__init__(self,source,cible,nom,any(map(lambda x:x.id_identite,morphismes)))
self._classe_morphismes = morphismes
def __iter__(self) -> Generator[Morphisme,None,None]:
for m in self._classe_morphismes:
yield m
def __repr__(self) -> str:
return '{'+','.join(map(str,self._classe_morphismes))+'}'
def __matmul__(self,other:'MorphismeQuotient') -> 'MorphismeQuotient':
return MorphismeQuotient(other.source,self.cible,{m2@m1 for m1 in other for m2 in self})
class CategorieQuotient(CategorieLibre):
"""Définit ce qu'est une catégorie quotient.
Les classes filles doivent surcharger une méthode :
- rel_equiv_morph : fonction qui définit la relation d'équivalence sur les morphismes
(les identités équivalentes définissent la relation d'équivalence sur les objets)."""
def __init__(self,categorie_a_quotienter:Categorie, nom:str = None):
Categorie.__init__(nom if nom != None else "Catégorie quotient de "+str(categorie_a_quotienter))
c = categorie_a_quotienter
self.categorie_a_quotienter = c
self._obj_vers_classe = dict() # associe à chaque objet son `ObjetQuotient` associé
morph_vers_classe = dict() # associe à chaque morphisme sa classe d'équivalence
classe_vers_morph = dict()
for obj in c.objets:
for cle in self._obj_vers_classe:
if self.rel_equiv_morph(c.identite(cle),c.identite(obj)):
self._obj_vers_classe[cle] |= {obj}
self._obj_vers_classe[obj] = self._obj_vers_classe[cle]
break
else:
self._obj_vers_classe[obj] = ObjetQuotient({obj})
for morph in c[c.objets,c.objets]:
for cle in morph_vers_classe:
if self.rel_equiv_morph(morph,cle):
morph_vers_classe[morph] = morph_vers_classe[cle]
classe_vers_morph[morph_vers_classe[cle]] |= {morph}
break
else:
morph_vers_classe[morph] = len(list(morph_vers_classe.values()))+1
classe_vers_morph[morph_vers_classe[morph]] = {morph}
classe_vers_morph_quotient = {classe:MorphismeQuotient(self._obj_vers_classe[classe_vers_morph[classe][0].source],\
self._obj_vers_classe[classe_vers_morph[classe][0].cible],classe_vers_morph[classe]) for classe in classe_vers_morph}
self._morph_vers_classe = {m:classe_vers_morph_quotient[morph_vers_classe[m]] for m in c[c.objets,c.objets]}
self |= set(self._obj_vers_classe.values())
def __getitem__(self,couple_sources_cibles:tuple) -> Generator[MorphismeQuotient,None,None]:
sources,cibles = couple_sources_cibles
for source in sources:
for cible in cibles:
\ No newline at end of file
......@@ -72,3 +72,9 @@ Catégorie aléatoire : laisser la possibilité que la composition donne l'ident
-1 donne les morphismes eux même lorsque composés (identité)
si source et target dans même classes d'équivalence, alors ajouter l'outcome -1
La catégorie squelettique n'est pas une catégorie squelettique, les cycles ne sont pas forcément des isomorphismes.
Trouver un autre nom pour ces catégories
Faire un argument par défaut pour call et getitem pour qu'on ai besoin de rien mettre pour avoir toutes les flèches
Markdown is supported
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