Commit 2ea6081c by Adam P. Goucher

### We can now determine the symmetries of a ruletree

parent 35efc7e2
Pipeline #49984525 passed with stages
in 7 minutes and 15 seconds
 ... ... @@ -44,10 +44,6 @@ def adjugate(mat): ''' return [list(adjugate_row(mat, j)) for j in range(len(mat))] def matmulvec(m, v): pass def matperms(pts): n = len(pts) ... ...
 ... ... @@ -3,6 +3,8 @@ from ast import literal_eval from .writetree import RuleTree from .automorph import matperms # Named neighbourhoods: nhoods = {'2': [(-1, 0), (1, 0), (0, 0), (0, 0)], '4': [(0, -1), (-1, 0), (1, 0), (0, 1), (0, 0), (0, 0)], ... ... @@ -84,6 +86,18 @@ def normalise_neighbourhood(nhood): return [(x - x0, y - y0) for (x, y) in nhood] def get_symmetries(n_states, nhood, list_of_nodes): numInputs = GetNumberOfInputs(nhood) rt = compress_tree(list_of_nodes, n_states, numInputs, seqonly=False) pts = nhood[:numInputs] perms = matperms(pts) perms = [p for p in perms if rt.invariant(p)] return perms def optimise_tree(n_states, nhood, list_of_nodes): numInputs = GetNumberOfInputs(nhood) ... ...
 ... ... @@ -163,6 +163,21 @@ class RuleTree: return self._treecompare(other, self.curndd, other.curndd) def invariant(self, perm): other = RuleTree(self.numStates, self.numInputs, initialise=False) other.seq = list(self.seq) other._shrink() perm = list(perm) for _ in range(len(perm)): for i in range(len(perm) - 1): if perm[i+1] < perm[i]: perm[i], perm[i+1] = perm[i+1], perm[i] other._shrink(swap_at=(len(perm) - i)) return (other == self) def __ne__(self, other): return not self.__eq__(other) ... ...
 ... ... @@ -5,6 +5,8 @@ import unittest import lifelib.genera.rulefiles.parsetree as parsetree import lifelib.genera.rulefiles.automorph as automorph from lifelib.genera.rulefiles import table_to_tree class TestTreeduce(unittest.TestCase): def test_adjugate(self): ... ... @@ -36,6 +38,8 @@ class TestTreeduce(unittest.TestCase): self.assertEqual(len(mp), 2) def test_fcc(self): d3 = [(x, y, z) for x in [-1, 0, 1] for y in [-1, 0, 1] for z in [-1, 0, 1] if x*x + y*y + z*z == 2] mp = list(automorph.matperms(d3)) ... ... @@ -55,35 +59,50 @@ class TestTreeduce(unittest.TestCase): mp = list(automorph.matperms(d4)) self.assertEqual(len(mp), 1152) def test_rotate4(self): ''' Tests that we can learn the symmetries of Langton's Loops from its rule tree alone. ''' # Load a rule table: filename = os.path.join(lifelib.lifelib_dir, 'rules', 'source', 'Langtons-Loops.table') with open(filename, 'r') as f: list_of_lines = list(f) # Convert it to a ruletree and optimise: list_of_lines = table_to_tree(list_of_lines) ruletree = parsetree.ParseRuleTree(list_of_lines) ruletree = parsetree.optimise_tree(*ruletree) # Determine that the rule has rotate4 symmetries but not reflections: syms = parsetree.get_symmetries(*ruletree) syms2 = [[0, 1, 2, 3, 4], [3, 0, 1, 2, 4], [1, 2, 3, 0, 4], [2, 3, 0, 1, 4]] self.assertEqual(set(map(tuple, syms)), set(map(tuple, syms2))) def test_reduce(self): ''' Tests that we can recognise an hexagonal rule embedded as a Moore CA. ''' # Load a ruletree as a list of lines: filename = os.path.join(lifelib.lifelib_dir, 'rules', 'source', 'Hex-B2omS2.tree') with open(filename, 'r') as f: list_of_lines = list(f) # Parse the ruletree and verify that it has the Moore neighbourhood: ruletree = parsetree.ParseRuleTree(list_of_lines) self.assertEqual(ruletree[1], [(-1, -1), (1, -1), (-1, 1), (1, 1), (0, -1), (-1, 0), (1, 0), (0, 1), (0, 0), (0, 0)]) self.assertEqual(len(ruletree[2]), 31) # Optimise the tree and verify that the neighbourhood has reduced: ruletree2 = parsetree.optimise_tree(*ruletree) self.assertEqual(ruletree2[1], [(-1, -1), (1, 1), (0, -1), (-1, 0), (1, 0), (0, 1), (0, 0), (0, 0)]) self.assertEqual(len(ruletree2[2]), 27) rt = parsetree.make_tree(*ruletree2) rt2 = parsetree.make_tree(*ruletree2) self.assertEqual(rt, rt2) rt2._shrink(swap_at=5) self.assertNotEqual(rt, rt2) rt2._shrink(swap_at=3) self.assertEqual(rt, rt2) # Determine that the resulting rule has exactly 12 symmetries: syms = parsetree.get_symmetries(*ruletree2) self.assertEqual(len(syms), 12) if __name__ == '__main__': unittest.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!