Commit 55201fab authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files

Debut pro homologues

parent 62b5bdf7
......@@ -364,6 +364,9 @@ def main():
# cat_cocones2 = CategorieCocones.CategorieCocones(diag2)
# cat_cocones2.transformer_graphviz(destination="graphviz/cat_cocones2")
# bouquets = Bouquets(diag1,diag2)
# bouquets.transformer_graphviz()
from Categorie import Categorie
from Morphisme import Morphisme
from Foncteur import Foncteur
......@@ -374,7 +377,7 @@ def main():
from CategoriePreordre import CategoriePreordre
cat2 = CategoriePreordre(cat)
n,o = [Morphisme('O','A','n'),Morphisme('O','B','o')]
cat2.ajouter_morphismes([n])
cat2.ajouter_morphismes([n,o])
cat2.transformer_graphviz()
cat_fleche = Categorie()
......
......@@ -47,7 +47,34 @@ class CategorieAlea(Categorie):
diag.faire_commuter()
if PRINT_AVANCEMENT_CREATION_CAT_ALEA:
print("Fin création")
class CategorieAleaIsomorph(Categorie):
"""Construit une catégorie aléatoire où tous les cycles sont des isomorphismes."""
def __init__(self, nb_objets = None, nb_morph = None):
"""nb_morph est le nombre de morphismes élémentaires à ajouter aléatoirement."""
Categorie.__init__(self,"Catégorie aléatoire")
if nb_objets == None:
nb_objets = random.randint(5,20)
if nb_morph == None:
nb_morph = random.randint(0,30)
if PRINT_AVANCEMENT_CREATION_CAT_ALEA:
print("Création d'une catégorie avec "+str(nb_objets)+" objets et "+str(nb_morph)+" morphismes")
self.ajouter_objets(list(range(nb_objets))) # ajout des objets
for i in range(nb_morph): # ajout des morphismes
pool = [(source,cible) for source,cible in itertools.product(range(nb_objets),repeat=2) if source != cible and len(self.enumerer_composees_sans_cycle(source,cible)) == 0 or len(self.enumerer_composees_sans_cycle(cible,source)) == 0]
if len(pool) == 0:
break
source,cible = random.choice(pool)
self.ajouter_morphisme(Morphisme(source,cible,str(i)))
#on définit la loi de composition pour les cycles
for obj in self.objets:
cycles = self.trouver_cycles_elementaires(obj)
for c in cycles:
diag = Parallele(self,[obj]*2,[c,self.identites[obj]])
diag.faire_commuter()
if PRINT_AVANCEMENT_CREATION_CAT_ALEA:
print("Fin création")
class CategorieAleaPreOrdre(Categorie):
"""Construit une catégorie pré-ordre aléatoire."""
......
......@@ -14,7 +14,6 @@ class CategorieCocones(Categorie):
self.foncteur = foncteur
cocones = [e for nadir in foncteur.cat_cible.objets for e in foncteur.enumerer_cocones(nadir)]
self.ajouter_objets(cocones)
app_obj_cocones = {obj:[c for c in cocones if c.nadir==obj] for obj in self.foncteur.cat_cible.objets} #associe à chaque objet la liste de cône de nadir cet objet
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)
......@@ -53,7 +52,8 @@ class CategorieCocones(Categorie):
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)))
# 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()
......@@ -83,16 +83,18 @@ class CategorieCocones(Categorie):
composable = False
break
if not composable:
print("Warning, on a tente de composer "+' , '.join(map(str,im)))
# 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)))
# 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)))
# 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
......@@ -100,7 +102,7 @@ class CategorieCocones(Categorie):
if len(self.objets) > 0:
graphe = defaultdict(list)
for cle,val in self.morph_entrants.items():
graphe[cle] = list(map(lambda x:x.cible,val))
graphe[cle] = list(map(lambda x:x.source,val))
noeuds_visites = []
noeud_courant = self.objets[0]
while len(graphe[noeud_courant]) > 0:
......
......@@ -13,7 +13,6 @@ class CategorieCones(Categorie):
self.foncteur = foncteur
cones = [e for apex in foncteur.cat_cible.objets for e in foncteur.enumerer_cones(apex)]
self.ajouter_objets(cones)
app_obj_cones = {obj:[c for c in cones if c.apex==obj] for obj in self.foncteur.cat_cible.objets} #associe à chaque objet la liste de cône d'apex cet objet
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)
......@@ -53,7 +52,8 @@ class CategorieCones(Categorie):
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)))
# 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()
......@@ -83,16 +83,18 @@ class CategorieCones(Categorie):
composable = False
break
if not composable:
print("Warning, on a tente de composer "+' , '.join(map(str,im)))
# 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)))
# 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)))
# 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
......@@ -132,8 +134,12 @@ class CategorieCones(Categorie):
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]
......@@ -145,8 +151,7 @@ class CategorieCones(Categorie):
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')
......
......@@ -22,6 +22,8 @@ class Diagramme(Foncteur.Foncteur):
self.categorie_indexee = categorie_indexee
self._id = Diagramme._id
Diagramme._id += 1
self.objets_select = set(application_objets.values()) #ensemble des objets sélectionnés par le diagramme
self.morph_select = set(application_morphismes.values()) #ensemble des morphismes sélectionnés par le diagramme
def __str__(self):
return "Diag"+str(self._id)
......@@ -47,7 +49,7 @@ class Diagramme(Foncteur.Foncteur):
composee_depart,composee_arrivee = composee_arrivee,composee_depart
if composee_depart != composee_arrivee:
if len(composee_depart) == len(composee_arrivee) == 1:
print("Warning : Identification de deux fleches elementaires : "+str(composee_depart)+" et "+str(composee_arrivee))
# print("Warning : Identification de deux fleches elementaires : "+str(composee_depart)+" et "+str(composee_arrivee))
if composee_depart.is_identite:
raise Exception("Identification d'une identite a un morphisme : "+str(composee_depart)+" et "+str(composee_arrivee))
else:
......@@ -61,7 +63,37 @@ class Diagramme(Foncteur.Foncteur):
return self.categorie_image()
def champ_perceptif(self):
return self.categorie_cones()
import CategorieCones
return CategorieCones.CategorieCones(self)
def champ_actif(self):
import CategorieCocones
return CategorieCocones.CategorieCocones(self)
def est_prohomologue_a(self,other):
"""Renvoie un foncteur isomorphisme entre les champs perceptifs des deux diagrammes s'il existe (les diagrammes sont prohomologues)
None sinon"""
import FoncteurOubli
assert(self.categorie_indexee == other.categorie_indexee)
cat_cones1 = self.champ_perceptif()
apex1 = set([e.apex for e in cat_cones1.objets])
cat_cones2 = other.champ_perceptif()
apex2 = set([e.apex for e in cat_cones2.objets])
if apex1 != apex2:
return None
if len(cat_cones1.morphismes) != len(cat_cones2.morphismes) or len(cat_cones1.objets) != len(cat_cones2.objets):
return None
oubli1 = FoncteurOubli.FoncteurOubli(cat_cones1)
oubli2 = FoncteurOubli.FoncteurOubli(cat_cones2)
app_obj = {}
app_morph = {}
for objet in apex1:
antecedants = [e for e in cat_cones1.objets if e.apex == objet]
images = [e for e in cat_cones2.objets if e.apex == objet]
def transformer_graphviz(self, destination=None):
"""Permet de visualiser la categorie indexee par le diagramme avec graphviz"""
......
......@@ -91,23 +91,8 @@ class Foncteur(Morphisme.Morphisme):
if destination == None:
destination = "graphviz/foncteur"+str(Foncteur.nb_viz)
##on determine s'il y a collision entre les noms des objets et morphismes des deux catégories
collision = False
for o in self.cat_source.objets:
if o in self.cat_cible.objets:
collision = True
break
if not collision:
cat_cible_representants = list(map(lambda x:str(x.representant),self.cat_cible.morphismes))
for morph in self.cat_source.morphismes:
if not morph.is_identite or afficher_identites:
if str(morph.representant) in cat_cible_representants:
collision = True
break
if collision:
suffixe1 = "_1"
else:
suffixe1 = ""
suffixe1_objet = "_1"
suffixe1_morph = "-1"
graph = Digraph('foncteur')
graph.attr(concentrate="true" if GRAPHVIZ_CONCENTRATE_GRAPHS else "false")
......@@ -116,43 +101,43 @@ class Foncteur(Morphisme.Morphisme):
cluster.attr(label=self.cat_source.nom)
nodes = []
for o in self.cat_source.objets:
cluster.node(str(o)+suffixe1)
cluster.node(str(o)+suffixe1_objet)
for morph in self.cat_source.morphismes:
if not morph.is_identite or afficher_identites:
cluster.node(str(morph.representant)+suffixe1,style="invis",shape="point")
graph.edge(str(morph.source)+suffixe1,str(morph.representant)+suffixe1,label=str(morph.representant)+suffixe1,headclip="False",arrowhead="none")
graph.edge(str(morph.representant)+suffixe1,str(morph.cible)+suffixe1,tailclip="false")
cluster.node(str(morph.representant)+suffixe1_morph,style="invis",shape="point")
graph.edge(str(morph.source)+suffixe1_objet,str(morph.representant)+suffixe1_morph,label=str(morph.representant)+suffixe1_morph,headclip="False",arrowhead="none")
graph.edge(str(morph.representant)+suffixe1_morph,str(morph.cible)+suffixe1_objet,tailclip="false")
if collision:
suffixe2 = "_2"
else:
suffixe2 = ""
suffixe2_objet = "_2"
suffixe2_morph = "-2"
with graph.subgraph(name='cluster_1') as cluster:
cluster.attr(label=self.cat_cible.nom)
nodes = []
for o in self.cat_cible.objets:
cluster.node(str(o)+suffixe2)
cluster.node(str(o)+suffixe2_objet)
for morph in self.cat_cible.morphismes:
if not morph.is_identite or afficher_identites:
cluster.node(str(morph.representant)+suffixe2,style="invis",shape="point")
graph.edge(str(morph.source)+suffixe2,str(morph.representant)+suffixe2,label=str(morph.representant)+suffixe2,headclip="False",arrowhead="none")
graph.edge(str(morph.representant)+suffixe2,str(morph.cible)+suffixe2,tailclip="false")
cluster.node(str(morph.representant)+suffixe2_morph,style="invis",shape="point")
graph.edge(str(morph.source)+suffixe2_objet,str(morph.representant)+suffixe2_morph,label=str(morph.representant)+suffixe2_morph,headclip="False",arrowhead="none")
graph.edge(str(morph.representant)+suffixe2_morph,str(morph.cible)+suffixe2_objet,tailclip="false")
composees_ajoutees = []
for source in self.app_morph:
if not source.is_identite or afficher_identites:
if self.app_morph[source] in self.cat_cible.morphismes:
graph.edge(str(source.representant)+suffixe1,str(self.app_morph[source].representant)+suffixe2,color="cyan")
graph.edge(str(source.representant)+suffixe1_morph,str(self.app_morph[source].representant)+suffixe2_morph,color="cyan")
elif self.app_morph[source] not in composees_ajoutees:
cluster.node(str(self.app_morph[source].representant)+suffixe2,style="invis",shape="point")
cluster.node(str(self.app_morph[source].representant)+suffixe2_morph,style="invis",shape="point")
composees_ajoutees += [self.app_morph[source]]
graph.edge(str(self.app_morph[source].source)+suffixe2,str(self.app_morph[source].representant)+suffixe2,label=str(self.app_morph[source].representant)+suffixe2,headclip="False",arrowhead="none",color="grey77")
graph.edge(str(self.app_morph[source].representant)+suffixe2,str(self.app_morph[source].cible)+suffixe2,tailclip="false",color="grey77")
graph.edge(str(source.representant)+suffixe1,str(self.app_morph[source].representant)+suffixe2,color="cyan")
graph.edge(str(self.app_morph[source].source)+suffixe2_morph,str(self.app_morph[source].representant)+suffixe2_morph,label=str(self.app_morph[source].representant)+suffixe2_morph,headclip="False",arrowhead="none",color="grey77")
graph.edge(str(self.app_morph[source].representant)+suffixe2_morph,str(self.app_morph[source].cible)+suffixe2_morph,tailclip="false",color="grey77")
graph.edge(str(source.representant)+suffixe1_morph,str(self.app_morph[source].representant)+suffixe2_morph,color="cyan")
for source in self.app_objets:
graph.edge(str(source)+suffixe1,str(self.app_objets[source])+suffixe2,color="blue")
graph.edge(str(source)+suffixe1_objet,str(self.app_objets[source])+suffixe2_objet,color="blue")
graph.render(destination)
......
from CategorieCones import *
from CategorieCocones import *
from Foncteur import Foncteur
class FoncteurOubli(Foncteur):
def __init__(self,categorie):
"""categorie : catégorie de cônes ou de cocônes"""
if issubclass(type(categorie),CategorieCones):
app_morph = categorie.app_morph_fleche_cone
elif issubclass(type(categorie),CategorieCocones):
app_morph = categorie.app_morph_fleche_cocone
else:
raise Exception("Foncteur d'oubli sur une categorie qui n'est pas une categorie de cones ou de cocones")
Foncteur.__init__(self, categorie, categorie.foncteur.cat_cible, {cone:cone.apex for cone in categorie.objets},
app_morph, representant = "Foncteur d'oubli de "+categorie.nom, is_identite = False)
def main():
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)))
foncteur_oubli = FoncteurOubli(cat3)
foncteur_oubli.transformer_graphviz()
if __name__ == '__main__':
main()
\ No newline at end of file
......@@ -4,9 +4,9 @@ import CategorieCones,CategorieCocones
import Bouquet
import random
random.seed(1215451)
random.seed(156451564156748745)
cat = CategorieAleatoire.CategorieAleaPreOrdre()
cat = CategorieAleatoire.CategorieAleaIsomorph()
cat.transformer_graphviz(complet=False)
cat.transformer_graphviz(complet=True)
......@@ -14,13 +14,13 @@ diag = Diagramme.DiagrammeAlea(cat,1)
diag.transformer_graphviz()
cat_cones = CategorieCones.CategorieCones(diag)
cat_cones.transformer_graphviz()
cat_cones.transformer_graphviz(complet=False)
for lim in cat_cones.limites():
lim.transformer_graphviz()
cat_cocones = CategorieCocones.CategorieCocones(diag)
cat_cocones.transformer_graphviz()
cat_cocones.transformer_graphviz(complet=False)
for lim in cat_cocones.colimites():
lim.transformer_graphviz()
\ No newline at end of file
......@@ -2,4 +2,5 @@
- Mettre en cache les composées enumérées dans catégorie
- tester catégorie cones avec un diagramme où la catégorie indexante n'a pas de flèches (on est censé avoir toutes les permutations de jambes)
- L200-205 Catégorie -> investiguer à quoi ça sert ?
- 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)
\ No newline at end of file
- 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
\ 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