#!/usr/bin/env python3 class Group: """ This class generate a group self._g based on the operation (here denoted +) with the function ope: (a ** b) % n In group theory, any group has an identity element (e), which with the binary operation, do not change the value and must satisfy the condition: $a + e = 0$ Attributes: n (Integer): It's the G_n elements in the Group g (List): The set of the Group operation (Function): Function for generating the Group identity (Integer): The identity of the group. reverse (Dict): For each elements of the Group of n, we have the reverse value """ def __init__(self, n, g, ope): self._n = n self._g = g self._operation = ope self._identity = 0 self._reverse = dict() def getG(self) -> list(): """ This function return the Group Returns: List of all elements in the Group """ return self._g def closure(self) -> bool: """ Check the closure law In a group, each element a, b belongs to G, such as a + b belongs to G Returns: Return a Boolean if the closure law is respected. True if yes otherwise it's False """ for e1 in self._g: for e2 in self._g: res = self._operation(e1, e2, self._n) if not res in self._g: # raise Exception(f"{res} not in g. g is not a group") return False return True def associative(self) -> bool: """ Check the associative law. In a group, for any a, b and c belongs to G, they must respect this condition: (a + b) + c = a + (a + b) Returns: Return a boolean if the Associative law is respected. True if yes otherwise it's False """ a = self._g[0] b = self._g[1] c = self._g[2] res_ope = self._operation(a, b, self._n) res1 = self._operation(res_ope, c, self._n) res_ope = self._operation(b, c, self._n) res2 = self._operation(a, res_ope, self._n) if res1 != res2: # raise Exception(f"{res1} is different from {res2}. g is not a group") return False return True def identity(self) -> bool: """ Check the identity law. In a group, an identity element exist and must be uniq Returns: Return a Boolean if the identity elements has been found. True if found otherwise it's False """ for a in self._g: for b in self._g: if not self._operation(a, b, self._n) == b: break self._identity = a return True return False def getIdentity(self) -> int: """ Return the identity element. The function identitu() must be called before. Returns: Return the identity element if it has been found """ return self._identity def reverse(self) -> bool: """ Check the inverse law In a group, for each element belongs to G they must have an inverse a ^ (-1) = e (identity) Returns: Return a Boolean if the all elements ha a reverse element. True if yes otherwise it's False """ reverse = False for a in self._g: for b in self._g: if self._operation(a, b, self._n) == self._identity: self._reverse[a] = b reverse = True break return reverse def getReverses(self) -> dict: """ This function return the dictionary of all reverses elements. The key is the element in G and the value is the reverse element Returns: Return the reverse dictionary """ return self._reverse