...
 
Commits (8)
#ifndef LIFELIB_VERSION /*
__version__=[x.replace('"', '') for x in '''
*/
#define LIFELIB_VERSION "ll2.2.11"
#define LIFELIB_VERSION "ll2.2.12"
// '''.split() if ('ll' in x)][0][2:]
#endif
......@@ -276,6 +276,16 @@ namespace apg {
}
}
}
for (auto it = components.begin(); it != components.end(); ++it) {
if ((*it) == "PATHOLOGICAL") {
// invalid separation
std::vector<std::string> newcomps;
newcomps.push_back(pat.apgcode());
return newcomps;
}
}
return components;
}
......
......@@ -10,9 +10,16 @@
#define LGATE_ANDN 3
#define LGATE_OUT 4
#define LGATE_IN 5
#define LGATE_NOP 6
struct zeropres {
/*
* Represents either an input node, output node, or a zero-preserving
* logic gate (AND, OR, XOR, or ANDN). If a logic gate has more than
* two inputs, it is interpreted as a left-associative fold over the
* list of inputs.
*/
uint32_t gatetype;
std::vector<uint32_t> inputs;
......@@ -40,6 +47,7 @@ struct zeropres {
if (gatetype == LGATE_ANDN) { s << "andn"; }
if (gatetype == LGATE_OUT) { s << "out "; }
if (gatetype == LGATE_IN) { s << "in "; }
if (gatetype == LGATE_NOP) { s << "nop "; }
s << " [";
......@@ -66,6 +74,7 @@ std::vector<zeropres> depth_sort(std::vector<zeropres> &orig) {
opts = 0;
maxdepth = 0;
for (int i = 0; i < orig.size(); i++) {
if (orig[i].inputs.size() == 0) { continue; } // skip NOPs
uint32_t x = 0;
for (auto it = orig[i].inputs.begin(); it != orig[i].inputs.end(); ++it) {
uint32_t y = *it;
......
......@@ -230,7 +230,7 @@ class WrappedLibrary(object):
warnings.warn("Could not ensure stack size, probably due to running on Windows. Expect segfaults soon.")
self.last_power = powerof2
def __del__(self):
def annihilate(self):
if self.remote:
try:
......@@ -240,6 +240,11 @@ class WrappedLibrary(object):
self.the_library.wait()
self.the_library.stdin.close()
self.the_library.stdout.close()
self.remote = False
def __del__(self):
self.annihilate()
if __name__ == '__main__':
......
......@@ -2,6 +2,7 @@ import os
from .lowlevel import *
from numbers import Integral
from .crt import chinese_remainder, large_primes
from .samples import download_synthesis as dsynth
def randfill(item, shape):
......@@ -30,9 +31,13 @@ class Pattern(object):
self.session = session
self.owner = owner
session.pattern_ptrs.add(ptr)
def __del__(self):
self.lifelib('DeletePattern', self.ptr)
if self.ptr in self.session.pattern_ptrs:
self.lifelib('DeletePattern', self.ptr)
self.session.pattern_ptrs.remove(self.ptr)
def __repr__(self):
......@@ -687,6 +692,22 @@ class Pattern(object):
return self.owner.download_samples(self.apgcode, self.getrule(), **kwargs)
def download_synthesis(self, tempfile='tempfile.rle', **kwargs):
rle = dsynth(self.apgcode, self.getrule(), tempfile=tempfile, **kwargs)
if rle is None:
synth = None
else:
synth = self.owner.load(tempfile)
try:
os.remove(tempfile)
except OSError:
pass
return synth
@property
def period(self):
......
......@@ -68,6 +68,27 @@ class SampleSoupList(Sequence):
def __repr__(self):
return 'SampleSoupList(%r, %r, %r, %r)' % (self.lt, self.rule, self.symmetry, self.samples)
def download_synthesis(apgcode, rule, domain='https://gol.hatsya.co.uk', tempfile='tempfile'):
if ('_' in rule) and ('_' not in apgcode):
rule, apgcode = apgcode, rule
try:
from urllib import urlretrieve
except ImportError:
from urllib.request import urlretrieve
url = domain + '/textsamples/' + apgcode + '/' + rule + '/synthesis'
urlretrieve(url, tempfile)
with open(tempfile, 'r') as f:
synthesis = f.read()
if 'x' not in synthesis:
return None
else:
return synthesis
def download_samples(lt, apgcode, rule, domain='https://gol.hatsya.co.uk', tempfile='tempfile'):
if ('_' in rule) and ('_' not in apgcode):
......
......@@ -3,6 +3,7 @@ from .pattern import Pattern
from .samples import download_samples as dsamples
from .samples import validate_symmetry
import os
import atexit
from ..genera import sanirule
......@@ -22,6 +23,8 @@ class Lifetree(object):
self.ptr = lifelib('CreateLifetree', memory, n_layers)
self.n_layers = n_layers
session.lifetree_ptrs.add(self.ptr)
def load(self, filename, compressed='deduce', tempfile='tempfile'):
filename = os.path.abspath(filename)
......@@ -110,7 +113,35 @@ class Lifetree(object):
def __del__(self):
self.lifelib('DeleteLifetree', self.ptr)
if self.ptr in self.session.lifetree_ptrs:
self.lifelib('DeleteLifetree', self.ptr)
self.session.lifetree_ptrs.remove(self.ptr)
all_sessions = []
def cleanup_sessions():
# Deallocate patterns
for sess in all_sessions:
for ptr in sess.pattern_ptrs:
sess.lifelib('DeletePattern', ptr)
sess.pattern_ptrs = set([])
# Deallocate lifetrees
for sess in all_sessions:
for ptr in sess.lifetree_ptrs:
sess.lifelib('DeleteLifetree', ptr)
sess.lifetree_ptrs = set([])
# Wait for child processes
for sess in all_sessions:
sess.lifelib.annihilate()
# Remove references
while all_sessions:
all_sessions.pop()
atexit.register(cleanup_sessions)
class Session(object):
......@@ -128,6 +159,10 @@ class Session(object):
self.default_planes = default_planes
self.rules = list(rules)
self.lifelib = WrappedLibrary(soname, local_bash=local_bash, local_python=local_python)
self.lifetree_ptrs = set([])
self.pattern_ptrs = set([])
all_sessions.append(self)
def lifetree(self, *args, **kwargs):
......
neighborhood:vonNeumann
symmetries:rotate4reflect
n_states:5
var any.0 = {0,1,2,3,4}
var any.1 = any.0
var any.2 = any.0
var h.0 = {2,3}
var _a0.0 = {0}
var _b0.0 = {0,1,2,4}
var _b0.1 = _b0.0
var _c0.0 = {0,1,4}
var _c0.1 = _c0.0
var _c0.2 = _c0.0
var _c0.3 = _c0.0
var _d0.0 = {0,2,3,4}
var _d0.1 = _d0.0
var _d0.2 = _d0.0
var _d0.3 = _d0.0
1, 4, any.0, any.1, any.2, 1
1, 1, _a0.0, 1, h.0, h.0
1, 1, 1, any.0, any.1, 1
1, 1, any.0, 1, any.1, 1
1, 3, 3, any.0, any.1, 2
1, 3, any.0, 3, any.1, 2
1, 2, _b0.0, _b0.1, h.0, h.0
1, 2, _b0.0, h.0, _b0.1, h.0
1, _c0.0, _c0.1, _c0.2, h.0, h.0
h.0, _d0.0, _d0.1, _d0.2, _d0.3, 4
4, _c0.0, _c0.1, _c0.2, _c0.3, 1
neighborhood: Moore
symmetries: rotate4reflect
n_states: 9
var any.0 = {0,1,2,3,4,5,6,7,8}
var any.1 = any.0
var any.2 = any.0
var any.3 = any.0
var any.4 = any.0
var any.5 = any.0
var any.6 = any.0
var any.7 = any.0
var d.0 = {1,4}
var b.0 = {0,2,3,5,6,7,8}
var b.1 = b.0
var b.2 = b.0
var b.3 = b.0
var b.4 = b.0
var b.5 = b.0
var b.6 = b.0
var e.0 = {2,3}
var c.0 = {0,1,2,3,4}
var c.1 = c.0
var c.2 = c.0
var c.3 = c.0
var c.4 = c.0
var c.5 = c.0
var c.6 = c.0
1, any.0, any.1, any.2, any.3, any.4, any.5, any.6, any.7, 2
4, any.0, any.1, any.2, any.3, any.4, any.5, any.6, any.7, 2
2, any.0, any.1, any.2, any.3, any.4, any.5, any.6, any.7, 3
6, any.0, any.1, any.2, any.3, any.4, any.5, any.6, any.7, 8
7, any.0, any.1, any.2, any.3, any.4, any.5, any.6, any.7, 8
8, any.0, any.1, any.2, any.3, any.4, any.5, any.6, any.7, 5
3, b.0, b.1, b.2, b.3, b.4, b.5, b.6, d.0, d.0
3, b.0, b.1, b.2, b.3, b.4, b.5, d.0, b.6, d.0
3, 1, 1, b.0, b.1, b.2, b.3, b.4, b.5, 4
3, 1, 4, b.0, b.1, b.2, b.3, b.4, b.5, 1
3, 4, 1, b.0, b.1, b.2, b.3, b.4, b.5, 1
3, 4, 4, b.0, b.1, b.2, b.3, b.4, b.5, 1
3, 1, b.0, 1, b.1, b.2, b.3, b.4, b.5, 1
3, 1, b.0, 4, b.1, b.2, b.3, b.4, b.5, 4
3, 1, b.0, 4, b.1, b.2, b.3, b.4, b.5, 4
3, 4, b.0, 4, b.1, b.2, b.3, b.4, b.5, 4
3, b.0, 1, b.1, 1, b.2, b.3, b.4, b.5, 1
3, b.0, 1, b.1, 4, b.2, b.3, b.4, b.5, 1
3, b.0, 1, b.1, b.2, b.3, b.4, b.5, 4, 1
3, b.0, 4, b.1, 4, b.2, b.3, b.4, b.5, 4
3, 1, b.0, b.1, 1, b.2, b.3, b.4, b.5, 4
3, 4, b.0, b.1, 1, b.2, b.3, b.4, b.5, 1
3, 1, b.0, b.1, 4, b.2, b.3, b.4, b.5, 4
3, 4, b.0, b.1, 4, b.2, b.3, b.4, b.5, 4
3, 1, b.0, b.1, b.2, 1, b.3, b.4, b.5, 4
3, 1, b.0, b.1, b.2, 4, b.3, b.4, b.5, 1
3, 1, b.0, b.1, b.2, 4, b.3, b.4, b.5, 1
3, 4, b.0, b.1, b.2, 4, b.3, b.4, b.5, 4
3, b.0, 1, b.1, b.2, b.3, 1, b.4, b.5, 4
3, b.0, 1, b.1, b.2, b.3, 4, b.4, b.5, 1
3, b.0, 1, b.1, b.2, b.3, 4, b.4, b.5, 1
3, b.0, 4, b.1, b.2, b.3, 4, b.4, b.5, 4
3, 7, c.0, c.1, c.2, c.3, c.4, c.5, c.6, 1
3, 6, c.0, c.1, c.2, c.3, c.4, c.5, c.6, 4
5, 0, 0, 1, 0, 0, 0, e.0, 0, 7
5, 0, 0, e.0, 0, 0, d.0, 0, 3, 6
5, 0, 0, e.0, 0, 0, d.0, 0, 1, 7
5, 0, 0, e.0, 0, 0, d.0, 0, 4, 7
5, 0, 0, e.0, 0, 0, 2, 1, 2, 7
5, 0, 0, e.0, 0, 0, 2, 4, 2, 6
......@@ -62,6 +62,10 @@ $3b3o3b2o3b2o3bo2bo7bo2bo12b3o$3bo2bo2b2o3b2o2bo3bo7bob2o12bo2bo$3bo
periods = [s[10000][-1000:1000, -1000:1000].period for s in samples['C2_2']]
self.assertEqual(periods[:20], [40]*20)
synth = pat.download_synthesis()
res = synth[1000]
self.assertEqual(res.period, 40)
def test_hashsoup(self):
x = self.lt.hashsoup("b3s23", "C1", "n_GcpqZ62YqD3310086454")
......
......@@ -61,3 +61,10 @@ for testtype in "unit" "integration" "indirection"; do
"$python_name" -m unittest discover "lifelib/tests/$testtype"
done
done
printf "\n\033[1;36m **** segfault tests ****\033[0m\n"
for python_name in "${pythons[@]}"; do
"$python_name" -c 'import lifelib; lt = lifelib.load_rules("b3s23").lifetree(); pat = lt.pattern(); f = lambda x : x'
done
printf "\n\033[1mAll tests completed successfully.\033[0m\n"