holo-antimemory

A memory where negation is a first-class object.

Most memory systems store presence. "This fact is known" is the only state they can represent. This tool stores presence and absence separately. Query returns one of four verdicts:

Verdict Meaning
YES X is asserted
NO X is denied
UNKNOWN neither asserted nor denied (or both below threshold)
AMBIGUOUS both asserted and denied with comparable weight

The store is a single complex vector space of dimension D. Two independent traces hold positive and negative assertions:

P_yes = sum_i w_i * bind(item_i, item_i)
P_no  = sum_i v_i * bind(item_i, item_i)

Query with item X reads both traces and returns a four-way verdict with the raw weights visible to the caller. Contradictions are not resolved silently β€” they are the fourth verdict, and they are queryable.

What it does

Store a fact. Deny a fact. Store and deny the same fact. Query any of them and get back a verdict that distinguishes all four states.

mem.store("paris_capital_france")
mem.deny("berlin_capital_france")
mem.store("water_is_wet")
mem.deny("water_is_wet")

mem.query("paris_capital_france")   # YES
mem.query("berlin_capital_france")  # NO
mem.query("water_is_wet")           # AMBIGUOUS
mem.query("tokyo_capital_japan")    # UNKNOWN

The AMBIGUOUS state is not an error. It is the store reporting that it holds both signals and that neither dominates. Contradiction is a first-class object.

Why this matters

Standard memory stores are sets. "X is in the store" is the only question they can answer. This means they cannot represent "X is not the case" as a fact β€” only as the absence of the fact. The two states are conflated.

The anti-memory separates them. An item's positive weight and negative weight are stored independently. A fact can be both asserted and denied at the same time, and the store reports the conflict rather than silently choosing one side. This is useful whenever the caller wants to reason about contradictions rather than resolve them:

  • Knowledge bases. Two sources disagree about the same fact. The store records both, and the query reports the conflict.
  • Reasoning over conflicting evidence. An agent receives contradictory signals. The anti-memory preserves both, and the agent's policy decides what to do with them.
  • Change over time. A fact was asserted in one session and denied in another. The store keeps the history rather than collapsing it.
  • Explicit negative knowledge. "I know that X is false" is different from "I don't know about X." The anti-memory distinguishes them.

Installation

pip install numpy        # required
pip install matplotlib   # optional, for the summary plot

Usage

Python

from holo_antimemory import AntiMemory

mem = AntiMemory(d=2048, margin=0.15)

mem.store("paris_capital_france")
mem.deny("berlin_capital_france")
mem.store("water_is_wet")
mem.deny("water_is_wet")

r = mem.query("water_is_wet")
print(r.verdict)   # "AMBIGUOUS"
print(r.raw_yes)   # ~1.00
print(r.raw_no)    # ~1.00
print(r.margin)    # ~0.00

CLI

python holo_antimemory.py
python holo_antimemory.py --output results/
python holo_antimemory.py --margin 0.25

Runs ten demonstrations and writes output to a directory.

Results

All results from a standard run at D=2048 with margin=0.15. The self-test verifies that cosine is scale-invariant while raw projection is not, which is the property that makes weight readout possible.

1. Verdict taxonomy

Item Weight (yes/no) Verdict raw_yes raw_no margin
asserted_only 1.0 / 0.0 YES +1.026 +0.003 +1.024
denied_only 0.0 / 1.0 NO -0.001 +1.023 -1.024
both_sides 1.0 / 1.0 AMBIGUOUS +1.026 +1.023 +0.004
never_seen 0.0 / 0.0 UNKNOWN 0.000 0.000 0.000

The four verdicts are clean. A perfectly balanced assertion and denial returns AMBIGUOUS with margin 0.004. A missing item returns UNKNOWN.

2. Contradiction detection

Items with weight on both sides are detected and ranked by conflict score (1.0 = perfectly balanced, 0.0 = one side dominates):

Item Weight (yes/no) Conflict
fact_a 1.00 / 1.00 1.000
fact_b 1.00 / 1.00 1.000
fact_d 1.00 / 0.30 0.462

fact_c (1.00 / 0.00) is not a contradiction and does not appear.

3. Weighted assertions

The margin parameter controls when two weights are "close enough" to be a contradiction. At margin=0.15:

Item Weight (yes/no) raw_yes raw_no margin Verdict
common_belief 1.00 / 0.30 +0.982 +0.267 +0.714 YES
balanced_debate 1.00 / 1.00 +0.981 +0.954 +0.027 AMBIGUOUS
weak_assertion 0.20 / 0.20 +0.249 +0.224 +0.025 AMBIGUOUS
strong_denial 0.00 / 5.00 -0.012 +4.990 -5.002 NO

The 10:3 ratio resolves to YES. The 1:1 ratio is a contradiction. The 5:0 denial is a NO. The raw projection recovers the stored weights to two decimal places.

4. Repeated store and deny

Storing the same fact five times accumulates weight. often_asserted (5 stores) shows raw_yes = +5.03. sometimes_denied (2 denials) shows raw_no = +2.00. A skewed item (1.0 vs 0.2) resolves to YES at margin=0.15 because the raw gap (0.886) exceeds the margin.

5. Entity-level denial

Denying all four facts about a person produces four perfectly balanced contradictions:

alice_lives_in_paris: AMBIGUOUS (raw_yes=+1.000, raw_no=+1.000)
alice_works_at_acme:  AMBIGUOUS (raw_yes=+0.990, raw_no=+0.990)
alice_has_a_dog:      AMBIGUOUS (raw_yes=+1.048, raw_no=+1.048)
alice_speaks_french:  AMBIGUOUS (raw_yes=+0.987, raw_no=+0.987)

The entity-level operation (deny_many) applies to the whole set in one call and produces contradictions per fact.

6. Margin sweep

Three items, each with both positive and negative weight, queried with the margin parameter varying from 0.0 to 0.8:

margin balanced skewed_2_to_1 skewed_5_to_1
0.00 YES YES YES
0.10 AMBIGUOUS YES YES
0.20 AMBIGUOUS YES YES
0.30 AMBIGUOUS YES YES
0.50 AMBIGUOUS YES YES
0.80 AMBIGUOUS AMBIGUOUS YES

Reference margins (the true weight differences):

  • balanced: +0.009
  • skewed_2_to_1: +0.518
  • skewed_5_to_1: +0.811

A balanced item stays AMBIGUOUS at every margin. A 2:1 skewed item stays YES until margin exceeds its gap of 0.518. A 5:1 skewed item stays YES through margin 0.80. The margin parameter is the user's choice of how close two sides must be to be called a contradiction.

7. Query noise robustness

Store is fixed. Query keys are noisy. Mean raw_yes across 20 items:

Query noise YES ok NO ok AMBIG ok mean raw_yes
0.00 20/20 20/20 1/1 1.006
0.10 20/20 20/20 1/1 1.005
0.30 20/20 20/20 1/1 0.985
0.50 20/20 20/20 1/1 0.930
0.80 20/20 20/20 1/1 0.808
1.20 20/20 20/20 1/1 0.629
2.00 20/20 20/20 1/1 0.416

Verdicts stay correct because the threshold (0.05) is well below the noise-degraded raw weight (0.416 at noise 2.0). The confidence degrades smoothly. A user who wants the store to refuse low-confidence retrievals raises the threshold; a user who wants maximum recall keeps it low.

8. Capacity of the two-trace store

Stored N positive items and N negative items simultaneously. Verdicts queried at the end of the run:

D N YES correct NO correct UNKNOWN correct
1024 100 100/100 100/100 100/100
1024 200 200/200 200/200 200/200
2048 200 200/200 200/200 200/200
4096 200 200/200 200/200 200/200

The two-trace store holds both sides at D=1024 with N=200. The raw projection readout is more robust than cosine here because cosine divides out the scale, which is where the weight information lives.

API reference

AntiMemory

AntiMemory(d=2048, seed=0, threshold=0.05, margin=0.15)

Storage

  • store(item, weight=1.0) β€” add positive weight for item.
  • deny(item, weight=1.0) β€” add negative weight for item.
  • store_many(items, weight=1.0) β€” positive for a list of items.
  • deny_many(items, weight=1.0) β€” negative for a list of items.

Query

  • query(item) -> QueryResult β€” four-way verdict with raw weights.
  • query_many(items) -> [QueryResult] β€” batch query.
  • contradictions() -> [(item, w_yes, w_no)] β€” all items with weight on both sides.
  • contradictions_with_conflict() -> [(item, w_yes, w_no, conflict)] β€” ranked by conflict score.

Maintenance

  • forget(item) β€” remove all trace of item from both traces.
  • reset() β€” clear the store.

Diagnostics

  • stats() -> dict β€” counts, magnitudes, contradiction count.
  • save_json(path) β€” full state as JSON.
  • plot(path) β€” bar chart of positive and negative weights per item.

QueryResult

@dataclass
class QueryResult:
    item: str
    verdict: str          # YES / NO / UNKNOWN / AMBIGUOUS
    raw_yes: float        # raw weight read from positive trace
    raw_no: float         # raw weight read from negative trace
    weight_yes: float     # total positive weight stored for this item
    weight_no: float      # total negative weight stored for this item
    confidence: float     # magnitude of the winning signal
    margin: float         # raw_yes - raw_no (positive means YES dominates)
    note: str             # explanatory note for the verdict

Design notes

Why two traces

A single signed trace would collapse balanced contradictions to zero. If X is asserted with weight 1 and denied with weight 1, a signed trace P = bind(X,X) - bind(X,X) = 0 carries no information about either side. The two-trace structure keeps both signals intact, which is what makes the AMBIGUOUS verdict possible.

Why raw projection, not cosine

Cosine is scale-invariant: cos(w*v, v) = 1.0 for any positive w. If the query readout uses cosine, it cannot see the stored weight. The raw projection vdot(u, v) / ||v||^2 returns the weight directly. For u = w*v, it returns w. For u = v + noise, it returns 1 + (noise projected onto v).

This is verified in the self-test:

cos(0.3*a) = 1.0000, cos(1.5*a) = 1.0000     (both equal)
proj(0.3*a) = 0.3000, proj(1.5*a) = 1.5000   (different)

Why the margin parameter

Two items with weights (1.0, 0.3) are not the same kind of thing as two items with weights (1.0, 1.0). The first is a mostly-asserted fact with a small counter-signal. The second is a genuine disagreement.

The margin parameter is the threshold between these two cases. An item whose weight difference exceeds the margin is resolved to the dominant side. An item whose weight difference is below the margin is called AMBIGUOUS. The user chooses the margin based on their application.

Limitations

No automatic resolution policy. The store reports AMBIGUOUS but does not decide what to do. The caller must decide: refuse to answer, return both sides, or apply a policy. This is deliberate β€” deciding how to handle contradictions is application-specific.

No provenance. The store tracks weights, not sources. Two sources that disagree about the same fact will produce an AMBIGUOUS verdict with no indication of which source contributed which weight. Adding a provenance role is possible but not implemented.

Weights do not decay. Storing the same fact 100 times produces weight 100, which may dominate other items. If decay is wanted, forget(item) removes all trace and the user can re-store with a smaller weight.

Repeated store and deny at capacity. At D=1024 with N=200, the store still separates all verdicts. Beyond that, the raw projection readout degrades faster than the pure item store because each item participates in both traces.

No truth maintenance. If a fact is stored and then denied, the store keeps both. It does not perform non-monotonic reasoning to retract dependents of the asserted fact. The AMBIGUOUS verdict is available; the caller decides what it implies.

Known limitations of the demonstration

EXP 7 noise sweep is verdict-insensitive at the default threshold. Mean raw_yes drops from 1.006 to 0.416 as noise increases from 0 to 2.0, but the verdict count stays 20/20/1 because the threshold (0.05) is well below even the degraded raw weight. This is not a bug β€” it is the store correctly reporting that the signal is above threshold even under heavy noise. To force verdict degradation, raise the threshold or raise the noise. The demo uses the default threshold so the reader can see the smooth degradation of confidence without the verdicts flipping.

Citation

@misc{holo-antimemory2026,
  title  = {holo-antimemory: A memory where negation is a
            first-class object},
  author = {zeechimp},
  year   = {2026},
  note   = {Four-way verdict memory with independent positive
            and negative traces.}
}

References

  • Plate, T. A. "Holographic Reduced Representations." IEEE Transactions on Neural Networks 6:3 (1995), 623–641.
  • Kanerva, P. "Hyperdimensional Computing." Cognitive Computation 1:2 (2009), 139–159.
  • Gayler, R. W. "Vector Symbolic Architectures Answer Jackendoff's Challenges." ICCS/ASCS (2003).

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