EnsFinis.py 5.27 KB
Newer Older
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from Morphisme import Morphisme
from Categorie import Categorie
import itertools
from config import *
if GRAPHVIZ_ENABLED:
    from graphviz import Digraph

class Application(Morphisme):
    """Une application A de E vers F (A : E->F) est une relation binaire telle que pour tout x de E il existe un y de F tel que F(x) = y <=> (x,y) \in A.
    On représente l'application par un dictionnaire où les clés sont des éléments de E et les valeurs des éléments de F.
    """
    nb_viz = 0
    
    def __init__(self, source:frozenset, cible:frozenset, application:dict):
        Morphisme.__init__(self,source,cible,None, source==cible and application == {x:x for x in source})
        self._app = application
        if TOUJOURS_VERIFIER_COHERENCE:
            self.verifier_coherence()
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
19
20
21
22
      
    def as_dict(self) -> dict:
        return self._app
      
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    def verifier_coherence(self):
        if len(frozenset(self._app.keys())) != len(self._app.keys()):
            raise Exception("Incoherence Application : un element a plusieurs images "+str(self._app))
        if frozenset(self._app.keys()) != self.source:
            raise Exception("Incoherence Application : l'application n'a pas suffisament ou a trop d'antecedants\n"+str(self._app)+'\n'+str(self.source))
        
    def __eq__(self,other:'Application') -> bool:
        if not issubclass(type(other),Application):
            raise TypeError("Tentative de comparaison avec un objet de type inconnu "+str(other))
        return self.source == other.source and self.cible == other.cible and self._app == other._app
        
    def __hash__(self) -> int:
        return hash((self.source,self.cible,frozenset(self._app.items())))
    
    def __call__(self, element:any) -> any:
        """Renvoie l'image de l'`element` par l'application."""
        return self._app[element]
    
    def __matmul__(self, other:'Application') -> 'Application':
42
        return Application(other.source,self.cible,{e:self(other(e)) for e in other.source})
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
43
        
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
44
45
46
47
    def __repr__(self):
        return "\n".join(map(lambda x:str(x[0])+':'+str(x[1]),self._app.items()))+'\n'
            
        
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
48
49
50
    def transformer_graphviz(self, destination:any=None):
        Application.nb_viz += 1
        if destination == None:
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
51
            destination = "graphviz/"+type(self).__name__+str(Application.nb_viz)
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
52
53
54
            
        graph = Digraph('application')
        graph.attr(concentrate="true" if GRAPHVIZ_CONCENTRATE_GRAPHS else "false")
55
        graph.attr(label="Application "+self.nom)
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
        with graph.subgraph(name='cluster_0') as cluster:
            cluster.attr(label=str(self.source))
            for o in self.source:
                cluster.node(str(o))

        with graph.subgraph(name='cluster_1') as cluster:
            cluster.attr(label=str(self.cible))
            for o in self.cible:
                cluster.node(str(o)+"'")
            
        for source in self._app:
                graph.edge(str(source),str(self(source))+"'")
                
        graph.render(destination)
        if CLEAN_GRAPHVIZ_MODEL:
            import os
            os.remove(destination) 
    
74
75
76
class CategorieEnsemblesFinis(Categorie):
    """CategorieEnsFinis peut être abrégé en EnsFinis
    Catégorie des ensembles finis, cette catégorie est infinie, on ajoute uniquement les ensembles dont on a besoin."""
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
77
    
78
    def __init__(self, objets:set = set(), nom:str = "Catégorie d'ensembles finis"):
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
79
80
        Categorie.__init__(self,objets,nom)
    
81
82
    def identite(self, ensemble:frozenset) -> Application:
        return Application(ensemble,ensemble,{e:e for e in ensemble})
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
83
        
84
    def __call__(self, sources:set, cibles:set) -> frozenset:
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
85
        result = frozenset()
86
87
        for a in sources:
            for b in cibles:
88
89
90
91
                if not issubclass(type(a),frozenset):
                    raise Exception("On s'attend à avoir des frozenset dans l'ensemble source, pas un "+str(type(a))+'\n'+str(source))
                if not issubclass(type(b),frozenset):
                    raise Exception("On s'attend à avoir des frozenset dans l'ensemble cible, pas un "+str(type(b))+'\n'+str(cible))
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
92
93
                result |= {Application(a,b,dict(zip(a,prod))) for prod in itertools.product(b,repeat=len(a))}
        return result
94
95
        
EnsFinis = CategorieEnsemblesFinis
96
97
98
99
100
101
102
103
104

class CategorieEnsembleParties(EnsFinis):
    """CategorieEnsembleParties peut être abrégé en EnsParties
    Catégorie de l'ensemble des parties d'un ensemble, les morphismes sont des applications."""
    
    def __init__(self, ensemble:set, nom:str = None):
        EnsFinis.__init__(self,{frozenset(ens) for i in range(len(ensemble)+1) for ens in itertools.combinations(ensemble,i)},"Catégorie des parties de "+str(ensemble) if nom == None else nom)
            
EnsParties = CategorieEnsembleParties
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
105
106
107
    
    
def test_EnsFinis():
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
108
    cat = EnsFinis(set(map(frozenset,[{},{1,2},{3,4,5}])))
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
109
110
111
    cat.transformer_graphviz()
    for fleche in cat({frozenset({1,2})},{frozenset({3,4,5})}):
        fleche.transformer_graphviz()
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
112
113
114
115
        
    for fleche in cat({frozenset({1,2})},{frozenset({})}):
        print("fleche de {1,2} vers {}")
        fleche.transformer_graphviz()
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
116

117
118
119
def test_EnsParties():
    cat = EnsParties({1,2,3})
    cat.transformer_graphviz()
Guillaume Sabbagh's avatar
Guillaume Sabbagh committed
120
121
    
if __name__ == '__main__':
122
123
    test_EnsFinis()
    test_EnsParties()