--- language: - en license: apache-2.0 library_name: holo-program tags: - memory - programmable-memory - membrane-computing - p-systems - cryptographic-memory - keyed-access - associative-memory - hyperdimensional-computing - vector-symbolic-architecture - numpy - educational - research datasets: [] metrics: - chain-execution-accuracy - membrane-inheritance - key-separation pipeline_tag: feature-extraction --- # holo-program **Programs as items, membranes as regions, keys as gates.** A memory substrate with three stacked layers under one interface. Programs are stored as key-value items and executed by unbind-then-classify. Membranes are nested regions with child-to-parent inheritance and P-systems operations. Cryptographic keying derives item vectors from a secret; without the key, the trace is noise. Everything is addressable through a single `ask()` primitive. The three layers are views of one vector space. The caller does not specify which layer to search. `ask()` returns heterogeneous hits. ## What it does ```python from holo_program import HoloProgram prog = HoloProgram(d=2048, key=None) # Programs as items prog.add_op("root", "inc", "0", "1") prog.add_op("root", "inc", "1", "2") prog.add_op("root", "double", "2", "4") # Execute a chain result = prog.run_chain("root", ["inc", "inc", "double"], "0") # result = {"path": ["0", "1", "2", "4"], "ok": True} # Membranes with inheritance prog.add_membrane("alice", parent="root") prog.store("alice", "alice_lives_in_paris") prog.query("alice", "alice_lives_in_paris") # ~1.0 prog.query("root", "alice_lives_in_paris") # ~0.0 # Keyed access p_secret = HoloProgram(key="secret") p_secret.store("root", "classified") p_wrong = HoloProgram(key="wrong") p_wrong.membranes["root"].trace = p_secret.membranes["root"].trace.copy() p_secret.query("root", "classified") # ~1.0 p_wrong.query("root", "classified") # ~0.0 # Non-flat query hits = prog.ask("inc") # [operation] membrane=root role=op inc(0) -> 1 # [operation] membrane=root role=op inc(1) -> 2 ``` ## Why three layers Standard memory tools are flat. A vector database accepts an embedding; a KV cache accepts a key; a graph database accepts a pattern. Each tool has one interface and one data layer. The user adapts the problem to the tool. The substrate here stacks three layers over the same vector space. Each layer has been built before. The composition is what is new. A user stores a fact, defines an operation, puts it in a membrane, and locks it behind a key — all through the same primitives, all retrievable through the same `ask()` call. ## Installation ```bash pip install numpy ``` No other dependencies. Single file, approximately 600 lines. ## Usage ### CLI ```bash python holo_program.py python holo_program.py --output results/ ``` Runs eight demonstrations and writes a JSON state file. ### Python ```python from holo_program import HoloProgram prog = HoloProgram(d=2048, key=None, threshold=0.05) # Membranes prog.add_membrane("alice", parent="root") prog.add_membrane("alice_kitchen", parent="alice") # Storage prog.store("root", "earth_round") prog.store("alice", "alice_lives_in_paris") prog.store("alice_kitchen", "manager_is_bob") # Operations prog.add_op("root", "serve", "customer", "coffee") prog.add_op("alice_kitchen", "brew", "coffee", "ready") # Execute result = prog.run_chain("root", ["inc", "inc"], "5") result = prog.apply("alice_kitchen", "brew", "coffee") # "ready" # Data-driven walk walk = prog.run_data_driven("root", "cold") # ["cold", "warm", ...] # P-systems operations prog.move("private_note", "alice", "root") prog.dissolve("alice_kitchen", "alice") # Non-flat query hits = prog.ask("coffee", top_k=8) # Cryptographic layer commitment = prog.commit("root", "secret_value", salt="random_salt_123") ok = prog.verify("root", "secret_value", "random_salt_123", commitment) ``` ## Results All results at D=2048, threshold=0.05. Self-test verifies four primitives before any demonstration: bind/unbind identity, key separation, projection recovery, and random-key key-value retrieval (49/50 at 50 superposed pairs). ### Program execution Twenty `inc` operations (i → i+1 for i = 0..19), twenty `double` operations (i → 2i), ten `square` operations (i → i²) stored as key-value pairs. | Chain | Start | Path | Result | |---|---|---|---| | inc, inc, double | 3 | 3 → 4 → 5 → 10 | correct | | square, inc | 4 | 4 → 16 → 17 | correct | | double, inc, inc | 5 | 5 → 10 → 11 → 12 | correct | | inc, square | 2 | 2 → 3 → 9 | correct | Single applies: `inc(7) = 8`, `double(7) = 14`, `square(7) = 49`. The chains compose across different operations. The substrate does not know which operations exist; it reads the key, retrieves the value, classifies the out, and passes the result forward. ### Data-driven execution State transitions: `cold → warm → hot → boiling → evaporated`. Starting at `cold` with no predefined chain, the substrate walks by finding whichever operation matches the current value at each step: ``` cold -> warm -> hot -> boiling -> evaporated steps: 4 ``` Starting at `evaporated` (no matching operation), the walk terminates immediately. ### Membrane inheritance Three nested membranes: `root`, `alice`, `alice_kitchen`. | Query | root | alice | alice_kitchen | |---|---|---|---| | earth_round | +1.028 | +1.028 | +1.028 | | alice_lives_in_paris | +0.023 | +1.004 | +1.004 | | kitchen_floor_5 | -0.026 | -0.026 | +1.020 | | manager_is_bob | -0.004 | -0.004 | +1.020 | The child sees the parent's facts. The parent does not see the child's. Inheritance is one-way, from child to parent. ### Movement and dissolution **Move.** `private_note` stored in `inner`: | | root | inner | |---|---|---| | before | +0.027 | +1.000 | | after | +1.027 | +1.027 | The content transferred completely. **Dissolution.** `middle_fact` in `middle`, then dissolve `middle` into `root`: | | root | middle | |---|---|---| | before | +0.009 | +1.000 | | after | +1.009 | (gone) | Content transferred, membrane removed. ### Cryptographic keying Two programs share the same trace. One has the correct key; the other has a wrong key. | Candidate | Correct key | Wrong key | |---|---|---| | classified_meeting_place | +0.997 | +0.004 | | classified_meeting_time | +0.997 | -0.007 | | paris | -0.018 | -0.022 | | 3pm | -0.028 | +0.034 | | unrelated_word | -0.028 | +0.010 | With the correct key, stored items read at +0.997 and non-stored at near zero. With the wrong key, all items read near zero. The trace carries no usable signal without the key. ### Commitment scheme Commitment = `bind(vector(label), vector(salt))`. Verification: | Correct (label, salt) | Wrong salt | Wrong label | |---|---|---| | True | False | False | Commitment vector magnitude is exactly 1.0000 (phase-only binding preserves unit modulus). ### Unified `ask()` Five example queries, each returning heterogeneous hits: | Query | Result | |---|---| | `alice` | `[membrane] alice` | | `alice_lives_in_paris` | `[item] alice sim=+1.004` | | `coffee` | `[operation] serve(customer) → coffee` in root; `[operation] brew(coffee) → ready` in alice_kitchen | | `alice_kitchen` | `[membrane] alice_kitchen` | | `manager_is_bob` | `[item] alice_kitchen sim=+1.020` | The caller does not specify which layer to search. The substrate reports what it has. ### Programs as items Querying `ask("inc")` returns the two stored `inc` operations. Querying `ask("3")` returns both the operation where `3` is an output (`inc(2) → 3`) and the operation where `3` is an input (`double(3) → 6`). The `role` field distinguishes them. The same primitive reads items and operations. There is no separate "program layer" from the caller's perspective. ## API reference ### `HoloProgram` ```python HoloProgram(d=2048, key=None, threshold=0.05) ``` **Membrane management** - `add_membrane(name, parent="root")` — create a nested membrane. **Storage** - `store(membrane, label, weight=1.0)` — store an item. - `add_op(membrane, op_name, in_val, out_val)` — store an operation. - `move(label, src, dst)` — transfer an item between membranes. - `dissolve(child, into)` — merge a child membrane into its parent. **Execution** - `apply(membrane, op_name, in_val) -> out_val | None` — single step. - `run_chain(membrane, ops, start) -> dict` — fixed sequence. - `run_data_driven(membrane, start, max_steps=20) -> dict` — follow whichever operation matches at each step. **Query** - `query(membrane, label) -> float` — similarity in the membrane's inheritance chain. - `ask(query, top_k=8) -> list[dict]` — heterogeneous search across all membranes and all layers. **Cryptographic** - `commit(membrane, label, salt) -> np.ndarray` — generate commitment. - `verify(membrane, label, salt, commitment) -> bool` — verify. **Diagnostics** - `stats() -> dict` — per-membrane counts and magnitudes. - `save_json(path)` — full state. ## Design notes ### Random keys, not structured keys Operations use fully random keys derived from a hash of `(op_name, in_val)`, not from a structured binding of role vectors. An earlier version used `norm(bind(op, op_name) + bind(in, in_val))`, which produced correlated keys for operations sharing a component. With twenty `inc` operations, the shared `inc` component made the keys correlated and cross-talk swamped the signal; only single applies worked. The random-key variant removes the cross-talk at the cost of treating every `(op, in)` pair as structurally distinct. The `op` role is still used for the value (`bind(out, out_val)`), but not for the key. ### Parent direction Inheritance goes from child to parent. A child sees its parent's facts; a parent does not see its child's facts. This is the natural direction for a "context" relation: a specific context inherits from a general one, not the other way around. ### Keyed codebook Item vectors are derived from `random_vector(key, label)`. Different keys produce uncorrelated vectors for the same label. A trace built with key A, queried with key B, produces similarity near zero because the two codebooks are independent. This is access control at the codebook level. Without the key, the trace is a random superposition of unknown vectors. ## Limitations **Programs are not Turing-complete.** Chains and data-driven walks compose operations. Branching, iteration, and recursion must be encoded as larger operation sets or implemented outside the substrate. **No catalysis.** An operation cannot require a third object to be present. The structure supports it (a catalyst could be a role in the operation and a check against the local trace) but it is not implemented. **No priority.** Multiple applicable operations are returned by `find_applicable` sorted by similarity. There is no specificity-based ordering or explicit precedence. **No timed rules.** Operations have no validity windows. **No provenance.** The substrate does not track which call produced which weight. Two sources that store the same fact look identical. **Keys are not secret against an adversary with the codebook.** The key separation prevents a wrong-key query from retrieving items. It does not prevent brute-force matching against the trace if the label space is small. **Commitments are not cryptographic.** `bind(vector(label), vector(salt))` is a hash-like operation in the substrate's algebra. It is not a cryptographically secure commitment in the formal sense. It is useful for cooperative verification, not for adversarial security. **No cross-membrane queries.** A query goes to one membrane. `ask()` searches all membranes for the query string, but it does not propagate the query through the inheritance chain. **No consolidation.** Traces grow linearly. Long-running stores need external management. The four-axis tool provides consolidation; it is not integrated here. ## Citation ```bibtex @misc{holo-program2026, title = {holo-program: Programs as items, membranes as regions, keys as gates}, author = {zeechimp}, year = {2026}, note = {A memory substrate with three stacked layers under a single non-flat interface.} } ``` ## 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. - Păun, Gh. "Computing with Membranes." *Journal of Computer and System Sciences* 61:1 (2000), 108–143. - Gayler, R. W. "Vector Symbolic Architectures Answer Jackendoff's Challenges." *ICCS/ASCS* (2003). ## License Apache 2.0