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, whetherwipe
(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 thecore: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 atrue
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 signaleffect
.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.