Scorbie wrote:Whoops, my bad. it's in Scripts/Python/glife.
I actually didn't have the scripts, or patterns installed, so I reinstalled it and it works now.
Scorbie wrote:Whoops, my bad. it's in Scripts/Python/glife.
@RULE testlife
@TABLE
n_states:2
neighborhood:Moore
symmetries:rotate4reflect
0,1,1,1,0,0,0,0,0,1
0,1,1,0,1,0,0,0,0,1
0,1,1,0,0,1,0,0,0,1
0,1,1,0,0,0,1,0,0,1
0,1,1,0,0,0,0,1,0,1
0,1,1,0,0,0,0,0,1,1
0,1,0,1,0,1,0,0,0,1
0,1,0,1,0,0,1,0,0,1
0,1,0,0,1,0,1,0,0,1
0,0,1,0,1,0,1,0,0,1
0,1,1,1,1,1,1,0,0,1
1,0,0,0,0,0,0,0,0,0
1,1,0,0,0,0,0,0,0,0
1,0,1,0,0,0,0,0,0,0
1,1,1,1,1,0,0,0,0,0
1,1,1,1,0,1,0,0,0,0
1,1,1,1,0,0,1,0,0,0
1,1,1,0,1,1,0,0,0,0
1,1,1,0,1,0,1,0,0,0
1,1,1,0,1,0,0,1,0,0
1,1,1,0,1,0,0,0,1,0
1,1,1,0,0,1,1,0,0,0
1,1,1,0,0,1,0,1,0,0
1,1,1,0,0,1,0,0,1,0
1,1,1,0,0,0,1,1,0,0
1,1,0,1,0,1,0,1,0,0
1,0,1,0,1,0,1,0,1,0
1,0,0,0,1,1,1,1,1,0
1,0,0,1,0,1,1,1,1,0
1,0,0,1,1,0,1,1,1,0
1,0,0,1,1,1,0,1,1,0
1,0,0,1,1,1,1,0,1,0
1,0,0,1,1,1,1,1,0,0
1,0,1,0,1,0,1,1,1,0
1,0,1,0,1,1,0,1,1,0
1,0,1,1,0,1,0,1,1,0
1,1,0,1,0,1,0,1,1,0
1,0,0,1,1,1,1,1,1,0
1,0,1,0,1,1,1,1,1,0
1,0,1,1,0,1,1,1,1,0
1,0,1,1,1,0,1,1,1,0
1,1,0,1,0,1,1,1,1,0
1,1,0,1,1,1,0,1,1,0
1,0,1,1,1,1,1,1,1,0
1,1,0,1,1,1,1,1,1,0
1,1,1,1,1,1,1,1,1,0
@COLORS
0 0 0 0
1 255 255 255
x = 5, y = 4, rule = testlife
o2bo$4bo$o3bo$b4o!
drc wrote:It classifies this:Code: Select allx = 5, y = 4, rule = testlife
o2bo$4bo$o3bo$b4o!
As "pathological"
For those wondering it's a regular LWSS.
Error reading APG_ContagiousLife_dlife.rule on line 242: 0,aa,ab,ba,ac,bb,bc,bd,be, -too few entries
x = 17, y = 10, rule = B3/S23
b2ob2obo5b2o$11b4obo$2bob3o2bo2b3o$bo3b2o4b2o$o2bo2bob2o3b4o$bob2obo5b
o2b2o$2b2o4bobo2b3o$bo3b5ob2obobo$2bo5bob2o$4bob2o2bobobo!
Saka wrote:I get an error every time I try to use dlife (from life variations thread):Not sure what's going on, the script works just fine for other rules (e.g. tlife, HeptaFish)Code: Select allError reading APG_ContagiousLife_dlife.rule on line 242: 0,aa,ab,ba,ac,bb,bc,bd,be, -too few entries
Saka wrote:I get an error every time I try to use dlife (from life variations thread):Not sure what's going on, the script works just fine for other rules (e.g. tlife, HeptaFish)Code: Select allError reading APG_ContagiousLife_dlife.rule on line 242: 0,aa,ab,ba,ac,bb,bc,bd,be, -too few entries
def saveContagiousLife(self):
comments = """
A variant of HistoricalLife used for detecting dependencies between
islands.
state 0: vacuum
state 1: ON
state 2: OFF
"""
table = "n_states:7\n"
table += "neighborhood:Moore\n"
if ruletype:
table += "symmetries:permute\n\n"
table += self.newvars(["a","b","c","d","e","f","g","h","i"], range(0, 7, 1))
table += self.newvars(["la","lb","lc","ld","le","lf","lg","lh","li"], range(1, 7, 2))
table += self.newvars(["da","db","dc","dd","de","df","dg","dh","di"], range(0, 7, 2))
table += self.newvar("p",[3, 4])
table += self.newvars(["ta","tb","tc","td","te","tf","tg","th","ti"], [3])
table += self.newvars(["qa","qb","qc","qd","qe","qf","qg","qh","qi"], [0, 1, 2, 4, 5, 6])
for i in xrange(9):
if (self.bee[i]):
table += self.scoline("l","d",4,3,i)
table += self.scoline("l","d",2,1,i)
table += self.scoline("l","d",0,1,i)
table += self.scoline("l","d",6,5,i)
table += self.scoline("t","q",0,4,i)
if (self.ess[i]):
table += self.scoline("l","d",3,3,i)
table += self.scoline("l","d",5,5,i)
table += self.scoline("l","d",1,1,i)
table += "# Default behaviour (death):\n"
table += self.scoline("","",1,2,0)
table += self.scoline("","",5,6,0)
table += self.scoline("","",3,4,0)
else:
rule1 = open(g.getdir("app") + "Rules/" + self.slashed + ".rule", "r")
lines1 = rule1.read().split("\n")
rule1.close()
for q in xrange(len(lines1)-1):
if lines1[q].startswith("@TABLE"):
lines1 = lines1[q:]
break
vars = []
for q in xrange(len(lines1)-1): #Copy symmetries and vars
i = lines1[q]
if i[:2] == "sy" or i[:1] == "sy":
table += i + "\n\n"
if i[:2] == "va" or i[:1] == "va":
table += self.newvar(i[4:5].replace("=", ""), [0, 1, 2])
vars.append(i[4:5].replace("=", ""))
if i != "":
if i[0] == "0" or i[0] == "1":
break
alpha = "abcdefghijklmnopqrstuvwxyz"
ovars = []
for i in alpha:
if not i in [n[0] for n in vars]: #Create new set of vars for ON cells
table += self.newvars([i + j for j in alpha[:9]], [1, 3, 5])
ovars = [i + j for j in alpha[:9]]
break
dvars = []
for i in alpha:
if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars]: #Create new set of vars for OFF cells
table += self.newvars([i + j for j in alpha[:9]], [0, 2, 4, 6])
dvars = [i + j for j in alpha[:9]]
break
for i in alpha:
if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars] and not i in [n[0] for n in dvars]:
for j in xrange(8-len(vars)):
table += self.newvar(i + alpha[j], [0, 1, 2, 3, 4, 5, 6])
vars.append(i + alpha[j])
break
qvars = []
for i in alpha:
if not i in [n[0] for n in vars] and not i in [n[0] for n in ovars] and not i in [n[0] for n in dvars]:
table += self.newvars([i + j for j in alpha[:9]], [0, 1, 2, 4, 5, 6])
qvars = [i + j for j in alpha[:9]]
break
for i in lines1:
q = i.split("#")[0].replace(" ", "").split(",")
if len(q) > 1 and not i.startswith("var"):
vn = 0
ovn = 0
dvn = 0
qvn = 0
table += str(2-int(q[0])) + ","
for j in q[1:-1]:
if j == "0":
table += dvars[dvn]
dvn += 1
elif j == "1":
table += ovars[ovn]
ovn += 1
elif j != "#":
table += vars[vn]
vn += 1
table += ","
if q[len(q)-1] == "0":
table += "2"
if q[len(q)-1] == "1":
table += "1"
table += "\n"
vn = 0
ovn = 0
dvn = 0
qvn = 0
table += str(4-int(q[0])) + ","
for j in q[1:-1]:
if j == "0":
table += dvars[dvn]
dvn += 1
elif j == "1":
table += ovars[ovn]
ovn += 1
elif j != "#":
table += vars[vn]
vn += 1
table += ","
if q[len(q)-1] == "0":
table += "4"
if q[len(q)-1] == "1":
table += "3"
table += "\n"
vn = 0
ovn = 0
dvn = 0
qvn = 0
table += str(6-int(q[0])) + ","
for j in q[1:-1]:
if j == "0":
table += dvars[dvn]
dvn += 1
elif j == "1":
table += ovars[ovn]
ovn += 1
elif j != "#":
table += vars[vn]
vn += 1
table += ","
if q[len(q)-1] == "0":
table += "6"
if q[len(q)-1] == "1":
table += "5"
table += "\n"
for i in lines1:
q = i.split("#")[0].replace(" ", "").split(",")
if len(q) > 1:
vn = 0
ovn = 0
dvn = 0
qvn = 0
if q[0] == "0":
table += "0,"
for j in q[1:-1]:
if j == "0":
table += dvars[dvn]
dvn += 1
elif j == "1":
table += ovars[ovn]
ovn += 1
elif j != "#":
table += vars[vn]
vn += 1
table += ","
if q[len(q)-1] == "1":
table += "1"
else:
table += "0"
table += "\n"
for i in lines1:
q = i.split("#")[0].replace(" ", "").split(",")
if len(q) > 1:
vn = 0
ovn = 0
dvn = 0
qvn = 0
if q[0] == "0":
table += "0,"
for j in q[1:-1]:
if j == "0":
table += qvars[qvn]
qvn += 1
elif j == "1":
table += "3"
elif j != "#":
table += vars[vn]
vn += 1
table += ","
if q[len(q)-1] == "1":
table += "4"
else:
table += "0"
table += "\n"
colours = """
0 0 0 0
1 0 0 255
2 0 0 127
3 255 0 0
4 127 0 0
5 0 255 0
6 0 127 0
"""
self.saverule("APG_ContagiousLife_"+self.alphanumeric, comments, table, colours)
drc wrote:I'm having trouble with the A for awesome's version of apgnano.
In this rule:Code: Select all@RULE testlife
@TABLE
[snip]
It classifies this:Code: Select allx = 5, y = 4, rule = testlife
o2bo$4bo$o3bo$b4o!
As "pathological"
gameoflifeboy wrote:In Move variants, apgsearch v0.54 + v0.1i reports gliders, even though the rule doesn't support them. I suspect the "gliders" it's reporting are actually "spinning gliders", a p4 oscillator in Move-like rules. In fact, the phase of the glider given by its apgcode is different from the spinning glider, which means apgsearch is recognizing the gliders by their wrong phase.
drc wrote:gameoflifeboy wrote:In Move variants, apgsearch v0.54 + v0.1i reports gliders, even though the rule doesn't support them. I suspect the "gliders" it's reporting are actually "spinning gliders", a p4 oscillator in Move-like rules. In fact, the phase of the glider given by its apgcode is different from the spinning glider, which means apgsearch is recognizing the gliders by their wrong phase.
I noticed that too, its weird
1,1,2,1,2,1,12,2,0,3
1,1,o,1,oa,1,io,ioa,io,3
o,oa,13,ob,oc,od,13,oe,of,o
#Survival
A for awesome wrote:Another (very dirtily) hacked variant of apgsearch, which enumerates all patterns within a given bounding box, runs them to completion, and censuses the result...
File "apgsearch-MxNrect-0.1.py", line 50, in hashsoup
for i in xrange(math.floor(math.log(sym+1, 2))+1):
TypeError: integer argument expected, got float
dvgrn wrote:A for awesome wrote:Another (very dirtily) hacked variant of apgsearch, which enumerates all patterns within a given bounding box, runs them to completion, and censuses the result...
Works better on my system with a small change to line 50. I got the errorCode: Select allFile "apgsearch-MxNrect-0.1.py", line 50, in hashsoup
for i in xrange(math.floor(math.log(sym+1, 2))+1):
TypeError: integer argument expected, got float
Wrapping math.floor() in an int() seemed to solve the problem:
for i in xrange(int(math.floor(math.log(sym+1, 2)))+1):
math.floor() is rumored to return a float in Python 2.x but not in 3.x. Is there a Python 2.x version that works with Golly but doesn't throw the above error?
Also, if you specify a number larger than the total possible number of MxN patterns, does the script stop when it has enumerated every possible pattern once? I'm trying a 5x5 run in B3/S23, so it will be a while before I get to 33554432 to see for myself.
I don't quite understand your line 11252; seems as if the min() calculation cuts the number of iterations down to the right size, but if I put in a really big number, the script would go round and round because the limit power-of-two value isn't being divided by the number of soups per page. Looks like it should be
for i in xrange(min(int((number-1)/spp)+1, int((2**(c.x*c.y)-1)/spp)+1)):
For example, that successfully runs just 2^9=512 3x3 soups, instead of going through 64x512 = 32768 of them before stopping.
Another random thought: the current script doesn't account for rotations and reflections, so in a 5x5 search it will eventually census all eight orientations of 2obo$b2obo$2ob2o$b3o! (for example).
Have you considered generating all orientations of each candidate pattern, and letting apgsearch run a candidate only if no other orientation sorts lower? Pretty much any sort criterion would work.
With all that extra flipping/rotating/sorting work, it might not save much time in the end, but you wouldn't end up with identical census results in lots of groups of two or four or eight.
A for awesome wrote:Another (very dirtily) hacked variant of apgsearch, which enumerates all patterns within a given bounding box, runs them to completion, and censuses the result:
There isn't much to explain. Just run it like you would normal apgsearch and enter in the number of soups (preferably a number higher than the total number of patterns that fit within the bounding box you're searching), the dimensions of the box you're searching, and the rule.
P.S. Don't be alarmed by the weird error message that shows up right after the results are displayed. As far as I know, it's inconsequential.
x = 5, y = 3, rule = B3/S23
o2b2o$ob2o$4o!
A for awesome wrote:Generating only one orientation of each pattern would probably be efficient enough by far to produce an increase in performance, but I have no idea how to do that.
Kazyan wrote:A for awesome wrote:Generating only one orientation of each pattern would probably be efficient enough by far to produce an increase in performance, but I have no idea how to do that.
Derive each pattern from a seed integer, in the same way that the official apgsearch derives a pattern from a SHA256 hash. Before running the pattern, take all of its reflections and rotations, and reverse-engineer their respective seeds. Run the pattern only if its seed is the lowest among its orientations.
A further performance speedup could be gained by considering the corner cells of the pattern. Try the above paragraph on 2x2 bounding boxes, and it turns out that you can throw out 10 of every 16 seed integers automatically. So, if you derive the corner cells of a pattern from the last four binary digits of a seed, you know that certain seed integers modulo 16 will be automatically invalid, and you can skip them.
EDIT: Correction; 10 of 16 patterns cannot be discarded for M=/=N, but some still can.
x = 9, y = 8, rule = B3/S23
2o$2o$6b2o$6bobo$7bo3$3b3o!
drc wrote:With apgsearch hacked 12-27-15
What's error-correcting phase?It seems to be screwing up the search and making it slower, things like still lifes and oscillators classed as gliders under xq1_(code), and xq1_0, which is impossible. It only seems to occur when no commas occur in the rule nodes.
drc wrote:Is there any apgsearch variant that you can run and it tallies objects of the current pattern?
gameoflifeboy wrote:drc wrote:Is there any apgsearch variant that you can run and it tallies objects of the current pattern?
Nathaniel once made a program that did something like this.
It became the Online Life-Like CA Soup Search, and you know what happened to that.
x = 6, y = 5, rule = B3/S23-a
2o$obo$o$3bo$3b3o!
#Hensel-test.py
#To setup, copy this into a file, name it "hensel-test.py",
# and put the file in Golly's scripts folder.
#Enter the name of the rule whose Hensel notation you want
# to determine, and this script copies the result to the clipboard.
import golly as g
class Foo:
slashed = g.getstring("Enter name of rule to test", "Life")
def testHensel(self):
#Dict containing all possible transitions:
dict = {
"0" : "0,0,0,0,0,0,0,0",
"1e" : "1,0,0,0,0,0,0,0", # N
"1c" : "0,1,0,0,0,0,0,0", # NE
"2a" : "1,1,0,0,0,0,0,0", # N, NE
"2e" : "1,0,1,0,0,0,0,0", # N, E
"2k" : "1,0,0,1,0,0,0,0", # N, SE
"2i" : "1,0,0,0,1,0,0,0", # N, S
"2c" : "0,1,0,1,0,0,0,0", # NE, SE
"2n" : "0,1,0,0,0,1,0,0", # NE, SW
"3a" : "1,1,1,0,0,0,0,0", # N, NE, E
"3n" : "1,1,0,1,0,0,0,0", # N, NE, SE
"3r" : "1,1,0,0,1,0,0,0", # N, NE, S
"3q" : "1,1,0,0,0,1,0,0", # N, NE, SW
"3j" : "1,1,0,0,0,0,1,0", # N, NE, W
"3i" : "1,1,0,0,0,0,0,1", # N, NE, NW
"3e" : "1,0,1,0,1,0,0,0", # N, E, S
"3k" : "1,0,1,0,0,1,0,0", # N, E, SW
"3y" : "1,0,0,1,0,1,0,0", # N, SE, SW
"3c" : "0,1,0,1,0,1,0,0", # NE, SE, SW
"4a" : "1,1,1,1,0,0,0,0", # N, NE, E, SE
"4r" : "1,1,1,0,1,0,0,0", # N, NE, E, S
"4q" : "1,1,1,0,0,1,0,0", # N, NE, E, SW
"4i" : "1,1,0,1,1,0,0,0", # N, NE, SE, S
"4y" : "1,1,0,1,0,1,0,0", # N, NE, SE, SW
"4k" : "1,1,0,1,0,0,1,0", # N, NE, SE, W
"4n" : "1,1,0,1,0,0,0,1", # N, NE, SE, NW
"4z" : "1,1,0,0,1,1,0,0", # N, NE, S, SW
"4j" : "1,1,0,0,1,0,1,0", # N, NE, S, W
"4t" : "1,1,0,0,1,0,0,1", # N, NE, S, NW
"4w" : "1,1,0,0,0,1,1,0", # N, NE, SW, W
"4e" : "1,0,1,0,1,0,1,0", # N, E, S, W
"4c" : "0,1,0,1,0,1,0,1", # NE, SE, SW, NW
"5a" : "0,0,0,1,1,1,1,1", # SE, S, SW, W, NW
"5n" : "0,0,1,0,1,1,1,1", # E, S, SW, W, NW
"5r" : "0,0,1,1,0,1,1,1", # E, SE, SW, W,
"5q" : "0,0,1,1,1,0,1,1", # E, SE, S, W, NW
"5j" : "0,0,1,1,1,1,0,1", # E, SE, S, SW, NW
"5i" : "0,0,1,1,1,1,1,0", # E, SE, S, SW, W
"5e" : "0,1,0,1,0,1,1,1", # NE, SE, SW, W, NW,
"5k" : "0,1,0,1,1,0,1,1", # NE, SE, S, W, NW
"5y" : "0,1,1,0,1,0,1,1", # NE, E, S, W, NW
"5c" : "1,0,1,0,1,0,1,1", # N, E, S, W, NW
"6a" : "0,0,1,1,1,1,1,1", # E, SE, S, SW, W, NW
"6e" : "0,1,0,1,1,1,1,1", # NE, SE, S, SW, W, NW
"6k" : "0,1,1,0,1,1,1,1", # NE, E, S, SW, W, NW
"6i" : "0,1,1,1,0,1,1,1", # NE, E, SE, SW, W, NW
"6c" : "1,0,1,0,1,1,1,1", # N, E, S, SW, W, NW
"6n" : "1,0,1,1,1,0,1,1", # N, E, SE, S, W, NW
"7e" : "0,1,1,1,1,1,1,1", # NE, E, SE, S, SW, W, NW
"7c" : "1,0,1,1,1,1,1,1", # N, E, SE, S, SW, W, NW
"8" : "1,1,1,1,1,1,1,1",
}
#Represents the encoding in dict:
neighbors = [(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1),(-1,-1)]
#Will store transitions temporarily:
d2 = [{},{}]
#Used to help a conversion later:
lnums = []
for i in xrange(9):
lnums.append([j for j in dict if int(j[0]) == i])
#Self-explanatory:
g.setrule(self.slashed)
#Test each transition in turn:
for i in xrange(2):
for j in dict:
j2 = dict[j].split(",")
g.new("Testing Hensel notation...")
for k in xrange(len(j2)):
k2 = int(j2[k])
g.setcell(neighbors[k][0], neighbors[k][1], k2)
g.setcell(0, 0, i)
g.run(1)
d2[i][j] = int(g.getcell(0, 0)) == 1
#Will become the main table of transitions:
trans_ = [[],[]]
#Will become the final output string:
not_ = "B"
for i in xrange(2):
#Convert d2 to a more usable form
for j in xrange(9):
trans_[i].append({})
for k in lnums[j]:
trans_[i][j][k] = d2[i][k]
#Make each set of transitions:
for j in xrange(9):
#Number of present transitions for B/S[[j]]
sum = 0
for k in trans_[i][j]:
if trans_[i][j][k]:
sum += 1
#No transitions present:
if sum == 0:
continue
#All transitions present:
if sum == len(trans_[i][j]):
not_ += str(j)
continue
str_ = str(j) #Substring for current set of transitions
#Minus sign needed if more than half of
#current transition set is present.
minus = (sum >= len(trans_[i][j])/2)
if minus:
str_ += "-"
str2 = "" #Another substring for current transition set
#Write transitions:
for k in trans_[i][j]:
if trans_[i][j][k] != minus:
str2 += k[1:]
#Append transitions:
not_ += str_ + "".join(sorted(str2))
if i == 0:
not_ += "/S"
g.new("Test finished.")
return not_
foo = Foo()
q = foo.testHensel()
g.setclipstr(q)
g.show(q + " copied to clipboard")
Users browsing this forum: No registered users and 0 guests