Commit 801cea03 authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files

Clusters fonctionnels

parent 79cc5242
This diff is collapsed.
...@@ -97,7 +97,10 @@ class Categorie: ...@@ -97,7 +97,10 @@ class Categorie:
## On vérifie que les identités sont neutres ## On vérifie que les identités sont neutres
for morphisme in self(self.objets,self.objets): for morphisme in self(self.objets,self.objets):
if not (morphisme@self.identite(morphisme.source) == self.identite(morphisme.cible)@morphisme == morphisme): 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.") raise Exception("Incoherence Categorie : le morphisme "+str(morphisme)+" est modifie par une identite.\n"\
+repr(morphisme)+" o "+repr(self.identite(morphisme.source))+" = "+repr(morphisme@self.identite(morphisme.source))+"\n"\
+repr(self.identite(morphisme.cible))+" o "+repr(morphisme)+" = "+repr(self.identite(morphisme.cible)@morphisme)+"\n"+\
repr(morphisme))
## On vérifie l'associativité ## On vérifie l'associativité
for m1,m2,m3 in itertools.product(sorted(self(self.objets,self.objets)),repeat=3): for m1,m2,m3 in itertools.product(sorted(self(self.objets,self.objets)),repeat=3):
......
from Categorie import Categorie
import Cluster
from Cluster import ClusterActif,CompositionClustersActifs
from Diagramme import Triangle,DiagrammeIdentite, DiagrammeObjets
import itertools
from Morphisme import Composition,Morphisme
from config import TOUJOURS_VERIFIER_COHERENCE
class CategorieClustersAbstraite(Categorie):
"""Catégorie dont les objets sont des diagrammes Di d'intérêt d'une catégorie C.
Les flèches entre les diagrammes sont des clusters."""
def __init__(self,categorie,representant="Categorie de clusters"):
Categorie.__init__(self,representant)
self.categorie_initiale = categorie
# on ajoute tous les diagrammes constants
self.diagrammes_constants = dict() #{obj:Δ(obj)}
self.cat_cones_cocones = {} #{diagramme:{"cat_cones":CategorieCones,"cat_cocones":CategorieCocones}}
for obj in categorie.objets:
print(obj)
diag_constant = DiagrammeObjets(categorie,[obj])
diag_constant.representant = "C("+str(obj)+")"
self.diagrammes_constants[obj] = diag_constant
self.ajouter_diagramme_interet(diag_constant)
if TOUJOURS_VERIFIER_COHERENCE:
self.verifier_coherence2()
def verifier_coherence2(self):
for A,B,C in itertools.product(self.objets,repeat=3):
for morph1 in self.fleches_elem(A,B,inclure_id=False):
for morph2 in self.fleches_elem(B,C,inclure_id=False):
if Composition(morph1,morph2) not in self.Composee.loi_de_composition:
raise Exception("Incohérence CategorieClustersAbstraite : les morphismes "+str(morph1)+" et "+str(morph2)+" n'ont pas de composée dans la loi de composition")
def ajouter_diagramme_interet(self,diagramme):
if diagramme.cat_cible != self.categorie_initiale:
raise Exception("Incohérence CategorieClustersAbstraite : tentative d'ajout d'un diagramme d'interet qui n'a pas pour cible la meme categorie initiale que les autres diagrammes."+str(diagramme))
self.ajouter_objet(diagramme)
for obj in self.objets:
cluster = self.chercher_clusters(obj,diagramme)
self.ajouter_morphismes(cluster)
if obj != diagramme: #on a déjà fait les flèches de diag vers diag
cluster = self.chercher_clusters(diagramme,obj)
self.ajouter_morphismes(cluster)
for A,B,C in itertools.product(self.objets,repeat=3):
for morph1 in self.fleches_elem(A,B,False):
for morph2 in self.fleches_elem(B,C,False):
composee = self.composer_clusters(morph1,morph2)
for fleche in self.morphismes:
if fleche == composee:
composee = fleche
break
else:
raise Exception("Composition des clusters n'est pas un cluster "+str(morph1)+" "+str(morph2)+" "+str(composee)+"\n"+str(self.morphismes))
diagramme = Triangle(self,[A,B,C],[morph1,morph2,composee])
diagramme.faire_commuter()
def chercher_clusters(self,source,cible):
raise NotImplementedError("Les classes filles doivent implementer la méthode chercher_clusters")
def composer_clusters(self,cluster1,cluster2):
raise NotImplementedError("Les classes filles doivent implementer la méthode composer_clusters")
class CategorieClustersActifs(CategorieClustersAbstraite):
"""Catégorie fleurie où les morphismes sont des bouquets actifs"""
def __init__(self,categorie,representant="Categorie de clusters actifs"):
CategorieClustersAbstraite.__init__(self,categorie,representant)
def chercher_clusters(self,source,cible):
result = ClusterActif(source,cible)
return [result] if result != None else []
def composer_clusters(self,cluster1,cluster2):
result = CompositionClustersActifs(cluster1,cluster2)
return result
def main():
import CategorieAleatoire
import random
import Diagramme
random.seed(196587456841456485485485648564856456565656564516412)
youpi = False
while not youpi:
cat = CategorieAleatoire.CategorieAleaPreOrdre(nb_objets = 5)
diag1 = Diagramme.DiagrammeAlea(cat)
diag2 = Diagramme.DiagrammeAlea(cat)
diag1.transformer_graphviz()
diag2.transformer_graphviz()
# cat_f = CategorieClustersActifs(cat)
# cat_f.transformer_graphviz(complet=True)
# cat_f.ajouter_diagramme_interet(diag1)
# cat_f.transformer_graphviz()
# cat_f.ajouter_diagramme_interet(diag2)
# cat_f.transformer_graphviz()
youpi = False
a = ClusterActif(diag1,diag2)
if a == None:
youpi = True
b = ClusterActif(diag2,diag1)
if b == None:
youpi = True
fonct = diag1.est_homologue_a(diag2)
if fonct == None or len(fonct.cat_source.objets) == 0:
youpi=False
cat.transformer_graphviz(afficher_identites=True)
fonct.transformer_graphviz()
print(a,b,fonct)
b.transformer_graphviz()
# cat = Categorie("3")
# cat.ajouter_objets("ABabC")
# F,G,f,g = [Morphisme('A','C','F'),Morphisme('B','C','G'),Morphisme('a','C','f'),Morphisme('b','C','g')]
# cat.ajouter_morphismes([F,G,f,g])
# diag1 = Diagramme.DiagrammeObjets(cat,"Aa")
# diag2 = Diagramme.DiagrammeObjets(cat,"Bb")
# diag1.transformer_graphviz()
# diag2.transformer_graphviz()
# cat_clusters = CategorieClustersActifs(cat)
# cat_clusters.transformer_graphviz(afficher_identites=True)
# cat_clusters.ajouter_diagramme_interet(diag1)
# cat_clusters.transformer_graphviz(afficher_identites=True)
# cat_clusters.ajouter_diagramme_interet(diag2)
# cat_clusters.transformer_graphviz(afficher_identites=True)
# cat_clusters.csv_loi_de_composition("lois de composition/loi1.csv",';')
# print(diag1.est_homologue_a(diag2))
if __name__ == '__main__':
main()
\ No newline at end of file
from Categorie import Categorie
from CategorieCones import CategorieCones
from CategorieCocones import CategorieCocones
from Bouquet import BouquetsPerceptifs, BouquetsActifs, Bouquets, Bouquet,CompositionBouquets
from Diagramme import Triangle,DiagrammeIdentite, DiagrammeObjets
import itertools
from Morphisme import Composition,Morphisme
from config import TOUJOURS_VERIFIER_COHERENCE
class CategorieFleurieAbstraite(Categorie):
"""Catégorie dont les objets sont des diagrammes Di d'intérêt d'une catégorie C.
Les flèches entre les diagrammes sont des bouquets perceptifs."""
def __init__(self,categorie,representant="Categorie fleurie"):
Categorie.__init__(self,representant)
self.categorie_initiale = categorie
# on ajoute tous les diagrammes constants
self.diagrammes_constants = dict() #{obj:Δ(obj)}
self.cat_cones_cocones = {} #{diagramme:{"cat_cones":CategorieCones,"cat_cocones":CategorieCocones}}
for obj in categorie.objets:
diag_constant = DiagrammeObjets(categorie,[obj])
diag_constant.representant = "C("+str(obj)+")"
self.diagrammes_constants[obj] = diag_constant
self.ajouter_diagramme_interet(diag_constant)
if TOUJOURS_VERIFIER_COHERENCE:
self.verifier_coherence2()
def verifier_coherence2(self):
for A,B,C in itertools.product(self.objets,repeat=3):
for morph1 in self.fleches_elem(A,B,inclure_id=False):
for morph2 in self.fleches_elem(B,C,inclure_id=False):
if Composition(morph1,morph2) not in self.Composee.loi_de_composition:
raise Exception("Incohérence CategorieFleurie : les morphismes "+str(morph1)+" et "+str(morph2)+" n'ont pas de composée dans la loi de composition")
def ajouter_objet(self,objet):
Categorie.ajouter_objet(self,objet)
cat_cones = CategorieCones(objet)
cat_cocones = CategorieCocones(objet)
self.cat_cones_cocones[objet] = {"cat_cones":cat_cones,"cat_cocones":cat_cocones}
def ajouter_diagramme_interet(self,diagramme):
if diagramme.cat_cible != self.categorie_initiale:
raise Exception("Incohérence CategorieFleurie : tentative d'ajout d'un diagramme d'interet qui n'a pas pour cible la meme categorie initiale que les autres diagrammes."+str(diagramme))
self.ajouter_objet(diagramme)
for obj in self.objets:
bouquets = self.chercher_bouquets(obj,diagramme)
self.ajouter_morphismes(bouquets)
if obj != diagramme: #on a déjà fait les flèches de diag vers diag
bouquets = self.chercher_bouquets(diagramme,obj)
self.ajouter_morphismes(bouquets)
for A,B,C in itertools.product(self.objets,repeat=3):
for morph1 in self.fleches_elem(A,B,False):
for morph2 in self.fleches_elem(B,C,False):
composee = CompositionBouquets(morph1,morph2)
for fleche in self.morphismes:
if fleche == composee:
composee = fleche
break
else:
raise Exception("Composition des bouquets n'est pas un bouquet "+str(morph1)+" "+str(morph2)+" "+str(composee)+"\n"+str(self.morphismes))
diagramme = Triangle(self,[A,B,C],[morph1,morph2,composee])
diagramme.faire_commuter()
def chercher_bouquets(self,source,cible):
raise NotImplementedError("Les classes filles doivent implementer la méthode chercher_bouquets")
class CategorieFleurie(CategorieFleurieAbstraite):
"""Catégorie fleurie où les morphismes sont des bouquets"""
def chercher_bouquets(self,source,cible):
return Bouquets(source,cible,self.cat_cones_cocones[source]["cat_cones"],self.cat_cones_cocones[cible]["cat_cones"],
self.cat_cones_cocones[source]["cat_cocones"], self.cat_cones_cocones[cible]["cat_cocones"])
class CategorieFleuriePerceptive(CategorieFleurieAbstraite):
"""Catégorie fleurie où les morphismes sont des bouquets perceptifs"""
def __init__(self,categorie,representant="Categorie fleurie perceptive"):
CategorieFleurieAbstraite.__init__(self,categorie,representant)
def chercher_bouquets(self,source,cible):
return BouquetsPerceptifs(source,cible,self.cat_cones_cocones[source]["cat_cones"],self.cat_cones_cocones[cible]["cat_cones"])
class CategorieFleurieActive(CategorieFleurieAbstraite):
"""Catégorie fleurie où les morphismes sont des bouquets actifs"""
def __init__(self,categorie,representant="Categorie fleurie active"):
CategorieFleurieAbstraite.__init__(self,categorie,representant)
def chercher_bouquets(self,source,cible):
return BouquetsActifs(source,cible,self.cat_cones_cocones[source]["cat_cocones"],self.cat_cones_cocones[cible]["cat_cocones"])
def main():
import CategorieAleatoire
import random
import Diagramme
# random.seed(1918652)
# cat = CategorieAleatoire.CategorieAleaPreOrdre()
# cat.transformer_graphviz(afficher_identites=True)
# cat_f = CategorieFleurieAbstraite(cat)
# cat_f.transformer_graphviz(complet=True)
cat = Categorie("2")
cat.ajouter_objets("AB")
f,g = [Morphisme('A','B','f'),Morphisme('A','B','g')]
cat.ajouter_morphismes([f,g])
diag1 = Diagramme.Fleche(cat,f)
diag2 = Diagramme.Fleche(cat,g)
diag1.transformer_graphviz()
diag2.transformer_graphviz()
cat_fleurie = CategorieFleurieActive(cat)
cat_fleurie.transformer_graphviz(afficher_identites=True)
cat_fleurie.ajouter_diagramme_interet(diag1)
cat_fleurie.transformer_graphviz(afficher_identites=True)
cat_fleurie.ajouter_diagramme_interet(diag2)
cat_fleurie.transformer_graphviz(afficher_identites=True)
cat_fleurie.csv_loi_de_composition("lois de composition/loi1.csv",';')
if __name__ == '__main__':
main()
\ No newline at end of file
...@@ -25,8 +25,8 @@ class CategoriePreordreZigZag(CategoriePreordreEngendree): ...@@ -25,8 +25,8 @@ class CategoriePreordreZigZag(CategoriePreordreEngendree):
objets_a_explorer = {source} objets_a_explorer = {source}
while len(objets_a_explorer) > 0: while len(objets_a_explorer) > 0:
explore = objets_a_explorer.pop() explore = objets_a_explorer.pop()
objets_a_explorer |= {morph.cible for morph in self._categorie_initiale(explore,abs(self)) if morph.cible not in objets_atteints} objets_a_explorer |= {morph.cible for morph in self._categorie_initiale({explore},abs(self)) if morph.cible not in objets_atteints}
objets_a_explorer |= {morph.source for morph in self._categorie_initiale(abs(self),explore) if morph.source not in objets_atteints} objets_a_explorer |= {morph.source for morph in self._categorie_initiale(abs(self),{explore}) if morph.source not in objets_atteints}
objets_atteints |= objets_a_explorer objets_atteints |= objets_a_explorer
return cible in objets_atteints return cible in objets_atteints
......
from Categorie import Categorie
from Interaction import Interaction,CategorieInteractions from Interaction import Interaction,CategorieInteractions
from Foncteur import Foncteur from Foncteur import Foncteur
from CommaCategorie import ObjetCommaCategorie,CategorieFSous from CommaCategorie import ObjetCommaCategorie,CategorieFSous
from CategoriePreordreZigZag import CatPZigZag from CategoriePreordreZigZag import CatPZigZag
from Interaction import CategorieInteractions from Interaction import CategorieInteractions
from config import * from config import *
class ProtoClusterActif(Interaction): class ProtoClusterActif(Interaction):
""" """
...@@ -14,195 +14,128 @@ class ProtoClusterActif(Interaction): ...@@ -14,195 +14,128 @@ class ProtoClusterActif(Interaction):
3) Pour toute flèche h:j->j' dans J et <i,g,j> \in G(i), on a <i,h@g,j'> \in G(i) 3) Pour toute flèche h:j->j' dans J et <i,g,j> \in G(i), on a <i,h@g,j'> \in G(i)
4) Pour toute flèche h:i'->i dans I et <i,g,j> \in G(i), on a <i',g@h,j> \in G(i') 4) Pour toute flèche h:i'->i dans I et <i,g,j> \in G(i), on a <i',g@h,j> \in G(i')
""" """
def __init__(self, D1:Foncteur, D2:Foncteur, composantes:set): def verifier_struct(interaction:Interaction) -> tuple:
"""composantes est un ensemble d'objets de la comma-catégorie (D1|D2)""" '''Renvoie (True,None) si la structure de cluster est vérifiée par l'`interaction`, (False,Exception) sinon.'''
Interaction.__init__(self,D1, D2, composantes) D1,D2 = interaction.source,interaction.cible
if TOUJOURS_VERIFIER_COHERENCE:
ProtoClusterActif.verifier_coherence(self)
def verifier_coherence(self):
D1,D2 = self.source,self.cible
Interaction.verifier_coherence(self)
# contrainte 1) au moins une flèche part de chacun des objets de D1 # contrainte 1) au moins une flèche part de chacun des objets de D1
for e in D1.source.objets: for e in D1.source.objets:
for composante in self: for composante in interaction:
if composante.e == e: if composante.e == e:
break break
else: else:
raise Exception("Incoherence ProtoClusterActif : l'objet "+str(e)+" de l'index de D1 n'a pas de de composante associée.") return False,Exception("Incoherence ProtoClusterActif : l'objet "+str(e)+" de l'index de D1 n'a pas de de composante associée.")
# contrainte 2) les composantes qui sortent d'un objet D1(i) mènent à des objets D2(j_i) reliés par un zig zag dans la comma catégorie (D1(i)|D2) # contrainte 2) les composantes qui sortent d'un objet D1(i) mènent à des objets D2(j_i) reliés par un zig zag dans la comma catégorie (D1(i)|D2)
for i in D1.source.objets: for i in D1.source.objets:
G_i = {compo for compo in self if compo.e == i} G_i = {compo for compo in interaction if compo.e == i}
comma_categorie = CategorieFSous(D2,D1(i)) comma_categorie = CategorieFSous(D2,D1(i))
cat_cc = CatPZigZag(comma_categorie) cat_cc = CatPZigZag(comma_categorie)
# on vérifie que tous les E(e) sont isomorphes dans la catégorie des composantes connexes de la catégorie sous D(d) # on vérifie que tous les E(e) sont isomorphes dans la catégorie des composantes connexes de la catégorie sous D(d)
composante_reference = G_i.pop() composante_reference = G_i.pop()
for composante in G_i: for composante in G_i:
if not cat_cc.existe_morphisme(composante,composante_reference): if not cat_cc.existe_morphisme(composante,composante_reference):
raise Exception("Incoherence ProtoClusterActif : la composante"+str(composante)+" n'est pas dans la même composante connexe que "+str(composante_reference)) return False,Exception("Incoherence ProtoClusterActif : la composante"+str(composante)+" n'est pas dans la même composante connexe que "+str(composante_reference))
# contrainte 3) hog = g' # contrainte 3) hog = g'
for composante in self: for composante in interaction:
for h in D2.source(abs(D2.source),abs(D2.source)): for h in D2.source({composante.d},abs(D2.source)):
if ObjetCommaCategorie(composante.e,D2(h)@composante.f,h.cible) not in self: if ObjetCommaCategorie(composante.e,D2(h)@composante.f,h.cible) not in interaction:
raise Exception("Incoherence ProtoClusterActif : la composee de la composante "+str(composante)+" avec la fleche "+str(D2(h))+" de D2 n'est pas dans le cluster.") return False,Exception("Incoherence ProtoClusterActif : la composee de la composante "+str(composante)+" avec la fleche "+str(D2(h))+" de D2 n'est pas dans le cluster.")
# contrainte 4) goh = g' # contrainte 4) goh = g'
for composante in self: for composante in interaction:
for h in D1.source(abs(D1.source),abs(D1.source)): for h in D1.source(abs(D1.source),{composante.e}):
if ObjetCommaCategorie(h.source,composante.f@D1(h),composante.d) not in self: if ObjetCommaCategorie(h.source,composante.f@D1(h),composante.d) not in interaction:
raise Exception("Incoherence ProtoClusterActif : la composee de la fleche "+str(D1(h))+" de D1 avec la composante "+str(composante)+" n'est pas dans le cluster") return False,Exception("Incoherence ProtoClusterActif : la composee de la fleche "+str(D1(h))+" de D1 avec la composante "+str(composante)+" n'est pas dans le cluster")
return True,None
class Cluster() def __init__(self, D1:Foncteur, D2:Foncteur, composantes:set):
"""composantes est un ensemble d'objets de la comma-catégorie (D1|D2)"""
Interaction.__init__(self,D1, D2, composantes)
if TOUJOURS_VERIFIER_COHERENCE:
ProtoClusterActif.verifier_coherence(self)
def verifier_coherence(self):
Interaction.verifier_coherence(self)
coherence,exception_levee = ProtoClusterActif.verifier_struct(self)
if not coherence:
raise exception_levee
class CategorieClusters(CategorieInteractions): class CategorieClusters(CategorieInteractions):
""" """
CategorieClusters est une catégorie d'organisations où les intéractions sont des clusters. CategorieClusters est une catégorie d'organisations où les intéractions sont des clusters.
""" """
def __init__(self, univers:Categorie ,objets:set = set(), nom:str = None): def __init__(self, univers:Categorie ,diagrammes:set = set(), nom:str = None):
CategorieInteractions.__init__(self,univers,objets,"Catégorie des diagrammes et clusters sur "+str(univers) if nom == None else nom) """
CategorieClusters est la catégorie dont les objets sont des diagrammes de cible `univers` et les morphismes sont des clusters.
Par défaut, on considère pour chaque objet O de l'`univers` le diagramme 1_O qui associe à un objet l'objet O.
On retrouve ainsi l'`univers` dans la catégorie des clusters.
`diagrammes` est un ensemble de diagrammes d'intérêts à ajouter à la catégorie.
"""
CategorieInteractions.__init__(self,univers,diagrammes,"Catégorie des diagrammes et clusters sur "+str(univers) if nom == None else nom)
def __identite__(self,objet:Diagramme) -> ProtoClusterActif: def identite(self,objet:Foncteur) -> ProtoClusterActif:
interactions = sorted(CategorieInteractions.__call__(self,{objet},{objet}),key=len,reverse=True)
identite_candidate = None
class ProtoClustersActifs: for interact in interactions:
def __init__(self, foncteur1, foncteur2): if ProtoClusterActif.verifier_struct(interact)[0]:
self.foncteur1 = foncteur1 if identite_candidate != None:
self.foncteur2 = foncteur2 if len(interact) < identite_candidate:
if self.foncteur1.cat_cible != self.foncteur2.cat_cible: return identite_candidate
raise Exception("Incoherence ClustersActifs : les deux foncteurs n'ont pas la meme image.")
self.categorie = self.foncteur1.cat_cible
self.clusters_actifs = []
# on énumère toutes les flèches de D1 à D2
objets_comma_category = {(i,j):self.categorie.enumerer_composees(self.foncteur1(i),self.foncteur2(j))\
for i in self.foncteur1.source.objets for j in self.foncteur2.source.objets}
fleches = [e for liste in objets_comma_category.values() for e in liste]
cat_cc = {d:CategorieComposantesConnexes(CategorieFSous(self.foncteur2, self.foncteur1(d))) for d in self.foncteur1.cat_source.objets}
# on énumère toutes les interactions de D1 à D2
for nb_fleches in range(1,len(fleches)+1):
for interaction in itertools.combinations(fleches,nb_fleches):
ajouter_cluster = True
# contrainte 1) au moins une flèche part de chacun des objets de D1
for d in self.foncteur1.cat_source.objets:
for composante in interaction:
if composante.source == self.foncteur1(d):
break
else:
ajouter_cluster = False #raise Exception("Incoherence ProtoClusterActif : l'objet "+str(self.foncteur1(d))+" de D1 n'a pas de d'image par le cluster")
if not ajouter_cluster:
continue
# contrainte 2) les composantes qui sortent d'un objet d de D1 mènent à des objets e de D2 reliés par un zig zag dans la catégorie sous d
for d in self.foncteur1.cat_source.objets:
E_e = [] #les images des composantes
for composante in interaction:
if composante.source == self.foncteur1(d):
E_e += [composante]
# on vérifie que tous les E(e) sont isomorphes dans la catégorie des composantes connexes de la catégorie sous D(d)
for e in E_e[1:]: #todo corriger tout ça !!!
for obj1 in cat_cc[d].objets: #todo corriger tout ça !!!
if obj1.f == e:
for obj2 in cat_cc[d].objets:
if obj2.f == E_e[0]:
if cat_cc[d].existe_composee(obj1,obj2) != None:
break
else:
continue
break
else:
ajouter_cluster = False #raise Exception("Incoherence ProtoClusterActif : l'objet "+str(E_e[0])+" n'est pas dans la même composante connexe que "+str(e))
break
else:
continue
break
if not ajouter_cluster:
continue
# contrainte 3) eog = g'
for composante in interaction:
for e in self.foncteur2.cat_source.objets:
if self.foncteur2(e) == composante.cible:
for eps in self.foncteur2.cat_source.morph_sortants[e]:
composee = self.categorie.Composee(composante,self.foncteur2(eps))
if composee not in interaction:
ajouter_cluster = False #raise Exception("Incoherence ProtoClusterActif : la composee de la composante "+str(composante)+" avec la fleche "+str(self.foncteur2(eps))+" de D2 n'est pas dans le cluster")
break
else:
continue
break
else:
continue
break
if not ajouter_cluster:
continue
# contrainte 4) god = g'
for composante in interaction:
for d in self.foncteur1.cat_source.objets:
if self.foncteur1(d) == composante.source:
for delta in self.foncteur1.cat_source.morph_entrants[d]:
composee = self.categorie.Composee(self.foncteur1(delta),composante)
if composee not in interaction:
ajouter_cluster = False #raise Exception("Incoherence ProtoClusterActif : la composee de la fleche "+str(self.foncteur1(delta))+" de D1 avec la composante "+str(composante)+" n'est pas dans le cluster")
break
else:
continue
break
else: else:
continue raise Exception("Plusieurs identites possibles pour "+str(objet)+" :\n"+str(identite_candidate)+"\n"+str(interact))
break else:
if not ajouter_cluster: identite_candidate = interact
continue if identite_candidate == None:
self.clusters_actifs += [ProtoClusterActif(self.foncteur1,self.foncteur2,interaction)] raise Exception("Pas d'identite trouvee pour "+str(objet))
return identite_candidate
def transformer_graphviz(self):
for cluster in self.clusters_actifs:
cluster.transformer_graphviz()
def __getitem__(self,key):
return self.clusters_actifs[key]
def __iter__(self): def __call__(self, sources:set, cibles:set) -> set:
for cluster in self.clusters_actifs: result = set()
yield cluster for source in sources:
for cible in cibles:
def __len__(self): interactions = sorted(CategorieInteractions.__call__(self,{source},{cible}),key=len,reverse=True)
return len(self.clusters_actifs) proto_cluster_maximaux = []
for interact in interactions:
if len(proto_cluster_maximaux) > 0 and len(interact) < len(proto_cluster_maximaux[0]):
# on a trouvé des proto-clusters et on examine maintenant des proto-clusters plus petits (qui ne seront pas maximaux)
break
if ProtoClusterActif.verifier_struct(interact)[0]:
proto_cluster_maximaux += [interact]
result |= set(proto_cluster_maximaux)
return result
def main(): def main():
from Categorie import Categorie from GrapheDeComposition import GC,MGC
from Morphisme import Morphisme from Diagramme import DiagrammeObjets,Fleche
from Foncteur import Foncteur
cat = Categorie() gc = GC()
cat.ajouter_objets("ABCDO") gc |= {'A','B','C'}
f,g,h,i,j,k,l,m = [Morphisme('O','A','f'),Morphisme('O','B','g'),Morphisme('A','B','h'),Morphisme('O','C','i'),Morphisme('O','D','j'),Morphisme('C','D','k'),Morphisme('B','C','l'),Morphisme('A','D','m')] morphismes = [MGC('A','B','f'),MGC('B','C','g'),MGC('A','C','h')]
cat.ajouter_morphismes([f,g,h,i,j,k,l,m]) gc |= morphismes
from CategoriePreordre import CategoriePreordre gc.transformer_graphviz()
cat2 = CategoriePreordre(cat)
n,o = [Morphisme('O','A','n'),Morphisme('O','B','o')] c_i = CategorieClusters(gc)
cat2.ajouter_morphismes([n,o])