def test_signal(mocker, activation_fixture): sig = SignalRef("mysig") with mocker.patch.object(activation_fixture, "resources", return_value=set()): assert not sig.evaluate() assert set(sig.signals()) == {SignalRef("mysig")} sig.acquire(Spike(sig="notmysig"), activation_fixture) assert not sig.evaluate() sig.acquire(Spike(sig="mysig"), activation_fixture) assert sig.evaluate() sig_and_dis = SignalRef("sig") & (SignalRef("dis") | SignalRef("junct")) assert not sig_and_dis.evaluate() sig_and_dis.acquire(Spike(sig="sig"), activation_fixture) assert not sig_and_dis.evaluate() sig_and_dis.acquire(Spike(sig="junct"), activation_fixture) assert sig_and_dis.evaluate() expected = [(sig, sig.spike)] return_value = list(sig.dereference()) assert expected == return_value sig.spike = Spike(sig='mysig') sig.spike._age = 200 return_value = list(sig.update(activation_fixture)) assert return_value == [sig] assert str(sig) == "mysig"
def test_signal(activation_fixture): sig = s("mysig") assert not sig.evaluate() assert set(sig.signals()) == {s("mysig")} sig.acquire(Spike(sig="notmysig"), activation_fixture) assert not sig.evaluate() sig.acquire(Spike(sig="mysig"), activation_fixture) assert sig.evaluate() sig_and_dis = s("sig") & (s("dis") | s("junct")) assert not sig_and_dis.evaluate() sig_and_dis.acquire(Spike(sig="sig"), activation_fixture) assert not sig_and_dis.evaluate() sig_and_dis.acquire(Spike(sig="junct"), activation_fixture) assert sig_and_dis.evaluate() expected = [(sig, sig.spike)] return_value = list(sig.dereference()) assert expected == return_value sig.spike = Spike(sig='mysig') sig.spike._age = 200 return_value = list(sig.update(activation_fixture)) assert return_value == [sig] assert str(sig) == "mysig"
def test_disjunct(activation_fixture): disjunct = (s("sig1") & s("sig2")) | s("sig3") assert not disjunct.evaluate() assert set(disjunct.signals()) == {s("sig1"), s("sig2"), s("sig3")} disjunct.acquire(Spike(sig="sig1"), activation_fixture) assert not disjunct.evaluate() disjunct.acquire(Spike(sig="sig3"), activation_fixture) assert disjunct.evaluate()
def acquire(self, spike: Spike, act: IActivation): if not self.spike and self.name == spike.name() and ( self.max_age < 0 or spike.age() <= act.secs_to_ticks(self.max_age)): assert not spike.is_wiped() self._min_age_ticks = act.secs_to_ticks(self.min_age) self.spike = spike with spike.causal_group() as cg: cg.acquired(spike, act, self.detached) return True return False
def test_conjunct(activation_fixture): conjunct = s("sig1") & s("sig2") & s("sig3") assert not conjunct.evaluate() assert set(conjunct.signals()) == {s("sig1"), s("sig2"), s("sig3")} conjunct.acquire(Spike(sig="sig1"), activation_fixture) assert not conjunct.evaluate() conjunct.acquire(Spike(sig="sig2"), activation_fixture) assert not conjunct.evaluate() conjunct.acquire(Spike(sig="sig2"), activation_fixture) assert not conjunct.evaluate() conjunct.acquire(Spike(sig="sig3"), activation_fixture) assert conjunct.evaluate()
def test_multiple_activation(state_fixture, context_with_property_fixture): sa1 = Activation(state_fixture, context_with_property_fixture) assert sa1.acquire( Spike(sig=DEFAULT_PROPERTY_CHANGED, consumable_resources={DEFAULT_PROPERTY_ID})) assert not sa1.acquire( Spike(sig='x', consumable_resources={DEFAULT_PROPERTY_ID})) sa2 = Activation(state_fixture, context_with_property_fixture) assert sa2.acquire( Spike(sig=DEFAULT_PROPERTY_CHANGED, consumable_resources={DEFAULT_PROPERTY_ID})) assert not sa2.acquire( Spike(sig='x', consumable_resources={DEFAULT_PROPERTY_ID}))
def acquire(self, spike: Spike, act: IActivation): if not self.spike and self.id() == spike.id() and ( self.max_age_value < 0 or spike.age() <= act.secs_to_ticks(self.max_age_value)): assert not spike.is_wiped() with spike.causal_group() as cg: # Causal group might refuse acquisition, if one of act's state's write-props is unavailable. if not cg.acquired(spike, act, self.detached_value): return False self.spike = spike self._min_age_ticks = act.secs_to_ticks(self.min_age_value) return True return False
def acquire(self, spike: Spike, act: IActivation): result = False # update causal group set to account for merges self._allowed_causal_groups = set( cg for cg in self._allowed_causal_groups) for si in self._signals: if spike.causal_group() in self._allowed_causal_groups: # the causal group is already allowed result |= si.acquire(spike, act) elif not si.completed_by: if si.acquire(spike, act): # add causal group to allowed, since the spike is a root cause self._allowed_causal_groups.add(spike.causal_group()) result = True return result
def test_disjunct(mocker, activation_fixture): disjunct = (SignalRef("sig1") & SignalRef("sig2")) | SignalRef("sig3") with mocker.patch.object(activation_fixture, "resources", return_value=set()): assert not disjunct.evaluate() assert set(disjunct.signals()) == { SignalRef("sig1"), SignalRef("sig2"), SignalRef("sig3") } disjunct.acquire(Spike(sig="sig1"), activation_fixture) assert not disjunct.evaluate() disjunct.acquire(Spike(sig="sig3"), activation_fixture) assert disjunct.evaluate()
def emit(self, signal, parents=None, wipe: bool = False, payload=None) -> None: # Copy instead of calling super to obtain reference to created spike. if wipe: self.wipe(signal) with self._lock: new_spike = Spike(sig=signal.id(), parents=parents, consumable_resources=set( self._properties.keys()), payload=payload) logger.debug(f"Emitting {new_spike}") service.spike(new_spike.id()) self._spikes_per_signal[signal].add(new_spike)
def emit(self, signal: Signal, parents: Set[Spike]=None, wipe: bool=False) -> None: """ Emit a signal to the signal processing loop. _Note:_ The signal will only be processed if #run() has been called! * `signal`: The signal to be emitted. * `parents`: The signal's parents, if it is supposed to be integrated into a causal group. * `wipe`: Boolean to control, whether #wipe(signal) should be called before the new spike is created. """ if wipe: self.wipe(signal) with self._lock: new_spike = Spike(sig=signal.name, parents=parents, consumable_resources=set(self._properties.keys())) logger.debug(f"Emitting {new_spike}") self._spikes.add(new_spike)
def emit(self, signal: Signal, parents: Set[Spike] = None, wipe: bool = False, payload: Any = None, boring: bool = False) -> Spike: """ Emit a signal to the signal processing loop. _Note:_ The spike will only be picked up by activations once `run_once`/`run` is called! * `signal`: The signal to be emitted. * `parents`: The signal's parents, if it is supposed to be integrated into a causal group. * `wipe`: Boolean to control, whether #wipe(signal) should be called before the new spike is created. * `payload`: Value that should be embedded in the new spike. * `boring`: Flag which indicates, whether the new spike is boring. Activations which acquire boring spikes will not count against the `core:activity` flag. **Returns:** The newly created spike object. """ if wipe: self.wipe(signal) with self._lock: new_spike = Spike(sig=signal.id(), parents=parents, consumable_resources=set( self._properties.keys()), payload=payload, boring=boring) logger.debug(f"Emitting {new_spike}") self._spikes_per_signal[signal].add(new_spike) return new_spike
def test_acquire_spike(activation_fixture): assert activation_fixture.acquire( Spike(sig=DEFAULT_PROPERTY_CHANGED, consumable_resources={DEFAULT_PROPERTY_ID}))
def test_acquire_spike_mismatches(activation_fixture): assert not activation_fixture.acquire( Spike(sig='x', consumable_resources={DEFAULT_PROPERTY_ID}))
def spike_fixture(): return Spike(sig=DEFAULT_PROPERTY_CHANGED)