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_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_repr(self): for g in self.perms: repr(g) self.assertEqual(repr(Perm(OrderedDict(((1, 2), (2, 1))))), "Perm(OrderedDict([(1, 2), (2, 1)]))") self.assertEqual(repr(Perm()), "Perm({})")
def test_table_format(self): for g in self.perms: g.table_format() self.assertEqual(Perm().table_format(), "Id\n") self.assertEqual( Perm(OrderedDict(((1, 2), (2, 1)))).table_format(), "1 2\n2 1") self.assertEqual( Perm(OrderedDict(((100, 2), (2, 100)))).table_format(), "100 2\n 2 100")
def test_str(self): for g in self.perms: str(g) self.assertEqual(str(Perm()), "Id"), self.assertEqual(str(self.perm2c), "(1 2)") self.assertEqual(str(self.perm3c), "(1 2 3)") self.assertEqual(str(self.perm6), "(1 2)(4 5 6)")
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_eq(self): for g in self.perms: self.assertEqual(g, g) self.assertEqual(g, Perm(g.mapping)) self.assertEqual(g, Perm(g.mapping.copy())) self.assertNotEqual(g, Perm({**g.mapping, -1: -2})) self.assertEqual(self.perm6, Perm({1: 2, 2: 1, 4: 5, 5: 6, 6: 4})) self.assertEqual(Perm({1: 2, 2: 1}), Perm({2: 1, 1: 2})) self.assertEqual(Perm({1: 2, 2: 1, 3: 3}), Perm({2: 1, 1: 2, 4: 4})) self.assertEqual(self.permoc, self.perm1c) self.assertEqual(self.permoc, self.operm) self.assertEqual(self.perm1c, self.operm) self.assertEqual(self.operm, Perm({1: 1})) self.assertEqual(self.operm, Perm({None: None})) for g, h in itertools.combinations( [p for p in self.reg_perms if len(p.mapping) > 2], 2): self.assertNotEqual(g, h)
def test_disjoint_cycle_decomposition(self): self.assertEqual(Perm().disjoint_cycle_decomposition_stable(), []) self.assertEqual(self.perm6.disjoint_cycle_decomposition_stable(), [[1, 2], [4, 5, 6]]) self.assertEqual(self.perm3c.disjoint_cycle_decomposition_stable(), [[1, 2, 3]]) # reconstruct permutations as a cycle composition for g in self.perms: self.assertEqual( reduce( mul, map(Perm.from_cycle, g.disjoint_cycle_decomposition_unstable()), Perm()), g) self.assertEqual( reduce( mul, map(Perm.from_cycle, g.disjoint_cycle_decomposition_stable()), Perm()), g)
def test_table_format(self): for g in self.perms: g.table_format() self.assertEqual(Perm().table_format(), "Id\n") self.assertEqual(Perm({1: 1}).table_format(), "1\n1") self.assertEqual(Perm({1: 100}).table_format(), " 1\n100") self.assertEqual(Perm({100: 1}).table_format(), "100\n 1") self.assertEqual(Perm({1: 2, 2: 1}).table_format(), "1 2\n2 1") self.assertEqual(Perm({2: 1, 1: 2}).table_format(), "1 2\n2 1") self.assertEqual(Perm({100: 2, 2: 100}).table_format(), " 2 100\n100 2") self.assertEqual(Perm({-2: 1, 1: -2}).table_format(), "-2 1\n 1 -2") self.assertEqual(Perm({-2: 1, 1: -2}).table_format(key=abs), " 1 -2\n-2 1") self.assertEqual(Perm({100: 2, 2: 100}).table_format(lambda x: -x), "100 2\n 2 100")
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_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())
def test_is_permutation(self): for g in self.perms: self.assertTrue(g.is_permutation()) self.assertFalse(Perm({1: 2, 2: 2}).is_permutation()) self.assertFalse(Perm({1: 2, 2: 3}).is_permutation())