diff --git a/brain/README.txt b/brain/README.txt index ff4b203..f7490e0 100644 --- a/brain/README.txt +++ b/brain/README.txt @@ -18,12 +18,17 @@ when creating a synapsis: [] >>> n01.receivers == [s0102] True - >>> n01.state.level + >>> n01.state.value 1.0 - >>> n02.state.level + >>> n02.state.value 1.0 +When we trigger a neuron, all its receivers get triggered so that the +receivers' state is updated: + >>> n01.trigger() - >>> n02.state.level + >>> n01.state.value + 1.0 + >>> n02.state.value 2.0 diff --git a/brain/interfaces.py b/brain/interfaces.py index 05d5057..7329e70 100644 --- a/brain/interfaces.py +++ b/brain/interfaces.py @@ -32,8 +32,7 @@ class ISynapsis(Interface): sender = Attribute("The sender neuron for this synapsis") reciever = Attribute("The receiver neuron for this synapsis") - transformation = Attribute("A transformation is used to transform " - "the sender neuron's state.") + transition = Attribute("A transition changes the sender neuron's state.") class INeuron(Interface): @@ -43,13 +42,10 @@ class INeuron(Interface): senders = Attribute("The sender synapses") receivers = Attribute("The receiver synapses") - stateMerger = Attribute("Merges a state with a list of other states " - "in order to create a new state.") - def trigger(): """ Notifies the neuron that something has happened. This method - should get the transformed states from all sender synapses - and merge them in order to calculate the neuron's new state; + executes all transitions from all sender synapses in order to + calculate the neuron's new state; then it should call the trigger() method on all downstream (receiver)neurons. In addition it may perform side effects like changing @@ -64,16 +60,9 @@ class IState(Interface): """ -class IStateTransformation(Interface): +class ITransition(Interface): - def transform(state): + def execute(state): """ Transform state to a new state value and return it. """ - -class IStateMerger(Interface): - - def merge(state, senderStates): - """ Transform state to a new value by taking into account a list - of sender neurons' states. This modifies state in-place. - """ diff --git a/brain/neuron.py b/brain/neuron.py index 9e51676..e3f8209 100644 --- a/brain/neuron.py +++ b/brain/neuron.py @@ -24,46 +24,47 @@ $Id: type.py 1129 2006-03-19 09:46:08Z helmutm $ from zope.interface import implements from cybertools.brain.interfaces import INeuron, ISynapsis -from cybertools.brain.state import State, StateMerger, StateTransformation +from cybertools.brain.state import State, Transition class Synapsis(object): """ A synapsis connects two neurons. """ + implements(ISynapsis) + sender = None reciever = None - transformation = None + transition = None def __init__(self, sender, receiver): self.sender = sender sender.receivers.append(self) self.receiver = receiver receiver.senders.append(self) - self.transformation = StateTransformation(self) - - def transformSenderState(self): - return self.transformation.transform(self.sender.state) + self.transition = Transition(self) class Neuron(object): + implements(INeuron) + state = None - stateMerger = None def __init__(self): self.senders = [] self.receivers = [] self.state = State() - self.stateMerger = StateMerger(self) self.active = False def trigger(self): if self.active: # avoid cycles return self.active = True - senderStates = [s.transformSenderState() for s in self.senders] - self.stateMerger.merge(self.state, senderStates) + state = self.state + for s in self.senders: + state = s.transition.execute(state) + self.state = state for r in self.receivers: r.receiver.trigger() self.active = False diff --git a/brain/state.py b/brain/state.py index e270559..726fb4f 100644 --- a/brain/state.py +++ b/brain/state.py @@ -17,38 +17,34 @@ # """ -Base classes for state and state manipulations. +Base classes for state and state manipulations using a float-based state. $Id$ """ from zope.interface import implements -from cybertools.brain.interfaces import IState, IStateMerger, IStateTransformation +from cybertools.brain.interfaces import IState, ITransition class State(object): """ The state of a neuron. """ - def __init__(self, level=1.0): - self.level = level + implements(IState) + + def __init__(self, value=1.0): + self.value = value -class StateTransformation(object): +class Transition(object): + + implements(ITransition) def __init__(self, synapsis, factor=1.0): self.synapsis = synapsis self.factor = factor - def transform(self, state): - return State(state.level * self.factor) + def execute(self, state): + return State(state.value + self.synapsis.sender.state.value * self.factor) -class StateMerger(object): - - def __init__(self, neuron): - self.neuron = neuron - - def merge(self, state, senderStates): - state.level += sum(st.level for st in senderStates) - diff --git a/brain/tests.py b/brain/tests.py index 1b09312..ab9ff3c 100755 --- a/brain/tests.py +++ b/brain/tests.py @@ -1,28 +1,29 @@ # $Id$ -import unittest +import unittest, doctest from zope.testing.doctestunit import DocFileSuite from zope.interface.verify import verifyClass -from zope.interface import implements from cybertools.brain.interfaces import INeuron, ISynapsis -from cybertools.brain.interfaces import IState, IStateTransformation, IStateMerger +from cybertools.brain.interfaces import IState, ITransition from cybertools.brain.neuron import Neuron, Synapsis -from cybertools.brain.state import State, StateTransformation, StateMerger +from cybertools.brain.state import State, Transition class TestBrain(unittest.TestCase): "Basic tests for the brain package." def testInterfaces(self): - pass + verifyClass(INeuron, Neuron) def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS return unittest.TestSuite(( unittest.makeSuite(TestBrain), - DocFileSuite('README.txt'), - )) + DocFileSuite('README.txt', + optionflags=flags,), + )) if __name__ == '__main__': unittest.main(defaultTest='test_suite')