Tutorials/lifelib
This tutorial explains how to install lifelib and use it interactively from a Jupyter notebook.
Installation
The recommended way to install the latest version of lifelib is through the Python package manager, pip.
To get a full featurecomplete installation of lifelib, run the following in a terminal (Linux / Mac OS X) or command prompt (Windows):
python m pip install upgrade pythonlifelib notebook imageio matplotlib
This installs the Python bindings for lifelib together with its dependencies. The three optional dependencies (notebook, imageio, and matplotlib) are helpful for interactive use and graphing/plotting.
Extra step (Windows only)
If you're running on Windows, then you'll need to additionally install Cygwin in order to use lifelib. There is functionality built into lifelib to make this easier. In particular, run the following in the command prompt:
python
which will open a Python interactive prompt. This should be marked with a triplechevron, >>>, instead of the usual prompt.
In the Python interactive prompt, run the following:
import lifelib lifelib.install_cygwin()
There will be a delay whilst this downloads the Cygwin setup program, followed shortly by a popup window which automatically installs Cygwin and the necessary dependencies for lifelib to run. Wait for this to complete and for the setup window to vanish. After that, you can type:
exit()
to leave the Python interactive prompt and return to a regular command prompt.
Creating a notebook
In your terminal or command prompt, launch a Jupyter notebook server by typing the following:
jupyter notebook
This will open a browser window that resembles the following:
Press the 'New' button in the topright corner and 'Python 3' to create an untitled notebook. Now in the first cell, enter the following two lines:
import lifelib sess = lifelib.load_rules('b3s23') lt = sess.lifetree(n_layers=1, memory=1000)
Then press Shift+Enter to execute the contents of the cell. If this is the first time, it will take a while (20 seconds on a fast machine; up to a minute on a slower machine) to compile lifelib. Subsequently, this delay will not be incurred until next time you upgrade lifelib or compile a different set of rules. This should display a progress bar resembling the following:
It is worth dissecting the syntax here to see what exactly is happening:
 The first line imports the lifelib Python package into Python.
 The second line compiles lifelib with a single rule (B3/S23) and loads the resulting compiled lifelib 'session'.
 The third line creates a HashLifecompatible container, or lifetree, with 1 bitlayer (so 2 states per cell) and 1000 megabytes of HashLife memory.
Loading and viewing patterns
Once you have a lifetree, you can very easily load patterns from RLE using the pattern method, and then view the result using the viewer method:
The output is an embedded interactive copy of Chris Rowett's LifeViewer containing the pattern.
In this case, we've stored the pattern in a Python variable called x. If we make any edits to the pattern in the LifeViewer, these can be 'saved' back to this variable x by pressing Ctrl+S.
Because lifelib uses HashLife, it means that (for example) you can run this pattern for one googol generations and report its population:
For another example, try copying and pasting this code into a Jupyter notebook cell and evaluating it (with Shift+Enter as before).
lidka = lt.pattern("bo7b$obo6b$bo7b8$8bo$6bobo$5b2obo2$4b3o!") print("Initial population: %d" % lidka.population) lidka_30k = lidka[30000] print("Final population: %d" % lidka_30k.population)
Finally, for periodic patterns (oscillators, spaceships, or stilllifes) and glider guns, the gif method allows you to render a seamless animated GIF of the pattern:
Syntax
Patterns in lifelib can be manipulated using a concise syntax.
Advancing and transforming
 x[100] returns a copy of the pattern x advanced by 100 generations.
 x(55, 89) returns a copy of the pattern x translated 55 cells east and 89 cells north.
 x('rccw') returns a copy of the pattern x rotated 90 degrees counterclockwise.
 x.centre() returns a copy of the pattern x translated such that the bounding box is centred on the origin.
 x.empty() and x.nonempty() are boolean functions for querying whether the pattern is empty.
Binary operators
 x + y returns the union of x and y.
 x ^ y returns the symmetric difference of x and y.
 x & y returns the intersection of x and y.
 x  y returns the difference of x and y.
Inplace binary operators
 x += y modifies the pattern inplace by pasting a copy of y on top of it.
 x = y removes the cells that are live in y from x.
Attributes
 x.population reports the population of the pattern x.
 x.bounding_box returns a 4element list of the form (left, top, width, height), or None if the pattern is empty.
 x.period returns the period of a periodic object (stilllife, oscillator or spaceship).
 x.displacement returns the displacement of a periodic object.
 x.apgcode returns the apgcode of a periodic object or glider gun.
Slicing, indexing, and coordinates
 x[5, 8] returns the integer state of the cell with coordinate (5, 8). This can be used as an lvalue to set the state of a cell.
 x[0:30, 0:20] returns the pattern restricted to a 30x20 rectangle beginning at the origin. This can be used as an lvalue to set the state of all cells within a rectangle (if the rvalue is an integer) or randomly fill a rectangle (if the rvalue is a float or a dictionary).
 x[arr] returns a shape(n,) numpy array of cell states at the coordinates specified in the shape(n,2) numpy array arr.
 x.coords() returns a shape(n,2) numpy array containing the coordinates of all nonzero cells in the pattern.
Loading, saving, and serialization
 x.save('path/to/filename.mc.gz') saves the pattern as a gzipped macrocell file. Supported extensions are .rle, .mc, .rle.gz, and .mc.gz, for consistency with Golly.
 x.rle_string() returns the RLE of the pattern as a Python string without requiring filesystem I/O.
Example notebooks
There are notebooks in various repositories that you can download and run to learn more about lifelib functionality.
