CIRCUIT COMPONENTS
temporal

Temporal-associative memory component.
See also: https://creatingintelligence.org/#temporal-associative-memory
Details and properties
- Learns the association of the previous state with the current input.
- Predicts the next input based on the current state.
- Supports temporal integration of signals across evaluation cycles, governed by update rule plugins.
- Uses the same temporal integration mechanism as
delay. - The state consists of the temporally integrated signal combined with optional context blocks.
- Always learns, even when the prediction is correct. This may broaden the base temporal associations.
- A closed feedback loop enables generative behavior.
- With the
permutationupdate rule, the temporal order of inputs is preserved. - Controls sparsity through stochastic subsampling
mechanisms.
- Represents the integrated state as a multiset.
- Supports multiple input or output blocks.
| Property | Default | Description |
|---|---|---|
send |
required | [integer,...]
representing one or more output slots |
receive |
required | one or more input slots with pathway tags |
plugin |
replacement |
update rule, governing the temporal integration logic |
rate_limit |
unlimited | subsample input if population exceeds the rate limit |
decay |
0 | pre-integration decay (leak rate) |
capacity |
0 | relative population carried over
from previous state (has no effect with replacement
plugin) |
decimate |
1 | proportional stochastic decimation |
Use standard style options to customize the component’s appearance in circuit schematics.
Temporal associative memory with replacement update
With the replacement update
rule, the current input replaces the internal state, bypassing
the capacity setting. This mechanism directly
associates each signal to the subsequent signal.
{ "hyperparameters": {"default": [1000, 10]},
"dataflow": [
{"component": "input", "send": [1]},
{"component": "temporal", "plugin": "replacement",
"send": [11], "receive": [1]},
{"component": "output", "receive": [11]}
]}
Temporal associative memory with state permutation
The temporal component with the permutation update rule
accumulates a temporal state by iteratively permuting it at
every timestep, encoding the ordering of prior inputs.
{ "hyperparameters": {"default": [1000, 10]},
"dataflow": [
{"component": "input", "send": [1]},
{"component": "temporal", "plugin": "permutation",
"send": [11], "receive": [1], "capacity": 2},
{"component": "output", "receive": [11]}
]}
Temporal associative memory with difference update
The difference
update rule replaces the internal state with the symmetric
multiset difference of the state and the incoming signal.
{ "hyperparameters": {"default": [1000, 10]},
"dataflow": [
{"component": "input", "send": [1]},
{"component": "temporal", "plugin": "difference",
"send": [11], "receive": [1]},
{"component": "output", "receive": [11]}
]}
Temporal associative memory with complement plugin
{ "hyperparameters": {"default": [1000, 10]},
"dataflow": [
{"component": "input", "send": [1]},
{"component": "temporal", "plugin": "complement",
"send": [11], "receive": [1], "capacity": 2},
{"component": "output", "receive": [11]}
]}
Temporal associative memory with state augmentation
The augmentation
update rule plugin aggregates an orderless temporal state.
{ "hyperparameters": {"default": [1000, 10]},
"dataflow": [
{"component": "input", "send": [1]},
{"component": "temporal", "plugin": "augmentation",
"send": [11], "receive": [1], "capacity": 5},
{"component": "output", "receive": [11]}
]}
Source code
def temporal(config):
"""
Temporal-associative memory component.
Learns first-order sequences by default (replacement plugin),
and higher-order sequences with the permutation plugin and capacity > 0.
A hybrid between auto-associative and hetero-associative architectures.
Uses the same temporal integration plugins and parameterization as
"delay". Default plugin: replacement.
The first input block is the item; further input blocks are context.
Learns (previous state & previous context) -> current item, and returns
the prediction for the next item only.
"""
plugin_factory = config.get("plugin", replacement)
if isinstance(plugin_factory, str):
import sys
plugin_factory = getattr(
sys.modules[__name__],
plugin_factory,
replacement)
# The update rule acts on the item block only, not on the context blocks.
plugin = plugin_factory(
{**config, "receive_blocks": config.get("send_blocks", [])})
receive_blocks = config.get("receive_blocks", [])
send_blocks = config.get("send_blocks", [])
# Memory parameters
paramsA = [sum(b[0] for b in receive_blocks),
sum(b[1] for b in receive_blocks)]
paramsB = list(send_blocks[0])
Nitem, Pitem = paramsB
contextdims = [b[0] for b in receive_blocks[1:]]
if contextdims:
Ncontext = sum(b[0] for b in receive_blocks[1:])
Pcontext = sum(b[1] for b in receive_blocks[1:])
else:
Ncontext, Pcontext = 0, 0
# Absolute rate limits. Default: unlimited.
limititem = round(Pitem * config.get("rate_limit", Nitem / Pitem))
limitcontext = (round(Pcontext * config.get("rate_limit", Ncontext / Pcontext))
if Pcontext > 0 else 0)
# Pre-integration decay (leak rate).
decay = config.get("decay", 0.0)
# Temporal capacity, carry over from previous cycle.
abscapacity = round(Pitem * config.get("capacity", 0.0))
# Proportional stochastic subsampling for memory query.
decimation = config.get("decimate", 1.0)
# Label indicating the number of context blocks.
label = plugin["label"] + "\u25a1" * len(contextdims)
# Instantiate the memory.
m_config = dict(config)
m_config.update({
"A_parameters": paramsA,
"B_parameters": paramsB
})
M = Memory(m_config)
Xstate = []
Xcontext = []
def f(item, *blocks):
nonlocal Xstate, Xcontext
# Multiset rate limiting of the current item.
X = item
if len(X) > limititem:
X = sorted(rng.choice(X, size=limititem, replace=False).tolist())
# Pre-integration stochastic decay of previous state.
if decay > 0.0:
keep_size = math.floor((1.0 - decay) * len(Xstate))
Xstate = sorted(
rng.choice(Xstate, size=keep_size, replace=False).tolist())
# Always learn (previous state & previous context) -> current item.
M["store"](resolve_block_join_normal([Xstate, Xcontext], [Nitem, Ncontext]),
resolve_normal(X))
# Multiset rate limiting of the items of the current context.
Xcontext = multiset_block_join(list(blocks), contextdims)
if len(Xcontext) > limitcontext:
Xcontext = sorted(
rng.choice(Xcontext, size=limitcontext, replace=False).tolist())
# Multiset subsampling applied to previous state.
if len(Xstate) > abscapacity:
Xstate = sorted(
rng.choice(Xstate, size=abscapacity, replace=False).tolist())
# Temporal integration via update rules.
Xstate = plugin["updaterule"](X, Xstate)
# Proportional multiset subsampling applied to the integrated state,
# to break symmetry during retrieval.
Xdec = multiset_block_join([Xstate, Xcontext], [Nitem, Ncontext])
if decimation < 1.0:
sample_size = math.floor(decimation * len(Xdec))
Xdec = sorted(
rng.choice(Xdec, size=sample_size, replace=False).tolist())
# Predict next token.
return (M["retrieve"](resolve_normal(Xdec)),)
result = dict(plugin)
result.update({
"function": f,
"checks": ["dimfirst", "oneout"],
"shape": "square", "label": label, "size": 10, "fill": 14
})
result.update(M)
return result