<jupyter_start><jupyter_text>New Object Hierarchy<jupyter_code>import numpy as np
import functools as fnc
import pprint as pp<jupyter_output><empty_output><jupyter_text>Magma<jupyter_code>class Magma:
    
    def __init__(self, elems, tbl):
        self.__elements = elems
        self.__table = np.array(tbl)
        
    def __contains__(self, element):
        return element in self.__elements

    def __getitem__(self, index):
        return self.__elements[index]
    
    @property
    def elements(self):
        return self.__elements
    
    def set_elements(self, new_elements):
        if isinstance(new_elements, list):
            self.__elements = new_elements
        elif isinstance(new_elements, dict):
            self.__elements = [new_elements[elem] for elem in self.__elements]
        return self
    
    @property
    def table(self):
        return self.__table

    def op(self, *args):
        if len(args) == 1:
            if args[0] in self.__elements:
                return args[0]
            else:
                raise ValueError(f"{args[0]} is not a valid element name")
        elif len(args) == 2:
            row = self.__elements.index(args[0])
            col = self.__elements.index(args[1])
            index = self.__table[row, col]
            return self.__elements[index]
        else:
            return fnc.reduce(lambda a, b: self.op(a, b), args)
    
    def __repr__(self):
        return f"{self.__class__.__name__}(\n{self.__elements}, \n{self.__table})"
    
    def table_with_names(self):
        return [[self.__elements[index] for index in row] for row in self.__table]<jupyter_output><empty_output><jupyter_text>Magma Examples  Rock-Paper-Scisors Magma This magma is obviously commutative, but not associative.See https://en.wikipedia.org/wiki/Commutative_magma* $M = \langle \{r,p,s\}, \cdot \rangle$* For all $x, y \in M$, if $x$ *beats* $y$, then $x \cdot y = y \cdot x = x$* Also, for all $x \in M$, $xx = x$<jupyter_code>rps = Magma(['r', 'p', 's'], [[0, 1, 0], [1, 1, 2], [0, 2, 2]])
rps<jupyter_output><empty_output><jupyter_text>The following demonstrates that the rps magma is non-associative:<jupyter_code>ps = rps.op('p', 's')
rp = rps.op('r', 'p')

r_ps = rps.op('r', ps)
rp_s = rps.op(rp, 's')

print(f"    r(ps) = r{ps} = {r_ps}, \nbut (rp)s = {rp}s = {rp_s}")<jupyter_output>r(ps) = rs = r, 
but (rp)s = ps = s<jupyter_text>For other magma examples, [see this discussion](https://math.stackexchange.com/questions/779507/can-you-give-me-some-concrete-examples-of-magmas).  Also, [see this paper on groupiods](https://arxiv.org/ftp/math/papers/0304/0304490.pdf).  Smarandache Groupoid This is Example 1.4.1 in the paper referenced, above.<jupyter_code>ex141_tbl = [[0, 3, 0, 3, 0, 3], [1, 4, 1, 4, 1, 4], [2, 5, 2, 5, 2, 5],
             [3, 0, 3, 0, 3, 0], [4, 1, 4, 1, 4, 1], [5, 2, 5, 2, 5, 2]]
ex141_magma = Magma(['a', 'b', 'c', 'd', 'e', 'f'], ex141_tbl)
ex141_magma<jupyter_output><empty_output><jupyter_text>Testing Magma Methods  Table and Element Accessors<jupyter_code>rps.table
rps.elements
rps.table_with_names()<jupyter_output><empty_output><jupyter_text>Magma as an Iterator and Container of Elements<jupyter_code>[el for el in rps]
'r' in rps<jupyter_output><empty_output><jupyter_text>Replacing ("Setting") Element Names<jupyter_code>full_names = ['rock', 'paper', 'scissors']
rps.set_elements(full_names)
orig_elems = ['r', 'p', 's']
mapping = dict(zip(rps.elements, orig_elems))
print(mapping)
rps.set_elements(orig_elems)<jupyter_output>{'rock': 'r', 'paper': 'p', 'scissors': 's'}<jupyter_text>Table Utilities<jupyter_code>def is_table_associative(table):
    result = True
    indices = range(len(table))  # [0, 1, 2, ..., n-1]
    for a in indices:
        for b in indices:
            for c in indices:
                ab = table[a][b]
                bc = table[b][c]
                if not (table[ab][c] == table[a][bc]):
                    result = False
                    break
    return result
def is_table_commutative(table):
    result = True
    indices = range(len(table))  # [0, 1, 2, ..., n-1]
    for a in indices:
        for b in indices:
            if table[a][b] != table[b][a]:
                result = False
                break
    return result
def table_has_identity(table):
    indices = range(len(table))
    id = None
    for x in indices:
        if all(table[x][y] == y for y in indices):
            id = x
            break
    return id<jupyter_output><empty_output><jupyter_text>Testing Table Utilities<jupyter_code># not assoc; is comm; no identity -- the RPS magma table, above
tbl1 = [[0, 1, 0], [1, 1, 2], [0, 2, 2]]

# is assoc; not comm; has identity (0) --- the S3 group table
tbl2 = [[0, 1, 2, 3, 4, 5], [1, 2, 0, 5, 3, 4], [2, 0, 1, 4, 5, 3],
        [3, 4, 5, 0, 1, 2], [4, 5, 3, 2, 0, 1], [5, 3, 4, 1, 2, 0]]

# is assoc; is comm; has identity (0) --- the Z4 group table
tbl3 = [[0, 1, 2, 3], [1, 2, 3, 0], [2, 3, 0, 1], [3, 0, 1, 2]]

# powerset(3) group table
tbl4 = [[0, 1, 2, 3, 4, 5, 6, 7], [1, 0, 4, 5, 2, 3, 7, 6], [2, 4, 0, 6, 1, 7, 3, 5],
        [3, 5, 6, 0, 7, 1, 2, 4], [4, 2, 1, 7, 0, 6, 5, 3], [5, 3, 7, 1, 6, 0, 4, 2],
        [6, 7, 3, 2, 5, 4, 0, 1], [7, 6, 5, 4, 3, 2, 1, 0]]

tbl5 = ex141_tbl  # Defined in magma section, above

test_tables = [tbl1, tbl2, tbl3, tbl4, tbl5]
print("   Table     Associative?  Commutative?  Identity?")
print('-'*55)
for tbl in test_tables:
    i = test_tables.index(tbl) + 1
    is_assoc = str(is_table_associative(tbl))
    is_comm = str(is_table_commutative(tbl))
    tbl_id = str(table_has_identity(tbl))
    print(f"{i :>{6}} {is_assoc :>{14}} {is_comm :>{12}} {tbl_id :>{12}}")<jupyter_output>Table     Associative?  Commutative?  Identity?
-------------------------------------------------------
     1          False         True         None
     2           True        False            0
     3           True         True            0
     4           True         True            0
     5           True        False         None<jupyter_text>Semigroup A semigroup is an associative magma.<jupyter_code>is_table_associative(rps.table)
class Semigroup(Magma):
    
    def __init__(self, elems, tbl):
        if is_table_associative(tbl):
            super().__init__(elems, tbl)
        else:
            raise ValueError("Table does not support associativity")<jupyter_output><empty_output><jupyter_text>The Semigroup constructor will fail if the table does not support associativity:<jupyter_code>try:
    Semigroup(['r', 'p', 's'], [[0, 1, 0], [1, 1, 2], [0, 2, 2]])
except:
    print("Something went wrong")<jupyter_output>Something went wrong<jupyter_text>See p. 67 in Pinter for a possible example  Monoid A monoid is a semigroup with an identity element.<jupyter_code>class Monoid(Semigroup):

    def __init__(self, elems, tbl):
        self.identity = has_identity(tbl)
        if self.identity:
            super().__init__(elems, tbl)
        else:
            raise ValueError("Table has no identity element")<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup