class TestCyclicGroup(unittest.TestCase): def setUp(self): # The cyclic group from the paper by Knuth. self.N = 6 self.H = Perm()(0, 1, 2, 4)(3, 5) self.group = Group() self.group.insert(self.H) def test_group(self): self.assertEqual(self.group.order(), 4) self.assertFalse(self.group.is_trivial()) self.assertTrue(Perm() in self.group) self.assertTrue(self.H in self.group) points = range(self.N) self.assertFalse(Perm()(*points) in self.group) self.assertEqual(self.group.orbits(points), [[0, 4, 2, 1], [3, 5]]) self.assertEqual(len(self.group.orbits(points)), 2) self.assertFalse(self.group.is_transitive(points)) def test_cyclic6(self): points = range(5) C6 = Group() C6.insert(Perm()(0, 1, 2)(3, 4)) self.assertEqual(C6.order(), 6) self.assertEqual(C6.orbits(points), [[0, 2, 1], [3, 4]]) self.assertEqual(len(C6.orbits(points)), 2) self.assertFalse(C6.is_transitive(points)) def tearDown(self): pass
class TestSudoku4x4(unittest.TestCase): def setUp(self): self.N = 16 self.group = Group() self.generators = [] self.generators.append( Perm()(1,2)(5,6)(9,10)(13,14)) self.generators.append( Perm()(3,4)(7,8)(11,12)(15,0)) self.generators.append( Perm()(1,3)(2,4)(5,7)(6,8)(9,11)(10,12)(13,15)(14,0)) self.generators.append( Perm()(1,5)(2,6)(3,7)(4,8)) self.generators.append( Perm()(9,13)(10,14)(11,15)(12,0)) self.generators.append( Perm()(1,9)(2,10)(3,11)(4,12)(5,13)(6,14)(7,15)(8,0)) self.generators.append( Perm()(1,4,0,13)(2,8,15,9)(3,12,14,5)(6,7,11,10)) def test_insert(self): for perm in self.generators: self.group.insert(perm) self.assertEqual(self.group.order(), 128) def tearDown(self): pass
class TestRubikGroup4Corner(unittest.TestCase): def setUp(self): self.N = 93 self.group = Group() self.order_rubik4 = 707195371192426622240452051915172831683411968000000000 X1 = Perm()(1,74,0,34)(2,70,92,38)(3,66,91,42)\ (4,63,90,46)(47,50,62,59)(48,54,61,55)(49,58,60,51)(52,53,57,56) X2 = Perm()(5,75,89,33)(6,71,88,37)(7,67,87,41)(8,64,86,45) X3 = Perm()(9,76,85,32)(10,72,84,36)(11,68,83,40)(12,65,82,44) Y1 = Perm()(4,59,81,18)(8,55,85,22)(12,51,89,26)\ (15,47,0,30)(31,34,46,43)(32,38,45,39)(33,42,44,35)(36,37,41,40) Y2 = Perm()(3,60,80,17)(7,56,84,21)(11,52,88,25)(14,48,92,29) Y3 = Perm()(2,61,79,16)(6,57,83,20)(10,53,87,24)(13,49,91,28) Z1 = Perm()(27,43,59,74)(28,44,60,75)(29,45,61,76)\ (30,46,62,77)(78,81,0,90)(79,85,92,86)(80,89,91,82)(83,84,88,87) Z2 = Perm()(23,39,55,70)(24,40,56,71)(25,41,57,72)(26,42,58,73) Z3 = Perm()(19,35,51,66)(20,36,52,67)(21,37,53,68)(22,38,54,69) #self.generators = [X1, X2, X3, Y1, Y2, Y3, Z1, Z2, Z3] self.generators = [X1, X2, X3] # order 64 #self.generators = [Y1, Y2, Y3] # order 64 #self.generators = [Z1, Z2, Z3] # order 64 def test_insert_generators(self): for perm in self.generators: self.group.insert(perm) #self.assertEqual(self.group.order(), self.order_rubik4) self.assertEqual(self.group.order(), 64) def tearDown(self): pass
class TestSymmetricGroup(unittest.TestCase): def setUp(self): pass def test_sym_5(self): self.N = 5 self.group = Group() self.assertEqual(self.group.order(), 1) self.group.insert(Perm()(0, 1)) self.assertEqual(self.group.order(), 2) self.group.insert(Perm()(1, 2)) self.assertEqual(self.group.order(), 6) self.group.insert(Perm()(2, 3)) self.assertEqual(self.group.order(), 24) self.group.insert(Perm()(3, 4)) self.assertEqual(self.group.order(), 120) self.assertTrue(Perm()(*range(self.N)) in self.group) self.assertTrue(self.group.is_transitive(points=range(self.N))) self.assertEqual(len(self.group.orbits(range(self.N))), 1) def test_sym_n(self): self.N = 4 self.group = Group() order = 1 for i in range(self.N-1): self.group.insert(Perm()(i, i+1)) order *= (i+2) self.assertEqual(self.group.order(), order) self.assertTrue(self.group.is_transitive(points=range(self.N))) self.assertEqual(len(self.group.orbits(range(self.N))), 1) def tearDown(self): pass
def test_cyclic6(self): points = range(5) C6 = Group() C6.insert(Perm()(0, 1, 2)(3, 4)) self.assertEqual(C6.order(), 6) self.assertEqual(C6.orbits(points), [[0, 2, 1], [3, 4]]) self.assertEqual(len(C6.orbits(points)), 2) self.assertFalse(C6.is_transitive(points))
def test_is_normal(self): a = Perm()(0, 1, 2) b = Perm()(0, 1) c = Perm()(0, 2, 1) G = Group() G.insert(a) G.insert(b) self.assertEqual(G.order(), 6) # G = S_3 H = Group() H.insert(a) H.insert(c) self.assertEqual(H.order(), 3) # H = A_3 self.assertTrue(H.is_normal(G))
class TestAlternatingGroup(unittest.TestCase): def setUp(self): pass def test_alt_5(self): self.N = 5 self.group = Group() self.assertEqual(self.group.order(), 1) self.group.insert(Perm()(0, 1, 2)) self.assertEqual(self.group.order(), 3) self.group.insert(Perm()(1, 2, 3)) self.assertEqual(self.group.order(), 12) self.group.insert(Perm()(2, 3, 4)) self.assertEqual(self.group.order(), 60) self.assertFalse(Perm()(0, 1) in self.group) self.assertTrue(Perm()(*range(self.N)) in self.group) # N is odd self.assertTrue(self.group.is_transitive(points=range(self.N))) self.assertEqual(len(self.group.orbits(range(self.N))), 1) def test_alt_n(self): self.N = 5 self.assertTrue(self.N > 2) self.group = Group() order = 1 for i in range(self.N-2): self.group.insert(Perm()(i, i+1, i+2)) order = order * (i+3) self.assertEqual(self.group.order(), order) self.assertTrue(self.group.is_transitive(points=range(self.N))) self.assertEqual(len(self.group.orbits(range(self.N))), 1) def tearDown(self): pass
class TestAlternatingGroup(unittest.TestCase): def setUp(self): pass def test_alt_5(self): self.N = 5 self.group = Group() self.assertEqual(self.group.order(), 1) self.group.insert(Perm()(0, 1, 2)) self.assertEqual(self.group.order(), 3) self.group.insert(Perm()(1, 2, 3)) self.assertEqual(self.group.order(), 12) self.group.insert(Perm()(2, 3, 4)) self.assertEqual(self.group.order(), 60) self.assertFalse(Perm()(0, 1) in self.group) self.assertTrue(Perm()(*range(self.N)) in self.group) # N is odd self.assertTrue(self.group.is_transitive(points=range(self.N))) self.assertEqual(len(self.group.orbits(range(self.N))), 1) def test_alt_n(self): self.N = 5 self.assertTrue(self.N > 2) self.group = Group() order = 1 for i in range(self.N - 2): self.group.insert(Perm()(i, i + 1, i + 2)) order = order * (i + 3) self.assertEqual(self.group.order(), order) self.assertTrue(self.group.is_transitive(points=range(self.N))) self.assertEqual(len(self.group.orbits(range(self.N))), 1) def tearDown(self): pass
class TestCyclicGroup(unittest.TestCase): def setUp(self): # The cyclic group from the paper by Knuth. self.N = 6 self.H = Perm()(0, 1, 2, 4)(3, 5) self.group = Group() self.group.insert(self.H) def test_group(self): self.assertEqual(self.group.order(), 4) self.assertFalse(self.group.is_trivial()) self.assertTrue(Perm() in self.group) self.assertTrue(self.H in self.group) self.assertFalse(Perm()(*range(self.N)) in self.group) self.assertFalse(self.group.is_transitive(points=range(self.N))) self.assertEqual(len(self.group.orbits(range(self.N))), 2) def tearDown(self): pass
class TestRubikGroup2(unittest.TestCase): def setUp(self): self.N = 21 self.group = Group() self.order_rubik2 = 3674160 # 6 * 9 * 12 * 15 * 18 * 21 R1 = Perm()(2,13,19,4) * Perm()(3,11,0,6) * Perm()(7,8,10,9) D1 = Perm()(5,9,13,16) * Perm()(6,10,14,17) * Perm()(18,19,0,20) B1 = Perm()(1,16,0,8) * Perm()(2,15,20,10) * Perm()(11,12,14,13) R2 = R1 * R1 R3 = R1 * R2 D2 = D1 * D1 D3 = D1 * D2 B2 = B1 * B1 B3 = B1 * B2 self.generators = [R1, D1, B1] # cwiartki i polowki self.face_turns = [R1, R2, R3, D1, D2, D3, B1, B2, B3] # tylko cwiartki self.quarter_turns = [R1, R3, D1, D3, B1, B3] def test_insert_generators(self): for perm in self.generators: #print "insert", perm #self.group.insert(perm) pass # too slow and to big #self.assertEqual(self.group.order(), self.order_rubik2) def test_insert_face_turns(self): for perm in self.face_turns: #print "insert", perm #self.group.insert(perm) pass # too slow and to big #self.assertEqual(self.group.order(), self.order_rubik2) def test_insert_quarter_turns(self): for perm in self.quarter_turns: #print "insert", perm #self.group.insert(perm) pass # too slow and to big #self.assertEqual(self.group.order(), self.order_rubik2) def test_insert(self): self.assertEqual(self.group.order(), 1) self.group.insert(Perm()(0, 1, 2)(3, 5, 4)) self.assertEqual(self.group.order(), 3) self.group.insert(Perm()(0, 3)(1, 4)(2, 5)) self.assertEqual(self.group.order(), 6) self.group.insert(Perm()(0, 6)(1, 7)(2, 8)) self.assertEqual(self.group.order(), 6 * 9) #self.group.insert(Perm()(0, 9)(1, 10)(2, 11)) #self.assertEqual(self.group.order(), 6 * 9 * 12) #self.group.insert(Perm()(0, 12)(1, 13)(2, 14)) #self.assertEqual(self.group.order(), 6 * 9 * 12 * 15) #self.group.insert(Perm()(0, 15)(1, 16)(2, 17)) #self.assertEqual(self.group.order(), 6 * 9 * 12 * 15 * 18) #self.group.insert(Perm()(0, 18)(1, 19)(2, 20)) #self.assertEqual(self.group.order(), 6 * 9 * 12 * 15 * 18 * 21) def tearDown(self): pass
class TestRubikGroup2(unittest.TestCase): def setUp(self): self.N = 21 self.group = Group() self.order_rubik2 = 3674160 # 6 * 9 * 12 * 15 * 18 * 21 R1 = Perm()(2, 13, 19, 4) * Perm()(3, 11, 0, 6) * Perm()(7, 8, 10, 9) D1 = Perm()(5, 9, 13, 16) * Perm()(6, 10, 14, 17) * Perm()(18, 19, 0, 20) B1 = Perm()(1, 16, 0, 8) * Perm()(2, 15, 20, 10) * Perm()(11, 12, 14, 13) R2 = R1 * R1 R3 = R1 * R2 D2 = D1 * D1 D3 = D1 * D2 B2 = B1 * B1 B3 = B1 * B2 self.generators = [R1, D1, B1] # cwiartki i polowki self.face_turns = [R1, R2, R3, D1, D2, D3, B1, B2, B3] # tylko cwiartki self.quarter_turns = [R1, R3, D1, D3, B1, B3] def test_insert_generators(self): for perm in self.generators: #self.group.insert(perm) pass # too slow and too big #self.assertEqual(self.group.order(), self.order_rubik2) def test_insert_face_turns(self): for perm in self.face_turns: #self.group.insert(perm) pass # too slow and too big #self.assertEqual(self.group.order(), self.order_rubik2) def test_insert_quarter_turns(self): for perm in self.quarter_turns: #self.group.insert(perm) pass # too slow and too big #self.assertEqual(self.group.order(), self.order_rubik2) def test_insert(self): self.assertEqual(self.group.order(), 1) self.group.insert(Perm()(0, 1, 2)(3, 5, 4)) self.assertEqual(self.group.order(), 3) self.group.insert(Perm()(0, 3)(1, 4)(2, 5)) self.assertEqual(self.group.order(), 6) self.group.insert(Perm()(0, 6)(1, 7)(2, 8)) self.assertEqual(self.group.order(), 6 * 9) #self.group.insert(Perm()(0, 9)(1, 10)(2, 11)) #self.assertEqual(self.group.order(), 6 * 9 * 12) #self.group.insert(Perm()(0, 12)(1, 13)(2, 14)) #self.assertEqual(self.group.order(), 6 * 9 * 12 * 15) #self.group.insert(Perm()(0, 15)(1, 16)(2, 17)) #self.assertEqual(self.group.order(), 6 * 9 * 12 * 15 * 18) #self.group.insert(Perm()(0, 18)(1, 19)(2, 20)) #self.assertEqual(self.group.order(), 6 * 9 * 12 * 15 * 18 * 21) def tearDown(self): pass
class TestDihedralGroup(unittest.TestCase): def setUp(self): self.N = 6 self.assertTrue(self.N > 2) self.group = Group() self.H = Perm()(*range(self.N)) self.group.insert(self.H) left = 1 right = self.N - 1 perm = Perm() while left < right: perm = perm * Perm()(left, right) left = left + 1 right = right - 1 self.group.insert(perm) def test_insert(self): self.assertEqual(self.group.order(), 2 * self.N) self.assertTrue(Perm() in self.group) self.assertTrue(self.H in self.group) def tearDown(self): pass
class TestRubikGroup3Corner(unittest.TestCase): def setUp(self): self.N = 51 self.group = Group() self.order_rubik3 = 43252003274489856000 X1 = Perm()(1,40,0,19)(2,37,50,22)(3,35,49,25)(26,28,34,32)(27,31,33,29) X2 = Perm()(4,41,48,18)(5,38,47,21)(6,36,46,24) Y1 = Perm()(3,32,45,10)(6,29,48,13)(8,26,0,16)(17,19,25,23)(18,22,24,20) Y2 = Perm()(2,33,44,9)(5,30,47,12)(7,27,50,15) Z1 = Perm()(14,23,32,40)(15,24,33,41)(16,25,34,42)(43,45,0,49)(44,48,50,46) Z2 = Perm()(11,20,29,37)(12,21,30,38)(13,22,31,39) #self.generators = [X1, X2, Y1, Y2, Z1, Z2] #self.generators = [X1, X2] # order 16 #self.generators = [Y1, Y2] # order 16 self.generators = [Z1, Z2] # order 16 def test_insert_generators(self): for perm in self.generators: self.group.insert(perm) #self.assertEqual(self.group.order(), self.order_rubik3) self.assertEqual(self.group.order(), 16) def tearDown(self): pass
class TestSubgroup(unittest.TestCase): def setUp(self): self.N = 4 # Tworze grupe symetryczna. self.group1 = Group() self.group1.insert(Perm()(0, 1)) self.group1.insert(Perm()(*range(self.N))) def test_subgroup_search(self): self.assertEqual(self.group1.order(), 24) # Dopuszczam permutacje parzyste - grupa alternujaca. self.group2 = self.group1.subgroup_search(lambda x: x.is_even()) self.assertEqual(self.group2.order(), 12) self.assertTrue(self.group2.is_transitive(points=range(self.N))) #print self.group2 def test_stabilizer(self): self.group2 = self.group1.stabilizer(3) self.assertEqual(self.group2.order(), 6) #print self.group2 def test_centralizer(self): # Tworze grupe cykliczna. self.group2 = Group() self.group2.insert(Perm()(*range(self.N))) self.assertEqual(self.group2.order(), self.N) # centrum grupy abelowej cyklicznej to cala grupa self.group3 = self.group2.center() self.assertEqual(self.group3.order(), self.N) # Dalej dla grupy symetrycznej. self.group2 = self.group1.center() self.assertEqual(self.group2.order(), 1) def test_is_subgroup(self): self.group2 = Group() # Tworze grupe cykliczna. self.group2.insert(Perm()(*range(self.N))) self.assertTrue(self.group2.is_subgroup(self.group1)) self.assertTrue(self.group2.is_abelian()) self.assertFalse(self.group1.is_abelian()) self.assertFalse(self.group2.is_normal(self.group1)) def tearDown(self): pass
class TestRubikGroup3Center(unittest.TestCase): def setUp(self): self.N = 48 self.group = Group() self.order_rubik3 = 43252003274489856000 U1 = Perm()(1,3,8,6)(2,5,7,4)(9,33,25,17)(10,34,26,18)(11,35,27,19) L1 = Perm()(33,35,40,38)(34,37,39,36)(1,9,41,32)(4,12,44,29)(6,14,46,27) F1 = Perm()(9,11,16,14)(10,13,15,12)(6,17,43,40)(7,20,42,37)(8,22,41,35) R1 = Perm()(17,19,24,22)(18,21,23,20)(8,25,0,16)(5,28,45,13)(3,30,43,11) B1 = Perm()(25,27,32,30)(26,29,31,28)(3,33,46,24)(2,36,47,21)(1,38,0,19) D1 = Perm()(41,43,0,46)(42,45,47,44)(14,22,30,38)(15,23,31,39)(16,24,32,40) U2 = U1 * U1 U3 = U1 * U2 L2 = L1 * L1 L3 = L1 * L2 F2 = F1 * F1 F3 = F1 * F2 R2 = R1 * R1 R3 = R1 * R2 D2 = D1 * D1 D3 = D1 * D2 B2 = B1 * B1 B3 = B1 * B2 #self.generators = [U1, L1, F1, R1, B1, D1] self.generators = [U1, D1] # order 16 # cwiartki i polowki #self.face_turns = [U1, U2, U3, L1, L2, L3, F1, F2, F3, R1, R2, R3, D1, D2, D3, B1, B2, B3] self.face_turns = [L1, R1] # order 16 # tylko cwiartki #self.quarter_turns = [U1, U3, L1, L3, F1, F3, R1, R3, D1, D3, B1, B3] self.quarter_turns = [F1, B1] # order 16 def test_insert_generators(self): for perm in self.generators: self.group.insert(perm) #self.assertEqual(self.group.order(), self.order_rubik3) self.assertEqual(self.group.order(), 16) def test_insert_face_turns(self): for perm in self.face_turns: self.group.insert(perm) #self.assertEqual(self.group.order(), self.order_rubik3) self.assertEqual(self.group.order(), 16) def test_insert_quarter_turns(self): for perm in self.quarter_turns: self.group.insert(perm) #self.assertEqual(self.group.order(), self.order_rubik3) self.assertEqual(self.group.order(), 16) def tearDown(self): pass
class TestGroupOrbits(unittest.TestCase): def setUp(self): pass def test_orbits1(self): self.N = 3 self.group = Group() self.group.insert(Perm()(0, 1)) self.assertEqual(self.group.orbits(range(self.N)), [[0, 1], [2]]) self.assertEqual(self.group.orbits([0, 1]), [[0, 1]]) self.assertFalse(self.group.is_transitive(points=range(self.N))) self.assertTrue( self.group.is_transitive(points=range(self.N), strict=False)) def test_orbits2(self): self.N = 4 self.group = Group() self.group.insert(Perm()(0, 1)) self.group.insert(Perm()(2, 3)) self.assertFalse(self.group.is_transitive(points=range(self.N))) self.assertEqual(self.group.orbits(range(self.N)), [[0, 1], [2, 3]]) self.assertEqual(self.group.orbits([0, 1]), [[0, 1]]) self.assertEqual(self.group.orbits([0, 1, 2]), [[0, 1], [2, 3]]) def test_orbits3(self): # grupa cykliczna self.N = 10 self.group = Group() self.group.insert(Perm()(*range(self.N))) self.assertTrue(self.group.is_transitive(points=range(self.N))) def test_orbits4(self): self.N = 10 self.group = Group() self.group.insert(Perm()(0, 1, 2)) self.assertFalse(self.group.is_transitive(points=range(self.N))) self.assertTrue( self.group.is_transitive(strict=False, points=range(self.N))) def tearDown(self): pass
def test_normal_closure(self): n = 5 # Make Cyclic(5). C5 = Group() C5.insert(Perm()(*range(n))) self.assertEqual(C5.order(), n) # Make Sym(5). S5 = Group() S5.insert(Perm()(*range(n))) S5.insert(Perm()(0, 1)) self.assertEqual(S5.order(), 120) A5 = S5.normal_closure(C5) # we get Alt(5) self.assertEqual(A5.order(), 60) for perm in A5: self.assertTrue(perm.is_even())
class TestGroupOrbits(unittest.TestCase): def setUp(self): pass def test_orbits1(self): self.N = 3 self.group = Group() self.group.insert(Perm()(0,1)) self.assertEqual(self.group.orbits(range(self.N)), [[0, 1],[2]]) self.assertEqual(self.group.orbits([0, 1]), [[0, 1]]) self.assertFalse(self.group.is_transitive(points=range(self.N))) self.assertTrue(self.group.is_transitive(points=range(self.N), strict=False)) def test_orbits2(self): self.N = 4 self.group = Group() self.group.insert(Perm()(0, 1)) self.group.insert(Perm()(2, 3)) self.assertFalse(self.group.is_transitive(points=range(self.N))) self.assertEqual(self.group.orbits(range(self.N)), [[0, 1],[2, 3]]) self.assertEqual(self.group.orbits([0, 1]), [[0, 1]]) self.assertEqual(self.group.orbits([0, 1, 2]), [[0, 1],[2, 3]]) def test_orbits3(self): # grupa cykliczna self.N = 10 self.group = Group() self.group.insert(Perm()(*range(self.N))) self.assertTrue(self.group.is_transitive(points=range(self.N))) def test_orbits4(self): self.N = 10 self.group = Group() self.group.insert(Perm()(0, 1, 2)) self.assertFalse(self.group.is_transitive(points=range(self.N))) self.assertTrue(self.group.is_transitive(strict=False, points=range(self.N))) def tearDown(self): pass
class TestSubgroup(unittest.TestCase): def setUp(self): self.N = 4 # Tworze grupe symetryczna. self.group1 = Group() self.group1.insert(Perm()(0, 1)) self.group1.insert(Perm()(*range(self.N))) def test_subgroup_search(self): self.assertEqual(self.group1.order(), 24) # Dopuszczam permutacje parzyste - grupa alternujaca. self.group2 = self.group1.subgroup_search(lambda x: x.is_even()) self.assertEqual(self.group2.order(), 12) self.assertTrue(self.group2.is_transitive(points=range(self.N))) #print self.group2 def test_stabilizer(self): self.group2 = self.group1.stabilizer(3) self.assertEqual(self.group2.order(), 6) #print self.group2 def test_centralizer(self): # Tworze grupe cykliczna. self.group2 = Group() self.group2.insert(Perm()(*range(self.N))) self.assertEqual(self.group2.order(), self.N) # centrum grupy abelowej cyklicznej to cala grupa self.group3 = self.group2.center() self.assertEqual(self.group3.order(), self.N) # Dalej dla grupy symetrycznej. self.group2 = self.group1.center() self.assertEqual(self.group2.order(), 1) def test_normalizer(self): pass def test_normal_closure(self): n = 5 # Make Cyclic(5). C5 = Group() C5.insert(Perm()(*range(n))) self.assertEqual(C5.order(), n) # Make Sym(5). S5 = Group() S5.insert(Perm()(*range(n))) S5.insert(Perm()(0, 1)) self.assertEqual(S5.order(), 120) A5 = S5.normal_closure(C5) # we get Alt(5) self.assertEqual(A5.order(), 60) for perm in A5: self.assertTrue(perm.is_even()) def test_derived_subgroup(self): pass def test_is_subgroup(self): self.group2 = Group() # Tworze grupe cykliczna C_N. self.group2.insert(Perm()(*range(self.N))) self.assertEqual(self.group2.order(), self.N) self.assertTrue(self.group2.is_subgroup(self.group1)) self.assertTrue(self.group2.is_abelian()) self.assertFalse(self.group1.is_abelian()) self.assertFalse(self.group2.is_normal(self.group1)) def test_is_normal(self): a = Perm()(0, 1, 2) b = Perm()(0, 1) c = Perm()(0, 2, 1) G = Group() G.insert(a) G.insert(b) self.assertEqual(G.order(), 6) # G = S_3 H = Group() H.insert(a) H.insert(c) self.assertEqual(H.order(), 3) # H = A_3 self.assertTrue(H.is_normal(G)) def tearDown(self): pass