Commit 5854c168 authored by Guillaume Sabbagh's avatar Guillaume Sabbagh
Browse files

CategorieClustersActifs opérationnelle

parent 878547e7
......@@ -46,10 +46,10 @@ class BouquetAbstrait(Morphisme):
return hash((tuple(self.tiges),self.foncteur1,self.foncteur2))
def __str__(self):
return '('+str(self.foncteur1)+','+'/'.join(map(str,self.tiges))+','+str(self.foncteur2)+')'
return '/'.join(map(str,self.tiges))
def __repr__(self):
return str(self)
return '('+str(self.foncteur1)+','+'/'.join(map(str,self.tiges))+','+str(self.foncteur2)+')'
def verifier_coherence(self):
......
from Morphisme import Morphisme
from CategorieCones import CategorieCones
from CategorieCocones import CategorieCocones
from config import *
import itertools
from collections import defaultdict
from copy import copy
if GRAPHVIZ_ENABLED:
from graphviz import Digraph
class BouquetAbstrait(Morphisme):
nb_viz = 0
def __eq__(self,other):
if issubclass(type(other),BouquetAbstrait):
if len([e for e in self.tiges if e not in other.tiges]) > 0:
return False
if len([e for e in other.tiges if e not in self.tiges]) > 0:
return False
return True
return False
def verifier_coherence(self):
raise NotImplementedError()
def transformer_graphviz(self, destination=None):
"""Permet de visualiser le bouquet avec graphviz
Composante rouge : diagramme 1
Composante verte : diagramme 2
Composante bleue : Cones
Composante bleue foncée : cocones
Composante orange: Bouquet"""
Bouquet.nb_viz += 1
if not hasattr(self,'cat_cones1'):
self.cat_cones1 = CategorieCones(self.foncteur1)
if not hasattr(self,'cat_cones2'):
self.cat_cones2 = CategorieCones(self.foncteur2)
if not hasattr(self,'cat_cocones1'):
self.cat_cocones1 = CategorieCocones(self.foncteur1)
if not hasattr(self,'cat_cocones2'):
self.cat_cocones2 = CategorieCocones(self.foncteur2)
image1 = self.foncteur1.categorie_image()
image2 = self.foncteur2.categorie_image()
if destination == None:
destination = "graphviz/bouquet"+str(Bouquet.nb_viz)
graph = Digraph('bouquet')
graph.attr(concentrate="true" if GRAPHVIZ_CONCENTRATE_GRAPHS else "false")
graph.attr(label="Bouquet entre "+str(self.foncteur1)+" et "+str(self.foncteur2))
for o in self.categorie.objets:
couleur = [0,0,0]
if o in image1.objets:
couleur[0] += 200
if o in image2.objets:
couleur[1] += 200
if o in [e.apex for e in self.cat_cones1.objets] or o in [e.apex for e in self.cat_cones2.objets]:
couleur[2] += 200
if o in [e.nadir for e in self.cat_cocones1.objets] or o in [e.nadir for e in self.cat_cocones2.objets]:
couleur[2] += 55
graph.node(str(o),color="#"+''.join(map(lambda x:(2-len(str(hex(x))[2:]))*"0"+str(hex(x))[2:],couleur)))#"grey60")
morphismes = self.categorie.morphismes+image1.morphismes+image2.morphismes+\
[e for cone in self.cat_cones1.objets for e in cone.jambes.values()]+\
[e for cone in self.cat_cones2.objets for e in cone.jambes.values()]+\
[e for cocone in self.cat_cocones1.objets for e in cocone.jambes.values()]+\
[e for cocone in self.cat_cocones2.objets for e in cocone.jambes.values()]+\
self.tiges
for morph in [morphismes[i] for i in range(len(morphismes)) if i==len(morphismes) or morphismes[i] not in morphismes[i+1:]]:
if not morph.is_identite or morph in [e for cone in self.cat_cones1.objets for e in cone.jambes.values()]+\
[e for cone in self.cat_cones2.objets for e in cone.jambes.values()]+\
[e for cocone in self.cat_cocones1.objets for e in cocone.jambes.values()]+\
[e for cocone in self.cat_cocones2.objets for e in cocone.jambes.values()]:
couleur = [0,0,0]
if morph in image1.morphismes:
couleur[0] += 200
if morph in image2.morphismes:
couleur[1] += 200
if morph in [e for cone in self.cat_cones1.objets for e in cone.jambes.values()]+\
[e for cone in self.cat_cones2.objets for e in cone.jambes.values()]:
couleur[2] += 200
if [e for cocone in self.cat_cocones1.objets for e in cocone.jambes.values()]+\
[e for cocone in self.cat_cocones2.objets for e in cocone.jambes.values()]:
couleur[2] += 55
if morph in self.tiges:
couleur = [255,110,0]
graph.edge(str(morph.source),str(morph.cible),label=str(morph.representant), color="#"+''.join(map(lambda x:(2-len(str(hex(x))[2:]))*"0"+str(hex(x))[2:],couleur)))
else:
graph.edge(str(morph.source),str(morph.cible),label=str(morph.representant), weight="1000", color="#"+''.join(map(lambda x:(2-len(str(hex(x))[2:]))*"0"+str(hex(x))[2:],couleur)))
graph.render(destination)
if CLEAN_GRAPHVIZ_MODEL:
import os
os.remove(destination)
class BouquetPerceptif(BouquetAbstrait):
"""Seules les contraintes sur les cônes sont prises en compte pour le bouquet perceptif"""
def __init__(self, foncteur1, foncteur2, tiges, cat_cones1=None,cat_cones2=None):
"""On peut fournir cat_cones1 et cat_cones2 pour économiser du temps de calcul."""
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
self.tiges = list(tiges) #liste de morphismes de la catégorie cible des foncteurs
self.categorie = self.foncteur1.cat_cible
self.cat_cones1 = cat_cones1
self.cat_cones2 = cat_cones2
if TOUJOURS_VERIFIER_COHERENCE:
BouquetPerceptif.verifier_coherence(self)
def verifier_coherence(self):
if self.foncteur1.cat_cible != self.foncteur2.cat_cible:
raise Exception("Incoherence Bouquet : les deux foncteurs n'ont pas la meme image.")
impl1, impl2 = [self.foncteur1.categorie_image(),self.foncteur2.categorie_image()]
for tige in self.tiges:
if tige.source not in impl1.objets:
raise Exception("Incoherence Bouquet : la tige "+str(tige)+" ne prend pas sa source dans l'image de F1")
if tige.cible not in impl2.objets:
raise Exception("Incoherence Bouquet : la tige "+str(tige)+" ne prend pas sa cible dans l'image de F2")
if self.cat_cones1 == None:
self.cat_cones1 = CategorieCones(self.foncteur1)
if self.cat_cones2 == None:
self.cat_cones2 = CategorieCones(self.foncteur2)
for cone1 in self.cat_cones1.objets:
list_qB = []
for A,pA in cone1.jambes.items():
for g in self.tiges:
if g.source == pA.cible:
list_qB += [self.categorie.Composee(pA,g)]
image_existe = False
for cone2 in self.cat_cones2.objets:
for j in cone2.jambes.values():
if j not in list_qB:
break
else:
image_existe = True
break
if not image_existe:
raise Exception("Incoherence Bouquet : le cone "+str(cone1)+" n'a pas d'image par le bouquet")
class BouquetActif(BouquetAbstrait):
"""Seules les contraintes sur les cocônes sont prises en compte pour le bouquet actif"""
def __init__(self, foncteur1, foncteur2, tiges,cat_cocones1=None,cat_cocones2=None):
"""On peut fournir cat_cocones1 et cat_cocones2 pour économiser du temps de calcul."""
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
self.tiges = list(tiges) #liste de morphismes de la catégorie cible des foncteurs
self.categorie = self.foncteur1.cat_cible
self.cat_cocones1 = cat_cocones1
self.cat_cocones2 = cat_cocones2
if TOUJOURS_VERIFIER_COHERENCE:
BouquetActif.verifier_coherence(self)
def verifier_coherence(self):
if self.foncteur1.cat_cible != self.foncteur2.cat_cible:
raise Exception("Incoherence Bouquet : les deux foncteurs n'ont pas la meme image.")
impl1, impl2 = [self.foncteur1.categorie_image(),self.foncteur2.categorie_image()]
for tige in self.tiges:
if tige.source not in impl1.objets:
raise Exception("Incoherence Bouquet : la tige "+str(tige)+" ne prend pas sa source dans l'image de F1")
if tige.cible not in impl2.objets:
raise Exception("Incoherence Bouquet : la tige "+str(tige)+" ne prend pas sa cible dans l'image de F2")
if self.cat_cocones1 == None:
self.cat_cocones1 = CategorieCocones(self.foncteur1)
if self.cat_cocones2 == None:
self.cat_cocones2 = CategorieCocones(self.foncteur2)
for cocone2 in self.cat_cocones2.objets:
list_pA = []
for B,qB in cocone2.jambes.items():
for g in self.tiges:
if g.cible == qB.source:
list_pA += [self.categorie.Composee(g,qB)]
image_existe = False
for cocone1 in self.cat_cocones1.objets:
for j in cocone1.jambes.values():
if j not in list_pA:
break
else:
image_existe = True
break
if not image_existe:
raise Exception("Incoherence Bouquet : le cocone "+str(cocone2)+" compose avec le bouquet n'a pas d'image")
class Bouquet(BouquetPerceptif,BouquetActif):
"""Un bouquet est à la fois perceptif et actif."""
def __init__(self, foncteur1, foncteur2, tiges, cat_cones1=None,cat_cones2=None,cat_cocones1=None,cat_cocones2=None):
"""On peut fournir cat_cones1, cat_cones2, cat_cocones1 et cat_cocones2 pour économiser du temps de calcul."""
BouquetPerceptif.__init__(self,foncteur1,foncteur2,tiges,cat_cones1,cat_cones2)
BouquetActif.__init__(self,foncteur1,foncteur2,tiges,cat_cocones1,cat_cocones2)
class BouquetsPerceptifs:
def __init__(self, foncteur1, foncteur2, cat_cones1=None, cat_cones2=None):
"""On peut spécifier les catégories de cônes pour économiser du temps de calcul"""
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
if self.foncteur1.cat_cible != self.foncteur2.cat_cible:
raise Exception("Incoherence BouquetsPerceptifs : les deux foncteurs n'ont pas la meme image.")
self.cat_cones1 = CategorieCones(foncteur1) if cat_cones1 == None else cat_cones1
self.cat_cones2 = CategorieCones(foncteur2) if cat_cones2 == None else cat_cones2
self.categorie = self.foncteur1.cible
self.bouquets_perceptifs = []
# 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]
# on énumère toutes les interactions de D1 à D2
for nb_fleches in range(1,len(objets_comma_category)+1):
for interaction in itertools.combinations(fleches,nb_fleches):
ajouter_bouquet = True
for cone in self.cat_cones1.objets:
fleches_generees = set()
for jambe in cone.jambes.values():
for fleche in interaction:
if fleche.source == jambe.cible:
fleches_generees |= {self.categorie.Composee(jambe,fleche)}
cone_a_l_arrivee = False
for cone2 in self.cat_cones2.objets:
if fleches_generees == set(cone2.jambes.values()):
cone_a_l_arrivee = True
break
if not cone_a_l_arrivee:
ajouter_bouquet = False
break
if ajouter_bouquet:
self.bouquets_perceptifs += [BouquetPerceptif(self.foncteur1,self.foncteur2,interaction,cat_cones1,cat_cones2)]
def transformer_graphviz(self):
for bouquet in self.bouquets_perceptifs:
bouquet.transformer_graphviz()
class BouquetsActifs:
def __init__(self, foncteur1, foncteur2, cat_cocones1=None, cat_cocones2=None):
"""On peut spécifier les catégories de cocônes pour économiser du temps de calcul"""
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
if self.foncteur1.cat_cible != self.foncteur2.cat_cible:
raise Exception("Incoherence BouquetsActifs : les deux foncteurs n'ont pas la meme image.")
self.cat_cocones1 = CategorieCocones(foncteur1) if cat_cocones1 == None else cat_cocones1
self.cat_cocones2 = CategorieCocones(foncteur2) if cat_cocones2 == None else cat_cocones2
self.categorie = self.foncteur1.cible
self.bouquets_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]
# on énumère toutes les interactions de D1 à D2
for nb_fleches in range(1,len(objets_comma_category)+1):
for interaction in itertools.combinations(fleches,nb_fleches):
ajouter_bouquet = True
for cocone in self.cat_cocones2.objets:
fleches_generees = set()
for jambe in cocone.jambes.values():
for fleche in interaction:
if fleche.cible == jambe.source:
fleches_generees |= {self.categorie.Composee(fleche,jambe)}
cocone_au_depart = False
for cocone1 in self.cat_cocones1.objets:
if fleches_generees == set(cocone1.jambes.values()):
cocone_au_depart = True
break
if not cocone_au_depart:
ajouter_bouquet = False
break
if ajouter_bouquet:
self.bouquets_actifs += [BouquetActif(self.foncteur1,self.foncteur2,interaction,cat_cocones1,cat_cocones2)]
def transformer_graphviz(self):
for bouquet in self.bouquets_actifs:
bouquet.transformer_graphviz()
class Bouquets:
def __init__(self, foncteur1, foncteur2, cat_cones1=None, cat_cones2=None, cat_cocones1=None, cat_cocones2=None):
"""On peut spécifier les catégories de cônes et cocônes pour économiser du temps de calcul"""
self.foncteur1 = foncteur1
self.foncteur2 = foncteur2
self.cat_cones1 = cat_cones1
self.cat_cones2 = cat_cones2
self.cat_cocones1 = cat_cocones1
self.cat_cocones2 = cat_cocones2
self.bouquets_perceptifs = BouquetsPerceptifs(foncteur1,foncteur2,cat_cones1,cat_cones2)
print("fin création bouquets perceptifs")
self.bouquets_actifs = BouquetsActifs(foncteur1,foncteur2,cat_cocones1,cat_cocones2)
print("fin création bouquets actifs")
self.bouquets = [Bouquet(foncteur1,foncteur2,b.tiges,cat_cones1,cat_cones2,cat_cocones1,cat_cocones2)\
for b in self.bouquets_perceptifs.bouquets_perceptifs if b in self.bouquets_actifs.bouquets_actifs]
def transformer_graphviz(self):
for bouquet in self.bouquets:
bouquet.transformer_graphviz()
def main():
# import random
# random.seed(156)
# import CategorieAleatoire
# cat1 = CategorieAleatoire.CategorieAleaPreOrdreAcyclique(10,0.5)
# from Morphisme import Morphisme
# nouveau = Morphisme(4,7,'m')
# cat1.ajouter_morphisme(nouveau)
# cat1.transformer_graphviz()
# import Diagramme
# diag1 = Diagramme.DiagrammeAlea(cat1,1)
# diag1.transformer_graphviz()
# for i in range(100):
# random.random()
# diag2 = Diagramme.DiagrammeAlea(cat1,1)
# diag2.transformer_graphviz()
# import CategorieCones, CategorieCocones
# cat_cones1 = CategorieCones.CategorieCones(diag1)
# cat_cones1.transformer_graphviz(destination="graphviz/cat_cones1")
# cat_cones2 = CategorieCones.CategorieCones(diag2)
# cat_cones2.transformer_graphviz(destination="graphviz/cat_cones2")
# cat_cocones1 = CategorieCocones.CategorieCocones(diag1)
# cat_cocones1.transformer_graphviz(destination="graphviz/cat_cocones1")
# 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
cat = Categorie()
cat.ajouter_objets("ABCDO")
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')]
cat.ajouter_morphismes([f,g,h,i,j,k,l,m])
from CategoriePreordre import CategoriePreordre
cat2 = CategoriePreordre(cat)
n,o = [Morphisme('O','A','n'),Morphisme('O','B','o')]
cat2.ajouter_morphismes([n,o])
cat2.transformer_graphviz()
cat_fleche = Categorie()
cat_fleche.ajouter_objets("AB")
a = Morphisme('A','B','a')
cat_fleche.ajouter_morphismes([a])
fonct1 = Foncteur(cat_fleche,cat2,{'A':'A','B':'B'},{a:h})
fonct2 = Foncteur(cat_fleche,cat2,{'A':'C','B':'D'},{a:k})
bouquets = BouquetsPerceptifs(fonct1,fonct1)
bouquets.transformer_graphviz()
if __name__ == '__main__':
main()
\ No newline at end of file
from Categorie import Categorie
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:
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(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_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",';')
if __name__ == '__main__':
main()
\ No newline at end of file
......@@ -85,7 +85,7 @@ class CategorieFleurieActive(CategorieFleurieAbstraite):
CategorieFleurieAbstraite.__init__(self,categorie,representant)
def chercher_bouquets(self,source,cible):
return BouquetsPerceptifs(source,cible,self.cat_cones_cocones[source]["cat_cocones"],self.cat_cones_cocones[cible]["cat_cocones"])
return BouquetsActifs(source,cible,self.cat_cones_cocones[source]["cat_cocones"],self.cat_cones_cocones[cible]["cat_cocones"])
def main():
import CategorieAleatoire
......@@ -109,7 +109,7 @@ def main():
diag1.transformer_graphviz()
diag2.transformer_graphviz()
cat_fleurie = CategorieFleuriePerceptive(cat)
cat_fleurie = CategorieFleurieActive(cat)
cat_fleurie.transformer_graphviz(afficher_identites=True)
cat_fleurie.ajouter_diagramme_interet(diag1)
cat_fleurie.transformer_graphviz(afficher_identites=True)
......
......@@ -10,6 +10,7 @@ class CategorieSous(Categorie):
def __new__(cls,categorie,objet):
if objet not in categorie.objets:
categorie.transformer_graphviz(complet=False)
raise Exception("Incohérence CategorieSous : objet "+str(objet)+" pas dans la categorie.")
result = copy(categorie)
for obj in categorie.objets:
......
......@@ -18,15 +18,7 @@ class ClusterAbstrait(Morphisme):
self.categorie = self.foncteur1.cat_cible
identite = False
if self.foncteur1 == self.foncteur2:
for composante in self.composantes:
if not composante.is_identite:
break
else:
for objet in self.foncteur1.app_objets.values():
if self.categorie.identites[objet] not in self.composantes:
break
else:
identite = True
identite = True
Morphisme.__init__(self,self.foncteur1,self.foncteur2,str(self),identite)
def __eq__(self,other):
......@@ -138,7 +130,7 @@ class ProtoClusterActif(ClusterAbstrait):
for composante in self.composantes:
if composante.source == self.foncteur1(d):
E_e += [composante.cible]
cat_sous = CategorieSous(self.categorie, d)
cat_sous = CategorieSous(self.categorie, self.foncteur1(d))
cat_cc = CategorieComposantesConnexes(cat_sous)
# 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:]:
......@@ -195,7 +187,7 @@ class ProtoClustersActifs:
for composante in interaction:
if composante.source == self.foncteur1(d):
E_e += [composante.cible]
cat_sous = CategorieSous(self.categorie, d)
cat_sous = CategorieSous(self.categorie, self.foncteur1(d))
cat_cc = CategorieComposantesConnexes(cat_sous)
# 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:]:
......@@ -263,7 +255,25 @@ class ClusterActif(ProtoClusterActif):
cluster_maxi = cluster
return copy(cluster_maxi)
class CompositionClustersActifs(ClusterActif):
def __new__(cls,*clusters):
if len(clusters) == 0:
raise Exception("Composition de 0 clusters")
backup = clusters
clusters = [m for m in clusters if not m.is_identite] #on supprime les identités
if len(clusters) == 0:
for i in range(1,len(backup)):
if backup[i-1] != backup[i]:
raise Exception("Composition d'identites differentes"+str(backup))
return backup[0]
elif len(clusters) == 1:
return clusters[0]
else:
for i in range(1,len(clusters)):
if clusters[i-1].cible != clusters[i].source:
raise Exception("Composition de clusters impossible : "+clusters.__repr__())
instance = ClusterActif(clusters[0].source,clusters[-1].cible)
return instance
def main():
......
;(Df,f,C(B));(Df,g,C(B));(Dg,f,C(B));(Dg,g,C(B));(C(A),f,C(B));(C(A),g,C(B));(Df,IdA,C(A));(Df,IdA/f,Df);(Df,IdA/g,Dg);(Df,IdB,C(B));(Dg,IdA,C(A));(Dg,IdA/f,Df);(Dg,IdA/g,Dg);(Dg,IdB,C(B));(C(A),IdA,C(A));(C(A),IdA/f,Df);(C(A),IdA/g,Dg);(C(B),IdB,C(B));(Df,IdA/IdB,Df);(Df,f/IdB,C(B));(Dg,IdA/IdB,Dg);(Dg,g/IdB,C(B));(Df,IdA/f/IdB,Df);(Dg,IdA/g/IdB,Dg)
(Df,f,C(B));X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;(Df,f,C(B));X;X;X;X;X;X
(Df,g,C(B));X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;(Df,g,C(B));X;X;X;X;X;X
(Dg,f,C(B));X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;(Dg,f,C(B));X;X;X;X;X;X
(Dg,g,C(B));X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;(Dg,g,C(B));X;X;X;X;X;X
(C(A),f,C(B));X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;(C(A),f,C(B));X;X;X;X;X;X
(C(A),g,C(B));X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;(C(A),g,C(B));X;X;X;X;X;X
(Df,IdA,C(A));X;X;X;X;(Df,f,C(B));(Df,g,C(B));X;X;X;X;X;X;X;X;(Df,IdA,C(A));(Df,IdA/f,Df);(Df,IdA/g,Dg);X;X;X;X;X;X;X
(Df,IdA/f,Df);(Df,f,C(B));(Df,g,C(B));X;X;X;X;(Df,IdA,C(A));(Df,IdA/f,Df);(Df,IdA/g,Dg);(Df,f,C(B));X;X;X;X;X;X;X;X;(Df,IdA/f,Df);(Df,f,C(B));X;X;(Df,IdA/f,Df);X
(Df,IdA/g,Dg);X;X;(Df,f,C(B));(Df,g,C(B));X;X;X;X;X;X;(Df,IdA,C(A));(Df,IdA/f,Df);(Df,IdA/g,Dg);(Df,g,C(B));X;X;X;X;X;X;(Df,IdA/g,Dg);(Df,g,C(B));X;(Df,IdA/g,Dg)
(Df,IdB,C(B));X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;X;(Df,IdB,C(B));X;X;X;X;X;X
(Dg,IdA,C(A));X;X;X;X;(Dg,f,C(B));(Dg,g,C(B));X;X;X;X;X;X;X;X;(Dg,IdA,C(A));(Dg,IdA/f,Df);(Dg,IdA/g,Dg);X;X;X;X;X;X;X
(Dg,IdA/f,Df);(Dg,f,C(B));(Dg,g,C(B));X;X;X;X;(Dg,IdA,C(A));(Dg,IdA/f,Df);(Dg,IdA/g,Dg);(Dg,f,C(B));X;X;X;X;X;X;X;X;(Dg,IdA/f,Df);(Dg,f,C(B));X;X;(Dg,IdA/f,Df);X
(Dg,IdA/g,Dg);X;X;(Dg,f,C(B));(Dg,g,C(B));X;X;X;X;X;X;(Dg,IdA,C(A));(Dg,IdA/f,Df);(Dg,IdA/g,Dg);(Dg,g,C(B));X;X;X;X;X;X;(Dg,IdA/g,Dg);(Dg,g,C(B));X;(Dg,IdA/g,Dg)