CommaCategorie.py 11.1 KB
Newer Older
1
from Morphisme import Morphisme
2
3
from Categorie import Categorie, mise_en_cache_call, mise_en_cache_getitem
from CategorieLibre import CategorieLibre
4
5
6
from Foncteur import Foncteur
from Diagramme import DiagrammeIdentite, DiagrammeObjets
from config import *
7
from typing import *
8

Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
9
class ObjetCommaCategorie(Morphisme):
10
11
12
    """Soit C une catégorie, T et S deux foncteurs de E dans C et D dans C.
       Un objet de la comma-categorie (T|S) est un triplet (e,f,d) où e est un objet de E, f une flèche de T(e) vers S(d) et d un objet de D. 
       (cf. Mac Lane "Categories for the working mathematician" P.45)
13
       On a changé l'ordre par rapport au texte de MacLane qui considérait plutôt les triplets (e,d,f)
14
15
16
17
18
19
       
       Objet : <e,f,d>
       
         e        d
       D1|        |D2
         V    f   V
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
20
21
       D1(e) --> D2(d)

Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
22
       On peut aussi voir ObjetCommaCategorie comme un morphisme, on peut alors composer deux objets de comma-catégorie <e1,f1,d1> et <e2,f2,d2> si d1=e2,
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
23
24
25
26
27
28
       on a alors  <e2,f2,d2>o<e1,f1,d1> = <e1,f2of1,d2>
       
         e1       d1=e2        d2 
        D1|         |D2        |D3    
          V   f1    V    f2    V   
       D1(e1) --> D2(d1) --> D3(d2)
29
    """
30
    def __init__(self, e:Any, f:Morphisme, d:Any):
31
32
33
        self.__e = e #attribut read-only
        self.__f = f #attribut read-only
        self.__d = d #attribut read-only
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
34
35
36
        Morphisme.__init__(self,self.e,self.d,'('+str(self.e)+','+str(self.f)+','+str(self.d)+')',self.f.is_identite and self.e == self.d)
    
    @property
37
    def e(self) -> any:
38
        return self.__e
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
39
    @property
40
    def f(self) -> Morphisme:
41
        return self.__f
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
42
    @property
43
    def d(self) -> any:
44
        return self.__d
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
45
46
    
    
47
48
49
50
51
52
53
    def __eq__(self,other:'ObjetCommaCategorie') -> bool:
        if not issubclass(type(other),ObjetCommaCategorie):
            raise TypeError("Tentative de comparaison avec un objet de type inconnu "+str(other))
        return self.e == other.e and self.f == other.f and self.d == other.d
        
    def __hash__(self) -> int:
        return hash((self.e,self.f,self.d))
54
        
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
55
    def __matmul__(self, other:'ObjetCommaCategorie') -> 'ObjetCommaCategorie':
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
56
        if self.e != other.d:
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
57
58
59
            raise Exception("Tentative de composer deux ObjetCommaCategorie pas composables : "+str(self)+" o "+str(other))
        return ObjetCommaCategorie(other.e, self.f@other.f, self.d)
        
60
61
62
63
64
65
66
67
68
69
70
71
72
class FlecheCommaCategorie(Morphisme):
    """Soit C une catégorie, T et S deux foncteurs de E dans C et D dans C.
       Une flèche de la comma-categorie (T|S) entre deux objets (e,f,d) et (e',f',d') est un couple (k,h)
       où k est une flèche de E(e,e') et h est une flèche de D(d,d') tel que la carré
        T(e) -T(k)-> T(e')
         |             |
         f             f'
         |             |
         v             v
        S(d) -S(h)-> S(d')
        commute.
       (cf. Mac Lane "Categories for the working mathematician" P.45)
    """
73
    def __init__(self, source:Any, cible:Any, k:Morphisme, h:Morphisme):
74
75
        self.__k = k #attribut read-only
        self.__h = h #attribut read-only
76
        Morphisme.__init__(self,source,cible,str(source)+" "+'('+str(self.k)+','+str(self.h)+')'+" "+str(cible),source == cible and k.is_identite and h.is_identite)
77
78
        
    @property
79
    def k(self) -> Morphisme:
80
81
        return self.__k
    @property
82
    def h(self) -> Morphisme:
83
84
        return self.__h 
        
85
86
87
    def __repr__(self) -> str:
        return str(source)+" "+str(self)+" "+str(cible)
        
88
89
    def verifier_coherence(self, T:Foncteur, S:Foncteur):
        if T.cible != S.cible:
90
            raise Exception("Incoherence FlecheCommaCategorie : T et S de cibles differentes : "+str(T)+" != "+str(S))
91
92
        categorie = T.cible
        if self.cible.f@T(self.k) != S(self.h)@self.source.f:
93
94
            raise Exception("Incoherence FlecheCommaCategorie : le carre ne commute pas, "+str(self.cible.f)+" o "+str(T(self.k))+" != "+str(S(self.h))+" o "+str(self.source.f))
            
95
96
    def __matmul__(self,other:'FlecheCommaCategorie') -> 'FlecheCommaCategorie':
        return FlecheCommaCategorie(other.source,self.cible,self.k@other.k,self.h@other.h)
97
98
        
    def __eq__(self,other:'FlecheCommaCategorie') -> bool:
99
100
        if not issubclass(type(other),FlecheCommaCategorie):
            return False
101
        return self.source == other.source and self.cible == other.cible and self.k == other.k and self.h == other.h
102
103
104
105
        
    def __hash__(self) -> int:
        return hash((self.k,self.h))
        
106
    
107
class CommaCategorie(CategorieLibre):
108
109
110
111
112
113
    """
    Soit C une catégorie, T et S deux foncteurs de E dans C et D dans C.
    Cette catégorie est (T|S).
    Voir Mac Lane "Categories for the working mathematician" P.45
    """
    
114
    def __init__(self, T:Foncteur, S:Foncteur, nom:str = None):
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
115
        Categorie.__init__(self,set(),"Comma-catégorie ("+str(T)+'|'+str(S)+')' if nom == None else nom)
116
117
118
        if T.cible != S.cible:
            raise Exception("Incoherence CommaCategorie : T et S de cibles differentes : "+str(T)+" vs "+str(S))
        self.__C = T.cible
119
120
        self._T = T
        self._S = S
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
121
        self |= {ObjetCommaCategorie(e,f,d) for e in T.source.objets for d in S.source.objets for f in self.__C({T(e)},{S(d)})} # on ajoute tous les objets
122
123
124
125
126
127
128
    
    def __eq__(self, other:'CommaCategorie') -> bool:
        return self._T == other._T and self._S == other._S

    def __hash__(self) -> int:
        return hash((self._T,self._S))
    
129
130
    def identite(self, objet:ObjetCommaCategorie) -> FlecheCommaCategorie:
        '''L'identité pour un objet (e,f,d) est la paire d'identité de T(e) et S(d).'''
131
132
133
134
135
136
137
138
139
140
        return FlecheCommaCategorie(objet,objet,self._T.source.identite(objet.e),self._S.source.identite(objet.d))
        
    def __getitem__(self, couple_sources_cibles:tuple) -> Generator[FlecheCommaCategorie, None, None]:
        sources,cibles = couple_sources_cibles
        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)
141
    
142
143
144
145
146
147
148
    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)
149
150
151
152
153
154
155
156
157
158
159
        
class CategorieFleches(CommaCategorie):
    """Catégorie des flèches d'une catégorie C.
    (cf. https://en.wikipedia.org/wiki/Comma_category#Arrow_category)
    """
    def __init__(self, C:Categorie, nom:str = None):
        CommaCategorie.__init__(self,DiagrammeIdentite(C),DiagrammeIdentite(C),"Categorie des flèches de "+str(C) if nom == None else nom)

class CategorieSous(CommaCategorie):
    """CategorieSous peut aussi être appelée CosliceCategorie.
       Soit C une catégorie, et b un objet de C.
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
160
       CategorieSous est la catégorie en-dessous de b (b|C)
161
162
163
164
       (cf. Mac Lane "Categories for the working mathematician" P.45)
       On construit la catégorie sous b en créant la comma-catégorie (1_b|Id(C)) c'est-à-dire
       la comma-catégorie du diagramme qui associe à un objet unique b avec le diagramme identité de C.
    """
165
    def __init__(self, C:Categorie, objet:Any, nom:str = None):
166
167
168
169
        CommaCategorie.__init__(self,DiagrammeObjets(C,{objet}),DiagrammeIdentite(C),str(C)+" sous "+str(objet) if nom == None else nom)

CosliceCategorie = CategorieSous

170
171
172
173
174
175
class CategorieFSous(CommaCategorie):
    """Soit C une catégorie, b un objet de C et F un foncteur de I vers C
       CategorieFSous est la catégorie F-en-dessous de b (b|F)
       (cf. Mac Lane "Categories for the working mathematician" P.45)
       On construit la catégorie sous b en créant la comma-catégorie (1_b|F) c'est-à-dire
       la comma-catégorie du diagramme qui associe à un objet unique b avec le foncteur F.
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
176
177
       
       Les objets de cette comma-catégorie sont de la forme <0,f,d>.
178
    """
179
    def __init__(self, F:Foncteur, objet:Any, nom:str = None):
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
180
        CommaCategorie.__init__(self,DiagrammeObjets(F.cible,{objet}),F,str(F)+" sous "+str(objet) if nom == None else nom)
181
182
183

CosliceCategorie = CategorieSous

184
185
186
class CategorieSur(CommaCategorie):
    """CategorieSur peut aussi être appelée SliceCategorie.
       Soit C une catégorie, et b un objet de C.
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
187
       CategorieSur est la catégorie au-dessus de b (C|b)
188
189
190
191
       (cf. Mac Lane "Categories for the working mathematician" P.45)
       On construit la catégorie sur b en créant la comma-catégorie (Id(C)|1_b) c'est-à-dire
       la comma-catégorie du diagramme identité de C avec le diagramme qui associe à un objet unique b .
    """
192
    def __init__(self, C:Categorie, objet:Any, nom:str = None):
193
194
195
196
        CommaCategorie.__init__(self,DiagrammeIdentite(C),DiagrammeObjets(C,{objet}),str(C)+" sur "+str(objet) if nom == None else nom)

SliceCategorie = CategorieSur

197
198
199
200
201
202
class CategorieFSur(CommaCategorie):
    """Soit C une catégorie, b un objet de C et F un foncteur de I vers C.
       CategorieFSur est la catégorie F-au-dessus de b (F|b)
       (cf. Mac Lane "Categories for the working mathematician" P.45)
       On construit la catégorie sur b en créant la comma-catégorie (F|1_b) c'est-à-dire
       la comma-catégorie de F avec le diagramme qui associe à un objet unique b .
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
203
       Les objets de cette comma-catégorie sont de la forme <e,f,0>.
204
    """
205
    def __init__(self, F:Foncteur, objet:Any, nom:str = None):
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
206
        CommaCategorie.__init__(self,F,DiagrammeObjets(F.cible,{objet}),str(F)+" sur "+str(objet) if nom == None else nom)
207
208


209
210
211
212
213
   
def test_CategorieFleches():
    from GrapheDeComposition import GC,MGC
    
    cat = GC('C')
214
    cat |= {'A','B','C'}
215
    morphismes = [MGC('A','B','f'),MGC('B','C','g')]
216
    cat |= morphismes
217
218
219
220
    cat.transformer_graphviz()
    
    cat_fleches = CategorieFleches(cat)
    cat_fleches.transformer_graphviz()
221
    
222
223
224
225
def test_CategorieSous():
    from GrapheDeComposition import GC,MGC
    
    cat = GC('C')
226
    cat |= {'A','B','C','D','E'}
227
    morphismes = [MGC('A','B','f'),MGC('B','C','g'),MGC('C','D','h'),MGC('E','C','i'),MGC('E','A','j')]
228
    cat |= morphismes
229
230
231
232
233
234
235
236
237
238
    cat.transformer_graphviz()
    
    cat_sous = CategorieSous(cat,'B')
    cat_sous.transformer_graphviz()
    
    
def test_CategorieSur():
    from GrapheDeComposition import GC,MGC
    
    cat = GC('C')
239
    cat |= {'A','B','C','D','E'}
240
    morphismes = [MGC('A','B','f'),MGC('B','C','g'),MGC('C','D','h'),MGC('E','C','i'),MGC('E','A','j')]
241
    cat |= morphismes
242
243
244
245
246
247
248
249
250
251
252
    cat.transformer_graphviz()
    
    cat_sur = CategorieSur(cat,'B')
    cat_sur.transformer_graphviz()  


    
if __name__ == '__main__':
    test_CategorieFleches()
    test_CategorieSous()
    test_CategorieSur()