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

CatOrdreTotal

parent 14e01209
......@@ -4,7 +4,7 @@ from Morphisme import Morphisme
import itertools
class CategorieAcyclique(CategorieQuotient):
"""`CategorieAcyclique` peut être abrégé en `CatAcyclique`.
"""`CategorieAcyclique` peut être abrégé en `CatAcyclique` ou en 'CatOrdre'.
Catégorie quotientée par la relation d'équivalence sur les objets suivante :
x ~ y ssi il existe f: x -> y et il existe g: y -> x."""
......@@ -24,7 +24,8 @@ class CategorieAcyclique(CategorieQuotient):
for m in categorie_a_quotienter({obj1},{obj1}):
self.identifier_morphismes(m,categorie_a_quotienter.identite(obj1))
CatAcyclique = CategorieAcyclique
CatAcyclique = CategorieAcyclique
CatOrdre = CatAcyclique
def test_CategorieAcyclique():
from CategorieAleatoire import GrapheCompositionAleatoire
......
......@@ -6,7 +6,7 @@ from CategorieProduit import CategorieProduit
from CategorieLibre import CategorieLibre
from CategorieComposantesConnexes import CatCC
from CategorieAcyclique import CatAcyclique
from CategorieFine import CategorieFine
from CategorieFine import CatFine
import random
import copy
import itertools
......@@ -387,7 +387,51 @@ def test_FoncteurAleatoireCatCC():
f.transformer_graphviz()
class FoncteurAleatoireCatFineAcycliqueConnexe(Foncteur):
"""Foncteur aléatoire entre deux catégories acycliques connexes."""
"""Foncteur aléatoire entre deux catégories fines acycliques et connexes."""
def __init__(self, categorie_indexante:Categorie, categorie_cible:Categorie, nom:Union[str,None] = None):
'''Les deux catégories doivent être fines, acycliques et connexes.'''
#todo : vérifier ques les catégories sont fines, acycliques et connexes
cat1,cat2 = categorie_indexante,categorie_cible
app_obj, app_morph = dict(),dict()
morph = None
for f in cat1[cat1.objets,cat1.objets]:
if not f.is_identite:
morph = f
break
if morph == None:
#il n'y a qu'une identité dans cat1 (il ne peut pas y en avoir plusieurs puisqu'on est dans une composante connexe)
app_obj[list(cat1.objets)[0]] = random.choice(list(cat2.objets))
else:
# on doit mapper le morphisme morph
fleches_deja_map = {morph}
app_morph[morph] = random.choice(list(cat2(cat2.objets,cat2.objets)))
app_obj[morph.source] = app_morph[morph].source
app_obj[morph.cible] = app_morph[morph].cible
print(morph,app_morph[morph])
continuer = True
while continuer:
continuer = False
for fleche_deja_map in fleches_deja_map:
for fleche_a_map in cat1[{fleche_deja_map.cible},cat1.objets]:
if fleche_a_map not in fleches_deja_map and not fleche_a_map.is_identite:
image = random.choice(list(cat2({app_obj[fleche_deja_map.cible]},cat2.objets)))
print(fleche_a_map,image)
fleche_deja_map |= {fleche_a_map}
app_morph[fleche_a_map] = image
app_obj[fleche_a_map.cible] = image.cible
continuer = True
for fleche_a_map in cat1[cat1.objets,{fleche_deja_map.source}]:
if fleche_a_map not in fleches_deja_map and not fleche_a_map.is_identite:
image = random.choice(list(cat2(cat2.objets,{app_obj[fleche_deja_map.source]})))
print(fleche_a_map,image)
fleche_deja_map |= {fleche_a_map}
app_morph[fleche_a_map] = image
app_obj[fleche_a_map.source] = image.source
continuer = True
Foncteur.__init__(self,cat1,cat2,app_obj,app_morph)
def test_FoncteurAleatoireCatFineAcycliqueConnexe():
import random
......@@ -396,7 +440,16 @@ def test_FoncteurAleatoireCatFineAcycliqueConnexe():
c1,c2 = GrapheCompositionAleatoire(),GrapheCompositionAleatoire()
c1.transformer_graphviz()
c2.transformer_graphviz()
f = FoncteurAleatoireCatFineAcycliqueConnexe(c1,c2)
c1,c2 = CatCC(c1),CatCC(c2)
c1.transformer_graphviz()
c2.transformer_graphviz()
c1_,c2_ = CatFine(CatAcyclique(c1.sous_cat_equiv(list(c1.objets)[0]))),CatFine(CatAcyclique(c2.sous_cat_equiv(list(c2.objets)[0])))
c1_.transformer_graphviz()
c2_.transformer_graphviz()
f = FoncteurAleatoireCatFineAcycliqueConnexe(c1_,c2_)
f.transformer_graphviz()
f.as_diagram().transformer_graphviz()
class FoncteurAleatoireCatAcycliques(Foncteur):
"""Foncteur aléatoire entre deux catégories acycliques."""
......
from Categorie import Categorie
from Foncteur import Foncteur
from CategorieQuotient import CategorieQuotient
from Morphisme import Morphisme
import itertools
from typing import *
class CategorieFine(CategorieQuotient):
"""`CategorieFine` est similaire à `CategoriePreordre`, elle passe par une catégorie quotient contrairement à cette dernière.
"""`CategorieFine` peut être abrégé en CatFine
`CategorieFine` est similaire à `CategoriePreordre`, elle passe par une catégorie quotient contrairement à cette dernière.
Catégorie quotientée par la relation d'équivalence sur les morphismes suivante :
f : A->B ~ g : C->D ssi A = C et B = D"""
......@@ -16,10 +15,9 @@ class CategorieFine(CategorieQuotient):
nom = "Catégorie fine engendrée par "+str(categorie_a_quotienter)
CategorieQuotient.__init__(self,categorie_a_quotienter,nom)
for obj1, obj2 in itertools.product(categorie_a_quotienter.objets,repeat=2):
morphismes = list(categorie_a_quotienter({obj1},{obj2}))
for morph in morphismes[1:]:
self.identifier_morphismes(morph,morphismes[0])
self.identifier_ensemble_morphismes(set(categorie_a_quotienter({obj1},{obj2})))
CatFine = CategorieFine
def test_CategorieFine():
from CategorieAleatoire import GrapheCompositionAleatoire
......
from Categorie import Categorie
from CategorieAcyclique import CatOrdre
from CategorieQuotient import CategorieQuotient
import copy
import itertools
from typing import *
class CategorieQuasiOrdreTotal(CategorieQuotient):
"""`CategorieQuasiOrdreTotal` peut être abrégé en `CatQuasiOrdreTotal`
Catégorie qui correspond à une quasi-relation d'ordre totale : catégorie acyclique telle que tous les éléments sont comparables (toutes les flèches sont composables).
/!\ il peut cependant y avoir plusieurs flèches entre deux objets contrairement à `CategorieOrdreTotal`/!\
Catégorie quotientée par la relation d'équivalence sur les objets suivante :
Les objets sans père sont équivalents.
Les enfants de ces objets sont équivalents (les enfants de A sont des objets B tel qu'il existe une flèche de A vers B mais il n'existe aucune flèche d'un C vers B tel qu'il existe une flèche de A vers C).
Les enfants des enfants de ces objets sont équivalents.
etc.
"""
def __init__(self,categorie_a_quotienter:CatOrdre, nom:str = None):
if nom == None:
nom = "Catégorie quasi-ordre total engendrée par "+str(categorie_a_quotienter)
CategorieQuotient.__init__(self,categorie_a_quotienter,nom)
cat = categorie_a_quotienter # on a besoin que d'une flèche entre deux objets
noeuds_courants = {obj for obj in cat.objets if all(map(lambda x:x.is_identite,cat[cat.objets,{obj}]))} # les objets sans père n'ont que l'identité comme flèche entrante
self.identifier_ensemble_morphismes(set(map(lambda x:cat.identite(x),noeuds_courants))) # on identifie les identités des objets de départ
while len(noeuds_courants) > 0:
fleches_descendantes = {f for f in cat(noeuds_courants,cat.objets) if not f.is_identite}
print(fleches_descendantes)
fils_associes = set(map(lambda x:x.cible,fleches_descendantes))
vrais_fils = copy.copy(fils_associes)
for fils in fils_associes:
vrais_fils -= {f.cible for f in cat({fils},cat.objets) if not f.is_identite}
fleches_courantes = set(cat(noeuds_courants,vrais_fils))
self.identifier_ensemble_morphismes(set(map(lambda x:cat.identite(x.cible),fleches_courantes))) # on identifie les identités des cibles des flèches courantes
self.identifier_ensemble_morphismes(fleches_courantes) # on identifie les identités des cibles des flèches courantes
noeuds_courants = vrais_fils
CatQuasiOrdreTotal = CategorieQuasiOrdreTotal
def test_CatQuasiOrdreTotal():
from CategorieAleatoire import GrapheCompositionAleatoire
import random
random.seed(3)
for i in range(10):
c = GrapheCompositionAleatoire()
c.transformer_graphviz()
c_o = CatOrdre(c)
c_o.transformer_graphviz()
c_ot = CatQuasiOrdreTotal(c_o)
c_ot.transformer_graphviz()
class CategorieOrdreTotal(CategorieQuotient):
"""`CategorieOrdreTotal` peut être abrégé en `CatOrdreTotal`
Catégorie qui correspond à une quasi-relation d'ordre totale : catégorie acyclique telle que tous les éléments sont comparables (toutes les flèches sont composables).
/!\ il peut cependant y avoir plusieurs flèches entre deux objets contrairement à `CategorieOrdreTotal`/!\
Catégorie quotientée par la relation d'équivalence sur les objets suivante :
Les objets sans père sont équivalents.
Les enfants de ces objets sont équivalents (les enfants de A sont des objets B tel qu'il existe une flèche de A vers B mais il n'existe aucune flèche d'un C vers B tel qu'il existe une flèche de A vers C).
Les enfants des enfants de ces objets sont équivalents.
etc.
"""
def __init__(self,categorie_a_quotienter:CatQuasiOrdreTotal, nom:str = None):
if nom == None:
nom = "Catégorie ordre total engendrée par "+str(categorie_a_quotienter)
CategorieQuotient.__init__(self,categorie_a_quotienter,nom)
# simples contraintes de catégorie fine
for obj1, obj2 in itertools.product(categorie_a_quotienter.objets,repeat=2):
self.identifier_ensemble_morphismes(set(categorie_a_quotienter({obj1},{obj2})))
CatOrdreTotal = CategorieOrdreTotal
def test_CatOrdreTotal():
from CategorieAleatoire import GrapheCompositionAleatoire
import random
random.seed(3)
for i in range(10):
c = GrapheCompositionAleatoire()
c_o = CatOrdre(c)
c_qot = CategorieQuasiOrdreTotal(c_o)
c_ot = CatOrdreTotal(c_qot)
c_ot.transformer_graphviz()
if __name__ == '__main__':
test_CatQuasiOrdreTotal()
test_CatOrdreTotal()
\ No newline at end of file
......@@ -132,6 +132,12 @@ class CategorieQuotient(CategorieLibre):
if m3.cible == m4.source:
if self._morph_vers_classe[m2@m1] != self._morph_vers_classe[m4@m3]:
self.identifier_morphismes(m2@m1,m4@m3)
def identifier_ensemble_morphismes(self, ens_morph:set):
"""Identifie l'ensemble des morphismes entre eux."""
liste_morph = list(ens_morph)
for m in liste_morph[1:]:
self.identifier_morphismes(m,liste_morph[0])
@property
def fonct_surjection(self) -> Foncteur:
......
......@@ -139,13 +139,13 @@ class CommaCategorie(CategorieLibre):
if obj_comma_cible.f@self._T(k) == self._S(h)@obj_comma_source.f:
yield FlecheCommaCategorie(obj_comma_source,obj_comma_cible,k,h)
def __call__(self, sources:set, cibles:set) -> Generator[FlecheCommaCategorie, None, None]:
for obj_comma_source in sources:
for obj_comma_cible in cibles:
for k in self._T.source({obj_comma_source.e},{obj_comma_cible.e}):
for h in self._S.source({obj_comma_source.d},{obj_comma_cible.d}):
if obj_comma_cible.f@self._T(k) == self._S(h)@obj_comma_source.f:
yield FlecheCommaCategorie(obj_comma_source,obj_comma_cible,k,h)
# def __call__(self, sources:set, cibles:set) -> Generator[FlecheCommaCategorie, None, None]:
# for obj_comma_source in sources:
# for obj_comma_cible in cibles:
# for k in self._T.source({obj_comma_source.e},{obj_comma_cible.e}):
# for h in self._S.source({obj_comma_source.d},{obj_comma_cible.d}):
# if obj_comma_cible.f@self._T(k) == self._S(h)@obj_comma_source.f:
# yield FlecheCommaCategorie(obj_comma_source,obj_comma_cible,k,h)
class CategorieFleches(CommaCategorie):
"""Catégorie des flèches d'une catégorie C.
......
http://www.plantuml.com/plantuml/png/ZL9BRjim4DtFAMON1uvp0A4j4hXDMw1jikZUeAYnn88VWQGC54xkqcLz3b-ieMWnCgt4tN66RnxdyRqRvvdrdPB0IkSjunwvPCxXadcgZHM4MrYWAN-HTrYW8mzpr4Q5ixT2ryzbJVw-1ymkOJlmFE4SLolEf5ojPivqbfExugAKv3AKg4XxuMdMlt89Jm3QU48hwiQZMR_iKXG38op9UqBtJDimMnDM5wRTxoppr5ciZF1eIM_CRx8WoU5Qxl_oXXnMX8TbSFy7upvNO3Gob0ovqPkmp7FTi5BuZgGaNCxOLNc9xnCBL8GCDsGTbbWnxVfPvlUx-6NBQo1TOL3nXfP1zq6BskzyOoewtXxbnG4ND7OwMZ7YputxRcpR2ATe2_E3L2omzmVcKV2e5cwLw0iiZP6PlRcXYddL1KjLU2UObIbC2mIt4loCHWRSgDOuqNzzrQ4QI91jYCVo6kvFRLhVrC4OKsTVCfdbRwAqXDjSKqr1lvh8APx8oyYA8esV5KdkHPQ3_KxkTugqPyBskNGfc25OFJokCLO6wNbyzxXOPDi0G5JysRAseO-qVFdLBGIfmjZaNMouhZnsyvWoFZF11v3bxPKtjyupB_WJIYDM5Qt6HXTO2UvXWRmX9KBjkrPIM2FHnWLI-SOcdxIx4reu60wuM3n-mAG7KXh2BJb8fsbWgXyi6LjPWfFEcS6lsfDbF2pfOB9xXk2dPTgjZLMiH_zWlhCaGpJWFp2uc6OtIh7KdFGxGlAvXgdsbdknXgFxOIPTZ_4FP3crRyuaIAx-LXBpHbY2l3Ny_4GQSf8lHXbfwexWj1L9KWnEVJTDciwxamH356_RLWhE-dr6vmXFMJw0xupcdZeBms4IbUgKnfFEDBiatb1cQ0B5Y4o3ulmehJ0wJqivpcAA8hpIZoJZ5sv8LvsI_m00
\ No newline at end of file
@startuml
abstract class Categorie {
- objets : set
+ nom : string
+ getObjets()
{abstract} + __call__(sources,cibles)
{abstract} + identite(objet)
}
note right of Categorie::__call__
Cette surcharge d'opérateur doit renvoyer
les flèches de sources à cibles,
on a la convention habituelle C(a,b) = flèches
de a vers b dans la catégorie C.
end note
note right of Categorie::identite
Cette méthode doit renvoyer l'identite d'un objet.
end note
abstract class Morphisme{
+ source : Objet
+ cible : Objet
+ is_identite : bool
+ nom : string
{abstract} + __matmul__(morph)
}
note right of Morphisme::__matmul__
Cette méthode doit renvoyer la
composition du morphisme avec morph.
On a la convention f@g = fog.
end note
abstract class CategorieLibre {
{abstract} + __getitem__(sources,cibles)
}
note right of CategorieLibre::__getitem__
Cette méthode doit renvoyer les morphismes
élémentaires des sources vers les cibles.
end note
Categorie <|-- CategorieLibre
class GrapheDeComposition{
+ __ior__(morph)
+ __isub__(morph)
}
CategorieLibre <|-- GrapheDeComposition
class MorphismeGrapheDeComposition{
+ {static} loi_de_composition : dict
- chemin : tuple
}
Morphisme <|-- MorphismeGrapheDeComposition
class EnsFinis
EnsFinis --|> Categorie
class CatFinies
CatFinies --|> Categorie
class CategoriePreordre
CategoriePreordre --|> Categorie
class CategorieInteractions
CategorieInteractions --|> Categorie
class CategorieTransformationsNaturelles
CategorieTransformationsNaturelles ---|> Categorie
class CommaCategorie
CategorieLibre <|-- CommaCategorie
class ChampActif
CommaCategorie <|-- ChampActif
class ChampPerceptif
CommaCategorie <|-- ChampPerceptif
class CategorieAleatoire
CategorieAleatoire --|> GrapheDeComposition
class CategorieHomologue
CategorieHomologue --|> CatFinies
class CategorieProhomologue
CategorieProhomologue --|> CatFinies
class Application
Application --|> Morphisme
class Foncteur
Foncteur--|> Morphisme
class MorphismePreordre
MorphismePreordre--|> Morphisme
class FlecheCommaCategorie
Morphisme ---|> FlecheCommaCategorie
class Interaction
Interaction --|> Morphisme
class TransformationNaturelle
TransformationNaturelle --|> Interaction
@enduml
\ No newline at end of file
......@@ -81,3 +81,5 @@ Faire un argument par défaut pour call et getitem pour qu'on ai besoin de rien
Factorisation inutile -> déjà trop de foncteurs pour cc, utiliser ça plus tard pour les foncteurs bijectifs.
On part plutôt sur une construction greedy aléatoire du foncteur alea
ajouter les remerciements pour Ehresmann Pastor Beurier
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