ravestate.context

create_and_run_context

create_and_run_context(*args, runtime_overrides=None)

Creates a new Context with the given parameters and runs it

Context

Context(self, *arguments, runtime_overrides: List[Tuple[str, str, Any]] = None)

emit

Context.emit(self, signal: ravestate.constraint.Signal, parents: Set[ravestate.spike.Spike] = None, wipe: bool = False, payload: Any = None, boring: bool = False) -> ravestate.spike.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.

wipe

Context.wipe(self, signal: ravestate.constraint.Signal)

Delete all spikes for the given signal. Partially fulfilled states that have acquired an affected spike will be forced to reject it. Wiping a parent spike will also wipe all child spikes.

  • signal: The signal for which all existing spikes (and their children) should be invalidated and forgotten.

run

Context.run(self) -> None

Creates a signal processing thread, starts it, and emits the core:startup signal.

shutting_down

Context.shutting_down(self) -> bool

Retrieve the shutdown flag value, which indicates whether shutdown() has been called.

shutdown

Context.shutdown(self) -> None

Sets the shutdown flag and waits for the signal processing thread to join.

add_module

Context.add_module(self, module_name: str) -> None

Add a module by python module folder name, or by ravestate module name.

  • module_name: The name of the module to be added. If it is the name of a python module that has not been imported yet, the python module will be imported, and any ravestate modules registered during the python import will also be added to this context.

add_state

Context.add_state(self, *, st: ravestate.state.State) -> None

Add a state to this context. It will be indexed wrt/ the properties/signals it depends on. Error messages will be generated for unknown signals/properties.

  • st: The state which should be added to this context.

rm_state

Context.rm_state(self, *, st: ravestate.state.State) -> None

Remove a state from this context. Note, that any state which is constrained on the signal that is emitted by the deleted state will also be deleted.

  • st: The state to remove. An error message will be generated, if the state was not previously added to this context with add_state().

add_prop

Context.add_prop(self, *, prop: ravestate.property.Property) -> None

Add a copy of a property to this context. An error message will be generated, if a property with the same name has already been added previously. Note: Context will adopt a copy of the given property, the actual property will not be changed.

  • prop: The property object that should be added.

rm_prop

Context.rm_prop(self, *, prop: ravestate.property.Property) -> None

Remove a property from this context. Generates error message, if the property was not added with add_prop() to the context previously

  • prop: The property to remove.object

conf

Context.conf(self, *, mod: str, key: Union[str, NoneType] = None) -> Any

Get a single config value, or all config values for a particular module.

  • mod: The module whose configuration should be retrieved.

  • key: A specific config key of the given module, if only a single config value should be retrieved.

Returns: The value of a single config entry if key and module are both specified and valid, or a dictionary of config entries if only the module name is specified (and valid).

signal_specificity

Context.signal_specificity(self, sig: ravestate.constraint.Signal) -> float

Called by state activation to determine it's constraint's specificity.

  • sig: The signal whose specificity should be returned.

Returns: The given signal's specificity.

reacquire

Context.reacquire(self, act: ravestate.iactivation.IActivation, sig: ravestate.constraint.Signal)

Called by activation, to indicate, that it needs a new Spike for the specified signal, and should for this purpose be referenced by context. Note: Not thread-safe, sync must be guaranteed by caller.

  • act: The activation that needs a new spike of the specified nature.

  • sig: Signal type for which a new spike is needed.

withdraw

Context.withdraw(self, act: ravestate.iactivation.IActivation, sig: ravestate.constraint.Signal)

Called by activation to make sure that it isn't referenced anymore as looking for the specified signal. This might be, because the activation chose to eliminate itself due to activation pressure, or because one of the activations conjunctions was fulfilled, so it is no longer looking for signals to fulfill the remaining conjunctions. Note: Not thread-safe, sync must be guaranteed by caller.

  • act: The activation that has lost interest in the specified signal.

  • sig: Signal type for which interest is lost.

secs_to_ticks

Context.secs_to_ticks(self, seconds: float) -> int

Convert seconds to an equivalent integer number of ticks, given this context's tick rate.

  • seconds: Seconds to convert to ticks.

Returns: An integer tick count.

possible_signals

Context.possible_signals(self, state: ravestate.state.State) -> Generator[ravestate.constraint.Signal, NoneType, NoneType]

Yields all signals, for which spikes may be created if the given state is executed.

  • state: The state, which should be analyzed for it's possibly generated signals (declared signal + property-changed signals).

run_once

Context.run_once(self, seconds_passed=1.0, debug=False) -> None

Run a single update for this context, which will ...
(0) progress cooled down state weights.
(1) reduce redundant candidate activations.
(2) associate new spikes with state activations.
(3) update state activations.
(4) forget spikes which have no suitors in their causal groups.
(5) age spikes.
(6) invoke garbage collection.
(7) update the core:activity and core:pressure variables.

  • seconds_passed: Seconds, as floatiing point, since the last update. Will be used to determine the number of ticks to add/subtract to/from spike/activation age/cooldown/deathclock.

test

Context.test(self) -> bool

Execute internal integrity checks.

ravestate.spike

Spike

Spike(self, *, sig: str, parents: Set[ForwardRef('Spike')] = None, consumable_resources: Set[str] = None, payload: Any = None, boring: bool = False)

This class encapsulates a single spike, to track ...
... it's consumption for different output properties (through CausalGroup).
... it's offspring instances (causal group -> spikes caused by this spike)

boring

Spike.boring(self)

Get the boring-flag of this spike, which indicates whether state of the activation that produced this spike was boring.

:return: True if the activation boring, false otherwise.

causal_group

Spike.causal_group(self) -> ravestate.causal.CausalGroup

Get this spike's causal group.

Returns: This instances causal group. Should never be None.

adopt

Spike.adopt(self, child: 'Spike') -> None

Called in spike constructor, for instances which claim to be caused by this spike.

  • child: The child to add to this spike's causal group.

wiped

Spike.wiped(self, child: 'ISpike') -> None

Called by an offspring signal, to notify the spike that it was wiped, and should therefore be removed from the children set.

  • child: The child to be forgotten.

wipe

Spike.wipe(self, already_wiped_in_causal_group: bool = False) -> None

Called either in Context run loop when the spike is found to be stale (with wiped_in_causal_group=True), or in Context.wipe(spike), or by parent (recursively). After this function is called, the spike should be cleaned up by GC.

  • already_wiped_in_causal_group: Boolean which indicates, whether wiped(spike) must still be called on the group to make sure sure that no dangling references to the spike are maintained by any state activations.

has_offspring

Spike.has_offspring(self)

Called by CausalGroup.stale(spike).

Returns: True if the spike has active offspring, false otherwise.

tick

Spike.tick(self) -> None

Increment this spike's age by 1.

age

Spike.age(self) -> int

Obtain this spike's age (in ticks).

offspring

Spike.offspring(self) -> Generator[ForwardRef('Spike'), NoneType, NoneType]

Recursively yields this spike's offspring and it's children's offspring.

Returns: All of this spike's offspring spikes.

is_wiped

Spike.is_wiped(self)

Check, whether this spike has been wiped, and should therefore not be acquired anymore.

payload

Spike.payload(self) -> Any

Get payload for this spike. The payload is an arbitrary value passed in Context.emit().

ravestate.activation

Activation

Activation(self, st: ravestate.state.State, ctx: ravestate.icontext.IContext)

Encapsulates the potential activation of a state. Tracks the collection of Spikes to fulfill of the state-defined activation constraints.

resources

Activation.resources(self) -> Set[str]

Return's the set of the activation's write-access property names.

specificity

Activation.specificity(self) -> float

Returns the lowest specificity among the specificity values of the activation's conjunct constraints. The specificity for a single conjunction is calculated as the sum of it's component signal's specificities, which in turn is calculated as one over the signal's subscriber count.

dereference

Activation.dereference(self, *, spike: Union[ravestate.iactivation.ISpike, NoneType] = None, reacquire: bool = False, reject: bool = False, pressured: bool = False) -> None

Notify the activation, that a single or all spike(s) are not available anymore, and should therefore not be referenced anymore by the activation. This is called by ...
... context when a state is deleted.
... causal group, when a referenced signal was consumed for a required property.
... causal group, when a referenced signal was wiped.
... this activation (with reacquire=True and pressured=True), if it gives in to activation pressure.

  • spike: The spike that should be forgotten by the activation, or none, if all referenced spikes should be forgotten.

  • reacquire: Flag which tells the function, whether for every rejected spike, the activation should hook into context for reacquisition of a replacement spike.

  • reject: Flag which controls, whether de-referenced spikes should be explicitely rejected through their causal groups.

  • pressured: Flag which controls, whether de-referencing should only occur for spikes of causal groups in the pressuring_causal_groups set.

acquire

Activation.acquire(self, spike: ravestate.spike.Spike) -> bool

Let the activation acquire a signal it is registered to be interested in.

  • spike: The signal which should fulfill at least one of this activation's signal constraints.

Returns: True if the spike was acquired by at least one signal, false if acquisition failed: This may happen for multiple reasons: (1) Acquisition failed, because the spike is too old (2) Acquisition failed, because the spike's causal group does not match it's completions. (3) Acquisition failed, because the spike's causal group does not offer all of this activation's state's write-props.

secs_to_ticks

Activation.secs_to_ticks(self, seconds: float) -> int

Convert seconds to an equivalent integer number of ticks, given this activation's tick rate.

  • seconds: Seconds to convert to ticks.

Returns: An integer tick count.

pressure

Activation.pressure(self, give_me_up: ravestate.iactivation.ICausalGroup)

Called by CausalGroup, to pressure the activation to make a decision on whether it is going to retain a reference to the given spike, given that there is a lower- specificity activation which is ready to run.

  • give_me_up: Causal group that wishes to be de-referenced by this activation.

is_pressured

Activation.is_pressured(self)

Called by context, to figure out whether the activation is pressured, and therefore the idle:bored signal should be emitted.

spiky

Activation.spiky(self, filter_boring=False) -> bool

Returns true, if the activation has acquired any spikes at all.

  • filter_boring: Flag to indicate, whether boring spikes should should NOT be counted against a true return value.

Returns: True, if any of this activation's constraint's signal is referencing a spike.

boring

Activation.boring(self) -> bool

Returns True, if the activation's state is boring. Called by context, to figure out whether this activation counts towards the system not setting the idle:bored property to True.

Returns: True, if the state assigned to this activation has the boring field set to true, False otherwise.

spikes

Activation.spikes(self) -> Generator[ravestate.spike.Spike, NoneType, NoneType]

Returns iterable for all the spikes currently acquired by the activation.

possible_signals

Activation.possible_signals(self) -> Generator[ForwardRef('Signal'), NoneType, NoneType]

Yields all signals, for which spikes may be created if this activation's state is executed.

effect_not_caused

Activation.effect_not_caused(self, group: ravestate.iactivation.ICausalGroup, effect: str) -> None

Notify the activation, that a follow-up signal will not be produced by the given causal group. The activation will go through it's constraint, and reject all completion spikes for signals of name effect, if the completion spikes are from the given causal group.

  • group: The causal group which will not contain a spike for signal effect.
  • effect: Name of the signal for which no spike will be produced.

update

Activation.update(self) -> bool

Called once per tick on this activation, to give it a chance to activate itself, or auto-eliminate, or reject spikes which have become too old.

Returns: True, if the target state is activated and teh activation be forgotten, false if needs further attention in the form of updates() by context in the future.

ravestate.causal

CausalGroup

CausalGroup(self, resources: Set[str])

Class which represents a causal group graph of spike parent/offspring spikes (a "superspike"). These must synchronize wrt/ their (un)written properties and state activation candidates, such that they don't cause output races.

Note: Always use a with ... construct to interact with a causal group. Otherwise, undefined behavior may occur due to race conditions.

merge

CausalGroup.merge(self, other: 'CausalGroup')

Merge this causal group with another. Unwritten props will become the set intersection of this group's unwritten props and other's unwritten props. consumed() will be called with all properties that are consumed by other, but not this. Afterwards, other's member objects will be set to this's.

acquired

CausalGroup.acquired(self, spike: 'ISpike', acquired_by: ravestate.iactivation.IActivation, detached: bool) -> bool

Called by Activation to notify the causal group, that it is being referenced by an activation constraint for a certain member spike.

  • spike: State activation instance, which is now being referenced by the specified causal group.

  • acquired_by: State activation instance, which is interested in this property.

  • detached: Tells the causal group, whether the reference is detached, and should therefore receive special treatment.

Returns: Returns True if all of the acquiring's write-props are free, and the group now refs. the activation, False otherwise.

rejected

CausalGroup.rejected(self, spike: 'ISpike', rejected_by: ravestate.iactivation.IActivation, reason: int) -> None

Called by a state activation, to notify the group that a member spike is no longer being referenced for the given state's write props. This may be because ...
... the activation's dereference function was called. (reason=0)
... the spike got too old. (reason=1)
... the activation happened and is dereferencing it's spikes. (reason=2)

  • spike: The member spike whose ref-set should be reduced.

  • rejected_by: State activation instance, which is no longer interested in this property.

  • reason: See about.

consent

CausalGroup.consent(self, ready_suitor: ravestate.iactivation.IActivation) -> bool

Called by constraint, to inquire whether this causal group would happily be consumed for the given state activation's properties. This will be called periodically on the group by state activations that are ready to go. Therefore, a False return value from this function is never a final judgement (more like a "maybe later").

  • ready_suitor: The state activation which would like to consume this instance for it's write props.

Returns: True if this instance agrees to proceeding with the given consumer for the consumer's write props, False otherwise.

activated

CausalGroup.activated(self, act: ravestate.iactivation.IActivation)

Called by activation which previously received a go-ahead from consent(), when it is truly proceeding with running (after it got the go-ahead from all it's depended=on causal groups).

  • act: The activation that is now running.

resigned

CausalGroup.resigned(self, act: ravestate.iactivation.IActivation) -> None

Called by activation, to let the causal group know that it failed, and a less specific activation may now be considered for the resigned state's write props.

  • act: The activation that is unexpectedly not consuming it's resources, because it's state resigned/failed.

consumed

CausalGroup.consumed(self, resources: Set[str]) -> None

Called by activation to notify the group, that it has been consumed for the given set of properties.

  • resources: The properties which have been consumed.

wiped

CausalGroup.wiped(self, spike: 'ISpike') -> None

Called by a spike, to notify the causal group that the instance was wiped and should no longer be remembered.

  • spike: The instance that should be henceforth forgotten.

stale

CausalGroup.stale(self, spike: 'ISpike') -> bool

Determine, whether a spike is stale (has no remaining interested activations and no children).

Returns: True, if no activations reference the given spike for any unwritten property. False otherwise.

check_reference_sanity

CausalGroup.check_reference_sanity(self) -> bool

Make sure, that the refcount-per-act-per-spike-per-resource value sum is equal to the number of spikes from this causal group acquired per activation for each activation in the index. :return: True if the criterion is fulfilled, False otherwise.