2015-05-31 22:13:14 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@author: jrpotter
|
|
|
|
@date: May 31st, 2015
|
|
|
|
"""
|
2015-06-01 00:58:09 +00:00
|
|
|
import copy
|
|
|
|
import enum
|
|
|
|
import numpy as np
|
2015-05-31 22:27:47 +00:00
|
|
|
|
2015-06-01 00:58:09 +00:00
|
|
|
|
|
|
|
class Rule(enum.Enum):
|
2015-05-31 22:27:47 +00:00
|
|
|
MATCH = 0
|
|
|
|
TOLERATE = 1
|
|
|
|
SATISFY = 2
|
|
|
|
|
2015-05-31 22:13:14 +00:00
|
|
|
|
|
|
|
class Ruleset:
|
|
|
|
"""
|
|
|
|
The following determines the next state of a given cell in a CAM.
|
|
|
|
|
|
|
|
Given a neighborhood and a tolerance level, the ruleset determines whether a given cell should be on or off after a tick.
|
|
|
|
For example, if the tolerance level is set to 100% (i.e. neighborhoods must exactly match desired neighborhood to be on),
|
|
|
|
then the ruleset iterates through all neighbors and verifies a match.
|
|
|
|
|
|
|
|
For the sake of clarity, we consider a neighborhood to actually contain the "rules" for matching, and a ruleset to be the
|
|
|
|
application of the rules as defined in the neighborhood. We state this since the actual expected values are declared in
|
|
|
|
a neighborhood instance's offsets member.
|
|
|
|
"""
|
|
|
|
|
2015-06-01 00:58:09 +00:00
|
|
|
@staticmethod
|
|
|
|
@np.vectorize
|
|
|
|
def update(cell, rules, neighborhood, *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.
|
|
|
|
"""
|
|
|
|
tmp = copy.deepcopy(cell)
|
|
|
|
if rules.method == Rule.MATCH:
|
|
|
|
tmp.value = rules.matches(cell, neighborhood, *args)
|
|
|
|
elif rules.method == Rule.TOLERATE:
|
|
|
|
tmp.value = rules.tolerate(cell, neighborhood, *args)
|
|
|
|
elif rules.method == Rule.SATISFY:
|
|
|
|
tmp.value = rules.satisfies(cell, neighborhood, *args)
|
|
|
|
|
|
|
|
return tmp
|
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, method):
|
2015-05-31 22:13:14 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
"""
|
2015-05-31 22:27:47 +00:00
|
|
|
self.method = method
|
2015-05-31 22:13:14 +00:00
|
|
|
|
|
|
|
|
2015-06-01 00:58:09 +00:00
|
|
|
def matches(self, cell, neighborhood):
|
2015-05-31 22:13:14 +00:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2015-06-01 00:58:09 +00:00
|
|
|
residents = neighborhood.neighbors(cell)
|
2015-05-31 22:13:14 +00:00
|
|
|
for resident in residents:
|
|
|
|
if resident[0].value != resident[1]:
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
2015-06-01 00:58:09 +00:00
|
|
|
def tolerate(self, cell, neighborhood, tolerance):
|
2015-05-31 22:13:14 +00:00
|
|
|
"""
|
|
|
|
Determines that neighborhood matches expectation within tolerance.
|
|
|
|
|
|
|
|
We see that the percentage of actual matches are greater than or equal to the given tolerance level. If so, we
|
|
|
|
consider this cell to be alive. Note tolerance must be a value 0 <= t <= 1.
|
|
|
|
"""
|
|
|
|
matches = 0
|
2015-06-01 00:58:09 +00:00
|
|
|
residents = neighborhood.neighbors(cell)
|
2015-05-31 22:13:14 +00:00
|
|
|
for resident in residents:
|
|
|
|
if resident[0].value == resident[1]:
|
|
|
|
matches += 1
|
|
|
|
|
|
|
|
return (matches / len(residents)) >= tolerance
|
|
|
|
|
|
|
|
|
2015-06-01 00:58:09 +00:00
|
|
|
def satisfies(self, cell, neighborhood, valid_func):
|
2015-05-31 22:13:14 +00:00
|
|
|
"""
|
|
|
|
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.
|
|
|
|
"""
|
2015-06-01 00:58:09 +00:00
|
|
|
residents = neighborhood.neighbors(cell)
|
2015-05-31 22:27:47 +00:00
|
|
|
|
2015-06-01 00:58:09 +00:00
|
|
|
return valid_func(cell, residents)
|
2015-05-31 22:27:47 +00:00
|
|
|
|
2015-05-31 22:13:14 +00:00
|
|
|
|