Commit 69aff9d4 authored by Adam P. Goucher's avatar Adam P. Goucher

Ability to recognise if a 2-state ruletree is isotropic and use the more efficient implementation

parent d6034608
Pipeline #55040835 passed with stages
in 8 minutes and 6 seconds
......@@ -3,7 +3,7 @@ import os
import re
from importlib import import_module
from .genuslist import genus_list
from .exceptions import NonCanonicalError
from .exceptions import NonCanonicalError, SurplusTreeError
from .rulefiles import rule2files
def obtain_genus(rulestring):
......@@ -36,9 +36,12 @@ def create_rule(rulestring):
def sanirule(rulestring, drop_history=False):
if '.' in rulestring:
rulestring = rule2files(rulestring)
if (rulestring[0] != 'x'):
raise ValueError("Rules specified by table/tree/code files must begin with a capital letter.")
try:
rulestring = rule2files(rulestring)
if (rulestring[0] != 'x'):
raise ValueError("Rules specified by table/tree/code files must begin with a capital letter.")
except SurplusTreeError as e:
rulestring = str(e)
rulestring = rulestring.lower()
......
class NonCanonicalError(ValueError):
pass
class SurplusTreeError(ValueError):
pass
from .parsetable import ReadRuleTable
from .parsetree import ReadRuleTree
from .parsetree import ReadRuleTree, SurplusTreeError
from .writetree import TransitionsToTree
from .writecode import NodesToCode
......@@ -130,11 +130,6 @@ def rule2segs(rulefile):
grulename = segments['@RULE'][0].strip().split()[1]
rulename = decapitalise(grulename)
if rulename != grulename:
message = "Rule name \033[31;1m%s (Golly)\033[0m converted to \033[32;1m%s (lifelib)\033[0m."
print(message % (grulename, rulename))
while '@CODE' not in segments:
# Apply transformations
......
......@@ -4,6 +4,8 @@ from ast import literal_eval
from .writetree import RuleTree
from .automorph import matperms
from ..isotropic import tab2str, str2tab
from ..exceptions import SurplusTreeError
# Named neighbourhoods:
nhoods = {'2': [(-1, 0), (1, 0), (0, 0), (0, 0)],
......@@ -144,6 +146,29 @@ def optimise_tree(n_states, nhood, list_of_nodes):
return n_states, nhood, list_of_nodes
def TreeToArray(nhood, list_of_nodes):
inputs = nhood[:GetNumberOfInputs(nhood)]
lord2 = []
indices = {(-1, -1): 0, (0, -1): 1, (1, -1): 2,
(-1, 0): 3, (0, 0): 4, (1, 0): 5,
(-1, 1): 6, (0, 1): 7, (1, 1): 8}
for i in range(512):
p = len(list_of_nodes) - 1
for k in inputs:
s = (i >> indices[k]) & 1
p = list_of_nodes[p][s+1]
lord2.append(p)
return lord2
def ReadRuleTree(list_of_lines):
# Parse the actual file into a rule tree:
......@@ -152,6 +177,15 @@ def ReadRuleTree(list_of_lines):
# Optimise the resulting rule tree:
n_states, nhood, list_of_nodes = optimise_tree(*ruletree)
# Determine whether rule is 2-state isotropic:
if (n_states == 2) and (GetNumberOfInputs(nhood) + 1 == len(nhood)):
chebyshev_range = max([abs(x) for y in nhood for x in y])
if (chebyshev_range <= 1):
rarray = TreeToArray(nhood, list_of_nodes)
rstring = tab2str(rarray)
if (rarray == str2tab(rstring)):
raise SurplusTreeError(rstring)
# Serialise tree to an array:
num_nodes = len(list_of_nodes)
......
num_states=2
num_neighbors=8
num_nodes=32
1 0 0
2 0 0
1 0 1
2 0 2
3 1 3
1 1 1
2 2 5
3 3 6
4 4 7
2 5 0
3 6 9
4 7 10
5 8 11
3 9 1
4 10 13
5 11 14
6 12 15
3 1 1
4 13 17
5 14 18
6 15 19
7 16 20
4 17 17
5 18 22
6 19 23
7 20 24
8 21 25
5 22 22
6 23 27
7 24 28
8 25 29
9 26 30
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment