def test_pow(self): # test if pow behaves as expected with conjugates for g, h in itertools.product(self.perms, self.perms): for n in range(10): self.assertEqual(h * g**n * h.inverse(), (h * g * h.inverse())**n) for g in self.perms: # check if iterative calculation agrees prod = self.operm for n in range(10): self.assertTrue((g**n).is_permutation()) self.assertEqual(g**n, prod) self.assertEqual(g**(-n), prod.inverse()) prod *= g # check if cyclic subgroup generated by g is abelian :) for a in range(-10, 10): for b in range(-10, 10): self.assertEqual(g**a * g**b, g**(a + b)) self.assertEqual(g**-1, g.inverse()) # check if the order divides the LCM of cycle lengths order = reduce(mul, map(len, g.disjoint_cycle_decomposition_unstable()), 1) self.assertEqual(g**order, self.operm) self.assertEqual( Perm.from_cycle(range(10))**9, Perm.from_cycle(range(10)).inverse())
def test_comp(self): for g in self.perms: self.assertEqual(g * g.inverse(), self.operm) for g, h in itertools.product(self.perms, self.perms): self.assertTrue((g * h).is_permutation()) # conjugates should preserve cycle type conj = h * g * h.inverse() self.assertCountEqual( list(map(len, g.disjoint_cycle_decomposition_unstable())), list(map(len, conj.disjoint_cycle_decomposition_unstable()))) # associativity of composition for g, h, k in itertools.product(*[self.perms] * 3): self.assertEqual((g * h) * k, g * (h * k)) self.assertEqual( Perm.from_cycle([4, 5, 6]) * self.perm6, Perm({ 1: 2, 2: 1, 4: 6, 5: 4, 6: 5 })) self.assertEqual( Perm.from_cycle([1, 2]) * Perm.from_cycle([2, 3]), Perm.from_cycle([1, 2, 3])) self.assertEqual(self.perm3c**3, self.operm)
def test_autoperm_decipher(self): sigma = Perm.from_cycle("ABCD") tau = Perm.from_cycle("AB") * Perm.from_cycle("CD") self.assertEqual(list(autoperm_decipher.func("BADCCB", sigma, tau)), list("ABCDAB")) self.assertEqual(list(autoperm_decipher.func("BADCC", sigma, tau)), list("ABCDA")) self.assertEqual(list(autoperm_decipher.func("", sigma, tau)), []) self.assertEqual(list(autoperm_decipher.func("B", sigma, tau)), ["A"])
def test_substitution(self): self.assertEqual("".join(substitution.func("", Perm())), "") self.assertEqual( "".join(substitution.func("ABC", Perm.from_cycle("AB"))), "BAC") self.assertEqual( "".join(substitution.func("ABCBD", Perm.from_cycle("AB"))), "BACAD") self.assertEqual( "".join(substitution.func("ABCBD", Perm.from_cycle("CD"))), "ABDBC")
def test_permutation_from_key(self): self.assertEqual(Perm(), permutation_from_key("")) self.assertEqual(Perm(), permutation_from_key("a")) self.assertEqual(Perm(), permutation_from_key("A")) self.assertEqual(Perm(), permutation_from_key("?a?")) self.assertEqual(Perm(), permutation_from_key("!!")) for ind, l in enumerate(string.ascii_uppercase): self.assertEqual(Perm.from_cycle(string.ascii_uppercase) ** ind, permutation_from_key(l)) self.assertEqual(Perm(dict(zip(string.ascii_uppercase, "LINUSTORVADEFGHJKMPQWXYZBC"))), permutation_from_key("linustorvalds")) self.assertEqual(Perm(dict(zip(string.ascii_uppercase, "LINUSTORVADEFGHJKMPQWXYZBC"))), permutation_from_key("linuStOrvALds")) self.assertEqual(Perm(dict(zip(string.ascii_uppercase, "LINUSTORVADEFGHJKMPQWXYZBC"))), permutation_from_key(" lin\nuStO&&(*rvA)*)(*Lds")) self.assertEqual(Perm(dict(zip(string.ascii_uppercase, "RICHADSTLMNOPQUVWXYZBEFGJK"))), permutation_from_key("richardstallman")) self.assertEqual(Perm(dict(zip(string.ascii_uppercase, "ZEBRACDFGHIJKLMNOPQSTUVWXY"))), permutation_from_key("zebra")) for _ in range(100): key = "".join(random.choices(string.ascii_uppercase, k=random.randrange(30))) self.assertTrue(permutation_from_key(key).is_permutation())
def test_inverse(self): for g in self.perms: self.assertEqual(g.inverse().inverse(), g) for g in self.operm, self.permoc, self.perm1c, self.perm2c: self.assertEqual(g.inverse(), g) self.assertTrue(g.inverse().is_permutation()) # standard inverse formula works for g, h in itertools.product(self.perms, self.perms): self.assertEqual((g * h).inverse(), h.inverse() * g.inverse()) self.assertEqual(Perm.from_cycle([3, 2, 1]).inverse(), self.perm3c)
def setUp(self): self.perm6 = Perm({1: 2, 2: 1, 3: 3, 4: 5, 5: 6, 6: 4}) self.operm = Perm({}) self.permoc = Perm.from_cycle([]) self.perm1c = Perm.from_cycle([1]) self.perm2c = Perm.from_cycle([1, 2]) self.perm3c = Perm.from_cycle([1, 2, 3]) # huge list of hopefully lots of different kinds of permutation covering # lots of edge cases self.reg_perms = [ self.permoc, self.perm1c, self.perm2c, self.perm3c, *(Perm.from_cycle(range(j, j + i)) for i in range(4, 9) for j in range(9 - i)), *(Perm.from_cycle(range(j, j + i)[::-1]) for i in range(2, 9) for j in range(9 - i)), self.operm, self.perm6 ] # add some more random permutations to hopefully catch more edge cases, # but keep them in a separate list so I can also access a deterministic # list of permutations that I can guarantee properties of self.perms = [ *self.reg_perms, *(Perm.random(range(i)) for i in range(4, 20)) ] for _ in range(10): a, b = sample(self.perms, 2) self.perms.append(a * b)
def test_from_cycle(self): self.assertEqual(self.permoc, self.operm) self.assertEqual(self.perm1c, self.operm) self.assertEqual(self.perm2c, Perm({1: 2, 2: 1})) self.assertEqual(self.perm3c, Perm({1: 2, 2: 3, 3: 1})) self.assertEqual(Perm.from_cycle([1] * 2), Perm()) self.assertEqual(Perm.from_cycle([1] * 3), Perm()) self.assertEqual(Perm.from_cycle([1] * 4), Perm()) self.assertEqual(Perm.from_cycle([2, 3, 1]), self.perm3c) self.assertEqual(Perm.from_cycle([3, 2, 1]), Perm({1: 3, 2: 1, 3: 2})) for i in range(20): for j in range(1, 5): self.assertEqual(Perm.from_cycle(list(range(i)) * j), Perm.from_cycle(range(i))) self.assertTrue( Perm.from_cycle(list(range(i)) * j).is_permutation())