Setup updating of cells in CAM
parent
f0790de0e3
commit
774cb8243d
17
src/cam.py
17
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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue