holo-working

A working memory substrate: fast buffer, slow long-term, and rehearsal between them.

Biological working memory has two components. A small, fast-decaying buffer holds what is currently in mind. A wide, slow long-term store holds everything that was ever processed. Consolidation between the two is what turns a momentary experience into a persistent memory.

This substrate implements that architecture over the holographic vector space.

What it does

from holo_working import WorkingMemory

mem = WorkingMemory(d=2048, buffer_decay=0.85,
                    consolidation_rate=0.2)

# Present items
mem.present("alpha")
mem.present("beta")
mem.present("gamma")

# Query the buffer, the long-term trace, or both
mem.query("alpha", source="buffer")   # recent items loud
mem.query("alpha", source="ltm")      # consolidated items loud
mem.query("alpha", source="max")      # the higher of the two

# Serial position test
seq = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]
report = mem.serial_position_test(seq, source="max")
mem.print_position_curve(report)

The serial position effect

Twelve items presented one at a time. Query each item with the max readout.

Position Buffer LTM Max
0 +0.125 +1.043 +1.043
5 +0.392 +0.821 +0.821
8 +0.619 +0.502 +0.619
11 +1.018 +0.017 +1.018

The curve is U-shaped. Primacy from LTM at early positions. Recency from buffer at late positions. Middle dip where neither is strong. This is the classical serial position effect, emergent from the two decay rules.

The four readouts

The same substrate state produces four different curves depending on which readout is chosen.

Readout Shape
buffer Recency-dominated
ltm Primacy-dominated
sum Monotonic
max U-shaped (classical)

The readout is the substrate's most consequential interface parameter.

Installation

pip install numpy

No other dependencies. Single file, approximately 600 lines.

Usage

CLI

python holo_working.py
python holo_working.py --output results/

Runs ten demonstrations.

Python

from holo_working import WorkingMemory

mem = WorkingMemory(
    d=2048,
    buffer_decay=0.85,       # fast decay
    ltm_decay=1.0,           # no decay on long-term
    consolidation_rate=0.2,  # 20% of buffer to LTM per step
    focus_weight=0.5,        # rehearsal strength
    threshold=0.05,
    max_focus=4,
)

# Present
for label in ["alpha", "beta", "gamma"]:
    mem.present(label)
mem.step()

# Focus (attention)
mem.focus("beta")
mem.unfocus("beta")
mem.clear_focus()

# Chunk (capacity expansion)
mem.chunk(["a1", "a2", "a3", "a4"], "chunk_A")
mem.present("chunk_A")

# Query
r = mem.query("alpha", source="max")
print(r["buffer_raw"], r["ltm_raw"], r["combined"], r["verdict"])

# Serial position
report = mem.serial_position_test(
    ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"],
    retention_steps=0,
    source="max",
)
mem.print_position_curve(report)

Results

All results at D=2048, buffer_decay=0.85, consolidation_rate=0.2.

Self-test

Check Result
bind/unbind identity PASS
raw projection PASS
buffer holds presented PASS
LTM holds after decay PASS

Buffer decay over time

Single item presented, then 15 steps.

Step Buffer LTM
0 1.000 0.000
5 0.444 0.742
10 0.197 1.071
15 0.087 1.217

Buffer decays geometrically. LTM accumulates and asymptotes.

Serial position curve

See the table above. U-shape confirmed.

Readout comparison

Readout Recency/mean Middle/mean Primacy/mean
buffer 1.18 0.86 1.21
ltm 0.62 0.77 1.44
sum 0.88 1.04 1.34
max 1.02 0.62 1.09

Four curves, one state.

Buffer decay parameter sweep

buffer_decay Recency/mean Primacy/mean
0.60 1.97 0.91
0.85 1.18 1.21
0.98 0.82 1.51

Fast decay β†’ strong recency. Slow decay β†’ strong primacy.

Consolidation rate parameter sweep

consolidation Recency/mean Primacy/mean
0.02 2.14 0.26
0.20 1.18 1.21
0.40 0.68 1.39

Low consolidation β†’ strong recency. High consolidation β†’ strong primacy.

Attention spotlight

Items c (position 2) and j (position 9) held in focus throughout presentation.

Position Score Focused?
2 +5.196 yes
9 +4.557 yes
Neighbors 0.71–1.12 no

Focused items are ~5Γ— their neighbors.

Chunking

Eight items stored without chunking: buffer scores 0.29–0.63 across positions.

Eight items stored as two chunks: buffer scores 0.83 and 0.99. Two slots carry eight items at full strength.

Two interleaved streams

Two streams L and R presented alternately. The buffer treats both by recency only. Stream membership is irrelevant. To keep streams separate, use distinct traces.

API reference

WorkingMemory

WorkingMemory(
    d=2048,
    buffer_decay=0.85,
    ltm_decay=1.0,
    consolidation_rate=0.2,
    focus_weight=0.5,
    threshold=0.05,
    max_focus=4,
    seed=0,
)

Presentation

  • present(label, weight=1.0) β€” consolidate, decay, add, rehearse.
  • step() β€” consolidate, decay, rehearse without adding.

Focus

  • focus(label) -> bool β€” add to focus set if room.
  • unfocus(label)
  • clear_focus()

Chunking

  • chunk(labels, name) β€” bind multiple items into a chunk vector.

Query

  • query(label, source="max") -> dict β€” source is one of buffer, ltm, sum, max, weighted, auto.
  • recall_scores(labels, source) β€” batch query.

Serial position

  • serial_position_test(sequence, retention_steps=0, source="max") -> dict
  • print_position_curve(report, width=60)

Diagnostics

  • stats() -> dict
  • save_json(path)
  • reset()

Design notes

Two stores, one substrate

The buffer and long-term traces share the same vector space. They are separate traces but the same codebook. Items presented to the buffer are the same vectors that accumulate in LTM. This means a query can ask about an item in either store using the same label.

Consolidation is not lossy

The buffer decays but its content is not lost; a fraction moves to LTM before decay. Over many steps, all presented items accumulate in LTM. The buffer is a short-term view; the LTM is the long-term record.

Attention is rehearsal

Focusing an item means adding it to the buffer at every step. The item doesn't decay because its buffer contribution is repeatedly refreshed. This is the substrate's model of what deliberate attention does: it keeps an item active.

The readout choice

The four readouts are not four different substrates; they are four projections of the same state. A user who wants a memory that emphasizes recent items picks buffer. A user who wants a memory that emphasizes consolidated items picks ltm. A user who wants the classical shape picks max.

Limitations

No hard capacity limit. The buffer holds as many items as presented, subject to interference. Real working memory has a capacity around 4Β±1.

No item-item interference model. Similar items interfere more than dissimilar ones, but this is emergent from geometry, not designed.

No temporal coding. Items do not carry position tags. Order is preserved only by recency.

Middle dip is at 70% of mean, not zero. Real working memory shows the middle dip near chance. The substrate's interference floor is higher.

Chunks are bundles, not structures. Unbinding a chunk returns a superposition, not clean parts.

ltm_decay is exposed but rarely changed. Default 1.0 means LTM never forgets. Setting it below 1.0 is possible but the parameter's effect is not characterized here.

Citation

@misc{holo-working2026,
  title  = {holo-working: A working memory substrate with buffer,
            long-term store, and rehearsal},
  author = {zeechimp},
  year   = {2026},
  note   = {Two-store architecture reproducing the serial position
            effect.}
}

References

  • Miller, G. A. "The Magical Number Seven, Plus or Minus Two." Psychological Review 63:2 (1956).
  • Atkinson, R. C., Shiffrin, R. M. "Human Memory: A Proposed System and its Control Processes." Psychology of Learning and Motivation 2 (1968).
  • Murdock, B. B. "The Serial Position Effect of Free Recall." Journal of Experimental Psychology 64:5 (1962).
  • Plate, T. A. "Holographic Reduced Representations." IEEE Transactions on Neural Networks 6:3 (1995).

License

Apache 2.0

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support