예제 #1
0
    def generate(self, elems):
        """
        Returns the subgroup of self generated by GroupElems elems

        If any of the items aren't already GroupElems, we will try to convert
        them to GroupElems before continuing.

        elems must be iterable
        """

        elems = Set(g if isinstance(g, GroupElem) else GroupElem(g, self) \
                    for g in elems)

        if not elems <= self.group_elems:
            raise ValueError("elems must be a subset of self.group_elems")
        if len(elems) == 0:
            raise ValueError("elems must have at least one element")

        oldG = elems
        while True:
            newG = oldG | Set(a * b for a in oldG for b in oldG)
            if oldG == newG: break
            else: oldG = newG
        oldG = Set(g.elem for g in oldG)

        return Group(oldG, self.bin_op.new_domains(oldG * oldG, oldG))
예제 #2
0
    def __div__(self, other):
        """ Returns the quotient group self / other """
        if not other.is_normal_subgroup(self):
            raise ValueError("other must be a normal subgroup of self")
        G = Set(Set(self.bin_op((g, h)) for h in other.Set) for g in self.Set)

        def multiply_cosets(x):
            h = x[0].pick()
            return Set(self.bin_op((h, g)) for g in x[1])

        return Group(G, Function(G * G, G, multiply_cosets))
예제 #3
0
    def subgroups(self):
        """Returns the Set of self's subgroups"""

        old_sgs = Set([self.generate([self.e])])
        while True:
            new_sgs = old_sgs | Set(self.generate(list(sg.group_elems) + [g]) \
                                     for sg in old_sgs for g in self \
                                     if g not in sg.group_elems)
            if new_sgs == old_sgs: break
            else: old_sgs = new_sgs

        return old_sgs
예제 #4
0
    def test_basics(self):
        s = Set([0, 1, 2, 3])
        t = Set([1, 2, 3, 4])
        f = Function(s, t, lambda x: x + 1)
        str(f)
        for x in range(4):
            self.assertEquals(f(x), x + 1)
        self.assertEquals(f, f)

        with self.assertRaises(TypeError):
            Function([0, 1, 2, 3], t, lambda x: x + 1)
        with self.assertRaises(TypeError):
            Function(s, [1, 2, 3, 4], lambda x: x + 1)
        with self.assertRaises(TypeError):
            Function(s, t, lambda x: x + 2)
예제 #5
0
def Dn(n):
    """Returns the dihedral group of order 2n """
    G = Set("%s%d" % (l, x) for l in "RS" for x in range(n))

    def multiply_symmetries(x):
        l1, l2 = x[0][0], x[1][0]
        x1, x2 = int(x[0][1:]), int(x[1][1:])
        if l1 == "R":
            if l2 == "R":
                return "R%d" % ((x1 + x2) % n)
            else:
                return "S%d" % ((x1 + x2) % n)
        else:
            if l2 == "R":
                return "S%d" % ((x1 - x2) % n)
            else:
                return "R%d" % ((x1 - x2) % n)

    return Group(G, Function(G * G, G, multiply_symmetries))
예제 #6
0
    def __init__(self, G, bin_op):
        """Create a group, checking group axioms"""

        # Test types
        if not isinstance(G, Set): raise TypeError("G must be a set")
        if not isinstance(bin_op, Function):
            raise TypeError("bin_op must be a function")
        if bin_op.codomain != G:
            raise TypeError("binary operation must have codomain equal to G")
        if bin_op.domain != G * G:
            raise TypeError("binary operation must have domain equal to G * G")

        # Test associativity
        if not all(bin_op((a, bin_op((b, c)))) == \
                   bin_op((bin_op((a, b)), c)) \
                   for a in G for b in G for c in G):
            raise ValueError("binary operation is not associative")

        # Find the identity
        found_id = False
        e = None
        for a in G:
            if all(bin_op((a, b)) == b for b in G):
                e = a
                found_id = True
                break
        if not found_id:
            raise ValueError("G doesn't have an identity")

        # Test for inverses
        for a in G:
            if not any(bin_op((a, b)) == e for b in G):
                raise ValueError("G doesn't have inverses")

        # At this point, we've verified that we have a Group.
        # Now determine if the Group is abelian:
        self.abelian = all(bin_op((a, b)) == bin_op((b, a)) \
                           for a in G for b in G)

        self.Set = G
        self.group_elems = Set(GroupElem(g, self) for g in G)
        self.e = GroupElem(e, self)
        self.bin_op = bin_op
예제 #7
0
    def test_simple(self):
        s = Set([0, 1, 2, 3])
        t = Set([1, 2, 3, 4])
        u = Set([0, 1, 2, 3, 4, 5])
        f = Function(s, t, lambda x: x + 1)
        g = Function(t, u, lambda x: x + 1)
        h = g.compose(f)
        i = Function(Set([-1, 0, 1]), Set([0, 1]), lambda x: abs(x))

        self.assertEquals(f.is_surjective(), True)
        self.assertEquals(f.is_injective(), True)
        self.assertEquals(f.is_bijective(), True)
        self.assertEquals(f.image(), t)
        str(f)

        self.assertEquals(g.is_surjective(), False)
        self.assertEquals(g.is_injective(), True)
        self.assertEquals(g.is_bijective(), False)
        self.assertEquals(g.image(), Set([2, 3, 4, 5]))
        str(g)

        self.assertEquals(h.is_surjective(), False)
        self.assertEquals(h.is_injective(), True)
        self.assertEquals(h.is_bijective(), False)
        self.assertEquals(h.image(), Set([2, 3, 4, 5]))
        str(h)

        self.assertEquals(i.is_surjective(), True)
        self.assertEquals(i.is_injective(), False)
        self.assertEquals(i.is_bijective(), False)
        self.assertEquals(i.image(), Set([0, 1]))
        str(i)

        with self.assertRaises(ValueError):
            i.compose(f)
        with self.assertRaises(ValueError):
            f.compose(i)
예제 #8
0
 def is_surjective(self):
     # Need to make self.domain into a Set, since it might not be in
     # subclasses of Function
     return self._image() == Set(self.codomain)
예제 #9
0
 def _image(self):
     """The literal image of the function"""
     return Set(self(elem) for elem in self.domain)
예제 #10
0
def Sn(n):
    """Returns the symmetric group of order n! """
    G = Set(g for g in itertools.permutations(range(n)))
    bin_op = Function(G * G, G, lambda x: tuple(x[0][j] for j in x[1]))
    return Group(G, bin_op)
예제 #11
0
def Zn(n):
    """Returns the cylic group of order n"""
    G = Set(range(n))
    bin_op = Function(G * G, G, lambda x: (x[0] + x[1]) % n)
    return Group(G, bin_op)
예제 #12
0
 def image(self):
     """Returns the image of the homomorphism as a Group object"""
     G = Set(g.elem for g in self._image())
     return Group(G, self.codomain.bin_op.new_domains(G * G, G))
예제 #13
0
 def kernel(self):
     """Returns the kernel of the homomorphism as a Group object"""
     G = Set(g.elem for g in self.domain if self(g) == self.codomain.e)
     return Group(G, self.domain.bin_op.new_domains(G * G, G))
예제 #14
0
 def multiply_cosets(x):
     h = x[0].pick()
     return Set(self.bin_op((h, g)) for g in x[1])
예제 #15
0
 def is_normal_subgroup(self, other):
     """Checks if self is a normal subgroup of other"""
     return self <= other and \
            all(Set(g * h for h in self) == Set(h * g for h in self) \
                for g in other)
예제 #16
0
 def test_identity(self):
     s = Set(["las", 3, "ksjfdlka"])
     ID = identity(s)
     str(ID)
     for item in s:
         self.assertEquals(ID(item), item)