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