This toolkit (titled CA2 for the time being) is a software framework to assist in investigating cellular automata, such as Conway's Game of Life. It is intended as the successor to a Python-based library I was developing previously for similar purposes; this version is written in C to permit more granular control of execution and more efficient computation (a highly relevant asset in, e.g., the case of brute force searches for automata patterns or rules with desired properties).
- An updated version of Python (at least 3.9 is preferred)
- Matplotlib
- Access to
gcc
andMake
(running using a terminal is preferred, though a standard compatibility layer should work fine if using Windows or a similar OS) - markdown-toc
Note that all of the above tools must be included in your PATH
environment variable (i.e., must be globally accessible).
Clone the repository and compile using make
, then execute the normal way.
This program includes an interactive mode (i.e., a command shell) for experimentation and entertainment; this will be entered automatically if the program is launched without passing any arguments (in the style of a REPL environment). It provides means for generating and simulating cellular automata, as well as reading and writing to local files. Data can be passed (piped) from one command to another using the >
operator. Most of the commands automatically handle special cases or extensions of the basic objects generated by other commands, such as collections/sets of states or simulations.
This is a non-exhaustive list of commands that can be run in the tool's interactive mode:
randomstate -n [int >= 1] -w [int >= 0] -h [int >= 0] -t [topology]
: Randomly generate a set of cellular automata statessimulate [rule] -i [int >= 1] -r auto -p
sort [property]
rchoice [collection] -n [int >= 0]
: Randomly select the specified number of elements from a collection; for example, passing a simulation will return a subset of that simulation's statesclone -n [int >= 1]
: Create a collection ofget [property]
: Extracts a property from the current selection, usually generating an array/matrix; as with the other commands, this will be distributed over iterable selections to produce a new axiswrite [path]
: Store a human-readable text summary of the data (state(s), simulation(s), etc.) passed to the command at the specified filepathsave [path]
print
: Display the current selection viastdout
render [path]
: Render the selected objects to an image fileplot
: Generate a plot from the current selection (using the Matplotlib wrapper)abbr short long
: Create an abbreviation that will be expanded before a command is run, similar to preprocessor directives and macros in Ccollapse
: Get the last state of one or more simulationsenumerate
: Iterate through possible states of a cellular automatonmin [property]
: Reduce a set of states based on the specified propertymax [property]
help
: Display this listrepeat
: Repeat the last command executedclear [object]
: Free (deallocate) the memory used to store an object (useful in interactive mode if you no longer need access to an earlier selection you generated)undo
: Revert previous command (only applicable to commands that mutate the current state/selection)redo
: Redo an undone command
These options can be used with any command:
--help [command]
: Display information about the provided command--dry
: Execute a "dry run", displaying information about the actions that would be executed without actually modifying the current selection or writing to any files--log [int]
: Set the verbosity level (an integer greater than or equal to 0) for this command (useful to set as a default for all commands)
Here are descriptions of the [types]
used in the above command descriptions:
int
: A simple integer; restrictions on the range of the number may be present for specific commands/optionsrule
: A named cellular automata rule, likecgol
property
: One of population, volume, densitypath
: A filepath (both relative and absolute are allowed)command
: A command name (see the list above)object
: An object that a selection can contain, e.g. a state, simulation, set of unrelated states, etc.
Commands can also be written into scripts using the .cas
extension; newlines will be interpreted as pipe operators, as in the following example:
randomstate
simulate -i 300
get population
plot
Here are a few practical examples that illustrate command usage (note that not all of these are fully implemented yet).
Generate 1000 random states, simulate for 200 iterations, and write the final states to a text file:
randomstate -n 1000 > simulate -i 200 > collapse > write ex1.txt
Simulate 100 iterations of Conway's Game of Life, rendering to stdout:
randomstate > simulate -i 100 -p
Enumerate 10000 states on a 4 by 4 grid and simulate CGOL for 50 iterations, automatically expanding the bounds to fit the current state, then write information about each state into a text file:
enumerate -n 10000 -wh 4 > simulate cgol -i 50 > write ex3.txt
Find and display the densest state resulting from evolving 5000 random states on a torus manifold for 100 steps:
randomstate -n 5000 -wh 30 -t torus > simulate cgol -i 100 > max density > print
Run a simulation and plot the population over each timestep:
randomstate > simulate cgol -i 100 > get population > plot
Run 200 simulations and plot their populations over each timestep:
randomstate -n 200 > simulate cgol -i 100 > get population > plot
Simulate different initial density conditions and simulation lengths and generate a heatmap of the resulting densities:
randomstate -n 100 -d 0.01:0.99 > simulate cgol -i 100 > plot density
Run 1000 simulations and generate a scatter plot of the final densities and average neighbor counts:
randomstate -n 1000 > simulate cgol -i 100 >
Run 1000 simulations and generate a histogram of the final populations, such that the full range is divided into 20 bins:
randomstate -n 1000 > simulate cgol -i 100 > get population > group -n 20 > plot
The main modules are subdirectories of the repository (array
, commands
, etc.); these generally contain a C source file, a corresponding C content file, a header file, and object file; and may have additional scripts or templates. A custom build script, build.py
transforms each .c0
file into a .c
file by inserting templates from .ct
(C template) files (a sort of fine-tuned pre-preprocessor), which is then used normally by the C compiler and linker.
Plain template files can be used to separate large source files into more manageable modules (see the commands
directory for an example); these are essentially copied and pasted into the source files like the C preprocessor does with directives and includes, via the following syntax:
{{template_name}}
where template_name.ct
is a file in the same directory.
Templates may also have arguments:
$template_name(arg_1:value_1,arg_2:value_2,...)$
These will be expanded into the corresponding fields in the template file. For example, the template
TYPE NAME(array a) {
TYPE output = INIT;
for (int i=0; i<a.size; i++) {
output = output OP a.data[i];
}
return output;
}
and reference
$ARRAY_REDUCE(name:array_sum,type:int,op:+,init:0)$
will produce an output similar to the following (with the appropriate date and time):
/* Imported from ./array/array_reduce.ct at 05/23/2022, 05:43:02 */
int array_sum(array a) {
int output = 0;
for (int i=0; i<a.size; i++) {
output = output + a.data[i];
}
return output;
}
The majority of the project is written in C, for reasons both of control and efficiency. The most notable exceptions are the build scripts and graphing/plotting utilities, both of which benefit greatly from improved concision and do not need to be highly specialized. The C-based command processor interfaces with those scripts using temporary local files to store data (where applicable) and system calls. The most notable example is the plotting code, which writes to pltdata.txt
and then calls plot/plot.py
.
Nomenclature
Generally, the following terms refer to the corresponding definitions specified (when used in documentation, comments, commits, etc.):
- object: An "instance" (to slightly abuse object-oriented terminology) of a struct, usually a state or simulation
- state: A "frame" of a cellular automata simulation; sometimes also referred to as a pattern
- simulation: A collection of states and associated information that allows the simulator to generate future states
cloc | github.com/AlDanial/cloc v 1.82 |
---|
Language | files | blank | comment | code |
---|---|---|---|---|
C | 19 | 285 | 311 | 1657 |
JSON | 2 | 0 | 0 | 1014 |
C/C++ Header | 19 | 165 | 85 | 767 |
Markdown | 2 | 131 | 0 | 307 |
Python | 2 | 8 | 9 | 65 |
make | 1 | 8 | 6 | 25 |
-------- | -------- | -------- | -------- | -------- |
SUM: | 45 | 597 | 411 | 3835 |
.
├── abbrs.txt
├── array
│ ├── array.c
│ ├── array.c0
│ ├── array.h
│ ├── array.o
│ ├── array_op.ct
│ └── array_reduce.ct
├── build.py
├── ca
├── ca.c
├── ca.c0
├── ca_log.txt
├── ca.o
├── ca_plot (copy).png
├── ca_plot.png
├── colors
│ ├── colors.c
│ ├── colors.c0
│ └── colors.o
├── commands
│ ├── commands.c
│ ├── commands.c0
│ ├── commands.h
│ ├── commands.o
│ ├── enumerate_cmd.ct
│ ├── print_cmd.ct
│ ├── randomstate_cmd.ct
│ ├── render_cmd.ct
│ ├── simulate_cmd.ct
│ └── write_cmd.ct
├── .gitignore
├── graph
│ ├── graph.c
│ ├── graph.c0
│ ├── graph.h
│ └── graph.o
├── hashing
│ ├── hashing.c
│ ├── hashing.c0
│ ├── hashing.h
│ └── hashing.o
├── helpers
│ ├── helpers.c
│ ├── helpers.c0
│ ├── helpers.h
│ └── helpers.o
├── image
│ ├── image.c
│ ├── image.c0
│ ├── image.h
│ └── image.o
├── list
│ ├── list.c
│ ├── list.h
│ └── list.o
├── mainheaders.h
├── makefile
├── package.json
├── package-lock.json
├── plot
│ ├── plot.c
│ ├── plot.c0
│ ├── plot.h
│ ├── plot.o
│ └── plot.py
├── pltdata.txt
├── progress
│ ├── progress.c
│ ├── progress.h
│ └── progress.o
├── pylog.txt
├── README.md
├── README.src.md
├── rule
│ ├── rule.c
│ ├── rule.c0
│ ├── rule.h
│ └── rule.o
├── session.c
├── session.h
├── session.o
├── simulate
├── simulation
│ ├── simulation.c
│ ├── simulation.c0
│ └── simulation.h
├── spng.h.gch
├── state
│ ├── extract.ct
│ ├── ptr_reduce.ct
│ ├── state.c
│ ├── state.c0
│ ├── state.h
│ └── state.o
├── test
│ └── test.h
├── test1.txt
├── test.png
├── timeinfo.c
├── timeinfo.h
├── timeinfo.o
├── tinypng
│ ├── TinyPngOut.c
│ ├── TinyPngOut.h
│ ├── TinyPngOut.h.gch
│ └── TinyPngOut.o
├── todo.txt
├── typing
│ ├── typing.c
│ ├── typing.c0
│ ├── typing.h
│ └── typing.o
└── vector
├── vector.c
├── vector.c0
├── vector.h
└── vector.o
17 directories, 101 files