summaryrefslogtreecommitdiffstats
path: root/src/act4e_solutions/semigroups_representation.py
blob: f5c2780031fc789706c1d1c323456a039452bc34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
from typing import Any, TypeVar

import act4e_interfaces as I
from .sets_representation import MyFiniteSet, SolFiniteSetRepresentation
from .sets_product import MyFiniteSetProduct
from .maps_representation import MyFiniteMap, SolFiniteMapRepresentation

X = TypeVar("X")

class MyFiniteSemigroup(I.FiniteSemigroup[X]):
    _carrier: I.FiniteSet[X]
    _composition: I.FiniteMap[X, X]

    def __init__(self, s: I.FiniteSet[X], f: I.FiniteMap[X, X]):
        self._carrier = s
        self._composition = f

    def carrier(self) -> I.FiniteSet[X]:
        return self._carrier

    def composition(self) -> I.FiniteMap[X, X]:
        return self._composition

    def compose(self, a: X, b: X) -> X:
        p = self._composition.source().pack([a, b])
        return self._composition(p)


class MyFiniteMonoid(MyFiniteSemigroup, I.FiniteMonoid[X]):
    _identity: X
    def __init__(self, s: I.FiniteSet[X], f: I.FiniteMap[X, X], e: X):
        super().__init__(s, f)
        self._identity = e

    # def compose(self, a: X, b: X) -> X:
    #     if self.carrier().equal(a, self._identity):
    #         return b
    #     elif self.carrier().equal(b, self._identity):
    #         return a
    #     else:
    #         return super().compose(a, b)

    def identity(self) -> X:
        return self._identity


class MyFiniteGroup(MyFiniteMonoid, I.FiniteGroup[X]):
    _inverse: I.FiniteMap[X, X]
    def __init__(self, s: I.FiniteSet[X], f: I.FiniteMap[X, X], e: X, i: I.FiniteMap[X, X]):
        super().__init__(s, f, e)
        self._inverse = i

    def inverse(self, a: X):
        return self._inverse(a)


class SolFiniteSemigroupRepresentation(I.FiniteSemigroupRepresentation):
    def load(self, h: I.IOHelper, s: I.FiniteSemigroup_desc) -> I.FiniteSemigroup[Any]:
        if not all(k in s.keys() for k in ["carrier", "composition"]):
            raise I.InvalidFormat()

        fsr = SolFiniteSetRepresentation()
        A = fsr.load(h, s["carrier"])

        # FIXME: maybe use this?
        # fmr = SolFiniteMapRepresentation()
        for inp, out in s["composition"]:
            if not all(A.contains(i) for i in inp):
                raise I.InvalidFormat()

            if not A.contains(out):
                raise I.InvalidFormat()

        p = MyFiniteSetProduct([A, A])
        f = MyFiniteMap(p, A, s["composition"])
        return MyFiniteSemigroup(A, f)

    def save(self, h: I.IOHelper, m: I.FiniteSemigroup[Any]) -> I.FiniteSemigroup_desc:
        fsr = SolFiniteSetRepresentation()
        fmr = SolFiniteMapRepresentation()

        d = {"carrier": fsr.save(h, m.carrier()),
             "composition": []}

        for a in m.carrier().elements():
            for b in m.carrier().elements():
                e = m.composition().source().pack([a, b])
                d["composition"].append([e, m.compose(a, b)])

        return d


class SolFiniteMonoidRepresentation(I.FiniteMonoidRepresentation):
    def load(self, h: I.IOHelper, s: I.FiniteMonoid_desc) -> I.FiniteMonoid[X]:
        fsgr = SolFiniteSemigroupRepresentation()
        semi = fsgr.load(h, s)

        if not ("neutral" in s.keys()):
            raise I.InvalidFormat()

        e = s["neutral"]
        if not semi.carrier().contains(e):
            raise I.InvalidFormat()

        return MyFiniteMonoid(semi.carrier(), semi.composition(), e)

    def save(self, h: I.IOHelper, m: I.FiniteMonoid[Any]) -> I.FiniteMonoid_desc:
        fsgr = SolFiniteSemigroupRepresentation()
        d = fsgr.save(h, m)
        d["neutral"] = m.identity()
        return d


class SolFiniteGroupRepresentation(I.FiniteGroupRepresentation):
    def load(self, h: I.IOHelper, s: I.FiniteGroup_desc) -> I.FiniteGroup[X]:
        fmor = SolFiniteMonoidRepresentation()
        m = fmor.load(h, s)

        if not "inverse" in s.keys():
            raise I.InvalidFormat()

        i = MyFiniteMap(m.carrier(), m.carrier(), s["inverse"])
        return MyFiniteGroup(m.carrier(), m.composition(), m.identity(), i)

    def save(self, h: I.IOHelper, m: I.FiniteGroup[Any]) -> I.FiniteGroup_desc:
        fmor = SolFiniteMonoidRepresentation()
        d = fmor.save(h, m)
        d["inverse"] = []
        for c in m.carrier().elements():
            d["inverse"].append([c, m.inverse(c)])
        return d