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:
|
class CAM:
|
||||||
"""
|
"""
|
||||||
Represents a Cellular Automata Machine (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
|
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.
|
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._dimen = dimen
|
||||||
self._bitplanes = [BitPlane(dimen) for i in bps]
|
self._planes = [CellPlane(dimen) for i in cps]
|
||||||
self._master = self._bitplanes[0].grid if bps > 0 else None
|
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.
|
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
|
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
|
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
|
@author: jrpotter
|
||||||
@date: May 31st, 2015
|
@date: May 31st, 2015
|
||||||
"""
|
"""
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
class Rule(Enum):
|
||||||
|
MATCH = 0
|
||||||
|
TOLERATE = 1
|
||||||
|
SATISFY = 2
|
||||||
|
|
||||||
|
|
||||||
class Ruleset:
|
class Ruleset:
|
||||||
"""
|
"""
|
||||||
|
@ -19,22 +26,22 @@ class Ruleset:
|
||||||
a neighborhood instance's offsets member.
|
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
|
self.wrap_around = wrap_around
|
||||||
|
|
||||||
|
|
||||||
def matches(self, cell, neighborhood):
|
def _matches(self, cell, grid, neighborhood):
|
||||||
"""
|
"""
|
||||||
Determines that neighborhood matches expectation exactly.
|
Determines that neighborhood matches expectation exactly.
|
||||||
|
|
||||||
Note this is just like the tolerate method with a tolerance of 1, but
|
Note this is just like the tolerate method with a tolerance of 1, but
|
||||||
recoding allows for short circuiting.
|
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:
|
for resident in residents:
|
||||||
if resident[0].value != resident[1]:
|
if resident[0].value != resident[1]:
|
||||||
return False
|
return False
|
||||||
|
@ -42,7 +49,7 @@ class Ruleset:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def tolerate(self, cell, neighborhood, tolerance):
|
def _tolerate(self, cell, grid, neighborhood, tolerance):
|
||||||
"""
|
"""
|
||||||
Determines that neighborhood matches expectation within 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.
|
consider this cell to be alive. Note tolerance must be a value 0 <= t <= 1.
|
||||||
"""
|
"""
|
||||||
matches = 0
|
matches = 0
|
||||||
residents = neighborhood.neighbors(cell, self.grid, self.wrap_around)
|
residents = neighborhood.neighbors(cell, grid, self.wrap_around)
|
||||||
for resident in residents:
|
for resident in residents:
|
||||||
if resident[0].value == resident[1]:
|
if resident[0].value == resident[1]:
|
||||||
matches += 1
|
matches += 1
|
||||||
|
@ -58,13 +65,32 @@ class Ruleset:
|
||||||
return (matches / len(residents)) >= tolerance
|
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.
|
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 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.
|
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