diff --git a/src/cam.py b/src/cam.py index 67efcb1..58b95a0 100644 --- a/src/cam.py +++ b/src/cam.py @@ -2,35 +2,34 @@ """ -from bitplane import Bitplane +from cell_plane import CellPlane class CAM: """ Represents a Cellular Automata Machine (CAM). - The CAM consists of any number of bit planes that allow for increasingly complex cellular automata. + The CAM consists of any number of cell planes that allow for increasingly complex cellular automata. This is the top-level module that should be used by anyone wanting to work with fifth, and provides all methods needed (i.e. supported) to interact/configure the cellular automata as desired. """ - def __init__(self, bps=1, dimen=(100,100)): + def __init__(self, cps=1, dimen=(100,100)): """ """ self._dimen = dimen - self._bitplanes = [BitPlane(dimen) for i in bps] - self._master = self._bitplanes[0].grid if bps > 0 else None + self._planes = [CellPlane(dimen) for i in cps] + self._master = self._planes[0].grid if cps > 0 else None - def tick(self, ruleset, neighborhood): + def tick(self, ruleset, neighborhood, *args): """ The tick function should be called whenever we want to change the current status of the grid. Every time the tick is called, the ruleset is applied to each cell and the next configuration is placed into the master grid. Depending on the timing specifications set by the user, this - may also change secondary bitplanes (the master is always updated on each tick). + may also change secondary cell planes (the master is always updated on each tick). """ - pass - + self._master = ruleset.update(self._master, self.master, neighborhood, *args) diff --git a/src/ruleset.py b/src/ruleset.py index e0f5f75..9f079cf 100644 --- a/src/ruleset.py +++ b/src/ruleset.py @@ -5,6 +5,13 @@ @author: jrpotter @date: May 31st, 2015 """ +from enum import Enum + +class Rule(Enum): + MATCH = 0 + TOLERATE = 1 + SATISFY = 2 + class Ruleset: """ @@ -19,22 +26,22 @@ class Ruleset: a neighborhood instance's offsets member. """ - def __init__(self, grid, wrap_around=True): + def __init__(self, method, wrap_around=True): """ """ - self.grid = grid + self.method = method self.wrap_around = wrap_around - def matches(self, cell, neighborhood): + def _matches(self, cell, grid, neighborhood): """ Determines that neighborhood matches expectation exactly. Note this is just like the tolerate method with a tolerance of 1, but recoding allows for short circuiting. """ - residents = neighborhood.neighbors(cell, self.grid, self.wrap_around) + residents = neighborhood.neighbors(cell, grid, self.wrap_around) for resident in residents: if resident[0].value != resident[1]: return False @@ -42,7 +49,7 @@ class Ruleset: return True - def tolerate(self, cell, neighborhood, tolerance): + def _tolerate(self, cell, grid, neighborhood, tolerance): """ Determines that neighborhood matches expectation within tolerance. @@ -50,7 +57,7 @@ class Ruleset: consider this cell to be alive. Note tolerance must be a value 0 <= t <= 1. """ matches = 0 - residents = neighborhood.neighbors(cell, self.grid, self.wrap_around) + residents = neighborhood.neighbors(cell, grid, self.wrap_around) for resident in residents: if resident[0].value == resident[1]: matches += 1 @@ -58,13 +65,32 @@ class Ruleset: return (matches / len(residents)) >= tolerance - def satisfies(self, cell, neighborhood, valid_func): + def _satisfies(self, cell, grid, neighborhood, valid_func): """ Allows custom function to relay next state of given cell. The passed function is supplied the list of 2-tuple elements, of which the first is a Cell and the second is the expected state as declared in the Neighborhood, as well as the grid and cell in question. """ - residents = neighborhood.neighbors(cell, self.grid, self.wrap_around) + residents = neighborhood.neighbors(cell, grid, self.wrap_around) + + return valid_func(cell, grid, residents) + + + @np.vectorize + def update(self, cell, *args): + """ + Allow for batch processing of rules. + + We choose our processing function based on the specified rule and update every cell in the grid simultaneously + via a vectorization. + """ + if self.method == Rule.MATCH: + cell.value = self._matches(cell, *args) + elif self.method == Rule.TOLERATE: + cell.value = self._tolerate(cell, *args) + elif self.method == Rule.SATISFY: + cell.value = self._satisfy(cell, *args) + + return cell - return valid_func(cell, self.grid, residents)