def parse_orbifold(orb_string): """ Parse an orbifold string like o234*2an*3bcxx into an Orbifold object. We assume that: - there are only single digit gyration and kaleidoscope numbers; - any symbol other than o, *, x, 0, 1, ..., 9 is a variable representing a parameter. """ orb_regex = 'o+|\\*[^ox*]*|x+|[^ox*]+' if not re.match('^(%s)+$' % orb_regex, orb_string): raise ValueError('Invalid orbifold string %s' % orb_string) feature_strings = re.findall(orb_regex, orb_string) gyrations = [] kaleidoscopes = [] handles = 0 crosscaps = 0 digits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] for fs in feature_strings: if fs[0] == 'o': handles = len(fs) elif fs[0] == 'x': crosscaps = len(fs) elif fs[0] == '*': kaleidoscopes.append([int(x) if x in digits else x for x in list(fs[1:])]) else: gyrations = list([int(x) if x in digits else x for x in list(fs)]) return Orbifold(gyrations, kaleidoscopes, handles, crosscaps)
def normalize_orbifold_parameters(orb, normalization_map): """ :param orb: an Orbifold :param normalization_map: a normalization map as returned by get_normalization_map on a face code :return: a new Orbifold with all parameters except 'n' in gyrations and kaleidoscopes normalized with the parameter names according to normalization_map. We assume that 'n' is the vertex parameter so it wouldn't be in the normalization_map (which is on faces). """ normalized_gyrations = TestFaceCodes.apply_normalization_map(normalization_map, orb.gyrations) normalized_kaleidoscopes = [TestFaceCodes.apply_normalization_map(normalization_map, k) for k in orb.kaleidoscopes] return Orbifold(normalized_gyrations, normalized_kaleidoscopes, orb.handles, orb.crosscaps)
def test_reverse_cyclic_shift(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([2, 3, 4, 5, 6], [4, 3, 2, 6, 5]), -1)
def test_cyclic_shift(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([2, 3, 4, 5, 6], [4, 5, 6, 2, 3]), 1)
def test_equal_lengths_totally_different(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([2, 3, 4], [5, 6, 7]), 0)
def test_same_kaleidoscope_ordering(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[1, 2, 3], [4, 5, 6, 7]], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[], kaleidoscopes=[[2, 3], [4, 5, 6, 7]], handles=0, crosscaps=0) self.assertTrue(o1 == o2)
def test_different_crosscaps(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[], handles=1, crosscaps=1) o2 = Orbifold(gyrations=[], kaleidoscopes=[], handles=1, crosscaps=2) self.assertTrue(o1 != o2)
def test_even_crosscaps_normalization(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[], handles=2, crosscaps=6) self.assertEqual(o1.handles, 4) self.assertEqual(o1.crosscaps, 2)
def test_gyration_normalization(self): o1 = Orbifold(gyrations=[3, 1, 1, 2], kaleidoscopes=[], handles=0, crosscaps=0) self.assertEqual(o1.gyrations, [2, 3])
def test_empty_kaleidoscope_2(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[1, 1, 1], [2, 3, 4]], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[], kaleidoscopes=[[], [4, 3, 2]], handles=0, crosscaps=0) self.assertTrue(o1 == o2)
def test_two_oppositely_oriented_kaleidoscopes_2(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[2, 3, 4], [5, 6, 7], [7, 6, 5]], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[], kaleidoscopes=[[2, 3, 4], [6, 7, 5], [6, 5, 7]], handles=0, crosscaps=0) self.assertTrue(o1 == o2)
def test_both_oriented_kaleidoscopes_2(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[2, 2, 3, 3], [5, 6, 7]], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[], kaleidoscopes=[[2, 2, 3, 3], [7, 6, 5]], handles=0, crosscaps=0) self.assertTrue(o1 == o2)
def test_different_oriented_kaleidoscopes_nonorientable(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[2, 3, 4], [5, 6, 7], [8, 9, 10, 11]], handles=0, crosscaps=1) o2 = Orbifold(gyrations=[], kaleidoscopes=[[3, 4, 2], [9, 10, 11, 8], [7, 6, 5]], handles=0, crosscaps=1) self.assertTrue(o1 == o2)
def test_same_oriented_kaleidoscopes(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[2, 3, 4], [5, 6, 7], [8, 9, 10, 11]], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[], kaleidoscopes=[[9, 10, 11, 8], [3, 4, 2], [7, 5, 6]], handles=0, crosscaps=0) self.assertTrue(o1 == o2)
def test_totally_different_kaleidoscopes(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[2, 3], [4, 5, 6]], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[], kaleidoscopes=[[4, 5], [7, 8, 9]], handles=0, crosscaps=0) self.assertTrue(o1 != o2)
def test_permutation_unequal(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([2, 3, 4, 5, 6], [4, 3, 5, 6, 2]), 0)
def test_both_orientations_two_runs(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([2, 2, 2, 3, 3], [2, 2, 3, 3, 2]), 2)
def test_exactly_same(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([2, 3, 4, 5], [2, 3, 4, 5]), 1)
def test_kaleidoscope_normalization(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[1, 1, 2, 3], [4, 1, 3]], handles=0, crosscaps=0) self.assertEqual(o1.kaleidoscopes, [[2, 3], [4, 3]])
def test_empty_kaleidoscopes(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([], []), 2)
def test_no_crosscaps_normalization(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[], handles=3, crosscaps=0) self.assertEqual(o1.handles, 3) self.assertEqual(o1.crosscaps, 0)
def test_different_lengths(self): self.assertEqual(Orbifold.normalized_kaleidoscopes_equal([2, 3, 4], [2, 3]), 0)
def test_gyrations_unequal(self): o1 = Orbifold(gyrations=[2, 4, 5, 1, 6, 6], kaleidoscopes=[], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[5, 6, 1, 1, 4, 2], kaleidoscopes=[], handles=0, crosscaps=0) self.assertTrue(o1 != o2)
def test_num_kaleidoscopes_different(self): o1 = Orbifold(gyrations=[], kaleidoscopes=[[]], handles=0, crosscaps=0) o2 = Orbifold(gyrations=[], kaleidoscopes=[[], []], handles=0, crosscaps=0) self.assertTrue(o1 != o2)