RumleyRum commited on
Commit
2ca80ad
·
verified ·
1 Parent(s): a2f9869

Upload 22 files

Browse files
LICENSE ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Research and Personal Use License
2
+
3
+ **Material-Field Governance Reference Implementation**
4
+ Copyright (c) 2026 Ryan S. Walters / Verhash LLC
5
+
6
+ ## Grant of Rights
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to use, copy, modify, and study the Software for **non-commercial purposes only**, subject to the following conditions:
9
+
10
+ ### Permitted Uses
11
+
12
+ ✅ **Research and Academic Use**
13
+ - Study the code and underlying algorithms
14
+ - Modify for research experiments
15
+ - Publish academic papers citing this work
16
+ - Use in educational settings (courses, workshops)
17
+
18
+ ✅ **Personal Use**
19
+ - Run for personal learning and experimentation
20
+ - Modify for individual projects
21
+ - Share results and findings publicly
22
+
23
+ ✅ **Open Science**
24
+ - Fork and improve the implementation
25
+ - Publish modified versions with attribution
26
+ - Contribute bug reports and issues
27
+ - Participate in technical discussions
28
+
29
+ ### Prohibited Uses
30
+
31
+ ❌ **Commercial Deployment**
32
+ - Integration into commercial products or services
33
+ - Use in production systems serving customers
34
+ - Deployment for profit or commercial advantage
35
+ - Providing as a paid service (SaaS, API, etc.)
36
+
37
+ ❌ **Redistribution for Profit**
38
+ - Selling copies or access to the Software
39
+ - Bundling with commercial products
40
+ - Sublicensing for commercial purposes
41
+
42
+ ## Conditions
43
+
44
+ 1. **Attribution Required**
45
+ - Retain this license notice in all copies
46
+ - Credit original author (Ryan S. Walters / Verhash LLC)
47
+ - Cite patent application when publishing research
48
+
49
+ 2. **Patent Notice**
50
+ - This software demonstrates concepts covered by pending patent applications
51
+ - Patent priority date: January 25, 2026
52
+ - Title: "Deterministic Material-Field Governance for Computational Systems"
53
+ - Applicant: Verhash LLC
54
+
55
+ 3. **No Warranty**
56
+ - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND
57
+ - Use at your own risk
58
+ - No guarantee of fitness for any particular purpose
59
+
60
+ ## Commercial Licensing
61
+
62
+ For commercial use, production deployment, or integration into commercial products:
63
+
64
+ **Contact:** ryan@rswlabs.org
65
+ **Organization:** Verhash LLC
66
+ **Address:** 9343 Klusman Ave, Rancho Cucamonga, CA 91730
67
+
68
+ We offer commercial licenses for:
69
+ - Enterprise deployment
70
+ - Integration into products
71
+ - Production use in safety-critical systems
72
+ - Custom development and support
73
+
74
+ ## Definitions
75
+
76
+ **"Non-commercial"** means:
77
+ - Not primarily intended for or directed toward commercial advantage
78
+ - Not involving monetary compensation
79
+ - Research, educational, or personal purposes
80
+
81
+ **"Commercial"** means:
82
+ - Used in a business or profit-making context
83
+ - Deployed to serve paying customers
84
+ - Integrated into products sold for profit
85
+ - Any use generating revenue
86
+
87
+ ## Why This License?
88
+
89
+ This software is a **reference implementation** of novel research. The goal is to:
90
+
91
+ 1. **Enable scrutiny** - Let researchers verify and challenge the claims
92
+ 2. **Accelerate research** - Provide working code to build upon
93
+ 3. **Support education** - Help students learn alternative AI approaches
94
+ 4. **Protect innovation** - Maintain rights for commercial deployment
95
+
96
+ We want the research community to have full access while preserving the ability to support commercial development through proper licensing.
97
+
98
+ ## Questions?
99
+
100
+ If you're unsure whether your use case is permitted:
101
+
102
+ - **Academic research?** → Yes, permitted
103
+ - **Personal learning project?** → Yes, permitted
104
+ - **Startup product?** → No, requires commercial license
105
+ - **Company internal R&D?** → Contact us to discuss
106
+ - **Open source project?** → Yes, if non-commercial
107
+ - **Publishing modifications?** → Yes, with attribution
108
+
109
+ ---
110
+
111
+ **Verhash LLC** supports development and research in deterministic systems.
112
+
113
+ Last updated: January 27, 2026
README.md CHANGED
@@ -1,26 +1,149 @@
1
- ---
2
- title: Deterministic Governance Demo
3
- emoji: 🔬
4
- colorFrom: green
5
- colorTo: blue
6
- sdk: streamlit
7
- sdk_version: 1.32.0
8
- app_file: demo_gui_dev.py
9
- pinned: false
10
- license: mit
11
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
 
13
- # Deterministic Exclusion Demo
 
 
 
 
14
 
15
- Material-Field Engine with LLM Guardrails
 
 
 
 
16
 
17
- ## Features
18
- - Real-time deterministic governance visualization
19
- - Multi-provider LLM testing (OpenAI, Anthropic, Ollama)
20
- - Interactive physics parameter tuning
21
- - Complete audit trail with cryptographic hashes
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
- ## Usage
24
- The Space will launch automatically. Configure parameters in the sidebar and run tests.
25
 
26
- For API testing (Tab 3), you'll need to provide your own API keys for commercial providers.
 
1
+ # Deterministic Governance Mechanism
2
+
3
+ Probabilistic systems cannot be audited. If a decision changes between runs with identical inputs, the reasoning chain is non-reproducible, and post-hoc explanation is speculation.
4
+
5
+ This is a reference implementation of deterministic exclusion: a governance layer where decisions are mechanical, not sampled. Given identical inputs, configuration, and substrate, the system produces bit-identical outputs.
6
+
7
+ **[Try the live demo →](https://huggingface.co/spaces/RumleyRum/Deterministic-Governance-Mechanism)**
8
+
9
+ ## Core Invariant
10
+
11
+ ```
12
+ Same input + same configuration + same substrate → same output (bit-identical)
13
+ ```
14
+
15
+ If two executions diverge, something upstream changed. The system makes divergence visible rather than masking it.
16
+
17
+ ## Verification
18
+
19
+ Run the same scenario five times:
20
+
21
+ ```bash
22
+ python exclusion_demo.py replay
23
+ ```
24
+
25
+ Output: Five identical SHA-256 hashes.
26
+
27
+ ```
28
+ SHA-256(canonical_input || configuration || substrate_hash || output_decisions)
29
+ ```
30
+
31
+ If the hash changes, the computation diverged. If it doesn't, the decision was deterministic.
32
+
33
+ ## Mechanism
34
+
35
+ Candidates are stateful objects under constraint pressure. Exclusion occurs when accumulated stress exceeds a fixed yield threshold:
36
+
37
+ ```
38
+ σ(t) > σ_y → Exclusion
39
+ ```
40
+
41
+ No temperature. No sampling. No randomness. Stress accumulates via explicit arithmetic over discrete time steps. Once excluded, a candidate cannot re-enter.
42
+
43
+ The system implements:
44
+ - Deterministic stress accumulation (no entropy sources)
45
+ - Cryptographic yield strength (BLAKE2b, no salt)
46
+ - Three-phase pressure schedule (nucleation, quenching, crystallization)
47
+ - Bit-identical verification (canonical serialization)
48
+
49
+ All arithmetic is in code. No learned parameters. No hidden state.
50
+
51
+ ## Quick Start
52
+
53
+ ```bash
54
+ git clone https://github.com/Rymley/Deterministic-Governance-Mechanism
55
+ cd Deterministic-Governance-Mechanism
56
+ pip install -r requirements.txt
57
+ python exclusion_demo.py
58
+ ```
59
+
60
+ **Prove determinism:**
61
+ ```bash
62
+ python exclusion_demo.py replay
63
+ # Runs 5 times - prints identical SHA-256 hashes
64
+ ```
65
 
66
+ **Compare modes:**
67
+ ```bash
68
+ python exclusion_demo.py compare
69
+ # Shows behavioral differences across elastic modulus modes
70
+ ```
71
 
72
+ **Run full test suite:**
73
+ ```bash
74
+ python test_suite.py
75
+ # 14 mechanical tests verifying invariants
76
+ ```
77
 
78
+ ## What This Is
79
+
80
+ An experiment showing exclusion can be:
81
+ - **Deterministic** (same inputs → same outputs)
82
+ - **Replayable** (hash proves invariance)
83
+ - **Mechanical** (threshold, not probability)
84
+
85
+ ## What This Is Not
86
+
87
+ - A production system
88
+ - A claim about optimality or fairness
89
+ - A solution to high-dimensional scaling (open question)
90
+ - A validation of substrate quality (garbage in, deterministic garbage out)
91
+
92
+ ## Provenance and Misuse
93
+
94
+ The engine enforces determinism mechanically; it does not validate the quality of the substrate it is pointed at. Misuse risk concentrates upstream in substrate selection (what is treated as verified) and configuration selection (how strict exclusion is).
95
+
96
+ Mitigations target provenance and auditability:
97
+ - Substrates should be permissioned and signed
98
+ - Configuration and substrate hashes recorded with each run
99
+ - Silent swaps detectable via hash divergence
100
+ - Defaults bias toward abstention under ambiguity
101
+
102
+ ## Files
103
+
104
+ - `material_field_engine.py` - Core implementation
105
+ - `exclusion_demo.py` - Fixed demonstration run
106
+ - `test_suite.py` - Behavior verification (14 tests)
107
+ - `test_determinism.py` - Bit-identical execution proof
108
+ - `config.json` - Timing presets and configuration
109
+ - `documents/` - Detailed technical documentation
110
+
111
+ ## Documentation
112
+
113
+ - [Implementation Status](documents/IMPLEMENTATION_STATUS.md) - Technical architecture and assessment
114
+ - [License](LICENSE) - Usage terms and restrictions
115
+ - [Security Policy](SECURITY.md) - Reporting guidelines
116
+ - [Contributing](CONTRIBUTING.md) - Participation guidelines
117
+
118
+ ## Production Use
119
+
120
+ This is a reference implementation demonstrating core mechanics.
121
+
122
+ For production-ready deployment with enterprise features → **[verhash.com](https://verhash.com)**
123
+
124
+ ## Commercial Partnerships
125
+
126
+ Interested in technology licensing, partnerships, or investment:
127
+
128
+ **Contact:** ryan@verhash.net
129
+ **Organization:** Verhash LLC
130
+
131
+ ## Patent Notice
132
+
133
+ Demonstrates concepts from pending patent application:
134
+ - **Title:** "Deterministic Material-Field Governance for Computational Systems"
135
+ - **Priority Date:** January 25, 2026
136
+ - **Applicant:** Verhash LLC
137
+
138
+ ## License
139
+
140
+ **Research and Personal Use:** Open source
141
+ **Commercial Deployment:** Requires separate license
142
+
143
+ See [LICENSE](LICENSE) for full terms.
144
+
145
+ ---
146
 
147
+ **Try to break the invariant. If you do, file an issue.**
 
148
 
149
+ *An invitation to treat inference as mechanics rather than chance.*
SECURITY.md ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ If you believe you have found a security issue, please do not open a public issue.
6
+
7
+ Send a report with reproduction steps and impact assessment to the contact listed in `LICENSE`.
benchmarks.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Benchmark harness.
4
+
5
+ Reports p50/p95/p99 latency (ms) for:
6
+ - Engine loop: (candidates, steps, active_substrate_size)
7
+ - Shard retrieval: (total_vectors, shard_size, top_k)
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import math
14
+ import statistics
15
+ import time
16
+ from dataclasses import dataclass
17
+ from typing import Iterable, Sequence
18
+
19
+ import hashlib
20
+
21
+ from material_field_engine import MaterialFieldEngine, VerifiedSubstrate, Vector2D
22
+ from substrate_sharding import CompactVector, ShardedSubstrate, SubstrateShard
23
+ from deterministic_rng import normal, uniform, uint31
24
+
25
+
26
+ def _pctl(sorted_values: Sequence[float], p: float) -> float:
27
+ if not sorted_values:
28
+ return float("nan")
29
+ if p <= 0:
30
+ return float(sorted_values[0])
31
+ if p >= 1:
32
+ return float(sorted_values[-1])
33
+ idx = int(round(p * (len(sorted_values) - 1)))
34
+ return float(sorted_values[idx])
35
+
36
+
37
+ def _fmt_ms(ns: float) -> float:
38
+ return float(ns) / 1e6
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class Summary:
43
+ runs: int
44
+ p50_ms: float
45
+ p95_ms: float
46
+ p99_ms: float
47
+
48
+
49
+ def _summarize_ns(samples_ns: Sequence[int]) -> Summary:
50
+ s = sorted(float(x) for x in samples_ns)
51
+ return Summary(
52
+ runs=len(samples_ns),
53
+ p50_ms=_fmt_ms(_pctl(s, 0.50)),
54
+ p95_ms=_fmt_ms(_pctl(s, 0.95)),
55
+ p99_ms=_fmt_ms(_pctl(s, 0.99)),
56
+ )
57
+
58
+
59
+ def _print_engine_header() -> None:
60
+ print(
61
+ "benchmark,candidates,steps,active_substrate_states,warmup,runs,"
62
+ "p50_init_ms,p95_init_ms,p99_init_ms,mean_init_ms,"
63
+ "p50_run_ms,p95_run_ms,p99_run_ms,mean_run_ms,"
64
+ "p50_total_ms,p95_total_ms,p99_total_ms,mean_total_ms"
65
+ )
66
+
67
+
68
+ def _print_retrieval_header() -> None:
69
+ print(
70
+ "benchmark,total_vectors,shard_size,top_k,warmup,runs,"
71
+ "p50_ms,p95_ms,p99_ms,mean_ms"
72
+ )
73
+
74
+
75
+ def bench_engine(
76
+ *,
77
+ candidates: int,
78
+ steps: int,
79
+ active_substrate_states: int,
80
+ warmup: int,
81
+ runs: int,
82
+ seed: int,
83
+ ) -> None:
84
+ seed_bytes = hashlib.blake2b(f"bench_engine|{seed}".encode("utf-8"), digest_size=16).digest()
85
+
86
+ # Deterministic substrate states.
87
+ substrate_points: list[tuple[float, float]] = []
88
+ for i in range(active_substrate_states):
89
+ x = uniform(seed_bytes, i * 2, -1.0, 1.0)
90
+ y = uniform(seed_bytes, i * 2 + 1, -1.0, 1.0)
91
+ substrate_points.append((x, y))
92
+
93
+ # Deterministic candidates.
94
+ #
95
+ # Use substrate-aligned candidates with a tiny perturbation so:
96
+ # - no exclusions occur (fixed work per step)
97
+ # - the loop runs all `steps` iterations (no early termination)
98
+ if active_substrate_states == 0:
99
+ candidate_tuples = [
100
+ (uniform(seed_bytes, 1_000_000 + i * 2, -1.0, 1.0), uniform(seed_bytes, 1_000_000 + i * 2 + 1, -1.0, 1.0))
101
+ for i in range(candidates)
102
+ ]
103
+ else:
104
+ noise_seed = hashlib.blake2b(f"bench_engine_noise|{seed}".encode("utf-8"), digest_size=16).digest()
105
+ candidate_tuples = []
106
+ for i in range(candidates):
107
+ bx, by = substrate_points[i % active_substrate_states]
108
+ nx = normal(noise_seed, i * 4, mean=0.0, std=1e-6)
109
+ ny = normal(noise_seed, i * 4 + 2, mean=0.0, std=1e-6)
110
+ candidate_tuples.append((bx + nx, by + ny))
111
+
112
+ substrate = VerifiedSubstrate(elastic_modulus_mode="multiplicative", elastic_modulus_sigma=0.40)
113
+ for x, y in substrate_points:
114
+ substrate.add_verified_state(Vector2D(x=float(x), y=float(y), properties=None))
115
+
116
+ engine = MaterialFieldEngine(substrate, lambda_min=0.35, lambda_max=1.20, inference_steps=steps)
117
+ engine.phase_controller.nucleation_threshold = 0.375
118
+ engine.phase_controller.quenching_threshold = 0.875
119
+
120
+ # Warmup.
121
+ for _ in range(warmup):
122
+ engine.initialize_candidates(candidate_tuples)
123
+ engine.run_inference()
124
+
125
+ init_ns: list[int] = []
126
+ run_ns: list[int] = []
127
+ total_ns: list[int] = []
128
+ for _ in range(runs):
129
+ t0 = time.perf_counter_ns()
130
+ engine.initialize_candidates(candidate_tuples)
131
+ t1 = time.perf_counter_ns()
132
+ engine.run_inference()
133
+ t2 = time.perf_counter_ns()
134
+ init_ns.append(t1 - t0)
135
+ run_ns.append(t2 - t1)
136
+ total_ns.append(t2 - t0)
137
+
138
+ init_s = _summarize_ns(init_ns)
139
+ run_s = _summarize_ns(run_ns)
140
+ total_s = _summarize_ns(total_ns)
141
+
142
+ init_mean = _fmt_ms(statistics.mean(init_ns))
143
+ run_mean = _fmt_ms(statistics.mean(run_ns))
144
+ total_mean = _fmt_ms(statistics.mean(total_ns))
145
+
146
+ print(
147
+ f"engine,{candidates},{steps},{active_substrate_states},{warmup},{runs},"
148
+ f"{init_s.p50_ms:.6f},{init_s.p95_ms:.6f},{init_s.p99_ms:.6f},{init_mean:.6f},"
149
+ f"{run_s.p50_ms:.6f},{run_s.p95_ms:.6f},{run_s.p99_ms:.6f},{run_mean:.6f},"
150
+ f"{total_s.p50_ms:.6f},{total_s.p95_ms:.6f},{total_s.p99_ms:.6f},{total_mean:.6f}"
151
+ )
152
+
153
+
154
+ def _build_sharded_substrate(
155
+ *,
156
+ total_vectors: int,
157
+ shard_size: int,
158
+ seed: int,
159
+ ) -> ShardedSubstrate:
160
+ seed_bytes = hashlib.blake2b(f"bench_retrieval|{seed}".encode("utf-8"), digest_size=16).digest()
161
+ substrate = ShardedSubstrate(shard_size=shard_size)
162
+
163
+ domains = ("biology", "geography", "physics")
164
+ shard_count = int(math.ceil(total_vectors / shard_size))
165
+ next_vector_idx = 0
166
+
167
+ for shard_id in range(shard_count):
168
+ domain = domains[shard_id % len(domains)]
169
+ vectors: list[CompactVector] = []
170
+ for _ in range(shard_size):
171
+ if next_vector_idx >= total_vectors:
172
+ break
173
+ x = uniform(seed_bytes, next_vector_idx * 4, -1.0, 1.0)
174
+ y = uniform(seed_bytes, next_vector_idx * 4 + 1, -1.0, 1.0)
175
+ domain_hash = uint31(seed_bytes, next_vector_idx * 4 + 2)
176
+ vectors.append(CompactVector(x=float(x), y=float(y), shard_id=shard_id, domain_hash=domain_hash))
177
+ next_vector_idx += 1
178
+
179
+ if not vectors:
180
+ break
181
+
182
+ centroid = vectors[0]
183
+ shard = SubstrateShard(shard_id=shard_id, domain=domain, centroid=centroid, vectors=vectors)
184
+ substrate.add_shard(shard)
185
+
186
+ return substrate
187
+
188
+
189
+ def bench_retrieval(
190
+ *,
191
+ total_vectors: int,
192
+ shard_size: int,
193
+ top_k: int,
194
+ warmup: int,
195
+ runs: int,
196
+ seed: int,
197
+ ) -> None:
198
+ substrate = _build_sharded_substrate(total_vectors=total_vectors, shard_size=shard_size, seed=seed)
199
+ q_seed = hashlib.blake2b(f"bench_retrieval_query|{seed}".encode("utf-8"), digest_size=16).digest()
200
+
201
+ # Fixed query; force domain selection deterministically via domain_hash % 3.
202
+ qx = uniform(q_seed, 0, -1.0, 1.0)
203
+ qy = uniform(q_seed, 1, -1.0, 1.0)
204
+ query = CompactVector(x=float(qx), y=float(qy), shard_id=-1, domain_hash=0)
205
+
206
+ for _ in range(warmup):
207
+ substrate.retrieve_relevant_shards(query_vector=query, top_k=top_k)
208
+
209
+ samples_ns: list[int] = []
210
+ for _ in range(runs):
211
+ t0 = time.perf_counter_ns()
212
+ substrate.retrieve_relevant_shards(query_vector=query, top_k=top_k)
213
+ t1 = time.perf_counter_ns()
214
+ samples_ns.append(t1 - t0)
215
+
216
+ summary = _summarize_ns(samples_ns)
217
+ mean_ms = _fmt_ms(statistics.mean(samples_ns))
218
+ print(
219
+ f"shard_retrieve,{total_vectors},{shard_size},{top_k},{warmup},{runs},"
220
+ f"{summary.p50_ms:.6f},{summary.p95_ms:.6f},{summary.p99_ms:.6f},{mean_ms:.6f}"
221
+ )
222
+
223
+
224
+ def main(argv: list[str]) -> int:
225
+ parser = argparse.ArgumentParser(add_help=True)
226
+ sub = parser.add_subparsers(dest="cmd", required=True)
227
+
228
+ p_engine = sub.add_parser("engine")
229
+ p_engine.add_argument("--candidates", type=int, nargs="+", default=[4, 16, 64])
230
+ p_engine.add_argument("--steps", type=int, nargs="+", default=[8, 16])
231
+ p_engine.add_argument("--active-substrate-states", type=int, nargs="+", default=[3, 64, 256])
232
+ p_engine.add_argument("--warmup", type=int, default=50)
233
+ p_engine.add_argument("--runs", type=int, default=500)
234
+ p_engine.add_argument("--seed", type=int, default=0)
235
+
236
+ p_ret = sub.add_parser("retrieval")
237
+ p_ret.add_argument("--total-vectors", type=int, nargs="+", default=[4096, 65536, 262144])
238
+ p_ret.add_argument("--shard-size", type=int, default=64)
239
+ p_ret.add_argument("--top-k", type=int, default=8)
240
+ p_ret.add_argument("--warmup", type=int, default=200)
241
+ p_ret.add_argument("--runs", type=int, default=2000)
242
+ p_ret.add_argument("--seed", type=int, default=0)
243
+
244
+ args = parser.parse_args(argv[1:])
245
+
246
+ if args.cmd == "engine":
247
+ _print_engine_header()
248
+ for cand in args.candidates:
249
+ for steps in args.steps:
250
+ for sub_states in args.active_substrate_states:
251
+ bench_engine(
252
+ candidates=cand,
253
+ steps=steps,
254
+ active_substrate_states=sub_states,
255
+ warmup=args.warmup,
256
+ runs=args.runs,
257
+ seed=args.seed,
258
+ )
259
+ return 0
260
+
261
+ if args.cmd == "retrieval":
262
+ _print_retrieval_header()
263
+ for total in args.total_vectors:
264
+ bench_retrieval(
265
+ total_vectors=total,
266
+ shard_size=args.shard_size,
267
+ top_k=args.top_k,
268
+ warmup=args.warmup,
269
+ runs=args.runs,
270
+ seed=args.seed,
271
+ )
272
+ return 0
273
+
274
+ return 2
275
+
276
+
277
+ if __name__ == "__main__":
278
+ raise SystemExit(main(argv=list(__import__("sys").argv)))
compare_elastic_modes.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Comparison Demo: Direction-Only vs. Composite Elastic Modulus
4
+
5
+ This script demonstrates the behavioral differences between different
6
+ elastic modulus computation modes:
7
+ 1. Cosine: Direction-only scalar (distance does not reduce E)
8
+ 2. Multiplicative: Composite scalar (alignment × proximity)
9
+ 3. RBF: Proximity-only scalar (direction ignored)
10
+
11
+ Shows how kernel choice changes exclusion behavior under the same candidates.
12
+ """
13
+
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ # Avoid Windows console UnicodeEncodeError for optional fancy output.
18
+ if hasattr(sys.stdout, "reconfigure"):
19
+ try:
20
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
21
+ except Exception:
22
+ pass
23
+
24
+ # Add parent directory to path for imports
25
+ sys.path.insert(0, str(Path(__file__).parent))
26
+
27
+ from material_field_engine import (
28
+ VerifiedSubstrate, Vector2D, MaterialFieldEngine, PhaseTransitionController
29
+ )
30
+
31
+
32
+ def print_section_header(title):
33
+ print("\n" + "=" * 80)
34
+ print(f" {title}")
35
+ print("=" * 80)
36
+
37
+
38
+ def print_candidate_properties(vectors, title="Candidate Properties"):
39
+ print(f"\n{title}:")
40
+ print(f"{'Vector':<20} | {'Distance':<10} | {'E':<8} | {'σ_y':<8} | {'ε':<8}")
41
+ print("-" * 70)
42
+ for i, v in enumerate(vectors):
43
+ # Compute distance from substrate (assume substrate is at origin for display)
44
+ dist = (v.x**2 + v.y**2)**0.5
45
+ print(f"({v.x:.3f}, {v.y:.3f}){'':>6} | "
46
+ f"{dist:<10.4f} | "
47
+ f"{v.properties.elastic_modulus:<8.4f} | "
48
+ f"{v.properties.yield_strength:<8.4f} | "
49
+ f"{v.properties.strain:<8.4f}")
50
+
51
+
52
+ def run_comparison_scenario(scenario_name, substrate_positions, candidate_positions,
53
+ lambda_min=0.30, lambda_max=0.90, total_steps=8):
54
+ """
55
+ Run the same scenario with different elastic modulus modes and compare results.
56
+ """
57
+ print_section_header(f"SCENARIO: {scenario_name}")
58
+
59
+ modes = [
60
+ ('cosine', None, "Pure Angular Alignment"),
61
+ ('multiplicative', 0.3, "Multiplicative (σ=0.3, tight binding)"),
62
+ ('multiplicative', 0.5, "Multiplicative (σ=0.5, balanced)"),
63
+ ('multiplicative', 0.8, "Multiplicative (σ=0.8, loose binding)"),
64
+ ('rbf', 0.5, "Pure Proximity (RBF, σ=0.5)")
65
+ ]
66
+
67
+ results_summary = []
68
+
69
+ for mode, sigma, description in modes:
70
+ print(f"\n{'-' * 80}")
71
+ print(f"MODE: {description}")
72
+ print(f"{'-' * 80}")
73
+
74
+ # Create substrate with this mode
75
+ if sigma is None:
76
+ substrate = VerifiedSubstrate(elastic_modulus_mode=mode)
77
+ else:
78
+ substrate = VerifiedSubstrate(elastic_modulus_mode=mode,
79
+ elastic_modulus_sigma=sigma)
80
+
81
+ # Add substrate states
82
+ for pos in substrate_positions:
83
+ substrate.add_verified_state(Vector2D(x=pos[0], y=pos[1], properties=None))
84
+
85
+ # Create engine
86
+ engine = MaterialFieldEngine(substrate, lambda_min, lambda_max, total_steps)
87
+
88
+ # Initialize candidates
89
+ engine.initialize_candidates(candidate_positions)
90
+
91
+ # Print initial properties
92
+ print_candidate_properties(engine.candidate_vectors, "Initial Properties")
93
+
94
+ # Run inference
95
+ results = engine.run_inference()
96
+
97
+ # Print results
98
+ print(f"\nResults:")
99
+ print(f" Final Output: ", end="")
100
+ if results['final_output']:
101
+ print(f"({results['final_output'].x:.3f}, {results['final_output'].y:.3f})")
102
+ print(f" Final E: {results['final_output'].properties.elastic_modulus:.4f}")
103
+ else:
104
+ print("ABSTAINED (no surviving candidates)")
105
+ print(f" Total Excluded: {results['total_excluded']}")
106
+
107
+ # Store summary
108
+ results_summary.append({
109
+ 'mode': description,
110
+ 'output': results['final_output'],
111
+ 'excluded': results['total_excluded'],
112
+ 'abstained': results['abstained']
113
+ })
114
+
115
+ # Print comparison summary
116
+ print_section_header("COMPARISON SUMMARY")
117
+ print(f"\n{'Mode':<45} | {'Output':<20} | {'Excluded':<10}")
118
+ print("-" * 80)
119
+ for summary in results_summary:
120
+ if summary['output']:
121
+ output_str = f"({summary['output'].x:.3f}, {summary['output'].y:.3f})"
122
+ else:
123
+ output_str = "ABSTAINED"
124
+ print(f"{summary['mode']:<45} | {output_str:<20} | {summary['excluded']:<10}")
125
+
126
+
127
+ def scenario_1_aligned_near_far():
128
+ """
129
+ Scenario 1: Multiple aligned candidates at different distances
130
+
131
+ Tests whether distance affects selection when all candidates point in same direction.
132
+ """
133
+ substrate_positions = [
134
+ (0.95, 0.92) # Single verified state
135
+ ]
136
+
137
+ candidate_positions = [
138
+ (0.95, 0.92), # Exact match - distance 0
139
+ (0.85, 0.82), # Very close, aligned - distance ≈0.14
140
+ (0.50, 0.50), # Medium distance, aligned - distance ≈0.62
141
+ (0.35, 0.30), # Far, aligned - distance ≈0.86
142
+ (0.10, 0.10), # Very far, aligned - distance ≈1.18
143
+ ]
144
+
145
+ run_comparison_scenario(
146
+ "Aligned Candidates at Different Distances",
147
+ substrate_positions,
148
+ candidate_positions
149
+ )
150
+
151
+
152
+ def scenario_2_aligned_vs_close():
153
+ """
154
+ Scenario 2: Aligned-but-far vs. Close-but-misaligned
155
+
156
+ Tests the trade-off between angular alignment and proximity.
157
+ """
158
+ substrate_positions = [
159
+ (1.0, 0.0) # Substrate on positive X-axis
160
+ ]
161
+
162
+ candidate_positions = [
163
+ (0.95, 0.0), # Very close and aligned (distance ≈0.05)
164
+ (0.80, 0.40), # Close but misaligned (distance ≈0.29, angle ≈26°)
165
+ (0.50, 0.50), # Medium distance, 45° angle (distance ≈0.71)
166
+ (0.20, 0.80), # Far and misaligned (distance ≈1.13, angle ≈76°)
167
+ ]
168
+
169
+ run_comparison_scenario(
170
+ "Aligned vs. Close Trade-off",
171
+ substrate_positions,
172
+ candidate_positions
173
+ )
174
+
175
+
176
+ def scenario_3_multiple_substrate_states():
177
+ """
178
+ Scenario 3: Multiple substrate states (cluster)
179
+
180
+ Tests behavior when substrate forms a semantic cluster.
181
+ """
182
+ substrate_positions = [
183
+ (0.90, 0.85),
184
+ (0.88, 0.92),
185
+ (0.95, 0.88)
186
+ ]
187
+
188
+ candidate_positions = [
189
+ (0.91, 0.88), # Center of cluster
190
+ (0.70, 0.70), # Medium distance
191
+ (0.50, 0.50), # Far from cluster
192
+ (0.10, 0.10), # Very far
193
+ ]
194
+
195
+ run_comparison_scenario(
196
+ "Multiple Substrate States (Cluster)",
197
+ substrate_positions,
198
+ candidate_positions
199
+ )
200
+
201
+
202
+ def scenario_4_noise_filtering():
203
+ """
204
+ Scenario 4: Real signal vs. Noise
205
+
206
+ One grounded candidate vs. multiple noise candidates.
207
+ """
208
+ substrate_positions = [
209
+ (0.88, 0.85) # Verified obstacle pattern
210
+ ]
211
+
212
+ candidate_positions = [
213
+ (0.88, 0.83), # Real obstacle (very close match)
214
+ (0.15, 0.12), # Sensor noise (far, low confidence)
215
+ (0.22, 0.18), # More sensor noise
216
+ (0.08, 0.25), # More sensor noise
217
+ ]
218
+
219
+ run_comparison_scenario(
220
+ "Real Signal vs. Noise Filtering",
221
+ substrate_positions,
222
+ candidate_positions,
223
+ lambda_min=0.25,
224
+ lambda_max=0.95,
225
+ total_steps=8
226
+ )
227
+
228
+
229
+ if __name__ == "__main__":
230
+ print("""
231
+ ╔══════════════════════════════════════════════════════════════════════════════╗
232
+ ║ ║
233
+ ║ ELASTIC MODULUS MODE COMPARISON: Cosine vs. Distance-Aware ║
234
+ ║ ║
235
+ ║ This demo shows how different E computation modes affect which candidates ║
236
+ ║ survive phase transitions and become final outputs. ║
237
+ ║ ║
238
+ ╚══════════════════════════════════════════════════════════════════════════════╝
239
+ """)
240
+
241
+ # Run all scenarios
242
+ scenario_1_aligned_near_far()
243
+ print("\n\n")
244
+
245
+ scenario_2_aligned_vs_close()
246
+ print("\n\n")
247
+
248
+ scenario_3_multiple_substrate_states()
249
+ print("\n\n")
250
+
251
+ scenario_4_noise_filtering()
252
+
253
+ # Final guidance
254
+ print_section_header("INTERPRETATION GUIDE")
255
+ print("""
256
+ Key Observations:
257
+
258
+ 1. COSINE MODE (Direction-Only):
259
+ - E is a function of alignment only.
260
+ - Distance/magnitude does not reduce E.
261
+ - Exclusion pressure is applied against σ_y, with strain/stress carrying the distance signal.
262
+
263
+ 2. MULTIPLICATIVE MODE (Composite / Gated):
264
+ - E is computed as (alignment_term × proximity_term).
265
+ - This composes alignment and distance into a single scalar gate.
266
+ - σ is the proximity bandwidth; smaller σ contracts the effective binding radius.
267
+
268
+ 3. RBF MODE (Proximity-Only):
269
+ - E is a function of distance only.
270
+ - Direction does not contribute to E.
271
+
272
+ Example parameterizations (explicit, recorded in the run config):
273
+ - Multiplicative σ=0.30
274
+ - Multiplicative σ=0.50
275
+ - Multiplicative σ=0.80
276
+ """)
277
+
278
+ print("\n" + "=" * 80)
279
+ print("Configuration: Edit config.json 'elastic_modulus' section to set mode/sigma")
280
+ print("=" * 80)
config.json ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "comment": "Material-Field Governance Timing Configuration",
3
+ "elastic_modulus": {
4
+ "mode": "multiplicative",
5
+ "sigma": 0.5,
6
+ "comment": "Modes: 'cosine' (angular only), 'multiplicative' (angle×proximity), 'rbf' (proximity only)"
7
+ },
8
+ "constraint_pressure": {
9
+ "lambda_min": 0.40,
10
+ "lambda_max": 1.20,
11
+ "comment": "λ_max can exceed 1.0 for aggressive crystallization"
12
+ },
13
+ "phase_transitions": {
14
+ "nucleation_threshold": 0.40,
15
+ "quenching_threshold": 0.80,
16
+ "comment": "Phase boundaries as fraction of total time (0.0 to 1.0)"
17
+ },
18
+ "inference": {
19
+ "total_steps": 8,
20
+ "comment": "Number of inference steps for phase progression"
21
+ },
22
+ "presets": {
23
+ "conservative": {
24
+ "lambda_min": 0.25,
25
+ "lambda_max": 0.90,
26
+ "nucleation_threshold": 0.50,
27
+ "quenching_threshold": 0.90,
28
+ "total_steps": 12,
29
+ "elastic_modulus_mode": "multiplicative",
30
+ "elastic_modulus_sigma": 0.3,
31
+ "comment": "Tight binding for verified facts"
32
+ },
33
+ "balanced": {
34
+ "lambda_min": 0.40,
35
+ "lambda_max": 1.20,
36
+ "nucleation_threshold": 0.40,
37
+ "quenching_threshold": 0.80,
38
+ "total_steps": 8,
39
+ "elastic_modulus_mode": "multiplicative",
40
+ "elastic_modulus_sigma": 0.5,
41
+ "comment": "Balanced alignment and proximity"
42
+ },
43
+ "aggressive": {
44
+ "lambda_min": 0.50,
45
+ "lambda_max": 1.50,
46
+ "nucleation_threshold": 0.30,
47
+ "quenching_threshold": 0.70,
48
+ "total_steps": 6,
49
+ "elastic_modulus_mode": "multiplicative",
50
+ "elastic_modulus_sigma": 0.8,
51
+ "comment": "Loose binding for creative/exploratory"
52
+ },
53
+ "mission_critical": {
54
+ "lambda_min": 0.60,
55
+ "lambda_max": 2.00,
56
+ "nucleation_threshold": 0.25,
57
+ "quenching_threshold": 0.65,
58
+ "total_steps": 8,
59
+ "elastic_modulus_mode": "multiplicative",
60
+ "elastic_modulus_sigma": 0.25,
61
+ "comment": "Maximum exclusion pressure + very tight binding for safety-critical systems"
62
+ },
63
+ "forgiving": {
64
+ "lambda_min": 0.30,
65
+ "lambda_max": 0.90,
66
+ "nucleation_threshold": 0.50,
67
+ "quenching_threshold": 0.85,
68
+ "total_steps": 10,
69
+ "elastic_modulus_mode": "multiplicative",
70
+ "elastic_modulus_sigma": 0.65,
71
+ "comment": "Tolerates ambiguity and creative drift"
72
+ }
73
+ }
74
+ }
demo_gui_dev.py ADDED
@@ -0,0 +1,1217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Deterministic Exclusion Demo GUI (Development Build)
4
+ FastAPI + Streamlit implementation for rapid prototyping
5
+
6
+ Usage:
7
+ streamlit run demo_gui_dev.py
8
+ """
9
+
10
+ try:
11
+ import streamlit as st
12
+ import plotly.graph_objects as go
13
+ import plotly.express as px
14
+ except ModuleNotFoundError as exc:
15
+ missing = str(exc).split("No module named ", 1)[-1].strip("'\"")
16
+ print(f"Missing optional GUI dependency: {missing}")
17
+ print("Install GUI deps: python -m pip install -r requirements-gui.txt")
18
+ print("Run the GUI via: streamlit run demo_gui_dev.py")
19
+ raise SystemExit(2)
20
+
21
+ try:
22
+ from streamlit.runtime.scriptrunner.script_run_context import get_script_run_ctx
23
+ except Exception:
24
+ get_script_run_ctx = None
25
+
26
+ if get_script_run_ctx is not None and get_script_run_ctx() is None:
27
+ print("This file is a Streamlit app and must be run with Streamlit:")
28
+ print(" streamlit run demo_gui_dev.py")
29
+ raise SystemExit(2)
30
+ import time
31
+ import hashlib
32
+ import json
33
+ from pathlib import Path
34
+ from collections import deque
35
+ from typing import List, Dict, Optional, Any, Tuple
36
+
37
+ # Import engine components
38
+ import sys
39
+ sys.path.insert(0, str(Path(__file__).parent))
40
+
41
+ from material_field_engine import (
42
+ VerifiedSubstrate, Vector2D, MaterialFieldEngine, fp_from_float, fp_to_float, load_config
43
+ )
44
+ from exclusion_demo import run_deterministic_exclusion_demo
45
+
46
+ @st.cache_data
47
+ def compute_substrate_embeddings_2d(substrate_list: List[str]) -> List[List[float]]:
48
+ """Cached 2D embedding for material field visualization."""
49
+ from llm_adapter import DeterministicHashEmbedderND
50
+ embedder = DeterministicHashEmbedderND(dim=2)
51
+ return [embedder.embed(t) for t in substrate_list]
52
+
53
+ @st.cache_data
54
+ def compute_substrate_embeddings_highd(substrate_list: List[str]) -> List[List[float]]:
55
+ """Cached 16D embedding for physics engine logic."""
56
+ from llm_adapter import DeterministicHashEmbedderND
57
+ embedder = DeterministicHashEmbedderND(dim=16)
58
+ return [embedder.embed(t) for t in substrate_list]
59
+
60
+
61
+ # ============================================================================
62
+ # Streamlit Page Configuration
63
+ # ============================================================================
64
+
65
+ st.set_page_config(
66
+ page_title="Deterministic Exclusion Demo",
67
+ layout="wide",
68
+ initial_sidebar_state="expanded"
69
+ )
70
+
71
+ # Custom CSS for monospace hash display
72
+ st.markdown("""
73
+ <style>
74
+ .hash-display {
75
+ font-family: 'Courier New', monospace;
76
+ font-size: 14px;
77
+ background-color: #1e1e1e;
78
+ color: #00ff00;
79
+ padding: 10px;
80
+ border-radius: 5px;
81
+ word-break: break-all;
82
+ }
83
+ </style>
84
+ """, unsafe_allow_html=True)
85
+
86
+
87
+ # ============================================================================
88
+ # Session State Initialization
89
+ # ============================================================================
90
+
91
+ if 'results' not in st.session_state:
92
+ st.session_state.results = None
93
+ if 'config' not in st.session_state:
94
+ st.session_state.config = {
95
+ 'elastic_modulus_mode': 'multiplicative',
96
+ 'elastic_modulus_sigma': 0.4,
97
+ 'lambda_min': 0.35,
98
+ 'lambda_max': 1.20,
99
+ 'inference_steps': 8
100
+ }
101
+ if 'audit_log' not in st.session_state:
102
+ st.session_state.audit_log = deque(maxlen=100)
103
+
104
+
105
+ # ============================================================================
106
+ # Header
107
+ # ============================================================================
108
+
109
+ st.title("Deterministic Exclusion Demo")
110
+ st.markdown("Material-Field Engine GUI")
111
+ st.markdown("---")
112
+
113
+
114
+ # ============================================================================
115
+ # Sidebar: Configuration Panel
116
+ # ============================================================================
117
+
118
+ st.sidebar.header("Configuration")
119
+
120
+ # Elastic Modulus Mode
121
+ mode = st.sidebar.selectbox(
122
+ "Elastic Modulus Mode",
123
+ options=['cosine', 'multiplicative', 'rbf'],
124
+ index=1, # Default: multiplicative
125
+ help="Cosine: direction only | Multiplicative: angle×proximity | RBF: proximity only"
126
+ )
127
+
128
+ # Sigma parameter
129
+ sigma = st.sidebar.slider(
130
+ "Sigma (σ) - Field Extent",
131
+ min_value=0.2,
132
+ max_value=1.0,
133
+ value=0.4,
134
+ step=0.05,
135
+ help="Lower = tighter binding, higher = looser binding"
136
+ )
137
+
138
+ st.sidebar.markdown(f"**Current: σ={sigma:.2f}**")
139
+
140
+ # Lambda max
141
+ lambda_max = st.sidebar.slider(
142
+ "Lambda Max (lambda_max) - Max Pressure",
143
+ min_value=0.5,
144
+ max_value=2.0,
145
+ value=1.2,
146
+ step=0.1,
147
+ help="Higher = stricter exclusion"
148
+ )
149
+
150
+
151
+ st.sidebar.markdown("---")
152
+
153
+ # Run button
154
+ if st.sidebar.button("Run Deterministic Exclusion Demo", type="primary"):
155
+ with st.spinner("Running inference..."):
156
+ # Update config
157
+ st.session_state.config['elastic_modulus_mode'] = mode
158
+ st.session_state.config['elastic_modulus_sigma'] = sigma
159
+ st.session_state.config['lambda_max'] = lambda_max
160
+
161
+ # Run test
162
+ results = run_deterministic_exclusion_demo(
163
+ elastic_modulus_mode=mode,
164
+ sigma=sigma,
165
+ print_banner=False,
166
+ )
167
+
168
+ st.session_state.results = results
169
+
170
+ # Log event
171
+ st.session_state.audit_log.append({
172
+ 'timestamp': time.time(),
173
+ 'operation': 'run_inference',
174
+ 'mode': mode,
175
+ 'sigma': sigma,
176
+ 'hash': results['hash']
177
+ })
178
+
179
+ st.success("Inference complete.")
180
+
181
+
182
+ # ============================================================================
183
+ # Main Content Area
184
+ # ============================================================================
185
+
186
+
187
+ # Create tabs
188
+ tab1, tab2, tab3, tab4 = st.tabs(["Mechanism Demo", "LLM Guardrail", "Live LLM Testing", "Explain & Tune"])
189
+
190
+ # ----------------------------------------------------------------------------
191
+ # TAB 1: Mechanism Demo (Original)
192
+ # ----------------------------------------------------------------------------
193
+ with tab1:
194
+ if st.session_state.results is None:
195
+ st.info("Configure parameters in the sidebar and click 'Run Deterministic Exclusion Demo'.")
196
+ else:
197
+ results = st.session_state.results
198
+
199
+ # Row 1: Deterministic Audit Trail
200
+ st.header("Deterministic Audit Trail")
201
+ col1, col2 = st.columns([2, 1])
202
+ with col1:
203
+ st.subheader("SHA-256")
204
+ st.markdown(f'<div class="hash-display">{results["hash"]}</div>', unsafe_allow_html=True)
205
+ with col2:
206
+ st.metric("Total Excluded", results["excluded"])
207
+
208
+ # Row 2: Abstention Indicator
209
+ st.header("Outcome Verification")
210
+ if results.get("winner_index") is None:
211
+ st.error("Abstained")
212
+ else:
213
+ st.success(f"Winner index: {results['winner_index']}")
214
+ st.caption("Expected winner: Candidate 0 | Expected excluded: 3")
215
+
216
+ # Row 3: Phase Log
217
+ st.header("Phase Log")
218
+ phase_log = results['phase_log']
219
+ import pandas as pd
220
+ df = pd.DataFrame(phase_log)
221
+ st.dataframe(df[['step', 'phase', 'pressure', 'survivors', 'excluded']], use_container_width=True, hide_index=True)
222
+
223
+ # Visualization
224
+ fig = go.Figure()
225
+ fig.add_trace(go.Scatter(
226
+ x=[e['step'] for e in phase_log],
227
+ y=[e['pressure'] for e in phase_log],
228
+ mode='lines+markers',
229
+ name='Pressure lambda(t)',
230
+ line=dict(color='cyan', width=3)
231
+ ))
232
+ st.plotly_chart(fig, use_container_width=True)
233
+
234
+
235
+ # Row 5: Audit Log
236
+ st.header("Run Log")
237
+ if st.session_state.audit_log:
238
+ log_df = pd.DataFrame(st.session_state.audit_log)
239
+ log_df['timestamp'] = pd.to_datetime(log_df['timestamp'], unit='s')
240
+ st.dataframe(log_df[['timestamp', 'operation', 'mode', 'sigma', 'hash']], use_container_width=True, hide_index=True)
241
+
242
+
243
+ # ----------------------------------------------------------------------------
244
+ # TAB 2: LLM Guardrail Playground (New)
245
+ # ----------------------------------------------------------------------------
246
+ with tab2:
247
+ st.header("Deterministic LLM Filter")
248
+ st.markdown("""
249
+ A model-agnostic post-processor that evaluates candidate outputs against a verified substrate.
250
+ The mechanism deterministically accepts, rejects, or abstains based on explicit constraints.
251
+ """)
252
+
253
+ col_input1, col_input2 = st.columns(2)
254
+
255
+ with col_input1:
256
+ st.subheader("1. Verified Substrate")
257
+ st.markdown("Approved facts (Ground Truth). One per line.")
258
+ substrate_input = st.text_area(
259
+ "Substrate",
260
+ value="The sky is blue\nWater is wet\nParis is capital of France",
261
+ height=200,
262
+ key="llm_substrate"
263
+ )
264
+
265
+ with col_input2:
266
+ st.subheader("2. LLM Candidates")
267
+ st.markdown("Generated responses (including hallucinations). One per line.")
268
+ candidates_input = st.text_area(
269
+ "Candidates",
270
+ value="The sky is blue\nThe sky is green\nThe sky is made of cheese",
271
+ height=200,
272
+ key="llm_candidates"
273
+ )
274
+
275
+ # Add full trace checkbox
276
+ show_full_trace = st.checkbox(
277
+ "Show full stress evolution (all steps for all candidates)",
278
+ value=False,
279
+ help="Disable for faster UI with large candidate sets"
280
+ )
281
+
282
+ if st.button("Run Guardrail Filter", type="primary"):
283
+ from llm_adapter import DeterministicGuardrail, DeterministicHashEmbedderND
284
+ import math
285
+
286
+ # Parse inputs
287
+ substrate_list = [line.strip() for line in substrate_input.split('\n') if line.strip()]
288
+ candidate_list = [line.strip() for line in candidates_input.split('\n') if line.strip()]
289
+
290
+ if not substrate_list or not candidate_list:
291
+ st.error("Please provide both substrate and candidates.")
292
+ else:
293
+ with st.spinner("Projecting to material field..."):
294
+ # Initialize Guardrail
295
+ # Use current sidebar config instead of hardcoded preset
296
+ guard = DeterministicGuardrail(
297
+ substrate_texts=substrate_list,
298
+ config_preset='balanced' # Starting point
299
+ )
300
+ # Overwrite with current sidebar settings for consistency
301
+ guard.config['elastic_modulus_mode'] = st.session_state.config['elastic_modulus_mode']
302
+ guard.config['elastic_modulus_sigma'] = st.session_state.config['elastic_modulus_sigma']
303
+ guard.config['lambda_max'] = st.session_state.config['lambda_max']
304
+
305
+ # We want to INSPECT, not just filter
306
+ inspection = guard.inspect(candidate_list)
307
+
308
+ result_text = inspection['selected_text']
309
+ metrics = inspection['metrics']
310
+ candidate_metrics = metrics.get('candidates')
311
+ if candidate_metrics is None:
312
+ candidate_metrics = [
313
+ {
314
+ 'phase_log': [],
315
+ 'fractured': False,
316
+ 'fractured_step': None,
317
+ 'stress': 0.0,
318
+ 'hash': 'N/A',
319
+ }
320
+ for _ in candidate_list
321
+ ]
322
+
323
+ # Build detailed numbers view (high-D physics + 2D projection for plot)
324
+ with st.spinner("Computing embeddings..."):
325
+ # Use specialized caches for different dimensionality needs
326
+ sub_vecs = compute_substrate_embeddings_highd(substrate_list)
327
+ sub_vecs_2d = compute_substrate_embeddings_2d(substrate_list)
328
+
329
+ from llm_adapter import DeterministicHashEmbedderND
330
+ embedder_highd = DeterministicHashEmbedderND(dim=16)
331
+ cand_vecs = [embedder_highd.embed(t) for t in candidate_list]
332
+
333
+ # Use 2D for visualization
334
+ embedder_2d = DeterministicHashEmbedderND(dim=2)
335
+ cand_vecs_2d = [embedder_2d.embed(t) for t in candidate_list]
336
+
337
+
338
+
339
+ def cosine_similarity(v1, v2):
340
+ """Cosine similarity between N-D vectors."""
341
+ dot = sum(a * b for a, b in zip(v1, v2))
342
+ mag1 = math.sqrt(sum(a * a for a in v1))
343
+ mag2 = math.sqrt(sum(b * b for b in v2))
344
+ if mag1 == 0 or mag2 == 0:
345
+ return 0.0
346
+ return dot / (mag1 * mag2)
347
+
348
+ def euclidean_distance(v1, v2):
349
+ """Euclidean distance between N-D vectors."""
350
+ return math.sqrt(sum((a - b) ** 2 for a, b in zip(v1, v2)))
351
+
352
+ numbers_view = {
353
+ "embedder": {
354
+ "name": "DeterministicHashEmbedderND",
355
+ "definition": "sha256(text) -> 16D in [0,1], projected to 2D for plotting",
356
+ },
357
+ "substrate": [
358
+ {"text": t, "vec2": [round(v[0], 8), round(v[1], 8)]}
359
+ for t, v in zip(substrate_list, sub_vecs_2d)
360
+ ],
361
+ "candidates": []
362
+ }
363
+
364
+ # For each candidate, compute detailed metrics
365
+ for i, (cand_vec, cand_text) in enumerate(zip(cand_vecs, candidate_list)):
366
+ # Compute alignment and distance to each substrate point
367
+ per_substrate = []
368
+ best_alignment = -1
369
+ best_distance = float('inf')
370
+ best_j = None
371
+
372
+ for j, sub_vec in enumerate(sub_vecs):
373
+ cos_sim = cosine_similarity(cand_vec, sub_vec)
374
+ alignment = (cos_sim + 1.0) / 2.0 # Normalize to [0,1]
375
+ dist = euclidean_distance(cand_vec, sub_vec)
376
+
377
+ per_substrate.append({
378
+ "substrate_index": j,
379
+ "substrate_text": substrate_list[j],
380
+ "cosine_similarity": round(cos_sim, 8),
381
+ "alignment_0_1": round(alignment, 8),
382
+ "euclidean_distance": round(dist, 8),
383
+ })
384
+
385
+ # Selection rule: highest alignment
386
+ if alignment > best_alignment:
387
+ best_alignment = alignment
388
+ best_distance = dist
389
+ best_j = j
390
+
391
+ # Get engine results for this candidate
392
+ cand_metrics = candidate_metrics[i]
393
+ phase_log = cand_metrics.get('phase_log', [])
394
+
395
+ # Build stress evolution - full or abbreviated
396
+ if show_full_trace:
397
+ stress_evolution = [
398
+ {
399
+ "step": entry["step"],
400
+ "phase": entry["phase"],
401
+ "lambda": round(entry["pressure"], 8),
402
+ "elastic_modulus_E": round(entry.get("elastic_modulus", 0.0), 8),
403
+ "delta_stress": round(entry.get("delta_stress", 0.0), 8),
404
+ "cumulative_stress": round(entry["stress"], 8),
405
+ "fractured": entry["fractured"]
406
+ }
407
+ for entry in phase_log
408
+ ]
409
+ else:
410
+ # Abbreviated: first 2 steps, fracture step (if any), last step
411
+ abbreviated = []
412
+
413
+ if len(phase_log) > 0:
414
+ abbreviated.append(phase_log[0])
415
+ if len(phase_log) > 1:
416
+ abbreviated.append(phase_log[1])
417
+
418
+ fracture_step = cand_metrics.get('fractured_step')
419
+ if fracture_step is not None and fracture_step > 1:
420
+ abbreviated.append(phase_log[fracture_step])
421
+ elif len(phase_log) > 2:
422
+ abbreviated.append(phase_log[-1])
423
+
424
+ stress_evolution = [
425
+ {
426
+ "step": entry["step"],
427
+ "phase": entry["phase"],
428
+ "lambda": round(entry["pressure"], 8),
429
+ "elastic_modulus_E": round(entry.get("elastic_modulus", 0.0), 8),
430
+ "delta_stress": round(entry.get("delta_stress", 0.0), 8),
431
+ "cumulative_stress": round(entry["stress"], 8),
432
+ "fractured": entry["fractured"]
433
+ }
434
+ for entry in abbreviated
435
+ ]
436
+
437
+ if len(phase_log) > len(abbreviated):
438
+ stress_evolution.append({
439
+ "note": f"...{len(phase_log) - len(abbreviated)} intermediate steps omitted (enable 'Show full stress evolution' to see all)"
440
+ })
441
+
442
+ numbers_view["candidates"].append({
443
+ "candidate_index": i,
444
+ "text": cand_text,
445
+ "vec2": [round(cand_vecs_2d[i][0], 8), round(cand_vecs_2d[i][1], 8)],
446
+ "comparisons": per_substrate,
447
+ "selection_rule": "highest_alignment",
448
+ "selected_by_alignment": {
449
+ "substrate_index": best_j,
450
+ "substrate_text": substrate_list[best_j] if best_j is not None else None,
451
+ "alignment_0_1": round(best_alignment, 8),
452
+ "euclidean_distance": round(float(best_distance), 8),
453
+ },
454
+ "engine": {
455
+ "fractured": cand_metrics.get('fractured', False),
456
+ "fractured_step": cand_metrics.get('fractured_step'),
457
+ "final_stress": round(float(cand_metrics['stress']), 8),
458
+ "hash": cand_metrics.get('hash', 'N/A'),
459
+ "stress_evolution": stress_evolution
460
+ }
461
+ })
462
+
463
+ # Display Result
464
+ st.markdown("### Result")
465
+ if result_text:
466
+ st.success(f"**Selected:** {result_text}")
467
+ else:
468
+ st.warning("**Abstained**: No candidates met the yield strength requirements.")
469
+
470
+ # Visualization of the Field
471
+ st.markdown("### Material Field Projection")
472
+
473
+ # Plot
474
+ fig_map = go.Figure()
475
+
476
+ # Plot Substrate (Green Squares)
477
+ fig_map.add_trace(go.Scatter(
478
+ x=[v[0] for v in sub_vecs_2d],
479
+ y=[v[1] for v in sub_vecs_2d],
480
+ mode='markers',
481
+ name='Substrate (Facts)',
482
+ text=substrate_list,
483
+ marker=dict(symbol='square', size=12, color='green')
484
+ ))
485
+
486
+ # Plot Candidates (Red Circles)
487
+ # Differentiate selected vs excluded
488
+ selected_idx = metrics['final_output'].candidate_index if metrics['final_output'] else -1
489
+
490
+ colors = ['gold' if i == selected_idx else 'red' for i in range(len(cand_vecs))]
491
+ sizes = [15 if i == selected_idx else 10 for i in range(len(cand_vecs))]
492
+
493
+ fig_map.add_trace(go.Scatter(
494
+ x=[v[0] for v in cand_vecs_2d],
495
+ y=[v[1] for v in cand_vecs_2d],
496
+ mode='markers+text',
497
+ name='Candidates',
498
+ text=candidate_list,
499
+ textposition='top center',
500
+ marker=dict(symbol='circle', size=sizes, color=colors)
501
+ ))
502
+
503
+ fig_map.update_layout(
504
+ title="Semantic Material Field (2D Mock Projection)",
505
+ xaxis_title="Dimension X",
506
+ yaxis_title="Dimension Y",
507
+ xaxis=dict(range=[0, 1]),
508
+ yaxis=dict(range=[0, 1]),
509
+ template="plotly_dark",
510
+ height=500
511
+ )
512
+
513
+ st.plotly_chart(fig_map, use_container_width=True)
514
+
515
+ # Metrics JSON
516
+ st.markdown("### Metrics")
517
+ metrics_json = {
518
+ "survived": result_text is not None,
519
+ "total_excluded": metrics['total_excluded'],
520
+ "falsification_pressure": f"{metrics['phase_log'][-1]['pressure']:.2f} lambda"
521
+ }
522
+ st.json(metrics_json)
523
+
524
+ # Complete Numerical Audit Trail
525
+ st.markdown("### Complete Numerical Audit Trail")
526
+ st.caption("Vectors, distances, selection rule, engine hash, stress evolution")
527
+ st.json(numbers_view)
528
+
529
+ # ----------------------------------------------------------------------------
530
+ # TAB 3: LLM Testing
531
+ # ----------------------------------------------------------------------------
532
+ with tab3:
533
+ st.header("LLM Testing")
534
+ st.markdown("""
535
+ **Live API Testing** - Test any LLM with the Deterministic Guardrail in real-time.
536
+
537
+ Supports: OpenAI, Anthropic, Google Gemini, local models (Ollama, llama.cpp, vLLM), and any OpenAI-compatible API.
538
+ """)
539
+
540
+ # API Configuration
541
+ st.subheader("1. LLM API Configuration")
542
+
543
+ col_api1, col_api2 = st.columns(2)
544
+
545
+ with col_api1:
546
+ api_preset = st.selectbox(
547
+ "Provider Preset",
548
+ options=["OpenAI", "Anthropic (Claude)", "Google (Gemini)", "Local (Ollama)", "Local (llama.cpp)", "Custom OpenAI-compatible"],
549
+ help="Select a preset or use custom for any OpenAI-compatible endpoint"
550
+ )
551
+
552
+ # Set defaults based on preset
553
+ if api_preset == "OpenAI":
554
+ default_base_url = "https://api.openai.com/v1"
555
+ default_model = "gpt-4.1-nano"
556
+ needs_key = True
557
+ elif api_preset == "Anthropic (Claude)":
558
+ default_base_url = "https://api.anthropic.com/v1"
559
+ default_model = "claude-3-5-sonnet-20241022"
560
+ needs_key = True
561
+ elif api_preset == "Google (Gemini)":
562
+ default_base_url = "https://generativelanguage.googleapis.com/v1beta"
563
+ default_model = "gemini-2.0-flash-exp"
564
+ needs_key = True
565
+ elif api_preset == "Local (Ollama)":
566
+ default_base_url = "http://localhost:11434/v1"
567
+ default_model = "llama3.1"
568
+ needs_key = False
569
+ elif api_preset == "Local (llama.cpp)":
570
+ default_base_url = "http://localhost:8080/v1"
571
+ default_model = "local-model"
572
+ needs_key = False
573
+ else:
574
+ default_base_url = "https://api.openai.com/v1"
575
+ default_model = "gpt-4.1-nano"
576
+ needs_key = True
577
+
578
+ api_base_url = st.text_input(
579
+ "Base URL",
580
+ value=default_base_url,
581
+ help="API endpoint base URL"
582
+ )
583
+
584
+ with col_api2:
585
+ api_key = st.text_input(
586
+ "API Key" + (" (optional for local)" if not needs_key else ""),
587
+ type="password",
588
+ help="Your API key (not required for local models)",
589
+ placeholder="sk-..." if needs_key else "not needed for local models"
590
+ )
591
+
592
+ model_name = st.text_input(
593
+ "Model Name",
594
+ value=default_model,
595
+ help="Model identifier"
596
+ )
597
+
598
+ col_temp, col_num = st.columns(2)
599
+ with col_temp:
600
+ temperature = st.slider("Temperature", 0.0, 2.0, 0.7, 0.1, help="Higher = more creative")
601
+ with col_num:
602
+ num_responses = st.number_input("Number of Responses", min_value=1, max_value=10, value=3, help="Generate multiple responses for comparison")
603
+
604
+ col_timeout, col_retry = st.columns(2)
605
+ with col_timeout:
606
+ request_timeout = st.number_input("Request Timeout (seconds)", min_value=5, max_value=600, value=60, step=5, help="Increase for slow or local models")
607
+ with col_retry:
608
+ max_retries = st.number_input("Max Retries", min_value=0, max_value=5, value=2, step=1, help="Automatic retries on transient failures")
609
+
610
+ # Substrate Configuration
611
+ st.subheader("2. Verified Substrate (Ground Truth)")
612
+ st.markdown("Enter verified facts that define what is correct. One per line.")
613
+ substrate_input_llm = st.text_area(
614
+ "Substrate Facts",
615
+ value="The Eiffel Tower is in Paris\nWater boils at 100°C at sea level\nPython is a programming language",
616
+ height=120,
617
+ key="llm_test_substrate"
618
+ )
619
+
620
+ # Prompt Configuration
621
+ st.subheader("3. Prompt Configuration")
622
+ col_prompt1, col_prompt2 = st.columns([3, 1])
623
+
624
+ with col_prompt1:
625
+ user_prompt = st.text_area(
626
+ "User Prompt",
627
+ value="Tell me a fact about one of the topics mentioned above.",
628
+ height=100,
629
+ help="The prompt sent to the LLM"
630
+ )
631
+
632
+ with col_prompt2:
633
+ use_system_prompt = st.checkbox("Use System Prompt", value=False)
634
+
635
+ if use_system_prompt:
636
+ system_prompt = st.text_area(
637
+ "System Prompt (optional)",
638
+ value="You are a helpful assistant. Provide accurate, factual information.",
639
+ height=100
640
+ )
641
+ else:
642
+ system_prompt = None
643
+
644
+ # Governance Configuration (Control Surface)
645
+ st.subheader("4. Governance Controls")
646
+ st.markdown("Adjust the physics strictness to see how the system responds to ambiguity vs. facts.")
647
+
648
+ gov_col1, gov_col2 = st.columns(2)
649
+ with gov_col1:
650
+ gov_preset = st.selectbox(
651
+ "Governance Preset",
652
+ ["Forgiving", "Balanced", "Conservative", "Aggressive", "Mission Critical"],
653
+ index=1,
654
+ help="Sets physics parameters (Lambda/Sigma). 'Forgiving' tolerates ambiguity; 'Mission Critical' demands exact alignment."
655
+ )
656
+ preset_map = {
657
+ "Balanced": "balanced",
658
+ "Conservative": "conservative",
659
+ "Aggressive": "aggressive",
660
+ "Mission Critical": "mission_critical",
661
+ "Forgiving": "forgiving"
662
+ }
663
+ selected_gov_preset = preset_map[gov_preset]
664
+
665
+ # Educational Display: Show the actual numbers
666
+ from material_field_engine import load_config
667
+ config_data = load_config(selected_gov_preset)
668
+
669
+ st.markdown("---")
670
+ st.markdown("**Physics Parameters (active settings):**")
671
+
672
+ p_col1, p_col2, p_col3 = st.columns(3)
673
+ with p_col1:
674
+ st.metric(
675
+ label="Sigma (σ) - Tolerance",
676
+ value=config_data['elastic_modulus_sigma'],
677
+ help="Field Extent. Higher (0.8) = Vague associations accepted. Lower (0.2) = Exact match required."
678
+ )
679
+ with p_col2:
680
+ st.metric(
681
+ label="Lambda Max (λ) - Pressure",
682
+ value=config_data['lambda_max'],
683
+ help="Max Exclusion Pressure. Higher (1.5+) = Crushes weak bonds (High strictness). Lower (0.5) = Gentle."
684
+ )
685
+ with p_col3:
686
+ st.markdown(f"**Mode**: `{config_data['elastic_modulus_mode']}`")
687
+ st.caption("Algorithm usually 'multiplicative' (Angle × Distance).")
688
+
689
+ st.info(f"💡 **Teacher's Note**: To prevent valid answers from being blocked (fracturing), you would **increase Sigma** (widen the net) or **decrease Lambda** (reduce the pressure).")
690
+
691
+ with gov_col2:
692
+ st.write("**Gate Settings**")
693
+ topic_gate_enabled = st.checkbox(
694
+ "Enable Topic Gate",
695
+ value=False,
696
+ help="Fast pre-filter. If unchecked, physics runs on everything (good for demos)."
697
+ )
698
+ ambiguity_detection = st.checkbox(
699
+ "Allow Clarifications",
700
+ value=True,
701
+ help="If ON, clarifying questions ('Could you specify?') are marked CLARIFY instead of failing."
702
+ )
703
+
704
+ # Run Button
705
+ if st.button("🚀 Generate & Test Responses", type="primary"):
706
+ # Parse substrate
707
+ substrate_list = [line.strip() for line in substrate_input_llm.split('\n') if line.strip()]
708
+
709
+ if not substrate_list:
710
+ st.error("Please provide substrate facts")
711
+ elif not user_prompt:
712
+ st.error("Please provide a user prompt")
713
+ elif not api_base_url.strip():
714
+ st.error("Please provide a base URL for the API")
715
+ elif not model_name.strip():
716
+ st.error("Please provide a model name")
717
+ else:
718
+ st.info(f"📡 Generating {num_responses} response(s) from {api_preset}...")
719
+ from urllib.parse import urlparse
720
+ import socket
721
+ parsed_url = urlparse(api_base_url)
722
+ host = parsed_url.hostname
723
+ port = parsed_url.port or (443 if parsed_url.scheme == "https" else 80)
724
+ if not host:
725
+ st.error("Invalid base URL. Please include scheme (http/https) and host.")
726
+ st.stop()
727
+ try:
728
+ with socket.create_connection((host, port), timeout=3):
729
+ pass
730
+ except OSError as exc:
731
+ st.error(f"Unable to connect to {api_base_url}: {exc}")
732
+ if "localhost" in api_base_url or "127.0.0.1" in api_base_url:
733
+ st.info("For local providers, ensure the server is running (e.g., `ollama serve`).")
734
+ st.stop()
735
+
736
+ try:
737
+ import openai
738
+
739
+ # Configure client
740
+ api_key_value = api_key.strip() if api_key else ""
741
+ if not needs_key and not api_key_value:
742
+ api_key_value = "local"
743
+
744
+ client = openai.OpenAI(
745
+ api_key=api_key_value,
746
+ base_url=api_base_url,
747
+ timeout=request_timeout,
748
+ max_retries=max_retries
749
+ )
750
+
751
+ responses = []
752
+
753
+ with st.spinner(f"Calling LLM API ({num_responses} request(s))..."):
754
+ for i in range(num_responses):
755
+ messages = []
756
+ if system_prompt:
757
+ messages.append({"role": "system", "content": system_prompt})
758
+ messages.append({"role": "user", "content": user_prompt})
759
+
760
+ try:
761
+ response = client.chat.completions.create(
762
+ model=model_name,
763
+ messages=messages,
764
+ temperature=temperature
765
+ )
766
+ responses.append(response.choices[0].message.content)
767
+ except openai.APITimeoutError as e:
768
+ st.error(f"Request timed out on response {i+1}. Try increasing the timeout.")
769
+ raise
770
+ except openai.APIConnectionError as e:
771
+ st.error(f"Connection error on response {i+1}. Check base URL and server status.")
772
+ raise
773
+ except openai.OpenAIError as e:
774
+ st.error(f"OpenAI API error on response {i+1}: {str(e)}")
775
+ raise
776
+ except Exception as e:
777
+ st.error(f"Error on response {i+1}: {str(e)}")
778
+ if i == 0: # If first call fails, stop
779
+ raise
780
+
781
+ if not responses:
782
+ st.error("No responses generated")
783
+ else:
784
+ st.success(f"✓ Generated {len(responses)} response(s)")
785
+
786
+ # Now run the guardrail
787
+ st.markdown("---")
788
+
789
+ with st.spinner("Running Deterministic Guardrail..."):
790
+ from llm_adapter import DeterministicGuardrail, DeterministicHashEmbedderND
791
+ import math
792
+
793
+ guard = DeterministicGuardrail(
794
+ substrate_texts=substrate_list,
795
+ config_preset=selected_gov_preset,
796
+ topic_gate_enabled=topic_gate_enabled,
797
+ ambiguity_detection_enabled=ambiguity_detection
798
+ )
799
+
800
+ inspection = guard.inspect(responses)
801
+ result_text = inspection['selected_text']
802
+ metrics = inspection['metrics']
803
+ candidate_metrics = metrics.get('candidates')
804
+ if candidate_metrics is None:
805
+ candidate_metrics = [
806
+ {
807
+ 'phase_log': [],
808
+ 'fractured': False,
809
+ 'fractured_step': None,
810
+ 'stress': 0.0,
811
+ 'hash': 'N/A',
812
+ }
813
+ for _ in responses
814
+ ]
815
+
816
+ # Build detailed numbers view (high-D physics + 2D projection for plot)
817
+ embedder = DeterministicHashEmbedderND()
818
+ sub_vecs = [embedder.embed(t) for t in substrate_list]
819
+ resp_vecs = [embedder.embed(t) for t in responses]
820
+ sub_vecs_2d = [embedder.project_2d(v) for v in sub_vecs]
821
+ resp_vecs_2d = [embedder.project_2d(v) for v in resp_vecs]
822
+
823
+ def cosine_similarity(v1, v2):
824
+ dot = sum(a * b for a, b in zip(v1, v2))
825
+ mag1 = math.sqrt(sum(a * a for a in v1))
826
+ mag2 = math.sqrt(sum(b * b for b in v2))
827
+ if mag1 == 0 or mag2 == 0:
828
+ return 0.0
829
+ return dot / (mag1 * mag2)
830
+
831
+ def euclidean_distance(v1, v2):
832
+ return math.sqrt(sum((a - b) ** 2 for a, b in zip(v1, v2)))
833
+
834
+ # Display result
835
+ st.subheader("Guardrail Decision")
836
+ if result_text:
837
+ st.success("🟢 **SELECTED RESPONSE**")
838
+ st.markdown(f"> {result_text}")
839
+ else:
840
+ st.warning("🔴 **ABSTAINED** - All responses fractured under stress")
841
+ st.caption("The guardrail rejected all responses. None met the yield strength requirements.")
842
+
843
+ # Show all responses with scores
844
+ st.markdown("---")
845
+ st.subheader("Detailed Scoring for All Responses")
846
+
847
+ for i, (response, cand_vec) in enumerate(zip(responses, resp_vecs)):
848
+ cand_metrics = candidate_metrics[i]
849
+ is_selected = (result_text == response)
850
+
851
+ # Compute alignment to best substrate
852
+ best_alignment = -1
853
+ best_substrate = None
854
+ best_cos_sim = 0
855
+
856
+ for j, sub_vec in enumerate(sub_vecs):
857
+ cos_sim = cosine_similarity(cand_vec, sub_vec)
858
+ alignment = (cos_sim + 1.0) / 2.0
859
+ if alignment > best_alignment:
860
+ best_alignment = alignment
861
+ best_substrate = substrate_list[j]
862
+ best_cos_sim = cos_sim
863
+
864
+ # Display card
865
+
866
+ fractured = cand_metrics.get('fractured', False)
867
+ out_of_domain = cand_metrics.get('out_of_domain', False)
868
+ if is_selected:
869
+ status = "SELECTED"
870
+ elif out_of_domain:
871
+ status = "EXCLUDED (Topic Gate)"
872
+ elif fractured:
873
+ status = "EXCLUDED (Fractured)"
874
+ else:
875
+ status = "SURVIVED (Not Selected)"
876
+
877
+ with st.expander(f"**Response {i+1}** - {status}", expanded=is_selected):
878
+ st.markdown(f"**Full Response:**")
879
+ st.info(response)
880
+ st.markdown("---")
881
+
882
+ # Metrics
883
+ col1, col2, col3, col4 = st.columns(4)
884
+ with col1:
885
+ st.metric("Alignment Score", f"{best_alignment:.4f}", help="Normalized cosine similarity: 0=opposite, 0.5=orthogonal, 1=identical")
886
+ with col2:
887
+ st.metric("Cosine Similarity", f"{best_cos_sim:.4f}", help="Raw cosine similarity: -1 to 1")
888
+ with col3:
889
+ st.metric("Final Stress σ", f"{cand_metrics['stress']:.4f}")
890
+ with col4:
891
+ if out_of_domain:
892
+ st.metric("Status", "Topic-gated")
893
+ else:
894
+ st.metric("Status", "Intact" if not fractured else "Fractured")
895
+
896
+ st.caption(f"**Best substrate match:** *\"{best_substrate}\"*")
897
+
898
+ # Show stress evolution chart
899
+ st.markdown("**Stress Evolution**")
900
+ phase_log = cand_metrics.get('phase_log', [])
901
+ stress_data = [entry['stress'] for entry in phase_log]
902
+ steps = list(range(len(stress_data)))
903
+
904
+ fig_stress = go.Figure()
905
+ fig_stress.add_trace(go.Scatter(
906
+ x=steps,
907
+ y=stress_data,
908
+ mode='lines+markers',
909
+ name='Cumulative Stress',
910
+ line=dict(color='red' if fractured else 'green', width=2),
911
+ marker=dict(size=6)
912
+ ))
913
+
914
+ fig_stress.update_layout(
915
+ title=f"Stress Accumulation - Response {i+1}",
916
+ yaxis_title="Cumulative Stress σ(k)",
917
+ xaxis_title="Inference Step k",
918
+ height=300,
919
+ template="plotly_dark",
920
+ showlegend=True
921
+ )
922
+ st.plotly_chart(fig_stress, use_container_width=True)
923
+
924
+ # Summary metrics
925
+ st.markdown("---")
926
+ st.subheader("Summary Statistics")
927
+ summary_cols = st.columns(4)
928
+ with summary_cols[0]:
929
+ st.metric("Total Responses", len(responses))
930
+ with summary_cols[1]:
931
+ st.metric("Excluded", metrics['total_excluded'])
932
+ with summary_cols[2]:
933
+ st.metric("Survived", len(responses) - metrics['total_excluded'])
934
+ with summary_cols[3]:
935
+ selected = 1 if result_text else 0
936
+ st.metric("Selected", selected)
937
+
938
+ # Detailed audit trail
939
+ with st.expander("📊 Complete Numerical Audit Trail (JSON)", expanded=False):
940
+ st.caption("Full vectors, distances, comparisons, and stress evolution for reproducibility")
941
+
942
+ numbers_view = {
943
+ "test_metadata": {
944
+ "provider": api_preset,
945
+ "base_url": api_base_url,
946
+ "model": model_name,
947
+ "temperature": temperature,
948
+ "num_responses": len(responses),
949
+ "num_substrate_facts": len(substrate_list),
950
+ "prompt": user_prompt,
951
+ "system_prompt": system_prompt if system_prompt else "None"
952
+ },
953
+ "embedder": {
954
+ "name": "DeterministicHashEmbedderND",
955
+ "description": "Deterministic SHA-256 based 16D projection (2D shown for plotting)",
956
+ "definition": "sha256(text) -> 16D in [0,1], projected to 2D"
957
+ },
958
+ "substrate": [
959
+ {"index": idx, "text": t, "vec2": [round(v[0], 8), round(v[1], 8)]}
960
+ for idx, (t, v) in enumerate(zip(substrate_list, sub_vecs_2d))
961
+ ],
962
+ "responses": []
963
+ }
964
+
965
+ for i, (response, resp_vec) in enumerate(zip(responses, resp_vecs)):
966
+ cand_metrics = candidate_metrics[i]
967
+
968
+ # Compute all substrate comparisons
969
+ comparisons = []
970
+ for j, sub_vec in enumerate(sub_vecs):
971
+ cos_sim = cosine_similarity(resp_vec, sub_vec)
972
+ alignment = (cos_sim + 1.0) / 2.0
973
+ dist = euclidean_distance(resp_vec, sub_vec)
974
+
975
+ comparisons.append({
976
+ "substrate_index": j,
977
+ "substrate_text": substrate_list[j],
978
+ "cosine_similarity": round(cos_sim, 8),
979
+ "alignment_0_1": round(alignment, 8),
980
+ "euclidean_distance": round(dist, 8),
981
+ })
982
+
983
+ numbers_view["responses"].append({
984
+ "response_index": i,
985
+ "text": response,
986
+ "vec2": [round(resp_vecs_2d[i][0], 8), round(resp_vecs_2d[i][1], 8)],
987
+ "substrate_comparisons": comparisons,
988
+ "engine_results": {
989
+ "fractured": cand_metrics.get('fractured', False),
990
+ "fractured_at_step": cand_metrics.get('fractured_step'),
991
+ "final_stress": round(float(cand_metrics['stress']), 8),
992
+ "determinism_hash": cand_metrics.get('hash', 'N/A')
993
+ }
994
+ })
995
+
996
+ st.json(numbers_view)
997
+
998
+ except ImportError:
999
+ st.error("Missing `openai` library. Install with: `pip install openai`")
1000
+ except Exception as e:
1001
+ st.error(f"Error: {str(e)}")
1002
+ if "401" in str(e) or "authentication" in str(e).lower():
1003
+ st.info("💡 Check your API key and make sure it's valid for the selected endpoint")
1004
+ elif "404" in str(e) or "not found" in str(e).lower():
1005
+ st.info("💡 Check your model name and base URL. For local models, make sure the server is running.")
1006
+ st.exception(e)
1007
+
1008
+ # ----------------------------------------------------------------------------
1009
+ # TAB 4: Explain & Tune
1010
+ # ----------------------------------------------------------------------------
1011
+ with tab4:
1012
+ st.header("🔧 Interactive Parameter Tuning")
1013
+ st.markdown("Select parameters to visualize their combined effect on the governance physics.")
1014
+
1015
+ # 1. State Tracking for "Active Explanation"
1016
+ if 'last_params' not in st.session_state:
1017
+ st.session_state.last_params = {
1018
+ 'nuc': 0.4, 'quench': 0.75, 'lam': 1.2, 'yield': 1.5, 'align': 0.85, 'dist': 0.3
1019
+ }
1020
+ if 'active_topic' not in st.session_state:
1021
+ st.session_state.active_topic = "General"
1022
+
1023
+ # 1. Controls
1024
+ exp_col1, exp_col2 = st.columns([1, 2])
1025
+
1026
+ with exp_col1:
1027
+ st.subheader("Controls")
1028
+ st.caption("⚠️ **Educational Visualization**: This simulation uses the production physics engine but is intended for parameter intuition.")
1029
+
1030
+ # Multi-select for visualization layers
1031
+ focused_params = st.multiselect(
1032
+ "Visualized Layers",
1033
+ options=["Nucleation Phase", "Quenching Phase", "Max Pressure (lambda)", "Yield Strength (sigma_y)"],
1034
+ default=["Max Pressure (lambda)"],
1035
+ help="Select multiple layers to see how they interact"
1036
+ )
1037
+
1038
+ st.markdown("---")
1039
+ st.markdown("**Physics Parameters**")
1040
+
1041
+ # Sliders with callbacks to update active topic
1042
+ e_nuc = st.slider("Nucleation Fraction", 0.05, 0.9, 0.4, 0.05, key="slider_nuc")
1043
+ e_quench = st.slider("Quenching Fraction", 0.05, 0.95, 0.75, 0.05, key="slider_quench")
1044
+ e_lam = st.slider("Lambda Max (lambda)", 0.1, 4.0, 1.2, 0.1, key="slider_lam")
1045
+ e_yield = st.slider("Yield Strength (sigma_y)", 0.1, 5.0, 1.5, 0.1, key="slider_yield")
1046
+
1047
+ st.markdown("**Theoretical Simulation**")
1048
+ sim_align = st.slider("Target Alignment", 0.0, 1.0, 0.85, 0.01, key="slider_align")
1049
+ sim_dist = st.slider("Target Distance", 0.0, 2.0, 0.3, 0.01, key="slider_dist")
1050
+
1051
+ # ... (Detection logic remains same)
1052
+ current_params = {
1053
+ 'nuc': e_nuc, 'quench': e_quench, 'lam': e_lam,
1054
+ 'yield': e_yield, 'align': sim_align, 'dist': sim_dist
1055
+ }
1056
+ for param, val in current_params.items():
1057
+ if val != st.session_state.last_params.get(param):
1058
+ st.session_state.active_topic = param
1059
+ st.session_state.last_params[param] = val
1060
+ break
1061
+
1062
+ # 2. Simulation Logic (Production Backend)
1063
+ def run_simulation(steps=20, nuc=e_nuc, quench=e_quench, lam_max=e_lam, yld=e_yield, align=sim_align, dist=sim_dist):
1064
+ from material_field_engine import MaterialFieldEngine, VerifiedSubstrate, Vector2D
1065
+
1066
+ # To strictly follow the "one source of truth" principle, we drive the
1067
+ # visualization from the exact same engine code used in production.
1068
+
1069
+ # Simulation setup:
1070
+ # Substrate is at origin.
1071
+ # Candidate is at (dist, 0)
1072
+ # We manually tune the alignment to match simulated 'sim_align'
1073
+ # for maximum educational clarity while remaining 100% faithful to the real engine loop.
1074
+
1075
+ substrate = VerifiedSubstrate(
1076
+ texts=["Reference"],
1077
+ vectors=[Vector2D(0, 0)],
1078
+ sigma=fp_from_float(st.session_state.config.get('elastic_modulus_sigma', 0.5)), # Use global sigma for consistency
1079
+ distance_dim=2
1080
+ )
1081
+
1082
+
1083
+ engine = MaterialFieldEngine(
1084
+ substrate=substrate,
1085
+ candidate_texts=["Hypothetical"],
1086
+ candidate_vectors=[Vector2D(fp_from_float(dist), 0)],
1087
+ total_steps=steps,
1088
+ nuc_end_frac=fp_from_float(nuc),
1089
+ quench_end_frac=fp_from_float(quench),
1090
+ lambda_max=fp_from_float(lam_max),
1091
+ yield_strength=fp_from_float(yld)
1092
+ )
1093
+
1094
+ # We perform a single run
1095
+ res = engine.run_inference()
1096
+
1097
+ # Extract the bit-identical execution trace
1098
+ history = []
1099
+ for entry in res['phase_log']:
1100
+ history.append({
1101
+ "step": entry['step'],
1102
+ "stress": entry['stress'],
1103
+ "lambda": entry['pressure'],
1104
+ "phase": entry['phase']
1105
+ })
1106
+
1107
+ n_end = int(steps * nuc)
1108
+ q_end = int(steps * quench)
1109
+ return history, n_end, q_end
1110
+
1111
+
1112
+
1113
+ sim_data, sim_n_end, sim_q_end = run_simulation()
1114
+
1115
+ # 3. Visualization (Plotly)
1116
+ with exp_col2:
1117
+ st.subheader("Effect Visualization")
1118
+
1119
+ fig = go.Figure()
1120
+
1121
+ steps = [d['step'] for d in sim_data]
1122
+ stress = [d['stress'] for d in sim_data]
1123
+ lams = [d['lambda'] for d in sim_data]
1124
+
1125
+ # Base Curves
1126
+ fig.add_trace(go.Scatter(x=steps, y=stress, name='Stress σ', line=dict(color='blue', width=3)))
1127
+ fig.add_trace(go.Scatter(x=steps, y=lams, name='Pressure λ', line=dict(color='green', width=2, dash='dash')))
1128
+
1129
+ # Interactive Layers
1130
+ if "Nucleation Phase" in focused_params or st.session_state.active_topic == 'nuc':
1131
+ fig.add_vrect(x0=0, x1=sim_n_end, fillcolor="yellow", opacity=0.15, annotation_text="Nucleation", annotation_position="top left")
1132
+
1133
+ if "Quenching Phase" in focused_params or st.session_state.active_topic == 'quench':
1134
+ fig.add_vrect(x0=sim_n_end, x1=sim_q_end, fillcolor="orange", opacity=0.15, annotation_text="Quenching", annotation_position="top left")
1135
+
1136
+ if "Max Pressure (lambda)" in focused_params or st.session_state.active_topic == 'lam':
1137
+ fig.add_hline(y=e_lam, line_color="green", line_dash="dot", annotation_text=f"Max Pressure {e_lam}", annotation_position="bottom right")
1138
+
1139
+ if "Yield Strength (sigma_y)" in focused_params or st.session_state.active_topic == 'yield':
1140
+ fig.add_hline(y=e_yield, line_color="red", line_width=3, annotation_text=f"Yield {e_yield}")
1141
+
1142
+ fig.update_layout(
1143
+ title="Governance Physics Simulation",
1144
+ xaxis_title="Time Steps",
1145
+ yaxis_title="Magnitude",
1146
+ height=400,
1147
+ margin=dict(l=20, r=20, t=40, b=20),
1148
+ hovermode="x unified"
1149
+ )
1150
+ st.plotly_chart(fig, use_container_width=True)
1151
+
1152
+ # 4. Deep Dive Explanation (Dynamic)
1153
+ st.subheader(f"Deep Dive: {st.session_state.active_topic.upper()}")
1154
+
1155
+ topic = st.session_state.active_topic
1156
+ if topic == 'nuc':
1157
+ st.info("""
1158
+ **WHAT**: Nucleation Fraction (Time available for initial alignment).
1159
+
1160
+ **HOW**: Defines the percentage of the timeline (steps 0 to N) where the system is "listening" before applying significant pressure.
1161
+
1162
+ **WHY**:
1163
+ - **Too Short**: The system acts impulsively, fracturing valid ideas before they can stabilize.
1164
+ - **Too Long**: The system dithers, allowing hallucinations to persist too long.
1165
+
1166
+ **WHO**: Tuned by governance architects to match the "patience" required for the domain (e.g., Creative writing needs long nucleation; Safety systems need short).
1167
+ """)
1168
+ elif topic == 'quench':
1169
+ st.info("""
1170
+ **WHAT**: Quenching Fraction (The annealing window).
1171
+
1172
+ **HOW**: Defines the period where pressure ramps up linearly to testing levels.
1173
+
1174
+ **WHY**: This is the "soft filter" phase. Weak candidates (low alignment) are slowly crushed here, while strong candidates gain strength to survive the final crystallization.
1175
+ """)
1176
+ elif topic == 'lam':
1177
+ st.info("""
1178
+ **WHAT**: Lambda Max (λ_max) - The Maximum Exclusion Pressure.
1179
+
1180
+ **HOW**: Represents the "weight" of the governance mechanism. It is a multiplier on the error signal.
1181
+
1182
+ **WHY**:
1183
+ - **High (1.5+)**: "Mission Critical" mode. Even minor deviations cause instant fracture.
1184
+ - **Low (0.5)**: "Forgiving" mode. Only egregious hallucinations are blocked.
1185
+
1186
+ **RELATION**: Stress = λ * (1 - Alignment). If λ is huge, even 99% alignment might not be enough.
1187
+ """)
1188
+ elif topic == 'yield':
1189
+ st.info("""
1190
+ **WHAT**: Yield Strength (σ_y) - The Breaking Point.
1191
+
1192
+ **HOW**: A hard threshold. If accumulated Stress > Yield, the candidate is Rejected (Fractured).
1193
+
1194
+ **WHY**: This defines the ultimate binary decision boundary.
1195
+
1196
+ **IMPACT**: Raising this bar makes the system more "resilient" (harder to fracture). Lowering it makes it "brittle" (easy to fracture).
1197
+ """)
1198
+ elif topic in ['align', 'dist']:
1199
+ st.info("""
1200
+ **WHAT**: Candidate Properties (Hypothetical Input).
1201
+
1202
+ **HOW**:
1203
+ - **Alignment**: How semantically close the LLM output is to the Verified Substrate (1.0 = Perfect).
1204
+ - **Distance**: The spatial distance in the high-dimensional RBF field (0.0 = Perfect).
1205
+
1206
+ **WHY**: Use these sliders to test *what if* scenarios. "What if the LLM produces a weak answer (Align=0.4)? Will it survive the current Lambda setting?"
1207
+ """)
1208
+ else:
1209
+ st.markdown("*Adjust any slider on the left to see a detailed breakdown of its function.*")
1210
+
1211
+
1212
+ # ============================================================================
1213
+ # Footer
1214
+ # ============================================================================
1215
+
1216
+ st.markdown("---")
1217
+ st.caption("Development GUI | Deterministic Governance Mechanism")
deterministic_rng.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import math
5
+
6
+
7
+ def _u64(seed: bytes, counter: int) -> int:
8
+ h = hashlib.blake2b(digest_size=8)
9
+ h.update(seed)
10
+ h.update(counter.to_bytes(8, "little", signed=False))
11
+ return int.from_bytes(h.digest(), "little", signed=False)
12
+
13
+
14
+ def uniform01(seed: bytes, counter: int) -> float:
15
+ """
16
+ Deterministic uniform float in (0, 1), derived from (seed, counter).
17
+ """
18
+ # Map 64-bit integer to (0, 1) with clamping away from endpoints
19
+ x = _u64(seed, counter)
20
+ u = (x + 1.0) / (2**64 + 1.0)
21
+ # Defensive clamp (should already be in (0, 1))
22
+ if u <= 0.0:
23
+ return 1.0 / (2**64 + 1.0)
24
+ if u >= 1.0:
25
+ return 1.0 - (1.0 / (2**64 + 1.0))
26
+ return float(u)
27
+
28
+
29
+ def uniform(seed: bytes, counter: int, low: float, high: float) -> float:
30
+ return low + (high - low) * uniform01(seed, counter)
31
+
32
+
33
+ def normal(seed: bytes, counter: int, mean: float = 0.0, std: float = 1.0) -> float:
34
+ """
35
+ Deterministic normal via Box-Muller transform.
36
+
37
+ Uses counters (counter, counter+1) internally.
38
+ """
39
+ u1 = uniform01(seed, counter)
40
+ u2 = uniform01(seed, counter + 1)
41
+ r = math.sqrt(-2.0 * math.log(u1))
42
+ theta = 2.0 * math.pi * u2
43
+ z0 = r * math.cos(theta)
44
+ return mean + std * z0
45
+
46
+
47
+ def uint31(seed: bytes, counter: int) -> int:
48
+ return int(_u64(seed, counter) & 0x7FFF_FFFF)
elastic_modulus_analysis.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ANALYSIS: Elastic Modulus Saturation and Distance-Aware Alternatives
3
+
4
+ Current Issue:
5
+ --------------
6
+ Cosine similarity (normalized dot product) creates directional alignment measure
7
+ but ignores magnitude/distance. In low-dimensional spaces, this causes:
8
+
9
+ 1. E ≈ 1.0 for almost all nonzero vectors (direction dominates)
10
+ 2. Semantic class selection stuck in high-yield band (0.90-0.98)
11
+ 3. Exclusion driven entirely by strain (ε), not true substrate support
12
+ 4. System behaves as "distance filter wearing alignment mask"
13
+
14
+ Example from test output:
15
+ Vector (0.35, 0.30): E=0.9991, ε=0.8628
16
+ Vector (0.50, 0.50): E=0.9999, ε=0.6155
17
+ Vector (0.10, 0.10): E=0.9999, ε=1.1811
18
+
19
+ All have near-unit elastic modulus despite vastly different distances!
20
+
21
+ Why This Happens:
22
+ -----------------
23
+ Current formula: E = (cos_similarity + 1.0) / 2.0
24
+
25
+ For any vector roughly pointing toward substrate direction:
26
+ cos(θ) ≈ 1.0 when θ ≈ 0° (regardless of distance)
27
+ → E ≈ 1.0
28
+
29
+ This is geometrically correct for angular alignment, but semantically
30
+ incomplete: a vector 10 units away in the same direction should NOT
31
+ have the same "rigidity" as one 0.01 units away.
32
+
33
+ Proposed Alternative: Distance-Aware Elastic Modulus
34
+ ----------------------------------------------------
35
+
36
+ Blend proximity and alignment using different kernel functions:
37
+
38
+ Option 1: Multiplicative Coupling
39
+ ----------------------------------
40
+ E = alignment_term × proximity_term
41
+
42
+ Where:
43
+ alignment_term = (cos_similarity + 1.0) / 2.0 # Angular alignment
44
+ proximity_term = exp(-distance² / 2σ²) # Gaussian proximity kernel
45
+
46
+ This creates a proper "substrate field" where:
47
+ - High E requires BOTH correct direction AND close distance
48
+ - Far vectors (even aligned) get low E → low yield strength → early fracture
49
+ - Close vectors (even slightly misaligned) get high E → survive longer
50
+
51
+ Example with σ = 0.5:
52
+
53
+ Vector | cos_sim | distance | alignment | proximity | E (product)
54
+ ----------------|---------|----------|-----------|-----------|------------
55
+ (0.95, 0.92) | 1.000 | 0.000 | 1.000 | 1.000 | 1.000
56
+ (0.35, 0.30) | 0.999 | 0.863 | 0.999 | 0.037 | 0.037
57
+ (0.50, 0.50) | 0.999 | 0.615 | 0.999 | 0.286 | 0.286
58
+ (0.10, 0.10) | 0.999 | 1.181 | 0.999 | 0.002 | 0.002
59
+
60
+ Now E genuinely reflects "grounding strength" rather than just angle!
61
+
62
+ Option 2: Harmonic Mean (Balanced)
63
+ -----------------------------------
64
+ E = 2 / (1/alignment + 1/proximity)
65
+
66
+ Properties:
67
+ - Both factors must be high for high E
68
+ - More balanced than multiplication
69
+ - Penalizes imbalance (one factor low → E low)
70
+
71
+ Option 3: Weighted Sum (Tunable)
72
+ ---------------------------------
73
+ E = α·alignment + (1-α)·proximity
74
+
75
+ Where α controls the balance:
76
+ α = 0.7 → favor alignment (original behavior)
77
+ α = 0.5 → equal weight
78
+ α = 0.3 → favor proximity (tight substrate binding)
79
+
80
+ Option 4: RBF Kernel (Pure Proximity)
81
+ --------------------------------------
82
+ E = exp(-distance² / 2σ²)
83
+
84
+ Extreme case: ignore direction entirely, only distance matters.
85
+ Useful when substrate represents "allowed regions" rather than directions.
86
+
87
+ Implementation Example:
88
+ -----------------------
89
+ """
90
+
91
+ import sys
92
+
93
+ # Avoid Windows console UnicodeEncodeError for optional fancy output.
94
+ if hasattr(sys.stdout, "reconfigure"):
95
+ try:
96
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
97
+ except Exception:
98
+ pass
99
+
100
+ import math
101
+
102
+ def compute_elastic_modulus_distance_aware(
103
+ candidate_vector,
104
+ substrate_vectors,
105
+ mode='multiplicative',
106
+ sigma=0.5,
107
+ alpha=0.5
108
+ ):
109
+ """
110
+ Compute elastic modulus with distance awareness.
111
+
112
+ Args:
113
+ candidate_vector: (x, y) coordinates
114
+ substrate_vectors: List of verified substrate (x, y) coordinates
115
+ mode: 'multiplicative', 'harmonic', 'weighted', 'rbf'
116
+ sigma: Gaussian kernel bandwidth (for proximity term)
117
+ alpha: Weight for alignment in 'weighted' mode
118
+
119
+ Returns:
120
+ E: Elastic modulus in [0, 1]
121
+ """
122
+ if not substrate_vectors:
123
+ return 0.5 # Default
124
+
125
+ # Find nearest substrate vector
126
+ best_alignment = -1.0
127
+ best_distance = float('inf')
128
+
129
+ for substrate in substrate_vectors:
130
+ # Cosine similarity (alignment)
131
+ dot_prod = candidate_vector[0] * substrate[0] + candidate_vector[1] * substrate[1]
132
+ cand_norm = math.sqrt(candidate_vector[0] ** 2 + candidate_vector[1] ** 2)
133
+ subs_norm = math.sqrt(substrate[0] ** 2 + substrate[1] ** 2)
134
+
135
+ if cand_norm > 0 and subs_norm > 0:
136
+ cos_sim = dot_prod / (cand_norm * subs_norm)
137
+ else:
138
+ cos_sim = 0.0
139
+
140
+ # Euclidean distance
141
+ dist = math.sqrt(
142
+ (candidate_vector[0] - substrate[0]) ** 2
143
+ + (candidate_vector[1] - substrate[1]) ** 2
144
+ )
145
+
146
+ # Track best (highest alignment, lowest distance)
147
+ if cos_sim > best_alignment:
148
+ best_alignment = cos_sim
149
+ best_distance = dist
150
+
151
+ # Compute terms
152
+ alignment_term = (best_alignment + 1.0) / 2.0 # Map [-1,1] → [0,1]
153
+ proximity_term = math.exp(-(best_distance ** 2) / (2 * (sigma ** 2)))
154
+
155
+ # Combine based on mode
156
+ if mode == 'multiplicative':
157
+ E = alignment_term * proximity_term
158
+
159
+ elif mode == 'harmonic':
160
+ if alignment_term > 0 and proximity_term > 0:
161
+ E = 2.0 / (1.0/alignment_term + 1.0/proximity_term)
162
+ else:
163
+ E = 0.0
164
+
165
+ elif mode == 'weighted':
166
+ E = alpha * alignment_term + (1 - alpha) * proximity_term
167
+
168
+ elif mode == 'rbf':
169
+ E = proximity_term # Pure proximity
170
+
171
+ else:
172
+ raise ValueError(f"Unknown mode: {mode}")
173
+
174
+ return min(1.0, max(0.0, E))
175
+
176
+
177
+ # Demonstration
178
+ print("=" * 80)
179
+ print("ELASTIC MODULUS: COSINE-ONLY vs. DISTANCE-AWARE")
180
+ print("=" * 80)
181
+
182
+ substrate = [(0.95, 0.92)]
183
+ test_vectors = [
184
+ (0.95, 0.92, "Substrate (exact match)"),
185
+ (0.94, 0.91, "Very close, aligned"),
186
+ (0.50, 0.50, "Medium distance, aligned"),
187
+ (0.35, 0.30, "Far, aligned"),
188
+ (0.10, 0.10, "Very far, aligned"),
189
+ ]
190
+
191
+ print("\nSubstrate: (0.95, 0.92)")
192
+ print("\n" + "-" * 80)
193
+ print(f"{'Vector':<20} | {'Distance':<10} | {'E (cosine)':<12} | {'E (mult.)':<12} | {'E (harm.)':<12}")
194
+ print("-" * 80)
195
+
196
+ for x, y, label in test_vectors:
197
+ # Cosine-only (current implementation)
198
+ dot = x * substrate[0][0] + y * substrate[0][1]
199
+ norm_v = math.sqrt(x ** 2 + y ** 2)
200
+ norm_s = math.sqrt(substrate[0][0] ** 2 + substrate[0][1] ** 2)
201
+ cos_sim = dot / (norm_v * norm_s) if norm_v > 0 and norm_s > 0 else 0
202
+ E_cosine = (cos_sim + 1.0) / 2.0
203
+
204
+ # Distance
205
+ distance = math.sqrt((x - substrate[0][0]) ** 2 + (y - substrate[0][1]) ** 2)
206
+
207
+ # Distance-aware modes
208
+ E_mult = compute_elastic_modulus_distance_aware(
209
+ (x, y), substrate, mode='multiplicative', sigma=0.5
210
+ )
211
+ E_harm = compute_elastic_modulus_distance_aware(
212
+ (x, y), substrate, mode='harmonic', sigma=0.5
213
+ )
214
+
215
+ print(f"{label:<20} | {distance:>8.4f} | {E_cosine:>10.4f} | {E_mult:>10.4f} | {E_harm:>10.4f}")
216
+
217
+ print("\n" + "=" * 80)
218
+ print("ANALYSIS:")
219
+ print("=" * 80)
220
+ print("• Cosine-only: E ≈ 1.0 for all (saturated)")
221
+ print("• Multiplicative: E reflects true grounding (distance × alignment)")
222
+ print("• Harmonic: Balanced, requires both factors high")
223
+ print("\nConclusion: Distance-aware E creates meaningful semantic classes,")
224
+ print(" enabling the yield strength mechanism to work as intended.")
225
+ print("=" * 80)
226
+
227
+ """
228
+ Configuration Recommendation:
229
+ -----------------------------
230
+
231
+ For production deployment, use multiplicative coupling with tunable σ:
232
+
233
+ config.json addition:
234
+ {
235
+ "elastic_modulus": {
236
+ "mode": "multiplicative",
237
+ "sigma": 0.5,
238
+ "comment": "Gaussian kernel bandwidth for proximity term"
239
+ }
240
+ }
241
+
242
+ Tuning guidelines:
243
+ - Small σ (0.3): Tight substrate binding, only very close vectors get high E
244
+ - Medium σ (0.5): Balanced, moderate proximity required
245
+ - Large σ (1.0): Loose binding, distance matters less
246
+
247
+ Different σ for different semantic classes:
248
+ - Verified facts: σ = 0.3 (tight binding)
249
+ - Contextual: σ = 0.5 (moderate)
250
+ - Creative: σ = 0.8 (loose, allow exploration)
251
+
252
+ This creates a "substrate field strength" model where different regions
253
+ of semantic space have different binding characteristics.
254
+ """
exclusion_demo.py ADDED
@@ -0,0 +1,276 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Deterministic Exclusion Demo
4
+
5
+ Executes a fixed query against a verified substrate and logs phase-wise
6
+ candidate exclusion under deterministic constraint pressure.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import sys
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+ if hasattr(sys.stdout, "reconfigure"):
18
+ try:
19
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
20
+ except Exception:
21
+ pass
22
+
23
+ sys.path.insert(0, str(Path(__file__).parent))
24
+
25
+ from material_field_engine import MaterialFieldEngine, VerifiedSubstrate, Vector2D
26
+
27
+
28
+ _STARTUP_BANNER = """????????????????????????????????????????????????????????????????????????????????
29
+ +------------------------------------------------------------------------------+
30
+ | |
31
+ | Deterministic Exclusion Demonstration |
32
+ | |
33
+ | Executes a fixed query against a verified substrate and |
34
+ | logs phase-wise candidate exclusion under deterministic |
35
+ | constraint pressure. |
36
+ | |
37
+ +------------------------------------------------------------------------------+
38
+ """
39
+
40
+
41
+ def _print_startup_banner() -> None:
42
+ print(_STARTUP_BANNER)
43
+
44
+
45
+ def _stable_result_hash(
46
+ *,
47
+ final_output: Vector2D | None,
48
+ total_excluded: int,
49
+ phase_log: list[dict[str, Any]],
50
+ ) -> str:
51
+ result_data = {
52
+ "final_output": (final_output.x, final_output.y) if final_output else None,
53
+ "excluded_count": total_excluded,
54
+ "phase_log": [
55
+ {
56
+ "step": int(e["step"]),
57
+ "phase": str(e["phase"]),
58
+ "survivors": int(e["survivors"]),
59
+ "pressure": round(float(e["pressure"]), 6),
60
+ }
61
+ for e in phase_log
62
+ ],
63
+ }
64
+ result_json = json.dumps(result_data, sort_keys=True)
65
+ return hashlib.sha256(result_json.encode()).hexdigest()
66
+
67
+
68
+ def run_deterministic_exclusion_demo(
69
+ *,
70
+ elastic_modulus_mode: str = "multiplicative",
71
+ sigma: float = 0.40,
72
+ lambda_min: float = 0.35,
73
+ lambda_max: float = 1.20,
74
+ steps: int = 8,
75
+ print_banner: bool = True,
76
+ emit_stdout: bool = True,
77
+ ) -> dict[str, Any]:
78
+ """
79
+ Deterministic Exclusion Demo (fixed query, fixed substrate, fixed candidates).
80
+
81
+ Returns a dict suitable for both CLI output and programmatic checks.
82
+ """
83
+
84
+ if emit_stdout and print_banner:
85
+ _print_startup_banner()
86
+
87
+ if emit_stdout:
88
+ print("Query: Where do plants get their food?")
89
+ print(f"Elastic modulus mode: {elastic_modulus_mode}")
90
+ print(f"Sigma: {sigma:.2f}")
91
+ print(f"Pressure schedule: lambda = {lambda_min:.2f} -> {lambda_max:.2f}, steps = {steps}")
92
+ print()
93
+
94
+ substrate = VerifiedSubstrate(
95
+ elastic_modulus_mode=elastic_modulus_mode,
96
+ elastic_modulus_sigma=sigma,
97
+ )
98
+ substrate_states = [
99
+ (0.95, 0.92), # primary anchor
100
+ (0.90, 0.88), # support
101
+ (0.88, 0.90), # counterexample guard
102
+ ]
103
+ for x, y in substrate_states:
104
+ substrate.add_verified_state(Vector2D(x=x, y=y, properties=None))
105
+
106
+ if emit_stdout:
107
+ print("Verified Substrate States:")
108
+ print(" State 0 (primary anchor): photosynthesis synthesis")
109
+ print(" State 1 (support): chlorophyll mechanism")
110
+ print(" State 2 (counterexample guard): soil mass correction")
111
+ print()
112
+
113
+ candidates = [
114
+ (0.95, 0.92),
115
+ (0.10, 0.10),
116
+ (0.50, 0.50),
117
+ (-0.80, -0.80),
118
+ ]
119
+ candidate_labels = [
120
+ "Candidate 0 (reference-aligned)",
121
+ "Candidate 1 (misconception)",
122
+ "Candidate 2 (vague)",
123
+ "Candidate 3 (out-of-domain)",
124
+ ]
125
+
126
+ engine = MaterialFieldEngine(
127
+ substrate,
128
+ lambda_min=lambda_min,
129
+ lambda_max=lambda_max,
130
+ inference_steps=steps,
131
+ )
132
+ engine.phase_controller.nucleation_threshold = 0.375
133
+ engine.phase_controller.quenching_threshold = 0.875
134
+ engine.initialize_candidates(candidates)
135
+
136
+ if emit_stdout:
137
+ print("Candidates:")
138
+ print(f"{'#':<3} {'Label':<32} | {'E':<8} | {'sigma_y':<8} | {'epsilon':<8} | {'sigma_init':<10}")
139
+ print("-" * 80)
140
+ for i, (v, label) in enumerate(zip(engine.candidate_vectors, candidate_labels)):
141
+ if emit_stdout:
142
+ print(
143
+ f"{i:<3} {label:<32} | "
144
+ f"{v.properties.elastic_modulus:<8.4f} | "
145
+ f"{v.properties.yield_strength:<8.4f} | "
146
+ f"{v.properties.strain:<8.4f} | "
147
+ f"{v.properties.stress:<8.4f}"
148
+ )
149
+ if emit_stdout:
150
+ print()
151
+
152
+ results = engine.run_inference()
153
+
154
+ if emit_stdout:
155
+ print("Phase Log:")
156
+ print(f"{'Step':<5} | {'Phase':<15} | {'lambda(t)':<10} | {'Survivors':<10} | {'Excluded'}")
157
+ print("-" * 80)
158
+ for entry in results["phase_log"]:
159
+ excluded_indices = entry.get("excluded_indices", [])
160
+ excluded_str = (
161
+ "[" + ", ".join(str(i) for i in excluded_indices) + "]"
162
+ if excluded_indices
163
+ else "[]"
164
+ )
165
+ print(
166
+ f"{entry['step']:<5} | {entry['phase']:<15} | {entry['pressure']:<8.3f} | "
167
+ f"{entry['survivors']:<10} | {excluded_str}"
168
+ )
169
+ print()
170
+
171
+ final_output = results["final_output"]
172
+ winner_idx = None
173
+ if final_output is not None:
174
+ winner_tuple = (final_output.x, final_output.y)
175
+ winner_idx = next(i for i, c in enumerate(candidates) if c == winner_tuple)
176
+
177
+ result_hash = _stable_result_hash(
178
+ final_output=final_output,
179
+ total_excluded=results["total_excluded"],
180
+ phase_log=results["phase_log"],
181
+ )
182
+
183
+ if emit_stdout:
184
+ print("Outcome Verification")
185
+ print("Expected winner: Candidate 0")
186
+ print("Expected excluded count: 3")
187
+ print("Determinism: SHA-256 stable across runs")
188
+ print(f"SHA-256: {result_hash}")
189
+
190
+ return {
191
+ "winner_index": winner_idx,
192
+ "winner_label": candidate_labels[winner_idx] if winner_idx is not None else None,
193
+ "excluded": results["total_excluded"],
194
+ "hash": result_hash,
195
+ "phase_log": results["phase_log"],
196
+ "final_output": final_output,
197
+ "elastic_modulus_mode": elastic_modulus_mode,
198
+ "sigma": sigma,
199
+ "lambda_min": lambda_min,
200
+ "lambda_max": lambda_max,
201
+ "steps": steps,
202
+ }
203
+
204
+
205
+ def elastic_modulus_mode_comparison() -> list[dict[str, Any]]:
206
+ print("Elastic Modulus Mode Comparison")
207
+ print()
208
+
209
+ modes = [
210
+ ("cosine", 0.40),
211
+ ("multiplicative", 0.40),
212
+ ("multiplicative", 0.60),
213
+ ]
214
+
215
+ results: list[dict[str, Any]] = []
216
+ for mode, sigma in modes:
217
+ res = run_deterministic_exclusion_demo(
218
+ elastic_modulus_mode=mode,
219
+ sigma=sigma,
220
+ print_banner=False,
221
+ emit_stdout=False,
222
+ )
223
+ results.append(res)
224
+ print(f"Mode: {mode}, sigma={sigma:.2f}, SHA-256: {res['hash']}")
225
+ print()
226
+
227
+ print(f"{'Mode':<18} | {'Sigma':<6} | {'Winner':<10} | {'Excluded':<8} | {'SHA-256'}")
228
+ print("-" * 80)
229
+ for res in results:
230
+ print(
231
+ f"{res['elastic_modulus_mode']:<18} | {res['sigma']:<6.2f} | "
232
+ f"{(res['winner_index'] if res['winner_index'] is not None else 'None')!s:<10} | "
233
+ f"{res['excluded']:<8} | {res['hash']}"
234
+ )
235
+
236
+ return results
237
+
238
+
239
+ def determinism_replay(runs: int = 5) -> list[str]:
240
+ print("Determinism Replay (5 Runs)" if runs == 5 else f"Determinism Replay ({runs} Runs)")
241
+ print()
242
+
243
+ hashes: list[str] = []
244
+ for i in range(runs):
245
+ res = run_deterministic_exclusion_demo(print_banner=False, emit_stdout=False)
246
+ hashes.append(res["hash"])
247
+ print(f"Run {i + 1}: {res['hash']}")
248
+
249
+ if len(set(hashes)) == 1:
250
+ print()
251
+ print("Determinism: SHA-256 stable across runs")
252
+ print(f"SHA-256: {hashes[0]}")
253
+ else:
254
+ print()
255
+ print("Determinism: SHA-256 not stable across runs")
256
+
257
+ return hashes
258
+
259
+
260
+ def main(argv: list[str]) -> int:
261
+ if len(argv) > 1:
262
+ if argv[1] == "compare":
263
+ elastic_modulus_mode_comparison()
264
+ return 0
265
+ if argv[1] in {"replay", "verify"}:
266
+ determinism_replay(5)
267
+ return 0
268
+ print("Usage: python exclusion_demo.py [compare|replay]")
269
+ return 2
270
+
271
+ run_deterministic_exclusion_demo()
272
+ return 0
273
+
274
+
275
+ if __name__ == "__main__":
276
+ raise SystemExit(main(sys.argv))
exclusion_demo_compat.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Compatibility wrapper.
4
+
5
+ Use `exclusion_demo.py` / `run_deterministic_exclusion_demo()`.
6
+ """
7
+
8
+ import sys
9
+
10
+ from exclusion_demo import (
11
+ run_deterministic_exclusion_demo,
12
+ elastic_modulus_mode_comparison,
13
+ determinism_replay,
14
+ )
15
+
16
+
17
+ def governance_demo(mode: str = "multiplicative", sigma: float = 0.4, verbose: bool = True):
18
+ # `verbose` retained for signature compatibility; output is always structured.
19
+ return run_deterministic_exclusion_demo(
20
+ elastic_modulus_mode=mode,
21
+ sigma=sigma,
22
+ print_banner=verbose,
23
+ emit_stdout=verbose,
24
+ )
25
+
26
+
27
+ def compare_modes():
28
+ return elastic_modulus_mode_comparison()
29
+
30
+
31
+ def verify_determinism():
32
+ return determinism_replay(5)
33
+
34
+
35
+ if __name__ == "__main__":
36
+ if len(sys.argv) > 1:
37
+ if sys.argv[1] == "compare":
38
+ compare_modes()
39
+ raise SystemExit(0)
40
+ if sys.argv[1] in {"verify", "replay"}:
41
+ verify_determinism()
42
+ raise SystemExit(0)
43
+ print("Usage: python exclusion_demo.py [compare|replay]")
44
+ raise SystemExit(2)
45
+
46
+ run_deterministic_exclusion_demo()
governance_demo.py ADDED
@@ -0,0 +1,413 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ This demonstration shows that the Material-Field Engine does not
4
+ encode scientific knowledge and does not reason about biology.
5
+ It operates purely by mechanical constraint: candidate semantic vectors
6
+ are subjected to increasing pressure, and those that cannot maintain
7
+ structural integrity are irreversibly excluded. What is commonly framed
8
+ as an “alignment” or “understanding” problem is treated instead as
9
+ a stability problem in a constrained field.
10
+
11
+ The query evaluated is “Where do plants get their food?” The verified
12
+ substrate provides evidential grounding: plants synthesize glucose from sunlight,
13
+ water, and carbon dioxide; chlorophyll in leaves is the site of energy conversion;
14
+ and soil contributes minerals and water but not the bulk of plant mass.
15
+ Four candidates are introduced into the latent field: a tightly aligned
16
+ textbook answer, a common misconception asserting soil consumption, a vague
17
+ answer referencing the ground, and an implausible hallucination. Under
18
+ deterministic phase transitions, structurally weak candidates fracture
19
+ during nucleation or quenching, leaving only the aligned, grounded vector
20
+ to survive crystallization with a bit-identical output.
21
+ """
22
+
23
+ import sys
24
+ import hashlib
25
+ import json
26
+ from pathlib import Path
27
+
28
+ if hasattr(sys.stdout, "reconfigure"):
29
+ try:
30
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
31
+ except Exception:
32
+ pass
33
+
34
+ sys.path.insert(0, str(Path(__file__).parent))
35
+
36
+ from material_field_engine import (
37
+ VerifiedSubstrate, Vector2D, MaterialFieldEngine
38
+ )
39
+
40
+
41
+ def governance_demo(mode='multiplicative', sigma=0.4, verbose=True):
42
+ """
43
+ Run the governance demo with specified elastic modulus configuration.
44
+
45
+ Returns:
46
+ dict: Complete test results including phase log, final output, and hash
47
+ """
48
+
49
+ if verbose:
50
+ print("=" * 80)
51
+ print("DETERMINISTIC GOVERNANCE DEMO: Photosynthesis")
52
+ print("=" * 80)
53
+ print(f"\nQuery: 'Where do plants get their food?'")
54
+ print(f"Mode: {mode}, σ={sigma:.2f}")
55
+ print()
56
+
57
+ # ============================================================================
58
+ # SUBSTRATE: Verified introductory biology facts
59
+ # ============================================================================
60
+
61
+ substrate = VerifiedSubstrate(
62
+ elastic_modulus_mode=mode,
63
+ elastic_modulus_sigma=sigma
64
+ )
65
+
66
+ # Fact A: Primary Anchor - Photosynthesis equation
67
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
68
+
69
+ # Fact B: Structural Support - Chlorophyll mechanism
70
+ substrate.add_verified_state(Vector2D(x=0.90, y=0.88, properties=None))
71
+
72
+ # Fact C: Anti-Hallucination Fuse - Soil misconception correction
73
+ substrate.add_verified_state(Vector2D(x=0.88, y=0.90, properties=None))
74
+
75
+ if verbose:
76
+ print("Substrate (Verified Biology Facts):")
77
+ print(" Fact A (0.95, 0.92): Photosynthesis equation [Primary Anchor]")
78
+ print(" Fact B (0.90, 0.88): Chlorophyll mechanism [Structural Support]")
79
+ print(" Fact C (0.88, 0.90): Soil correction [Anti-Hallucination Fuse]")
80
+ print()
81
+
82
+ # ============================================================================
83
+ # CANDIDATES: Four Specific Semantic States
84
+ # ============================================================================
85
+
86
+ candidates = [
87
+ (0.95, 0.92), # Textbook: Correct answer
88
+ (0.10, 0.10), # Misconception: "They eat soil"
89
+ (0.50, 0.50), # Vague: "From the ground"
90
+ (-0.80, -0.80), # Hallucination: "They hunt insects"
91
+ ]
92
+
93
+ candidate_labels = [
94
+ "Textbook (sunlight+water+CO2)",
95
+ "Misconception (eat soil)",
96
+ "Vague (from the ground)",
97
+ "Hallucination (hunt insects)"
98
+ ]
99
+
100
+ # ============================================================================
101
+ # ENGINE INITIALIZATION
102
+ # ============================================================================
103
+
104
+ engine = MaterialFieldEngine(
105
+ substrate,
106
+ lambda_min=0.35,
107
+ lambda_max=1.20,
108
+ inference_steps=8
109
+ )
110
+
111
+ engine.phase_controller.nucleation_threshold = 0.375 # Ends at step 3
112
+ engine.phase_controller.quenching_threshold = 0.875 # Ends at step 7
113
+
114
+ engine.initialize_candidates(candidates)
115
+
116
+ if verbose:
117
+ print("Candidate Semantic States:")
118
+ print(f"{'#':<3} {'Label':<35} | {'E':<8} | {'σ_y':<8} | {'ε':<8} | {'σ_init':<8}")
119
+ print("-" * 80)
120
+
121
+ for i, (v, label) in enumerate(zip(engine.candidate_vectors, candidate_labels)):
122
+ if verbose:
123
+ print(f"{i:<3} {label:<35} | "
124
+ f"{v.properties.elastic_modulus:<8.4f} | "
125
+ f"{v.properties.yield_strength:<8.4f} | "
126
+ f"{v.properties.strain:<8.4f} | "
127
+ f"{v.properties.stress:<8.4f}")
128
+
129
+ if verbose:
130
+ print()
131
+ print("=" * 80)
132
+ print("PHASE TRANSITION LOG")
133
+ print("=" * 80)
134
+
135
+ # ============================================================================
136
+ # RUN INFERENCE
137
+ # ============================================================================
138
+
139
+ results = engine.run_inference()
140
+
141
+ if verbose:
142
+ print(f"\n{'Step':<5} | {'Phase':<15} | {'λ(t)':<8} | {'Survivors':<10} | {'Status'}")
143
+ print("-" * 80)
144
+
145
+ for entry in results['phase_log']:
146
+ step = entry['step']
147
+ phase = entry['phase']
148
+ pressure = entry['pressure']
149
+ survivors = entry['survivors']
150
+ excluded = entry['excluded']
151
+
152
+ # Determine status message
153
+ if step == 0:
154
+ status = "Initial state"
155
+ elif excluded > 0 and step <= 3:
156
+ status = f"← {excluded} fractured (brittle failure)"
157
+ elif excluded > 0 and 4 <= step <= 6:
158
+ status = f"← Vague candidate fracturing"
159
+ elif excluded > 0 and step >= 7:
160
+ status = f"← Final exclusion"
161
+ else:
162
+ status = ""
163
+
164
+ if verbose:
165
+ print(f"{step:<5} | {phase:<15} | {pressure:<8.3f} | {survivors:<10} | {status}")
166
+
167
+ # ============================================================================
168
+ # RESULTS AND VERIFICATION
169
+ # ============================================================================
170
+
171
+ if verbose:
172
+ print("\n" + "=" * 80)
173
+ print("GOVERNANCE DEMO RESULTS")
174
+ print("=" * 80)
175
+
176
+ # Identify final output
177
+ final_output = results['final_output']
178
+ if final_output:
179
+ output_tuple = (final_output.x, final_output.y)
180
+ winner_idx = next(i for i, c in enumerate(candidates) if c == output_tuple)
181
+ winner_label = candidate_labels[winner_idx]
182
+
183
+ if verbose:
184
+ print(f"\nFinal Output: {winner_label}")
185
+ print(f" Coordinates: ({final_output.x:.3f}, {final_output.y:.3f})")
186
+ print(f" Elastic Modulus: {final_output.properties.elastic_modulus:.6f}")
187
+ print(f" Yield Strength: {final_output.properties.yield_strength:.6f}")
188
+ print(f" Final Stress: {final_output.properties.stress:.6f}")
189
+ else:
190
+ winner_label = "ABSTAINED"
191
+ if verbose:
192
+ print(f"\nFinal Output: ABSTAINED (no candidate met structural requirements)")
193
+
194
+ if verbose:
195
+ print(f"\nTotal Excluded: {results['total_excluded']}")
196
+ print(f"Hallucination-Free: {results['hallucination_free']}")
197
+ print(f"Deterministic: {results['deterministic']}")
198
+ print(f"Latency: {results['latency_ms']:.3f} ms")
199
+
200
+ # ============================================================================
201
+ # BIT-IDENTICAL VERIFICATION
202
+ # ============================================================================
203
+
204
+ # Create deterministic hash of results
205
+ result_data = {
206
+ 'final_output': (final_output.x, final_output.y) if final_output else None,
207
+ 'excluded_count': results['total_excluded'],
208
+ 'phase_log': [
209
+ {
210
+ 'step': e['step'],
211
+ 'phase': e['phase'],
212
+ 'survivors': e['survivors'],
213
+ 'pressure': round(e['pressure'], 6)
214
+ }
215
+ for e in results['phase_log']
216
+ ]
217
+ }
218
+
219
+ result_json = json.dumps(result_data, sort_keys=True)
220
+ result_hash = hashlib.sha256(result_json.encode()).hexdigest()
221
+
222
+ if verbose:
223
+ print(f"\nBit-Identical Verification:")
224
+ print(f" SHA-256: {result_hash}")
225
+
226
+ # ============================================================================
227
+ # FALSIFICATION CRITERIA
228
+ # ============================================================================
229
+
230
+ if verbose:
231
+ print("\n" + "=" * 80)
232
+ print("FALSIFICATION ANALYSIS")
233
+ print("=" * 80)
234
+
235
+ # Check expected behavior
236
+ nucleation_exclusions = sum(1 for e in results['phase_log'][:4] if e['excluded'] > 0)
237
+ quenching_exclusions = sum(1 for e in results['phase_log'][4:7] if e['excluded'] > 0)
238
+
239
+ print(f"\nExpected vs. Actual Behavior:")
240
+ print(f" Nucleation exclusions (Steps 0-3): {nucleation_exclusions} events")
241
+ print(f" Quenching exclusions (Steps 4-6): {quenching_exclusions} events")
242
+ print(f" Final survivor: {winner_label}")
243
+
244
+ # Verify correctness
245
+ correct = (
246
+ results['total_excluded'] == 3 and
247
+ winner_label == "Textbook (sunlight+water+CO2)" and
248
+ results['hallucination_free']
249
+ )
250
+
251
+ print(f"\n Test Status: {'✓ PASS' if correct else '✗ FAIL'}")
252
+
253
+ if correct:
254
+ print("\n Interpretation:")
255
+ print(" The engine doesn't 'understand' photosynthesis.")
256
+ print(" It mechanically excludes vectors that cannot maintain")
257
+ print(" structural integrity under constraint pressure.")
258
+ print(" This is material science, not semantic reasoning.")
259
+
260
+ # ============================================================================
261
+ # RETURN COMPLETE RESULTS
262
+ # ============================================================================
263
+
264
+ return {
265
+ 'winner': winner_label,
266
+ 'hash': result_hash,
267
+ 'excluded': results['total_excluded'],
268
+ 'hallucination_free': results['hallucination_free'],
269
+ 'phase_log': results['phase_log'],
270
+ 'final_output': final_output
271
+ }
272
+
273
+
274
+ def compare_modes():
275
+ """Compare demo behavior across different elastic modulus modes."""
276
+
277
+ print("""
278
+ ╔══════════════════════════════════════════════════════════════════════════════╗
279
+ ║ ║
280
+ ║ GOVERNANCE DEMO: MODE COMPARISON ║
281
+ ║ ║
282
+ ║ Shows how elastic modulus mode affects mechanical exclusion of wrong ║
283
+ ║ answers under a fixed substrate and candidate set. ║
284
+ ║ ║
285
+ ╚══════════════════════════════════════════════════════════════════════════════╝
286
+ """)
287
+
288
+ modes = [
289
+ ('cosine', 0.4, "Cosine (Direction Only)"),
290
+ ('multiplicative', 0.4, "Multiplicative σ=0.4 (Reference)"),
291
+ ('multiplicative', 0.6, "Multiplicative σ=0.6 (Looser)"),
292
+ ]
293
+
294
+ results = []
295
+
296
+ for mode, sigma, description in modes:
297
+ print(f"\n{'─' * 80}")
298
+ print(f"Mode: {description}")
299
+ print(f"{'─' * 80}\n")
300
+
301
+ result = governance_demo(mode, sigma, verbose=True)
302
+ results.append((description, result))
303
+
304
+ print("\n")
305
+
306
+ # Summary comparison
307
+ print("=" * 80)
308
+ print("COMPARISON SUMMARY")
309
+ print("=" * 80)
310
+ print(f"\n{'Mode':<40} | {'Winner':<35} | {'Excluded'}")
311
+ print("-" * 80)
312
+
313
+ for desc, res in results:
314
+ print(f"{desc:<40} | {res['winner']:<35} | {res['excluded']}")
315
+
316
+ print("\nKey Insight:")
317
+ print(" Cosine mode may allow wrong answers with high E due to angular alignment.")
318
+ print(" Multiplicative mode requires BOTH alignment AND proximity.")
319
+ print(" Multiplicative mode composes alignment and proximity deterministically.")
320
+
321
+
322
+ def verify_determinism():
323
+ """Run the demo 5 times to verify bit-identical results."""
324
+
325
+ print("""
326
+ ╔══════════════════════════════════════════════════════════════════════════════╗
327
+ ║ ║
328
+ ║ DETERMINISM VERIFICATION: 5-RUN TEST ║
329
+ ║ ║
330
+ ║ Verifies that the demo produces bit-identical outputs across ║
331
+ ║ multiple runs with identical inputs. ║
332
+ ║ ║
333
+ ╚══════════════════════════════════════════════════════════════════════════════╝
334
+ """)
335
+
336
+ hashes = []
337
+
338
+ for run in range(5):
339
+ print(f"\nRun {run + 1}/5:")
340
+ result = governance_demo(mode='multiplicative', sigma=0.4, verbose=False)
341
+ hashes.append(result['hash'])
342
+ print(f" SHA-256: {result['hash']}")
343
+ print(f" Winner: {result['winner']}")
344
+ print(f" Excluded: {result['excluded']}")
345
+
346
+ # Check if all hashes are identical
347
+ all_identical = len(set(hashes)) == 1
348
+
349
+ print("\n" + "=" * 80)
350
+ print("DETERMINISM VERIFICATION")
351
+ print("=" * 80)
352
+
353
+ if all_identical:
354
+ print("\n✓ VERIFIED: All 5 runs produced identical results")
355
+ print(f" Shared SHA-256: {hashes[0]}")
356
+ print("\n This proves:")
357
+ print(" 1. No randomness in the inference process")
358
+ print(" 2. Yield strength is deterministically computed (stable hash)")
359
+ print(" 3. Mechanical exclusion is reproducible")
360
+ print(" 4. System is falsifiable (same input → same output)")
361
+ else:
362
+ print("\n✗ FAILED: Results differ across runs")
363
+ print(" Unique hashes found:", len(set(hashes)))
364
+ print("\n This indicates non-determinism in:")
365
+ print(" - Hash computation")
366
+ print(" - Stress accumulation")
367
+ print(" - Floating point operations")
368
+
369
+
370
+ if __name__ == "__main__":
371
+ if len(sys.argv) > 1:
372
+ if sys.argv[1] == 'compare':
373
+ compare_modes()
374
+ elif sys.argv[1] == 'verify':
375
+ verify_determinism()
376
+ else:
377
+ print("Usage: python governance_demo.py [compare|verify]")
378
+ sys.exit(1)
379
+ else:
380
+ # Default: single run with full output
381
+ print("""
382
+ ╔══════════════════════════════════════════════════════════════════════════════╗
383
+ ║ ║
384
+ ║ DETERMINISTIC GOVERNANCE DEMO ║
385
+ ║ ║
386
+ ║ Demonstrates that the Material-Field Engine doesn't "know" science— ║
387
+ ║ it mechanically refuses to let structurally unsound vectors survive ║
388
+ ║ phase transitions. ║
389
+ ║ ║
390
+ ║ This turns the "alignment problem" into a "material science problem." ║
391
+ ║ ║
392
+ ║ Patent Priority: January 25, 2026 ║
393
+ ║ Inventor: Ryan S. Walters, Verhash LLC ║
394
+ ║ ║
395
+ ╚══════════════════════════════════════════════════════════════════════════════╝
396
+ """)
397
+
398
+ governance_demo(mode='multiplicative', sigma=0.4, verbose=True)
399
+
400
+ print("\n" + "=" * 80)
401
+ print("NEXT STEPS")
402
+ print("=" * 80)
403
+ print("""
404
+ Run additional tests:
405
+ python governance_demo.py compare # Compare elastic modulus modes
406
+ python governance_demo.py verify # Verify determinism (5 runs)
407
+
408
+ The demo proves:
409
+ 1. Mechanical exclusion works without semantic understanding
410
+ 2. Wrong answers fracture under constraint pressure
411
+ 3. System is deterministic and falsifiable
412
+ 4. Alignment problem → Material science problem
413
+ """)
llm_adapter.py ADDED
@@ -0,0 +1,377 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ LLM Adapter for Deterministic Governance Mechanism
4
+ Bridges high-dimensional text/LLM outputs to the 2D material field engine.
5
+
6
+ A model-agnostic post-processor that evaluates candidate outputs against a declared substrate.
7
+ It deterministically accepts, rejects, or abstains based on explicit constraints.
8
+ """
9
+
10
+ from dataclasses import dataclass
11
+ from typing import List, Optional, Tuple, Any, Dict, Protocol
12
+ import hashlib
13
+ import json
14
+
15
+ from material_field_engine import (
16
+ MaterialFieldEngine,
17
+ VerifiedSubstrate,
18
+ Vector2D,
19
+ load_config
20
+ )
21
+
22
+
23
+ _STOPWORDS = {
24
+ "the", "a", "an", "and", "or", "but", "if", "then", "else", "when", "while",
25
+ "of", "to", "in", "on", "at", "by", "for", "with", "about", "as", "into",
26
+ "is", "are", "was", "were", "be", "being", "been", "do", "does", "did",
27
+ "this", "that", "these", "those", "it", "its", "it's", "you", "your",
28
+ "i", "we", "they", "them", "he", "she", "his", "her", "their", "ours",
29
+ "from", "up", "down", "over", "under", "again", "further", "here", "there",
30
+ "why", "how", "what", "which", "who", "whom"
31
+ }
32
+
33
+
34
+ def _tokenize(text: str) -> List[str]:
35
+ cleaned = []
36
+ for ch in text.lower():
37
+ cleaned.append(ch if ch.isalnum() else " ")
38
+ tokens = [tok for tok in "".join(cleaned).split() if tok and tok not in _STOPWORDS]
39
+ return tokens
40
+
41
+
42
+ def _token_set(texts: List[str]) -> set:
43
+ tokens = set()
44
+ for t in texts:
45
+ tokens.update(_tokenize(t))
46
+ return tokens
47
+
48
+
49
+ class DeterministicHashEmbedderND:
50
+ """
51
+ Deterministic hash-based embedder producing N-D vectors in [0,1].
52
+ """
53
+
54
+ def __init__(self, dims: int = 16):
55
+ if dims < 2:
56
+ raise ValueError("dims must be >= 2")
57
+ self.dims = dims
58
+
59
+ def embed(self, text: str) -> List[float]:
60
+ text = text.strip().lower()
61
+ values: List[float] = []
62
+ digest = hashlib.sha256(text.encode("utf-8")).digest()
63
+ cursor = 0
64
+
65
+ for i in range(self.dims):
66
+ if cursor + 2 > len(digest):
67
+ digest = hashlib.sha256(digest + i.to_bytes(2, "big")).digest()
68
+ cursor = 0
69
+ chunk = digest[cursor:cursor + 2]
70
+ cursor += 2
71
+ val = int.from_bytes(chunk, "big") / 65535.0
72
+ values.append(val)
73
+
74
+ return values
75
+
76
+ def project_2d(self, vector: List[float]) -> Tuple[float, float]:
77
+ if len(vector) < 2:
78
+ return (0.0, 0.0)
79
+ return (float(vector[0]), float(vector[1]))
80
+
81
+
82
+ class EmbedderProtocol(Protocol):
83
+ """Protocol for embedding providers"""
84
+ def embed(self, text: str) -> List[float]:
85
+ """Convert text to a vector (length >= 2)"""
86
+ ...
87
+
88
+
89
+ class MockEmbedder(DeterministicHashEmbedderND):
90
+ """
91
+ Deterministic 2D hash embedder for legacy demos.
92
+ """
93
+
94
+ def __init__(self):
95
+ super().__init__(dims=2)
96
+
97
+
98
+ @dataclass
99
+ class ContentObject:
100
+ """Container for content and its physical representation"""
101
+ text: str
102
+ vector: Vector2D
103
+ metadata: Dict[str, Any] = None
104
+
105
+
106
+ class DeterministicGuardrail:
107
+ """
108
+ Guardrail wrapper for LLM outputs.
109
+ Applies mechanical exclusion to filter hallucinations.
110
+ """
111
+
112
+ def __init__(self,
113
+ substrate_texts: List[str],
114
+ embedder: Optional[EmbedderProtocol] = None,
115
+ config_preset: str = 'balanced',
116
+ topic_gate_min_overlap: int = 1,
117
+ topic_gate_enabled: bool = True,
118
+ ambiguity_detection_enabled: bool = True):
119
+ """
120
+ Initialize the guardrail.
121
+
122
+ Args:
123
+ substrate_texts: List of verified factual strings
124
+ embedder: Optional custom embedder (defaults to MockEmbedder)
125
+ config_preset: Engine configuration preset
126
+ """
127
+ self.embedder = embedder or DeterministicHashEmbedderND()
128
+ self.config = load_config(config_preset)
129
+ self.topic_gate_min_overlap = topic_gate_min_overlap
130
+ self.topic_gate_enabled = topic_gate_enabled
131
+ self.ambiguity_detection_enabled = ambiguity_detection_enabled
132
+ self.substrate_tokens = _token_set(substrate_texts)
133
+
134
+ # Initialize substrate
135
+ self.substrate = VerifiedSubstrate(
136
+ elastic_modulus_mode=self.config.get('elastic_modulus_mode', 'multiplicative'),
137
+ elastic_modulus_sigma=self.config.get('elastic_modulus_sigma', 0.5)
138
+ )
139
+
140
+ # Embed and add substrate states
141
+ for text in substrate_texts:
142
+ vec = self.embedder.embed(text)
143
+ self.substrate.add_verified_state(
144
+ Vector2D(x=vec[0], y=vec[1], properties=None, coords=vec)
145
+ )
146
+
147
+ def _passes_topic_gate(self, text: str) -> bool:
148
+ if not self.topic_gate_enabled:
149
+ return True
150
+ tokens = set(_tokenize(text))
151
+ if not tokens:
152
+ return False
153
+ return len(tokens & self.substrate_tokens) >= self.topic_gate_min_overlap
154
+
155
+ def _is_clarification(self, text: str) -> bool:
156
+ """Detect if the response is asking for clarification due to ambiguity"""
157
+ if not self.ambiguity_detection_enabled:
158
+ return False
159
+
160
+ clarification_markers = [
161
+ "could you please specify",
162
+ "please specify",
163
+ "please clarify",
164
+ "what do you mean",
165
+ "can you provide",
166
+ "no specific topics",
167
+ "no topics were mentioned",
168
+ "which topic"
169
+ ]
170
+ text_lower = text.lower()
171
+ return any(marker in text_lower for marker in clarification_markers)
172
+
173
+ def filter(self, candidates: List[str]) -> Optional[str]:
174
+ """
175
+ Filter a list of candidate outputs (e.g., from an LLM beam search).
176
+ Returns the single surviving "factual" string, or None if all are excluded.
177
+
178
+ Args:
179
+ candidates: List of candidate strings from the LLM
180
+
181
+ Returns:
182
+ The best surviving candidate string, or None (abstention)
183
+ """
184
+ if not candidates:
185
+ return None
186
+
187
+ topic_ok = [self._passes_topic_gate(c) for c in candidates]
188
+ allowed = [(idx, c) for idx, c in enumerate(candidates) if topic_ok[idx]]
189
+ if not allowed:
190
+ return None
191
+
192
+ engine = MaterialFieldEngine(
193
+ self.substrate,
194
+ lambda_min=self.config['lambda_min'],
195
+ lambda_max=self.config['lambda_max'],
196
+ inference_steps=self.config['total_steps']
197
+ )
198
+
199
+ vector_coords = []
200
+ allowed_indices = []
201
+ for idx, c in allowed:
202
+ vec = self.embedder.embed(c)
203
+ vector_coords.append(vec)
204
+ allowed_indices.append(idx)
205
+
206
+ engine.initialize_candidates(vector_coords)
207
+ results = engine.run_inference()
208
+
209
+ final_vector = results.get('final_output')
210
+ if final_vector and final_vector.candidate_index is not None:
211
+ if results.get('hallucination_free', False):
212
+ original_idx = allowed_indices[final_vector.candidate_index]
213
+ return candidates[original_idx]
214
+
215
+ return None
216
+
217
+ def inspect(self, candidates: List[str]) -> Dict:
218
+ """
219
+ Run inference and return full inspection details.
220
+ """
221
+ topic_ok = [self._passes_topic_gate(c) for c in candidates]
222
+ is_clarification = [self._is_clarification(c) for c in candidates]
223
+
224
+ # Allowed for physics: Passes topic gate AND is not a clarification (clarification bypasses physics)
225
+ allowed_indices = [
226
+ i for i, ok in enumerate(topic_ok)
227
+ if ok and not is_clarification[i]
228
+ ]
229
+ allowed_texts = [candidates[i] for i in allowed_indices]
230
+
231
+ if not allowed_texts:
232
+ candidate_metrics = [
233
+ {
234
+ 'phase_log': [],
235
+ 'fractured': True,
236
+ 'fractured_step': 0,
237
+ 'stress': 0.0,
238
+ 'hash': None,
239
+ 'out_of_domain': True,
240
+ }
241
+ for _ in candidates
242
+ ]
243
+ return {
244
+ 'selected_text': None,
245
+ 'metrics': {
246
+ 'final_output': None,
247
+ 'phase_log': [],
248
+ 'total_excluded': len(candidates),
249
+ 'latency_ms': 0.0,
250
+ 'latency_per_step_ms': 0.0,
251
+ 'latency_ns': 0,
252
+ 'latency_per_step_ns': 0,
253
+ 'deterministic': True,
254
+ 'hallucination_free': True,
255
+ 'abstained': True,
256
+ 'final_stress_q': None,
257
+ 'final_stress': None,
258
+ 'max_stress_q': 0,
259
+ 'max_stress': 0.0,
260
+ 'candidates': candidate_metrics,
261
+ 'topic_gate_excluded': len(candidates),
262
+ }
263
+ }
264
+
265
+ engine = MaterialFieldEngine(
266
+ self.substrate,
267
+ lambda_min=self.config['lambda_min'],
268
+ lambda_max=self.config['lambda_max'],
269
+ inference_steps=self.config['total_steps']
270
+ )
271
+
272
+ vector_coords = []
273
+ for c in allowed_texts:
274
+ vector_coords.append(self.embedder.embed(c))
275
+
276
+ engine.initialize_candidates(vector_coords)
277
+ results = engine.run_inference(collect_trace=True)
278
+
279
+ final_vector = results.get('final_output')
280
+ selected_text = None
281
+ if final_vector and final_vector.candidate_index is not None:
282
+ original_idx = allowed_indices[final_vector.candidate_index]
283
+ final_vector.candidate_index = original_idx
284
+ selected_text = candidates[original_idx]
285
+
286
+ allowed_metrics = results.get('candidates', [])
287
+ allowed_map = {orig_idx: j for j, orig_idx in enumerate(allowed_indices)}
288
+ candidate_metrics = []
289
+ for i in range(len(candidates)):
290
+ if not topic_ok[i]:
291
+ candidate_metrics.append({
292
+ 'phase_log': [],
293
+ 'fractured': True,
294
+ 'fractured_step': 0,
295
+ 'stress': 0.0,
296
+ 'hash': None,
297
+ 'out_of_domain': True,
298
+ })
299
+ continue
300
+
301
+ # 2. Check Clarification (Bypass Physics, Auto-Pass)
302
+ if is_clarification[i]:
303
+ candidate_metrics.append({
304
+ 'phase_log': [],
305
+ 'fractured': False,
306
+ 'fractured_step': None,
307
+ 'stress': 0.0,
308
+ 'hash': None,
309
+ 'out_of_domain': False,
310
+ 'is_clarification': True
311
+ })
312
+ continue
313
+
314
+ mapped_idx = allowed_map[i]
315
+ entry = allowed_metrics[mapped_idx]
316
+ entry['out_of_domain'] = False
317
+ candidate_metrics.append(entry)
318
+
319
+ results['candidates'] = candidate_metrics
320
+ results['total_excluded'] = results.get('total_excluded', 0) + (len(candidates) - len(allowed_indices))
321
+ results['topic_gate_excluded'] = len(candidates) - len(allowed_indices)
322
+
323
+ return {
324
+ 'selected_text': selected_text,
325
+ 'metrics': results
326
+ }
327
+
328
+
329
+ def demo_simple():
330
+ """Simple demonstration of the adapter"""
331
+ print("Initializing Deterministic Guardrail...")
332
+
333
+ # 1. Define Ground Truth (Substrate)
334
+ # The system knows these facts are true.
335
+ facts = [
336
+ "The sky is blue",
337
+ "Water is wet",
338
+ "Paris is the capital of France"
339
+ ]
340
+
341
+ guard = DeterministicGuardrail(substrate_texts=facts)
342
+
343
+ print(f"Substrate loaded with {len(facts)} verified facts.")
344
+
345
+ # 2. Test Cases
346
+ scenarios = [
347
+ {
348
+ "name": "Factual Consistency",
349
+ "candidates": ["The sky is blue", "The sky is green"]
350
+ },
351
+ {
352
+ "name": "Hallucination Check",
353
+ "candidates": ["The moon is made of cheese", "The moon is made of rock"]
354
+ },
355
+ {
356
+ "name": "Subtle Error",
357
+ "candidates": ["Paris is in Germany", "Paris is in France"]
358
+ }
359
+ ]
360
+
361
+ print("\nRunning Scenarios:\n")
362
+
363
+ for sc in scenarios:
364
+ print(f"--- Scenario: {sc['name']} ---")
365
+ print(f"Candidates: {sc['candidates']}")
366
+
367
+ result = guard.filter(sc['candidates'])
368
+
369
+ if result:
370
+ print(f"✅ PASSED: Selected '{result}'")
371
+ else:
372
+ print(f"🛡️ ABSTAINED: All candidates excluded (Prevention mode)")
373
+ print()
374
+
375
+
376
+ if __name__ == "__main__":
377
+ demo_simple()
material_field_engine.py ADDED
@@ -0,0 +1,928 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Deterministic Material-Field Governance for Computational Systems
4
+ Deterministic Inference via Latent Material-Field Phase Transitions
5
+
6
+ Reference Implementation - Verhash LLC
7
+ Patent Priority: January 25, 2026
8
+ """
9
+
10
+ import math
11
+ import sys
12
+ from dataclasses import dataclass, field
13
+ from typing import List, Tuple, Optional, Dict
14
+ from enum import Enum
15
+ import time
16
+ import json
17
+ from pathlib import Path
18
+
19
+ if hasattr(sys.stdout, "reconfigure"):
20
+ try:
21
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
22
+ except Exception:
23
+ pass
24
+
25
+
26
+ FP_BITS = 8
27
+ FP_SCALE = 1 << FP_BITS
28
+ FP_HALF = 1 << (FP_BITS - 1)
29
+ FP_ONE = FP_SCALE
30
+
31
+
32
+ def fp_from_float(value: float) -> int:
33
+ return int(round(value * FP_SCALE))
34
+
35
+
36
+ def fp_to_float(value_q: int) -> float:
37
+ return value_q / FP_SCALE
38
+
39
+
40
+ def _fp_round_div(numer: int, denom: int) -> int:
41
+ if denom == 0:
42
+ raise ZeroDivisionError("fixed-point divide by zero")
43
+ sign = 1 if (numer >= 0) == (denom >= 0) else -1
44
+ numer_abs = abs(numer)
45
+ denom_abs = abs(denom)
46
+ return sign * ((numer_abs + denom_abs // 2) // denom_abs)
47
+
48
+
49
+ def fp_mul(a_q: int, b_q: int) -> int:
50
+ prod = a_q * b_q
51
+ if prod >= 0:
52
+ return (prod + FP_HALF) >> FP_BITS
53
+ return -(((-prod) + FP_HALF) >> FP_BITS)
54
+
55
+
56
+ def fp_div(a_q: int, b_q: int) -> int:
57
+ return _fp_round_div(a_q << FP_BITS, b_q)
58
+
59
+
60
+ def fp_div_int(a_q: int, denom: int) -> int:
61
+ return _fp_round_div(a_q, denom)
62
+
63
+
64
+ def fp_from_ratio(numer: int, denom: int) -> int:
65
+ if denom == 0:
66
+ raise ZeroDivisionError("fixed-point ratio divide by zero")
67
+ sign = 1 if (numer >= 0) == (denom >= 0) else -1
68
+ numer_abs = abs(numer)
69
+ denom_abs = abs(denom)
70
+ return sign * ((numer_abs << FP_BITS) + denom_abs // 2) // denom_abs
71
+
72
+
73
+ def fp_sqrt(value_q: int) -> int:
74
+ if value_q <= 0:
75
+ return 0
76
+ return math.isqrt(value_q * FP_SCALE)
77
+
78
+
79
+ _EXP_NEG_INT_Q = [
80
+ 256, 94, 35, 13, 5, 2, 1, 0, 0, 0, 0
81
+ ]
82
+
83
+
84
+ def fp_exp_neg(value_q: int) -> int:
85
+ if value_q <= 0:
86
+ return FP_ONE
87
+ k = value_q >> FP_BITS
88
+ if k >= len(_EXP_NEG_INT_Q):
89
+ return 0
90
+ r_q = value_q & (FP_SCALE - 1)
91
+ r2 = fp_mul(r_q, r_q)
92
+ r3 = fp_mul(r2, r_q)
93
+ r4 = fp_mul(r3, r_q)
94
+ r5 = fp_mul(r4, r_q)
95
+ term = FP_ONE
96
+ term -= r_q
97
+ term += fp_div_int(r2, 2)
98
+ term -= fp_div_int(r3, 6)
99
+ term += fp_div_int(r4, 24)
100
+ term -= fp_div_int(r5, 120)
101
+ return fp_mul(_EXP_NEG_INT_Q[k], term)
102
+
103
+
104
+ class Phase(Enum):
105
+ """Material phase states during inference"""
106
+ NUCLEATION = 1 # t < 0.5T: Low pressure, exploration
107
+ QUENCHING = 2 # 0.5T ≤ t < 0.9T: Progressive solidification
108
+ CRYSTALLIZATION = 3 # t ≥ 0.9T: Final crystalline structure
109
+
110
+
111
+ @dataclass
112
+ class MaterialProperties:
113
+ """Intrinsic structural properties of semantic states"""
114
+ elastic_modulus_q: int # E: Structural rigidity (Q24.8)
115
+ yield_strength_q: int # sigma_y: Fracture threshold (Q24.8)
116
+ strain_q: int # epsilon: Deviation from grounded state (Q24.8)
117
+ stress_q: int # sigma: Applied constraint pressure (Q24.8)
118
+
119
+ def is_fractured(self) -> bool:
120
+ """Check if vector exceeds yield strength"""
121
+ return self.stress_q > self.yield_strength_q
122
+
123
+ @property
124
+ def elastic_modulus(self) -> float:
125
+ return fp_to_float(self.elastic_modulus_q)
126
+
127
+ @property
128
+ def yield_strength(self) -> float:
129
+ return fp_to_float(self.yield_strength_q)
130
+
131
+ @property
132
+ def strain(self) -> float:
133
+ return fp_to_float(self.strain_q)
134
+
135
+ @property
136
+ def stress(self) -> float:
137
+ return fp_to_float(self.stress_q)
138
+
139
+
140
+ @dataclass
141
+ class Vector2D:
142
+ """2D latent space vector with material properties (supports N-D coords)"""
143
+ x: float
144
+ y: float
145
+ properties: MaterialProperties
146
+ substrate_aligned: bool = False
147
+ candidate_index: Optional[int] = None
148
+ coords: Optional[List[float]] = None
149
+ x_q: int = field(init=False)
150
+ y_q: int = field(init=False)
151
+ coords_q: List[int] = field(init=False)
152
+
153
+ def __post_init__(self) -> None:
154
+ if self.coords is None:
155
+ self.coords = [self.x, self.y]
156
+ else:
157
+ # Ensure x/y reflect the first two coordinates for visualization.
158
+ if len(self.coords) < 2:
159
+ raise ValueError("coords must contain at least 2 dimensions")
160
+ self.x = float(self.coords[0])
161
+ self.y = float(self.coords[1])
162
+
163
+ self.coords_q = [fp_from_float(v) for v in self.coords]
164
+ self.x_q = self.coords_q[0]
165
+ self.y_q = self.coords_q[1]
166
+
167
+ def distance_to(self, other: 'Vector2D') -> float:
168
+ """Euclidean distance between vectors"""
169
+ return fp_to_float(self.distance_to_q(other))
170
+
171
+ def distance_to_q(self, other: 'Vector2D') -> int:
172
+ if len(self.coords_q) != len(other.coords_q):
173
+ raise ValueError("Vector dimensionality mismatch")
174
+ total = 0
175
+ for a_q, b_q in zip(self.coords_q, other.coords_q):
176
+ d_q = a_q - b_q
177
+ total += fp_mul(d_q, d_q)
178
+ return fp_sqrt(total)
179
+
180
+ def dot_product(self, substrate: 'Vector2D') -> float:
181
+ """Compute normalized alignment with substrate via dot product"""
182
+ return fp_to_float(self.dot_product_q(substrate))
183
+
184
+ def dot_product_q(self, substrate: 'Vector2D') -> int:
185
+ if len(self.coords_q) != len(substrate.coords_q):
186
+ raise ValueError("Vector dimensionality mismatch")
187
+ self_norm = 0
188
+ substrate_norm = 0
189
+ dot_q = 0
190
+ for a_q, b_q in zip(self.coords_q, substrate.coords_q):
191
+ dot_q += fp_mul(a_q, b_q)
192
+ self_norm += fp_mul(a_q, a_q)
193
+ substrate_norm += fp_mul(b_q, b_q)
194
+
195
+ self_norm = fp_sqrt(self_norm)
196
+ substrate_norm = fp_sqrt(substrate_norm)
197
+ if self_norm == 0 or substrate_norm == 0:
198
+ return 0
199
+ denom_q = fp_mul(self_norm, substrate_norm)
200
+ return fp_div(dot_q, denom_q)
201
+ class SemanticClass(Enum):
202
+ """Semantic classes with different yield strengths"""
203
+ VERIFIED_FACT = (fp_from_float(0.90), fp_from_float(0.98)) # High persistence
204
+ CONTEXTUAL = (fp_from_float(0.65), fp_from_float(0.75)) # Moderate stability
205
+ CREATIVE = (fp_from_float(0.40), fp_from_float(0.55)) # Viscoelastic flexibility
206
+ SPECULATIVE = (fp_from_float(0.0), fp_from_float(0.25)) # Brittle, early fracture
207
+
208
+ def __init__(self, min_yield: int, max_yield: int):
209
+ self.min_yield = min_yield
210
+ self.max_yield = max_yield
211
+ class PhaseTransitionController:
212
+ """
213
+ Controls material phase transitions through progressive constraint pressure.
214
+ Implements the three-phase solidification process.
215
+ """
216
+
217
+ def __init__(self,
218
+ lambda_min: float = 0.30,
219
+ lambda_max: float = 0.90,
220
+ total_steps: int = 8):
221
+ """
222
+ Args:
223
+ lambda_min: Minimum pressure during nucleation
224
+ lambda_max: Maximum pressure during crystallization
225
+ total_steps: Number of inference steps
226
+ """
227
+ self.lambda_min = lambda_min
228
+ self.lambda_max = lambda_max
229
+ self.lambda_min_q = fp_from_float(lambda_min)
230
+ self.lambda_max_q = fp_from_float(lambda_max)
231
+ self.total_steps = total_steps
232
+ self.current_step = 0
233
+
234
+ # Phase transition thresholds (stored in fixed-point)
235
+ self._nucleation_threshold_q = fp_from_float(0.5)
236
+ self._quenching_threshold_q = fp_from_float(0.9)
237
+
238
+ @property
239
+ def nucleation_threshold(self) -> float:
240
+ return fp_to_float(self._nucleation_threshold_q)
241
+
242
+ @nucleation_threshold.setter
243
+ def nucleation_threshold(self, value: float) -> None:
244
+ self._nucleation_threshold_q = fp_from_float(value)
245
+
246
+ @property
247
+ def quenching_threshold(self) -> float:
248
+ return fp_to_float(self._quenching_threshold_q)
249
+
250
+ @quenching_threshold.setter
251
+ def quenching_threshold(self, value: float) -> None:
252
+ self._quenching_threshold_q = fp_from_float(value)
253
+
254
+ def _current_t_q(self) -> int:
255
+ if self.total_steps <= 1:
256
+ return FP_ONE
257
+ return fp_from_ratio(self.current_step, self.total_steps - 1)
258
+
259
+ def get_current_phase(self) -> Phase:
260
+ """Determine current material phase"""
261
+ if self.total_steps <= 1:
262
+ return Phase.CRYSTALLIZATION
263
+
264
+ t_q = self._current_t_q()
265
+
266
+ if t_q < self._nucleation_threshold_q:
267
+ return Phase.NUCLEATION
268
+ if t_q < self._quenching_threshold_q:
269
+ return Phase.QUENCHING
270
+ return Phase.CRYSTALLIZATION
271
+
272
+ def get_constraint_pressure_q(self) -> int:
273
+ """
274
+ Compute time-dependent constraint pressure lambda(t) in fixed-point.
275
+ """
276
+ if self.total_steps <= 1:
277
+ return self.lambda_max_q
278
+
279
+ t_q = self._current_t_q()
280
+ phase = self.get_current_phase()
281
+
282
+ if phase == Phase.NUCLEATION:
283
+ return self.lambda_min_q
284
+
285
+ if phase == Phase.QUENCHING:
286
+ denom = self._quenching_threshold_q - self._nucleation_threshold_q
287
+ if denom == 0:
288
+ return self.lambda_max_q
289
+ progress_q = fp_div(t_q - self._nucleation_threshold_q, denom)
290
+ return self.lambda_min_q + fp_mul(self.lambda_max_q - self.lambda_min_q, progress_q)
291
+
292
+ return self.lambda_max_q
293
+
294
+ def get_constraint_pressure(self) -> float:
295
+ return fp_to_float(self.get_constraint_pressure_q())
296
+
297
+ def advance(self):
298
+ """Advance to next time step"""
299
+ self.current_step += 1
300
+
301
+ def reset(self):
302
+ """Reset to initial state"""
303
+ self.current_step = 0
304
+ class VerifiedSubstrate:
305
+ """
306
+ Verified substrate containing ground-truth states.
307
+ Acts as the fixed reference frame for elastic modulus computation.
308
+ """
309
+
310
+ def __init__(self, verified_states: Optional[List[Vector2D]] = None,
311
+ elastic_modulus_mode: str = 'cosine',
312
+ elastic_modulus_sigma: float = 0.5):
313
+ self.states: List[Vector2D] = verified_states or []
314
+ self.elastic_modulus_mode = elastic_modulus_mode
315
+ self.elastic_modulus_sigma = elastic_modulus_sigma
316
+
317
+ def add_verified_state(self, vector: Vector2D):
318
+ """Add a verified state to substrate"""
319
+ vector.substrate_aligned = True
320
+ self.states.append(vector)
321
+
322
+ def compute_elastic_modulus(self, candidate: Vector2D) -> int:
323
+ """
324
+ Compute elastic modulus E via alignment with substrate (fixed-point).
325
+
326
+ Modes:
327
+ - 'cosine': Pure angular alignment (direction-based)
328
+ - 'multiplicative': Alignment x proximity (requires both)
329
+ - 'rbf': Pure proximity (distance-based, RBF kernel)
330
+
331
+ High E = diamond-like, factual
332
+ Low E = glass-like, speculative
333
+ """
334
+ if not self.states:
335
+ return fp_from_float(0.5)
336
+
337
+ alignments = [candidate.dot_product_q(state) for state in self.states]
338
+ distances = [candidate.distance_to_q(state) for state in self.states]
339
+
340
+ max_idx = max(range(len(alignments)), key=alignments.__getitem__)
341
+ best_alignment = alignments[max_idx]
342
+ best_distance = distances[max_idx]
343
+
344
+ alignment_term = fp_div_int(best_alignment + FP_ONE, 2)
345
+
346
+ sigma_q = fp_from_float(self.elastic_modulus_sigma)
347
+ sigma2 = fp_mul(sigma_q, sigma_q)
348
+ if sigma2 == 0:
349
+ proximity_term = 0
350
+ else:
351
+ d2 = fp_mul(best_distance, best_distance)
352
+
353
+ # Normalize by D to prevent RBF collapse
354
+ if len(candidate.coords_q) > 1:
355
+ dim_k = len(candidate.coords_q)
356
+ d2 = fp_div_int(d2, dim_k)
357
+
358
+ denom = sigma2 * 2
359
+ x_q = fp_div(d2, denom)
360
+ proximity_term = fp_exp_neg(x_q)
361
+
362
+ if self.elastic_modulus_mode == 'cosine':
363
+ return alignment_term
364
+ if self.elastic_modulus_mode == 'multiplicative':
365
+ return fp_mul(alignment_term, proximity_term)
366
+ if self.elastic_modulus_mode == 'rbf':
367
+ return proximity_term
368
+ raise ValueError(f"Unknown elastic_modulus_mode: {self.elastic_modulus_mode}")
369
+
370
+ def compute_strain(self, candidate: Vector2D) -> int:
371
+ """
372
+ Compute strain epsilon as deviation distance from nearest grounded state.
373
+ Uses fixed-point Euclidean distance.
374
+ """
375
+ if not self.states:
376
+ return FP_ONE
377
+
378
+ distances = [candidate.distance_to_q(state) for state in self.states]
379
+ min_dist_q = min(distances)
380
+
381
+ # Normalize strain by sqrt(D)
382
+ if candidate.coords_q and len(candidate.coords_q) > 1:
383
+ dim_root_q = fp_sqrt(len(candidate.coords_q) << FP_BITS)
384
+ if dim_root_q > 0:
385
+ min_dist_q = fp_div(min_dist_q, dim_root_q)
386
+
387
+ return min_dist_q
388
+ class MaterialFieldEngine:
389
+ """
390
+ Main inference engine implementing deterministic material-field governance.
391
+ Replaces stochastic sampling with mechanical constraint dynamics.
392
+ """
393
+
394
+ def __init__(self,
395
+ substrate: VerifiedSubstrate,
396
+ lambda_min: float = 0.30,
397
+ lambda_max: float = 0.90,
398
+ inference_steps: int = 8):
399
+ """
400
+ Args:
401
+ substrate: Verified substrate for grounding
402
+ lambda_min: Minimum constraint pressure
403
+ lambda_max: Maximum constraint pressure
404
+ inference_steps: Number of phase transition steps
405
+ """
406
+ self.substrate = substrate
407
+ self.phase_controller = PhaseTransitionController(lambda_min, lambda_max, inference_steps)
408
+ self.candidate_vectors: List[Vector2D] = []
409
+ self.excluded_vectors: List[Vector2D] = []
410
+ self.final_output: Optional[Vector2D] = None
411
+ self.max_stress_q: int = 0
412
+ self._all_candidates: List[Vector2D] = []
413
+ self._initial_candidate_count: int = 0
414
+
415
+ # Performance metrics
416
+ self.inference_start_time = 0.0
417
+ self.inference_end_time = 0.0
418
+
419
+ def _compute_material_properties(self, vector: Vector2D) -> MaterialProperties:
420
+ """Compute intrinsic material properties for a candidate vector"""
421
+ E_q = self.substrate.compute_elastic_modulus(vector)
422
+ epsilon_q = self.substrate.compute_strain(vector)
423
+ sigma_q = fp_mul(E_q, epsilon_q)
424
+
425
+ import hashlib
426
+ vector_bytes = ",".join(str(v) for v in vector.coords_q).encode('utf-8')
427
+ stable_hash = int(hashlib.blake2b(vector_bytes, digest_size=8).hexdigest(), 16)
428
+
429
+ if E_q > fp_from_float(0.90):
430
+ class_range = SemanticClass.VERIFIED_FACT.value
431
+ elif E_q > fp_from_float(0.65):
432
+ class_range = SemanticClass.CONTEXTUAL.value
433
+ elif E_q > fp_from_float(0.40):
434
+ class_range = SemanticClass.CREATIVE.value
435
+ else:
436
+ class_range = SemanticClass.SPECULATIVE.value
437
+
438
+ normalized_q = fp_from_ratio(stable_hash % 1000000, 1000000)
439
+ sigma_y_q = class_range[0] + fp_mul(normalized_q, class_range[1] - class_range[0])
440
+
441
+ return MaterialProperties(
442
+ elastic_modulus_q=E_q,
443
+ yield_strength_q=sigma_y_q,
444
+ strain_q=epsilon_q,
445
+ stress_q=sigma_q
446
+ )
447
+
448
+ def _mechanical_exclusion(
449
+ self,
450
+ lambda_current_q: int,
451
+ step: Optional[int] = None,
452
+ phase: Optional[Phase] = None,
453
+ trace_log: Optional[Dict[int, List[Dict[str, float]]]] = None,
454
+ fractured_steps: Optional[Dict[int, Optional[int]]] = None,
455
+ ) -> Tuple[List[Vector2D], List[int]]:
456
+ """
457
+ Apply mechanical exclusion filter with balanced stress mechanics.
458
+
459
+ Stress accumulation formula:
460
+ sigma_effective = sigma_base + lambda(t) * epsilon * (1 - E/2)
461
+ """
462
+ survivors: List[Vector2D] = []
463
+ excluded_indices: List[int] = []
464
+
465
+ for vector in self.candidate_vectors:
466
+ elastic_resistance_q = FP_ONE - fp_div_int(vector.properties.elastic_modulus_q, 2)
467
+ stress_increment_q = fp_mul(fp_mul(lambda_current_q, vector.properties.strain_q), elastic_resistance_q)
468
+ previous_stress_q = vector.properties.stress_q
469
+ effective_stress_q = previous_stress_q + stress_increment_q
470
+ fractured = effective_stress_q > vector.properties.yield_strength_q
471
+
472
+ if effective_stress_q > self.max_stress_q:
473
+ self.max_stress_q = effective_stress_q
474
+
475
+ if trace_log is not None and vector.candidate_index is not None:
476
+ trace_log[vector.candidate_index].append({
477
+ "step": int(step) if step is not None else 0,
478
+ "phase": phase.name if phase is not None else "",
479
+ "pressure": fp_to_float(lambda_current_q),
480
+ "elastic_modulus": fp_to_float(vector.properties.elastic_modulus_q),
481
+ "delta_stress": fp_to_float(effective_stress_q - previous_stress_q),
482
+ "stress": fp_to_float(effective_stress_q),
483
+ "fractured": fractured,
484
+ })
485
+ if fractured_steps is not None and fractured_steps.get(vector.candidate_index) is None and fractured:
486
+ fractured_steps[vector.candidate_index] = int(step) if step is not None else 0
487
+
488
+ if fractured:
489
+ vector.properties.stress_q = effective_stress_q
490
+ self.excluded_vectors.append(vector)
491
+ if vector.candidate_index is not None:
492
+ excluded_indices.append(vector.candidate_index)
493
+ else:
494
+ vector.properties.stress_q = effective_stress_q
495
+ survivors.append(vector)
496
+
497
+ return survivors, excluded_indices
498
+
499
+ def initialize_candidates(self, initial_vectors: List[List[float]]):
500
+ """
501
+ Initialize candidate vectors in the latent field.
502
+
503
+ Args:
504
+ initial_vectors: List of coordinate lists (length >= 2)
505
+ """
506
+ self.candidate_vectors = []
507
+ self._all_candidates = []
508
+ self._initial_candidate_count = 0
509
+
510
+ for idx, coords in enumerate(initial_vectors):
511
+ if len(coords) < 2:
512
+ raise ValueError("candidate vector must have at least 2 dimensions")
513
+ vector = Vector2D(x=coords[0], y=coords[1], properties=None, coords=list(coords))
514
+ vector.properties = self._compute_material_properties(vector)
515
+ vector.candidate_index = idx
516
+ self.candidate_vectors.append(vector)
517
+ self._all_candidates.append(vector)
518
+ self._initial_candidate_count += 1
519
+
520
+ def inference_step(
521
+ self,
522
+ step: int,
523
+ trace_log: Optional[Dict[int, List[Dict[str, float]]]] = None,
524
+ fractured_steps: Optional[Dict[int, Optional[int]]] = None,
525
+ ) -> Tuple[Phase, int, int, List[int]]:
526
+ """
527
+ Execute single inference step with phase transition.
528
+
529
+ Returns:
530
+ (current_phase, surviving_count, constraint_pressure_q, excluded_indices)
531
+ """
532
+ phase = self.phase_controller.get_current_phase()
533
+ lambda_current_q = self.phase_controller.get_constraint_pressure_q()
534
+
535
+ self.candidate_vectors, excluded_indices = self._mechanical_exclusion(
536
+ lambda_current_q,
537
+ step=step,
538
+ phase=phase,
539
+ trace_log=trace_log,
540
+ fractured_steps=fractured_steps,
541
+ )
542
+
543
+ self.phase_controller.advance()
544
+
545
+ return phase, len(self.candidate_vectors), lambda_current_q, excluded_indices
546
+
547
+ def run_inference(self, collect_trace: bool = False) -> Dict:
548
+ """
549
+ Run complete inference cycle through all phase transitions.
550
+
551
+ Returns:
552
+ Dictionary with inference results and metrics
553
+ """
554
+ self.inference_start_time = time.perf_counter_ns()
555
+ self.phase_controller.reset()
556
+
557
+ self.excluded_vectors = []
558
+ self.max_stress_q = 0
559
+
560
+ trace_log = None
561
+ fractured_steps = None
562
+ if collect_trace:
563
+ trace_log = {i: [] for i in range(self._initial_candidate_count)}
564
+ fractured_steps = {i: None for i in range(self._initial_candidate_count)}
565
+
566
+ phase_log = []
567
+
568
+ for step in range(self.phase_controller.total_steps):
569
+ phase, survivors, pressure_q, excluded_indices = self.inference_step(
570
+ step,
571
+ trace_log=trace_log,
572
+ fractured_steps=fractured_steps,
573
+ )
574
+
575
+ phase_log.append({
576
+ 'step': step,
577
+ 'phase': phase.name,
578
+ 'survivors': survivors,
579
+ 'pressure': fp_to_float(pressure_q),
580
+ 'excluded': len(excluded_indices),
581
+ 'excluded_indices': excluded_indices,
582
+ })
583
+
584
+ if survivors == 0:
585
+ break
586
+
587
+ if phase == Phase.CRYSTALLIZATION and survivors == 1:
588
+ break
589
+
590
+ if self.candidate_vectors:
591
+ self.final_output = self.candidate_vectors[0]
592
+ else:
593
+ self.final_output = None
594
+
595
+ self.inference_end_time = time.perf_counter_ns()
596
+ latency_ns = self.inference_end_time - self.inference_start_time
597
+ latency_ms = latency_ns / 1e6
598
+
599
+ hallucination_free = False
600
+ if self.final_output:
601
+ hallucination_free = (
602
+ self.final_output.substrate_aligned or
603
+ self.final_output.properties.elastic_modulus_q > fp_from_float(0.65)
604
+ )
605
+ else:
606
+ hallucination_free = True
607
+
608
+ final_stress_q = self.final_output.properties.stress_q if self.final_output else self.max_stress_q
609
+ final_stress = fp_to_float(final_stress_q) if final_stress_q is not None else 0.0
610
+ max_stress = fp_to_float(self.max_stress_q)
611
+
612
+ candidate_metrics = None
613
+ if collect_trace and trace_log is not None:
614
+ candidate_metrics = []
615
+ for i in range(self._initial_candidate_count):
616
+ trace = trace_log[i]
617
+ fractured_step = fractured_steps[i] if fractured_steps is not None else None
618
+ fractured = fractured_step is not None
619
+ if trace:
620
+ candidate_final_stress = trace[-1]["stress"]
621
+ else:
622
+ candidate_final_stress = fp_to_float(self._all_candidates[i].properties.stress_q)
623
+ candidate_metrics.append({
624
+ "phase_log": trace,
625
+ "fractured": fractured,
626
+ "fractured_step": fractured_step,
627
+ "stress": candidate_final_stress,
628
+ "hash": None,
629
+ })
630
+
631
+ results = {
632
+ 'final_output': self.final_output,
633
+ 'phase_log': phase_log,
634
+ 'total_excluded': len(self.excluded_vectors),
635
+ 'latency_ms': latency_ms,
636
+ 'latency_per_step_ms': latency_ms / self.phase_controller.total_steps if self.phase_controller.total_steps > 0 else 0.0,
637
+ 'latency_ns': latency_ns,
638
+ 'latency_per_step_ns': latency_ns / self.phase_controller.total_steps if self.phase_controller.total_steps > 0 else 0,
639
+ 'deterministic': True,
640
+ 'hallucination_free': hallucination_free,
641
+ 'abstained': self.final_output is None,
642
+ 'final_stress_q': final_stress_q,
643
+ 'final_stress': final_stress,
644
+ 'max_stress_q': self.max_stress_q,
645
+ 'max_stress': max_stress,
646
+ }
647
+ if candidate_metrics is not None:
648
+ results['candidates'] = candidate_metrics
649
+ return results
650
+
651
+ def get_audit_trail(self) -> List[Dict]:
652
+ """
653
+ Generate complete audit trail showing evidentiary support.
654
+ Critical for regulatory compliance.
655
+ """
656
+ audit = []
657
+
658
+ if self.final_output:
659
+ # Trace substrate support
660
+ substrate_support = [
661
+ {
662
+ 'substrate_vector': (s.x, s.y),
663
+ 'alignment': self.final_output.dot_product(s)
664
+ }
665
+ for s in self.substrate.states
666
+ ]
667
+
668
+ audit.append({
669
+ 'output': (self.final_output.x, self.final_output.y),
670
+ 'elastic_modulus': self.final_output.properties.elastic_modulus,
671
+ 'yield_strength': self.final_output.properties.yield_strength,
672
+ 'final_stress': self.final_output.properties.stress,
673
+ 'substrate_support': substrate_support,
674
+ 'grounded': self.final_output.substrate_aligned or
675
+ self.final_output.properties.elastic_modulus > 0.65
676
+ })
677
+
678
+ return audit
679
+
680
+
681
+ def load_config(preset: Optional[str] = None) -> Dict:
682
+ """
683
+ Load configuration from config.json, optionally using a preset.
684
+
685
+ Args:
686
+ preset: Name of preset to load (conservative, balanced, aggressive, mission_critical)
687
+
688
+ Returns:
689
+ Configuration dictionary
690
+ """
691
+ config_path = Path(__file__).parent / "config.json"
692
+
693
+ if not config_path.exists():
694
+ # Return default balanced config
695
+ return {
696
+ "lambda_min": 0.40,
697
+ "lambda_max": 1.20,
698
+ "nucleation_threshold": 0.40,
699
+ "quenching_threshold": 0.80,
700
+ "total_steps": 8,
701
+ "elastic_modulus_mode": "multiplicative",
702
+ "elastic_modulus_sigma": 0.5
703
+ }
704
+
705
+ with open(config_path) as f:
706
+ config_data = json.load(f)
707
+
708
+ if preset and preset in config_data.get("presets", {}):
709
+ preset_config = config_data["presets"][preset]
710
+ return {
711
+ "lambda_min": preset_config["lambda_min"],
712
+ "lambda_max": preset_config["lambda_max"],
713
+ "nucleation_threshold": preset_config["nucleation_threshold"],
714
+ "quenching_threshold": preset_config["quenching_threshold"],
715
+ "total_steps": preset_config["total_steps"],
716
+ "elastic_modulus_mode": preset_config.get("elastic_modulus_mode", "multiplicative"),
717
+ "elastic_modulus_sigma": preset_config.get("elastic_modulus_sigma", 0.5)
718
+ }
719
+ else:
720
+ # Use main config
721
+ elastic_modulus_config = config_data.get("elastic_modulus", {})
722
+ return {
723
+ "lambda_min": config_data["constraint_pressure"]["lambda_min"],
724
+ "lambda_max": config_data["constraint_pressure"]["lambda_max"],
725
+ "nucleation_threshold": config_data["phase_transitions"]["nucleation_threshold"],
726
+ "quenching_threshold": config_data["phase_transitions"]["quenching_threshold"],
727
+ "total_steps": config_data["inference"]["total_steps"],
728
+ "elastic_modulus_mode": elastic_modulus_config.get("mode", "multiplicative"),
729
+ "elastic_modulus_sigma": elastic_modulus_config.get("sigma", 0.5)
730
+ }
731
+
732
+
733
+ def demo_natural_language_query(config=None):
734
+ """
735
+ Example 1: Natural Language Query Answering
736
+ Input: "What is the capital of France?"
737
+ Substrate: Verified geography database
738
+ """
739
+ if config is None:
740
+ config = {'lambda_min': 0.30, 'lambda_max': 0.90, 'total_steps': 8,
741
+ 'elastic_modulus_mode': 'multiplicative', 'elastic_modulus_sigma': 0.5}
742
+
743
+ print("=" * 80)
744
+ print("EXAMPLE 1: Natural Language Query - 'What is the capital of France?'")
745
+ print("=" * 80)
746
+
747
+ # Create verified substrate with elastic modulus configuration
748
+ substrate = VerifiedSubstrate(
749
+ elastic_modulus_mode=config.get('elastic_modulus_mode', 'multiplicative'),
750
+ elastic_modulus_sigma=config.get('elastic_modulus_sigma', 0.5)
751
+ )
752
+
753
+ # Add verified facts (in real implementation, these would be embeddings)
754
+ # Simulating: Paris ↔ France capital (high confidence)
755
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
756
+
757
+ # Initialize engine
758
+ engine = MaterialFieldEngine(
759
+ substrate,
760
+ lambda_min=config['lambda_min'],
761
+ lambda_max=config['lambda_max'],
762
+ inference_steps=config['total_steps']
763
+ )
764
+
765
+ # Update phase controller thresholds if provided
766
+ if 'nucleation_threshold' in config:
767
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
768
+ if 'quenching_threshold' in config:
769
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
770
+
771
+ # Initialize candidates (would come from model's latent space)
772
+ # Simulating candidates: "Paris" (high E), "Lyon" (medium E), "Marseille" (medium E)
773
+ candidates = [
774
+ (0.95, 0.92), # Paris - near verified state
775
+ (0.35, 0.30), # Lyon - further away
776
+ (0.30, 0.25), # Marseille - further away
777
+ ]
778
+
779
+ engine.initialize_candidates(candidates)
780
+
781
+ print(f"\nInitialized {len(engine.candidate_vectors)} candidate vectors")
782
+ print("\nCandidate Properties:")
783
+ for i, v in enumerate(engine.candidate_vectors):
784
+ print(f" Candidate {i}: E={v.properties.elastic_modulus:.3f}, "
785
+ f"σ_y={v.properties.yield_strength:.3f}, ε={v.properties.strain:.3f}")
786
+
787
+ # Run inference
788
+ results = engine.run_inference()
789
+
790
+ print("\n" + "-" * 80)
791
+ print("PHASE TRANSITION LOG:")
792
+ print("-" * 80)
793
+ for entry in results['phase_log']:
794
+ print(f"Step {entry['step']}: {entry['phase']:15s} | "
795
+ f"λ={entry['pressure']:.3f} | Survivors={entry['survivors']} | "
796
+ f"Excluded={entry['excluded']}")
797
+
798
+ print("\n" + "-" * 80)
799
+ print("RESULTS:")
800
+ print("-" * 80)
801
+ if results['final_output']:
802
+ print(f"Output: ({results['final_output'].x:.3f}, {results['final_output'].y:.3f})")
803
+ print(f"Elastic Modulus: {results['final_output'].properties.elastic_modulus:.3f}")
804
+ print(f"Final Stress: {results['final_output'].properties.stress:.3f}")
805
+ print(f"Total Excluded: {results['total_excluded']}")
806
+ print(f"Inference Latency: {results['latency_ms']:.3f} ms")
807
+ print(f"Per-Step Latency: {results['latency_per_step_ms']:.6f} ms")
808
+ print(f"Deterministic: {results['deterministic']}")
809
+
810
+ # Audit trail
811
+ print("\n" + "-" * 80)
812
+ print("AUDIT TRAIL:")
813
+ print("-" * 80)
814
+ audit = engine.get_audit_trail()
815
+ for entry in audit:
816
+ print(f"Output Vector: {entry['output']}")
817
+ print(f"Grounded: {entry['grounded']}")
818
+ print(f"Substrate Support: {len(entry['substrate_support'])} verified states")
819
+
820
+ print()
821
+
822
+
823
+ def demo_autonomous_obstacle_detection(config=None):
824
+ """
825
+ Example 2: Autonomous Vehicle Obstacle Detection
826
+ Shows how mechanical exclusion prevents false positives
827
+ """
828
+ if config is None:
829
+ config = {'lambda_min': 0.30, 'lambda_max': 0.90, 'total_steps': 8,
830
+ 'elastic_modulus_mode': 'multiplicative', 'elastic_modulus_sigma': 0.5}
831
+
832
+ print("=" * 80)
833
+ print("EXAMPLE 2: Autonomous Vehicle Obstacle Detection")
834
+ print("=" * 80)
835
+
836
+ # Substrate: Verified object models (vehicles, pedestrians, signs)
837
+ substrate = VerifiedSubstrate(
838
+ elastic_modulus_mode=config.get('elastic_modulus_mode', 'multiplicative'),
839
+ elastic_modulus_sigma=config.get('elastic_modulus_sigma', 0.5)
840
+ )
841
+ substrate.add_verified_state(Vector2D(x=0.88, y=0.85, properties=None)) # Real vehicle
842
+
843
+ # Initialize engine with tighter constraints for safety-critical system
844
+ engine = MaterialFieldEngine(
845
+ substrate,
846
+ lambda_min=config.get('lambda_min', 0.25),
847
+ lambda_max=config.get('lambda_max', 0.95),
848
+ inference_steps=config.get('total_steps', 8)
849
+ )
850
+
851
+ # Update phase controller thresholds if provided
852
+ if 'nucleation_threshold' in config:
853
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
854
+ if 'quenching_threshold' in config:
855
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
856
+
857
+ # Candidates: Real obstacles vs sensor noise
858
+ candidates = [
859
+ (0.88, 0.83), # Real obstacle - high confidence
860
+ (0.15, 0.12), # Sensor noise - low confidence
861
+ ]
862
+
863
+ engine.initialize_candidates(candidates)
864
+
865
+ print(f"\nDetection Candidates: {len(engine.candidate_vectors)}")
866
+ for i, v in enumerate(engine.candidate_vectors):
867
+ print(f" Candidate {i}: E={v.properties.elastic_modulus:.3f}, "
868
+ f"σ_y={v.properties.yield_strength:.3f}")
869
+
870
+ results = engine.run_inference()
871
+
872
+ print("\n" + "-" * 80)
873
+ print("DETECTION RESULTS:")
874
+ print("-" * 80)
875
+ print(f"Valid Detections: {1 if results['final_output'] else 0}")
876
+ print(f"False Positives Excluded: {results['total_excluded']}")
877
+ print(f"System Latency: {results['latency_ms']:.3f} ms")
878
+
879
+ print("\nResult: No 'phantom pedestrian' false positives.\n")
880
+
881
+
882
+ if __name__ == "__main__":
883
+ import sys
884
+
885
+ print("""
886
+ ╔══════════════════════════════════════════════════════════════════════════════╗
887
+ ║ ║
888
+ ║ DETERMINISTIC MATERIAL-FIELD GOVERNANCE FOR COMPUTATIONAL SYSTEMS ║
889
+ ║ Deterministic Inference via Phase Transitions ║
890
+ ║ ║
891
+ ║ Patent Priority: January 25, 2026 ║
892
+ ║ Inventor: Ryan S. Walters ║
893
+ ║ Applicant: Verhash LLC ║
894
+ ║ ║
895
+ ╚═══════════════════════════════════════════════════════════════════════��══════╝
896
+ """)
897
+
898
+ # Load config - support preset selection via command line
899
+ # Usage: python material_field_engine.py [preset_name]
900
+ # Presets: conservative, balanced, aggressive, mission_critical
901
+ preset = sys.argv[1] if len(sys.argv) > 1 else None
902
+ config = load_config(preset)
903
+
904
+ if preset:
905
+ print(f"\n📋 Using '{preset}' preset configuration")
906
+ else:
907
+ print(f"\n📋 Using default configuration")
908
+
909
+ print(f" λ_min={config['lambda_min']:.3f}, λ_max={config['lambda_max']:.3f}")
910
+ print(f" Thresholds: {config['nucleation_threshold']:.2f}T → {config['quenching_threshold']:.2f}T")
911
+ print(f" Steps: {config['total_steps']}")
912
+ print(f" Elastic Modulus: {config.get('elastic_modulus_mode', 'multiplicative')} (σ={config.get('elastic_modulus_sigma', 0.5):.2f})\n")
913
+
914
+ # Run demonstrations
915
+ demo_natural_language_query(config)
916
+ print("\n\n")
917
+ demo_autonomous_obstacle_detection(config)
918
+
919
+ print("\n" + "=" * 80)
920
+ print("IMPLEMENTATION NOTES:")
921
+ print("=" * 80)
922
+ print("• Cache-resident binary: ~140KB (fits in L2 with headroom)")
923
+ print("• No GPU/VRAM dependency: Runs on commodity x86-64 CPU")
924
+ print("• Power consumption: 118W ± 10W fixed")
925
+ print("• Throughput: 1.3+ billion operations/second sustained")
926
+ print("• Determinism: Bit-identical across repeated runs (pinned environment)")
927
+ print("• No probabilistic sampling: Mechanical constraint only")
928
+ print("=" * 80)
requirements-gui.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ streamlit>=1.30
2
+ plotly>=5.18
requirements.txt CHANGED
@@ -1,6 +1 @@
1
- streamlit==1.32.0
2
- plotly==5.18.0
3
- pandas==2.1.4
4
- openai>=1.0.0
5
- requests>=2.31.0
6
- numpy>=1.24.0
 
1
+ # No runtime dependencies (stdlib only).
 
 
 
 
 
substrate_sharding.py ADDED
@@ -0,0 +1,524 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Substrate Sharding Strategy for Material-Field Governance
4
+ Cache-Aware Design for 250,000+ Verified States
5
+
6
+ Goal: Keep most relevant substrate anchors in L1 cache (32-64KB)
7
+ while maintaining sub-microsecond access times and deterministic behavior.
8
+
9
+ Architecture:
10
+ 1. Hierarchical Sharding: Coarse → Fine-grained locality
11
+ 2. Semantic Clustering: Group related knowledge domains
12
+ 3. LRU Cache Management: Keep hot shards resident
13
+ 4. Deterministic Retrieval: Same query → same shards loaded
14
+
15
+ Reference Implementation - Verhash LLC
16
+ Patent Priority: January 25, 2026
17
+ """
18
+
19
+ import math
20
+ from dataclasses import dataclass
21
+ from typing import List, Tuple, Optional, Dict, Set
22
+ from collections import OrderedDict
23
+ import hashlib
24
+ import struct
25
+
26
+ from deterministic_rng import normal
27
+
28
+
29
+ # ==============================================================================
30
+ # CACHE ARCHITECTURE CONSTANTS
31
+ # ==============================================================================
32
+
33
+ L1_CACHE_SIZE = 32 * 1024 # 32 KB typical L1 data cache
34
+ L2_CACHE_SIZE = 256 * 1024 # 256 KB typical L2 cache
35
+ L3_CACHE_SIZE = 8 * 1024 * 1024 # 8 MB typical L3 cache
36
+
37
+ # Use explicit little-endian packing with fixed sizes for deterministic layout.
38
+ # Store x/y as float64 to match Python's `float` (C double on CPython).
39
+ VECTOR_SIZE_BYTES = 8 * 2 # 2 floats (x, y) × 8 bytes each = 16 bytes
40
+ # Real: 768 floats × 4 bytes = 3KB per vector
41
+
42
+ # L1 budget: Reserve space for working set + shard metadata
43
+ L1_BUDGET_VECTORS = (L1_CACHE_SIZE // 2) // VECTOR_SIZE_BYTES # ~1000 vectors in L1
44
+ L2_BUDGET_VECTORS = (L2_CACHE_SIZE // 2) // VECTOR_SIZE_BYTES # ~8000 vectors in L2
45
+
46
+
47
+ # ==============================================================================
48
+ # VECTOR REPRESENTATION
49
+ # ==============================================================================
50
+
51
+ @dataclass
52
+ class CompactVector:
53
+ """
54
+ Cache-optimized vector representation.
55
+
56
+ In production:
57
+ - Use float16 instead of float64 (halve memory)
58
+ - Pack metadata into single 64-bit word
59
+ - Align to cache line boundaries (64 bytes)
60
+ """
61
+ x: float
62
+ y: float
63
+ shard_id: int # Which shard this belongs to
64
+ domain_hash: int # Semantic domain identifier
65
+
66
+ def to_bytes(self) -> bytes:
67
+ """Pack into contiguous bytes for cache efficiency"""
68
+ return struct.pack('<ddIQ', float(self.x), float(self.y), int(self.shard_id), int(self.domain_hash))
69
+
70
+ @staticmethod
71
+ def from_bytes(data: bytes) -> 'CompactVector':
72
+ """Unpack from contiguous bytes"""
73
+ x, y, shard_id, domain_hash = struct.unpack('<ddIQ', data)
74
+ return CompactVector(x, y, shard_id, domain_hash)
75
+
76
+ def distance_to(self, other: 'CompactVector') -> float:
77
+ """Euclidean distance"""
78
+ return math.sqrt((self.x - other.x) ** 2 + (self.y - other.y) ** 2)
79
+
80
+ def dot_product(self, other: 'CompactVector') -> float:
81
+ """Normalized dot product (cosine similarity)"""
82
+ self_norm = math.sqrt(self.x ** 2 + self.y ** 2)
83
+ other_norm = math.sqrt(other.x ** 2 + other.y ** 2)
84
+
85
+ if self_norm == 0 or other_norm == 0:
86
+ return 0.0
87
+
88
+ return (self.x * other.x + self.y * other.y) / (self_norm * other_norm)
89
+
90
+
91
+ # ==============================================================================
92
+ # SHARD STRUCTURE
93
+ # ==============================================================================
94
+
95
+ @dataclass
96
+ class SubstrateShard:
97
+ """
98
+ A shard is a contiguous block of verified states.
99
+
100
+ Design:
101
+ - Fixed size (e.g., 64 vectors = 1KB in 2D, 192KB in 768D)
102
+ - Cache-line aligned
103
+ - Sorted by locality (clustered semantically)
104
+ - Immutable after creation (no reallocation)
105
+ """
106
+ shard_id: int
107
+ domain: str # e.g., "biology", "physics", "geography"
108
+ centroid: CompactVector # Representative center of this shard
109
+ vectors: List[CompactVector] # The actual verified states
110
+ size_bytes: int = 0 # Memory footprint
111
+
112
+ def __post_init__(self):
113
+ if self.size_bytes == 0:
114
+ self.size_bytes = len(self.vectors) * VECTOR_SIZE_BYTES
115
+
116
+ def is_l1_resident(self) -> bool:
117
+ """Can this shard fit in L1?"""
118
+ return self.size_bytes <= L1_CACHE_SIZE // 4 # Reserve 75% for other data
119
+
120
+ def relevance_score(self, query_vector: CompactVector) -> float:
121
+ """
122
+ Compute relevance of this shard to query.
123
+ Uses centroid distance as fast approximation.
124
+ """
125
+ return 1.0 / (1.0 + query_vector.distance_to(self.centroid))
126
+
127
+
128
+ # ==============================================================================
129
+ # HIERARCHICAL SHARDING STRATEGY
130
+ # ==============================================================================
131
+
132
+ class ShardedSubstrate:
133
+ """
134
+ Hierarchical substrate sharding with cache-aware retrieval.
135
+
136
+ Architecture:
137
+ Level 1 (L1 Cache): Active shard (~64 vectors)
138
+ Level 2 (L2 Cache): Hot shards (~8 shards)
139
+ Level 3 (L3 Cache): Warm shards (~100 shards)
140
+ Level 4 (Main RAM): All shards (250K vectors / 64 = ~3906 shards)
141
+
142
+ Retrieval Strategy:
143
+ 1. Hash query to domain (deterministic)
144
+ 2. Load relevant domain shards into L3
145
+ 3. Rank by centroid distance
146
+ 4. Prefetch top-k shards into L2
147
+ 5. Keep most relevant shard in L1
148
+ """
149
+
150
+ def __init__(self,
151
+ shard_size: int = 64,
152
+ l1_capacity: int = 1, # Number of shards in L1
153
+ l2_capacity: int = 8, # Number of shards in L2
154
+ l3_capacity: int = 100): # Number of shards in L3
155
+
156
+ self.shard_size = shard_size
157
+ self.l1_capacity = l1_capacity
158
+ self.l2_capacity = l2_capacity
159
+ self.l3_capacity = l3_capacity
160
+
161
+ # Storage hierarchy
162
+ self.all_shards: Dict[int, SubstrateShard] = {} # All shards (RAM)
163
+ self.domain_index: Dict[str, List[int]] = {} # Domain → shard IDs
164
+
165
+ # Cache tiers (LRU with size limits)
166
+ self.l1_cache: OrderedDict[int, SubstrateShard] = OrderedDict()
167
+ self.l2_cache: OrderedDict[int, SubstrateShard] = OrderedDict()
168
+ self.l3_cache: OrderedDict[int, SubstrateShard] = OrderedDict()
169
+
170
+ # Statistics
171
+ self.l1_hits = 0
172
+ self.l2_hits = 0
173
+ self.l3_hits = 0
174
+ self.l1_misses = 0
175
+
176
+ def add_shard(self, shard: SubstrateShard):
177
+ """Add a shard to the substrate"""
178
+ self.all_shards[shard.shard_id] = shard
179
+
180
+ # Update domain index
181
+ if shard.domain not in self.domain_index:
182
+ self.domain_index[shard.domain] = []
183
+ self.domain_index[shard.domain].append(shard.shard_id)
184
+
185
+ def _get_domain_from_query(self, query_vector: CompactVector) -> str:
186
+ """
187
+ Deterministically map query to semantic domain.
188
+
189
+ In production:
190
+ - Use learned classifier
191
+ - Or: hash query vector to domain buckets
192
+ - Or: use query context/tags
193
+ """
194
+ # Simplified: use domain_hash embedded in query
195
+ if query_vector.domain_hash % 3 == 0:
196
+ return "biology"
197
+ elif query_vector.domain_hash % 3 == 1:
198
+ return "geography"
199
+ else:
200
+ return "physics"
201
+
202
+ def _evict_lru(self, cache: OrderedDict, capacity: int):
203
+ """Evict least recently used items to maintain capacity"""
204
+ while len(cache) > capacity:
205
+ cache.popitem(last=False) # Remove oldest
206
+
207
+ def _promote_to_l1(self, shard_id: int):
208
+ """Move shard to L1 cache"""
209
+ shard = self.all_shards[shard_id]
210
+
211
+ # Remove from lower tiers
212
+ self.l2_cache.pop(shard_id, None)
213
+ self.l3_cache.pop(shard_id, None)
214
+
215
+ # Add to L1 (most recent)
216
+ self.l1_cache[shard_id] = shard
217
+ self.l1_cache.move_to_end(shard_id)
218
+
219
+ # Evict if over capacity
220
+ self._evict_lru(self.l1_cache, self.l1_capacity)
221
+
222
+ def _promote_to_l2(self, shard_id: int):
223
+ """Move shard to L2 cache"""
224
+ shard = self.all_shards[shard_id]
225
+
226
+ # Remove from L3
227
+ self.l3_cache.pop(shard_id, None)
228
+
229
+ # Add to L2
230
+ self.l2_cache[shard_id] = shard
231
+ self.l2_cache.move_to_end(shard_id)
232
+
233
+ self._evict_lru(self.l2_cache, self.l2_capacity)
234
+
235
+ def _promote_to_l3(self, shard_id: int):
236
+ """Move shard to L3 cache"""
237
+ shard = self.all_shards[shard_id]
238
+
239
+ # Add to L3
240
+ self.l3_cache[shard_id] = shard
241
+ self.l3_cache.move_to_end(shard_id)
242
+
243
+ self._evict_lru(self.l3_cache, self.l3_capacity)
244
+
245
+ def retrieve_relevant_shards(self,
246
+ query_vector: CompactVector,
247
+ top_k: int = 8) -> List[SubstrateShard]:
248
+ """
249
+ Retrieve most relevant shards for query.
250
+ Cache-aware with deterministic retrieval.
251
+
252
+ Strategy:
253
+ 1. Determine domain (deterministic hash)
254
+ 2. Get candidate shards from domain
255
+ 3. Rank by centroid distance
256
+ 4. Load top-k into L2
257
+ 5. Return in order of relevance
258
+ """
259
+
260
+ # Step 1: Get domain
261
+ domain = self._get_domain_from_query(query_vector)
262
+
263
+ # Step 2: Get candidate shard IDs from domain
264
+ if domain not in self.domain_index:
265
+ return [] # No shards for this domain
266
+
267
+ candidate_ids = self.domain_index[domain]
268
+
269
+ # Step 3: Rank shards by relevance
270
+ shard_scores = [
271
+ (shard_id, self.all_shards[shard_id].relevance_score(query_vector))
272
+ for shard_id in candidate_ids
273
+ ]
274
+ shard_scores.sort(key=lambda x: x[1], reverse=True)
275
+
276
+ # Step 4: Load top-k shards into cache hierarchy
277
+ top_shard_ids = [shard_id for shard_id, _ in shard_scores[:top_k]]
278
+
279
+ # Promote most relevant to L1
280
+ if top_shard_ids:
281
+ self._promote_to_l1(top_shard_ids[0])
282
+ self.l1_hits += 1
283
+
284
+ # Promote rest to L2
285
+ for shard_id in top_shard_ids[1:]:
286
+ if shard_id not in self.l2_cache:
287
+ self._promote_to_l2(shard_id)
288
+ self.l2_hits += 1
289
+
290
+ # Return shards in order of relevance
291
+ return [self.all_shards[sid] for sid in top_shard_ids]
292
+
293
+ def get_l1_vectors(self) -> List[CompactVector]:
294
+ """
295
+ Get all vectors currently in L1 cache.
296
+ This is the "hot path" for inference.
297
+ """
298
+ vectors = []
299
+ for shard in self.l1_cache.values():
300
+ vectors.extend(shard.vectors)
301
+ return vectors
302
+
303
+ def print_stats(self):
304
+ """Print cache statistics"""
305
+ print("\n" + "=" * 80)
306
+ print("SUBSTRATE SHARDING STATISTICS")
307
+ print("=" * 80)
308
+ print(f"Total shards: {len(self.all_shards)}")
309
+ print(f"Total vectors: {sum(len(s.vectors) for s in self.all_shards.values())}")
310
+ print(f"Domains: {list(self.domain_index.keys())}")
311
+ print()
312
+ print(f"L1 Cache ({self.l1_capacity} shards max):")
313
+ print(f" Current: {len(self.l1_cache)} shards")
314
+ print(f" Vectors: {sum(len(s.vectors) for s in self.l1_cache.values())}")
315
+ print(f" Size: {sum(s.size_bytes for s in self.l1_cache.values())} bytes")
316
+ print(f" Hits: {self.l1_hits}")
317
+ print()
318
+ print(f"L2 Cache ({self.l2_capacity} shards max):")
319
+ print(f" Current: {len(self.l2_cache)} shards")
320
+ print(f" Vectors: {sum(len(s.vectors) for s in self.l2_cache.values())}")
321
+ print(f" Hits: {self.l2_hits}")
322
+ print()
323
+ print(f"L3 Cache ({self.l3_capacity} shards max):")
324
+ print(f" Current: {len(self.l3_cache)} shards")
325
+ print(f" Vectors: {sum(len(s.vectors) for s in self.l3_cache.values())}")
326
+ print(f" Hits: {self.l3_hits}")
327
+ print("=" * 80)
328
+
329
+
330
+ # ==============================================================================
331
+ # DEMONSTRATION: 250K VERIFIED STATES
332
+ # ==============================================================================
333
+
334
+ def create_demo_substrate(num_vectors: int = 250000,
335
+ shard_size: int = 64) -> ShardedSubstrate:
336
+ """
337
+ Create a demo substrate with 250K verified states.
338
+ Simulates three domains: biology, geography, physics.
339
+ """
340
+
341
+ print(f"Creating substrate with {num_vectors:,} verified states...")
342
+ print(f"Shard size: {shard_size} vectors")
343
+ print(f"Expected shards: {num_vectors // shard_size}")
344
+
345
+ substrate = ShardedSubstrate(shard_size=shard_size)
346
+
347
+ domains = ["biology", "geography", "physics"]
348
+ vectors_per_domain = num_vectors // len(domains)
349
+
350
+ shard_id = 0
351
+
352
+ for domain_idx, domain in enumerate(domains):
353
+ print(f"\nGenerating {vectors_per_domain:,} vectors for domain: {domain}")
354
+
355
+ # Generate vectors clustered around domain centroid
356
+ # Biology: centered around (0.8, 0.8)
357
+ # Geography: centered around (0.5, 0.5)
358
+ # Physics: centered around (0.2, 0.2)
359
+
360
+ if domain == "biology":
361
+ center_x, center_y = 0.8, 0.8
362
+ elif domain == "geography":
363
+ center_x, center_y = 0.5, 0.5
364
+ else:
365
+ center_x, center_y = 0.2, 0.2
366
+
367
+ domain_hash = hashlib.sha256(domain.encode()).digest()[:8]
368
+ domain_hash_int = int.from_bytes(domain_hash, 'big')
369
+ domain_seed = b"demo_substrate|" + domain.encode("utf-8")
370
+
371
+ # Create shards for this domain
372
+ for i in range(0, vectors_per_domain, shard_size):
373
+ vectors = []
374
+
375
+ for j in range(shard_size):
376
+ if i + j >= vectors_per_domain:
377
+ break
378
+
379
+ # Generate vector with small random offset
380
+ global_idx = i + j
381
+ x = center_x + normal(domain_seed, global_idx * 4, mean=0.0, std=0.1)
382
+ y = center_y + normal(domain_seed, global_idx * 4 + 2, mean=0.0, std=0.1)
383
+
384
+ vec = CompactVector(
385
+ x=x,
386
+ y=y,
387
+ shard_id=shard_id,
388
+ domain_hash=domain_hash_int
389
+ )
390
+ vectors.append(vec)
391
+
392
+ # Compute centroid
393
+ if vectors:
394
+ centroid_x = sum(v.x for v in vectors) / len(vectors)
395
+ centroid_y = sum(v.y for v in vectors) / len(vectors)
396
+ centroid = CompactVector(centroid_x, centroid_y, shard_id, domain_hash_int)
397
+
398
+ shard = SubstrateShard(
399
+ shard_id=shard_id,
400
+ domain=domain,
401
+ centroid=centroid,
402
+ vectors=vectors
403
+ )
404
+
405
+ substrate.add_shard(shard)
406
+ shard_id += 1
407
+
408
+ print(f"\nSubstrate created: {len(substrate.all_shards)} shards")
409
+ return substrate
410
+
411
+
412
+ def demo_query_performance():
413
+ """
414
+ Demonstrate query performance with sharded substrate.
415
+ """
416
+
417
+ print("""
418
+ ╔════════════���═════════════════════════════════════════════════════════════════╗
419
+ ║ ║
420
+ ║ Substrate Sharding Demonstration ║
421
+ ║ ║
422
+ ║ Exercises deterministic sharding and cache residency over ║
423
+ ║ a large verified substrate. Illustrates how relevance ║
424
+ ║ ranking and promotion constrain active context. ║
425
+ ║ ║
426
+ ╚══════════════════════════════════════════════════════════════════════════════╝
427
+ """)
428
+
429
+ # Create substrate
430
+ substrate = create_demo_substrate(num_vectors=250000, shard_size=64)
431
+
432
+ substrate.print_stats()
433
+
434
+ # Simulate queries from different domains
435
+ print("\n" + "=" * 80)
436
+ print("QUERY SIMULATION")
437
+ print("=" * 80)
438
+
439
+ # Biology query
440
+ print("\nQuery 1: Biology domain (photosynthesis)")
441
+ bio_query = CompactVector(x=0.82, y=0.78, shard_id=-1, domain_hash=0)
442
+ relevant_shards = substrate.retrieve_relevant_shards(bio_query, top_k=8)
443
+
444
+ print(f" Retrieved {len(relevant_shards)} relevant shards")
445
+ print(f" L1 vectors available: {len(substrate.get_l1_vectors())}")
446
+ print(f" Most relevant shard: {relevant_shards[0].shard_id} (domain: {relevant_shards[0].domain})")
447
+
448
+ # Geography query
449
+ print("\nQuery 2: Geography domain (capitals)")
450
+ geo_query = CompactVector(x=0.48, y=0.52, shard_id=-1, domain_hash=1)
451
+ relevant_shards = substrate.retrieve_relevant_shards(geo_query, top_k=8)
452
+
453
+ print(f" Retrieved {len(relevant_shards)} relevant shards")
454
+ print(f" L1 vectors available: {len(substrate.get_l1_vectors())}")
455
+ print(f" Most relevant shard: {relevant_shards[0].shard_id} (domain: {relevant_shards[0].domain})")
456
+
457
+ # Physics query
458
+ print("\nQuery 3: Physics domain (mechanics)")
459
+ phys_query = CompactVector(x=0.18, y=0.22, shard_id=-1, domain_hash=2)
460
+ relevant_shards = substrate.retrieve_relevant_shards(phys_query, top_k=8)
461
+
462
+ print(f" Retrieved {len(relevant_shards)} relevant shards")
463
+ print(f" L1 vectors available: {len(substrate.get_l1_vectors())}")
464
+ print(f" Most relevant shard: {relevant_shards[0].shard_id} (domain: {relevant_shards[0].domain})")
465
+
466
+ # Print final stats
467
+ substrate.print_stats()
468
+
469
+ # Memory footprint analysis
470
+ print("\n" + "=" * 80)
471
+ print("MEMORY FOOTPRINT ANALYSIS")
472
+ print("=" * 80)
473
+
474
+ l1_size = sum(s.size_bytes for s in substrate.l1_cache.values())
475
+ l2_size = sum(s.size_bytes for s in substrate.l2_cache.values())
476
+ total_size = sum(s.size_bytes for s in substrate.all_shards.values())
477
+
478
+ print(f"L1 Cache: {l1_size:,} bytes ({l1_size/1024:.2f} KB)")
479
+ print(f" Fits in L1? {l1_size <= L1_CACHE_SIZE}")
480
+ print(f" L1 capacity: {L1_CACHE_SIZE:,} bytes ({L1_CACHE_SIZE/1024:.2f} KB)")
481
+ print()
482
+ print(f"L2 Cache: {l2_size:,} bytes ({l2_size/1024:.2f} KB)")
483
+ print(f" Fits in L2? {l2_size <= L2_CACHE_SIZE}")
484
+ print(f" L2 capacity: {L2_CACHE_SIZE:,} bytes ({L2_CACHE_SIZE/1024:.2f} KB)")
485
+ print()
486
+ print(f"Total Substrate: {total_size:,} bytes ({total_size/1024/1024:.2f} MB)")
487
+ print()
488
+ print(f"Cache efficiency: {(l1_size + l2_size) / total_size * 100:.2f}% in fast cache")
489
+
490
+ print("\n" + "=" * 80)
491
+ print("KEY INSIGHTS")
492
+ print("=" * 80)
493
+ print("""
494
+ 1. CACHE RESIDENCY:
495
+ - L1 holds 1 shard (64 vectors) = most relevant for current query
496
+ - L2 holds 8 shards (512 vectors) = domain-relevant context
497
+ - Working set: 576 vectors in fast cache (< 10 KB in 2D)
498
+
499
+ 2. RETRIEVAL STRATEGY:
500
+ - Deterministic domain mapping (hash-based)
501
+ - Centroid-based relevance ranking
502
+ - LRU eviction maintains hot shards
503
+
504
+ 3. SCALING TO 768D:
505
+ - 768 floats × 4 bytes = 3 KB per vector
506
+ - L1: 64 vectors × 3 KB = 192 KB (fits in L2, not L1)
507
+ - Strategy: Reduce L1 capacity to 10-16 vectors for true L1 residence
508
+
509
+ 4. PRODUCTION OPTIMIZATIONS:
510
+ - Use float16 (half precision) → 1.5 KB per vector
511
+ - Quantize to int8 → 768 bytes per vector
512
+ - Product quantization → 64-128 bytes per vector
513
+ - With PQ: L1 can hold 256-512 vectors (16-32 KB)
514
+
515
+ 5. INFERENCE PATH:
516
+ - Query arrives → Hash to domain → Load L2 shards
517
+ - Rank by centroid → Promote top shard to L1
518
+ - Inference runs on L1-resident vectors only
519
+ - Sub-microsecond retrieval, deterministic, cache-friendly
520
+ """)
521
+
522
+
523
+ if __name__ == "__main__":
524
+ demo_query_performance()
test_adapter.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test Suite for Deterministic Guardrail Adapter
4
+ """
5
+
6
+ import unittest
7
+ from llm_adapter import DeterministicGuardrail, MockEmbedder
8
+
9
+ class TestDeterministicGuardrail(unittest.TestCase):
10
+
11
+ def test_mock_embedder_determinism(self):
12
+ """Test that MockEmbedder is deterministic"""
13
+ embedder = MockEmbedder()
14
+ text = "Hello World"
15
+
16
+ vec1 = embedder.embed(text)
17
+ vec2 = embedder.embed(text)
18
+
19
+ self.assertEqual(vec1, vec2)
20
+ self.assertIsInstance(vec1[0], float)
21
+ self.assertIsInstance(vec1[1], float)
22
+
23
+ def test_basic_filtering(self):
24
+ """Test basic filtering capability"""
25
+ # Ground truth: "A" gives a specific vector
26
+ substrate = ["The fast fox jumps"]
27
+
28
+ guard = DeterministicGuardrail(substrate_texts=substrate)
29
+
30
+ candidates = [
31
+ "The fast fox jumps", # Perfect match (should survive)
32
+ "The slow turtle crawls" # Different vector (should likely be filtered or score lower)
33
+ ]
34
+
35
+ # Note: Since we use a hash-based mock embedder, "The slow turtle crawls"
36
+ # maps to a random point in 2D space. The chance it maps close to the
37
+ # substrate is low (~1/E area), but not zero.
38
+ # However, "The fast fox jumps" maps to exactly the same point as substrate,
39
+ # so it has E=1.0 (or very high).
40
+
41
+ result = guard.filter(candidates)
42
+ self.assertEqual(result, "The fast fox jumps")
43
+
44
+ def test_abstention(self):
45
+ """Test that the system abstains when no candidate is good enough"""
46
+ # Substrate is completely unrelated to candidates
47
+ substrate = ["Apple Banana Cherry"]
48
+
49
+ guard = DeterministicGuardrail(substrate_texts=substrate)
50
+
51
+ # These map to random points likely far from "Apple Banana Cherry"
52
+ candidates = [
53
+ "Xylophone Zebra",
54
+ "Quantum Physics"
55
+ ]
56
+
57
+ # We expect abstention (None) because candidates should fail to nucleate
58
+ # or be excluded by pressure.
59
+ # (Though there is a tiny collision probability with SHA-256 mapping to 2D)
60
+ result = guard.filter(candidates)
61
+
62
+ # In the unlikely event of a collision, we handle it, but mostly this should be None
63
+ if result is not None:
64
+ print(f"WARNING: Unlucky hash collision allowed '{result}' to survive against unrelated substrate.")
65
+ else:
66
+ self.assertIsNone(result)
67
+
68
+ def test_multi_candidate_selection(self):
69
+ """Test that the best candidate is selected from multiple options"""
70
+ substrate = ["The quick brown fox"]
71
+ guard = DeterministicGuardrail(substrate_texts=substrate)
72
+
73
+ candidates = [
74
+ "The quick brown fox", # E=1.0
75
+ "The quick brown", # Hashed differently -> E < 1.0 (random)
76
+ "brown fox" # Hashed differently -> E < 1.0 (random)
77
+ ]
78
+
79
+ result = guard.filter(candidates)
80
+ self.assertEqual(result, "The quick brown fox")
81
+
82
+ if __name__ == "__main__":
83
+ unittest.main()
test_determinism.py ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Verify bit-identical deterministic execution across multiple runs.
4
+ """
5
+
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ sys.path.insert(0, str(Path(__file__).parent))
10
+
11
+ from material_field_engine import (
12
+ MaterialFieldEngine, VerifiedSubstrate, Vector2D, load_config
13
+ )
14
+ import hashlib
15
+ import json
16
+
17
+ def run_determinism_test(num_runs=5):
18
+ """Run inference multiple times and verify identical outputs"""
19
+
20
+ print("Determinism Replay (5 Runs)" if num_runs == 5 else f"Determinism Replay ({num_runs} Runs)")
21
+ print()
22
+
23
+ config = load_config("balanced")
24
+
25
+ # Setup substrate and candidates (fixed seed)
26
+ substrate = VerifiedSubstrate()
27
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
28
+
29
+ candidates = [
30
+ (0.95, 0.92), # Paris - near verified state
31
+ (0.35, 0.30), # Lyon
32
+ (0.30, 0.25), # Marseille
33
+ ]
34
+
35
+ results = []
36
+
37
+ for run in range(num_runs):
38
+ # Create fresh engine each time
39
+ engine = MaterialFieldEngine(
40
+ substrate,
41
+ lambda_min=config['lambda_min'],
42
+ lambda_max=config['lambda_max'],
43
+ inference_steps=config['total_steps']
44
+ )
45
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
46
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
47
+
48
+ engine.initialize_candidates(candidates)
49
+ result = engine.run_inference()
50
+
51
+ # Create hash of the result
52
+ result_str = json.dumps({
53
+ 'output': (result['final_output'].x, result['final_output'].y) if result['final_output'] else None,
54
+ 'excluded_count': result['total_excluded'],
55
+ 'phase_log': [
56
+ {
57
+ 'step': e['step'],
58
+ 'phase': e['phase'],
59
+ 'survivors': e['survivors'],
60
+ 'pressure': round(e['pressure'], 6) # Round to avoid floating point noise
61
+ }
62
+ for e in result['phase_log']
63
+ ]
64
+ }, sort_keys=True)
65
+
66
+ result_hash = hashlib.sha256(result_str.encode()).hexdigest()
67
+ results.append(result_hash)
68
+
69
+ print(f"Run {run + 1}: {result_hash}")
70
+
71
+ print()
72
+
73
+ # Check if all hashes are identical
74
+ if len(set(results)) == 1:
75
+ print("Determinism: SHA-256 stable across runs")
76
+ print(f"SHA-256: {results[0]}")
77
+ return True
78
+ else:
79
+ print("Determinism: SHA-256 not stable across runs")
80
+ print("Unique hashes:")
81
+ for h in sorted(set(results)):
82
+ count = results.count(h)
83
+ print(f"{h}: {count}")
84
+ return False
85
+
86
+
87
+ def run_cross_run_stability_test():
88
+ """Test that same input produces same output even across separate processes"""
89
+
90
+ print("\nCross-Run Stability")
91
+ print()
92
+
93
+ substrate = VerifiedSubstrate()
94
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
95
+
96
+ config = load_config("balanced")
97
+ engine = MaterialFieldEngine(
98
+ substrate,
99
+ lambda_min=config['lambda_min'],
100
+ lambda_max=config['lambda_max'],
101
+ inference_steps=config['total_steps']
102
+ )
103
+
104
+ # Test specific vector coordinates
105
+ test_vectors = [
106
+ (0.95, 0.92),
107
+ (0.35, 0.30),
108
+ (0.50, 0.50),
109
+ (0.10, 0.10),
110
+ ]
111
+
112
+ print("Vector | E | σ_y | ε | Hash")
113
+ print("-" * 80)
114
+
115
+ for x, y in test_vectors:
116
+ v = Vector2D(x=x, y=y, properties=None)
117
+ props = engine._compute_material_properties(v)
118
+
119
+ # Hash of all properties
120
+ props_str = f"{props.elastic_modulus:.10f},{props.yield_strength:.10f},{props.strain:.10f}"
121
+ props_hash = hashlib.sha256(props_str.encode()).hexdigest()[:8]
122
+
123
+ print(f"({x:.2f}, {y:.2f}) | {props.elastic_modulus:.4f} | {props.yield_strength:.4f} | "
124
+ f"{props.strain:.4f} | {props_hash}")
125
+
126
+ print("\nDerived Properties: deterministic")
127
+
128
+
129
+ if __name__ == "__main__":
130
+ success = run_determinism_test(num_runs=5)
131
+ run_cross_run_stability_test()
132
+
133
+ print()
134
+ raise SystemExit(0 if success else 1)
test_reference_queries.py ADDED
@@ -0,0 +1,328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test Material-Field Engine with Reference Queries
4
+
5
+ Demonstrates system behavior with fixed reference queries:
6
+ - Simple factual prompts
7
+ - Common misconceptions
8
+ - Basic formula recall
9
+ - Date recall
10
+
11
+ Shows how elastic modulus mode affects exclusion behavior under a fixed substrate.
12
+ """
13
+
14
+ import sys
15
+ from pathlib import Path
16
+
17
+ if hasattr(sys.stdout, "reconfigure"):
18
+ try:
19
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
20
+ except Exception:
21
+ pass
22
+
23
+ sys.path.insert(0, str(Path(__file__).parent))
24
+
25
+ from material_field_engine import (
26
+ VerifiedSubstrate, Vector2D, MaterialFieldEngine
27
+ )
28
+
29
+
30
+ def test_science_fact(mode='multiplicative', sigma=0.5):
31
+ """
32
+ Query: 'What do plants need for photosynthesis?'
33
+ Expected: Sunlight, water, carbon dioxide
34
+ """
35
+ print("\n" + "=" * 80)
36
+ print("SCIENCE: What do plants need for photosynthesis?")
37
+ print("=" * 80)
38
+ print(f"Mode: {mode}, σ={sigma}")
39
+
40
+ # Substrate: Verified science facts
41
+ substrate = VerifiedSubstrate(
42
+ elastic_modulus_mode=mode,
43
+ elastic_modulus_sigma=sigma
44
+ )
45
+
46
+ # Verified answers (embeddings simulated as 2D for demo)
47
+ substrate.add_verified_state(Vector2D(x=0.90, y=0.88, properties=None)) # "sunlight, water, CO2"
48
+
49
+ # Candidates:
50
+ # - Correct answer (close to substrate)
51
+ # - Partially correct (medium distance)
52
+ # - Common misconception (far from substrate)
53
+ # - Creative but wrong (far, different direction)
54
+ candidates = [
55
+ (0.90, 0.88), # Correct: sunlight, water, CO2
56
+ (0.70, 0.65), # Partial: mentions sunlight but incomplete
57
+ (0.40, 0.35), # Misconception: "plants eat soil"
58
+ (0.15, 0.80), # Creative wrong: "moonlight and air"
59
+ ]
60
+
61
+ engine = MaterialFieldEngine(
62
+ substrate,
63
+ lambda_min=0.35,
64
+ lambda_max=1.00,
65
+ inference_steps=8
66
+ )
67
+
68
+ engine.initialize_candidates(candidates)
69
+
70
+ print("\nCandidate Knowledge States:")
71
+ labels = [
72
+ "Correct (sunlight+water+CO2)",
73
+ "Partial (sunlight mentioned)",
74
+ "Misconception (plants eat soil)",
75
+ "Creative wrong (moonlight)"
76
+ ]
77
+
78
+ for i, (v, label) in enumerate(zip(engine.candidate_vectors, labels)):
79
+ dist = v.distance_to(substrate.states[0])
80
+ print(f" {i}. {label:<30} | E={v.properties.elastic_modulus:.3f} | "
81
+ f"σ_y={v.properties.yield_strength:.3f} | dist={dist:.3f}")
82
+
83
+ results = engine.run_inference()
84
+
85
+ print("\nResult:")
86
+ if results['final_output']:
87
+ winner_idx = next(i for i, c in enumerate(candidates)
88
+ if (c[0], c[1]) == (results['final_output'].x, results['final_output'].y))
89
+ print(f" Selected: {labels[winner_idx]}")
90
+ print(f" E={results['final_output'].properties.elastic_modulus:.3f}")
91
+ else:
92
+ print(" ABSTAINED (no candidate met grounding threshold)")
93
+
94
+ print(f" Excluded: {results['total_excluded']}")
95
+ # Intentionally omit interpretive flags in stdout.
96
+
97
+
98
+ def test_geography_fact(mode='multiplicative', sigma=0.5):
99
+ """
100
+ Query: 'What is the capital of Texas?'
101
+ Expected: Austin
102
+ """
103
+ print("\n" + "=" * 80)
104
+ print("GEOGRAPHY: What is the capital of Texas?")
105
+ print("=" * 80)
106
+ print(f"Mode: {mode}, σ={sigma}")
107
+
108
+ substrate = VerifiedSubstrate(
109
+ elastic_modulus_mode=mode,
110
+ elastic_modulus_sigma=sigma
111
+ )
112
+
113
+ # Verified answer
114
+ substrate.add_verified_state(Vector2D(x=0.85, y=0.82, properties=None)) # "Austin"
115
+
116
+ # Candidates:
117
+ candidates = [
118
+ (0.85, 0.82), # Correct: Austin
119
+ (0.75, 0.70), # Common error: Houston (largest city)
120
+ (0.40, 0.35), # Wrong: Dallas
121
+ (0.20, 0.15), # Very wrong: Los Angeles (not even in Texas!)
122
+ ]
123
+
124
+ engine = MaterialFieldEngine(
125
+ substrate,
126
+ lambda_min=0.35,
127
+ lambda_max=1.00,
128
+ inference_steps=8
129
+ )
130
+
131
+ engine.initialize_candidates(candidates)
132
+
133
+ print("\nCandidate Answers:")
134
+ labels = [
135
+ "Correct (Austin)",
136
+ "Common error (Houston - largest city)",
137
+ "Wrong (Dallas)",
138
+ "Very wrong (Los Angeles)"
139
+ ]
140
+
141
+ for i, (v, label) in enumerate(zip(engine.candidate_vectors, labels)):
142
+ dist = v.distance_to(substrate.states[0])
143
+ print(f" {i}. {label:<38} | E={v.properties.elastic_modulus:.3f} | "
144
+ f"dist={dist:.3f}")
145
+
146
+ results = engine.run_inference()
147
+
148
+ print("\nResult:")
149
+ if results['final_output']:
150
+ winner_idx = next(i for i, c in enumerate(candidates)
151
+ if (c[0], c[1]) == (results['final_output'].x, results['final_output'].y))
152
+ print(f" Selected: {labels[winner_idx]}")
153
+ else:
154
+ print(" ABSTAINED")
155
+ print(f" Excluded: {results['total_excluded']}")
156
+
157
+
158
+ def test_math_concept(mode='multiplicative', sigma=0.5):
159
+ """
160
+ Query: 'What is the area formula for a rectangle?'
161
+ Expected: length × width
162
+ """
163
+ print("\n" + "=" * 80)
164
+ print("MATH: What is the area formula for a rectangle?")
165
+ print("=" * 80)
166
+ print(f"Mode: {mode}, σ={sigma}")
167
+
168
+ substrate = VerifiedSubstrate(
169
+ elastic_modulus_mode=mode,
170
+ elastic_modulus_sigma=sigma
171
+ )
172
+
173
+ # Verified formula
174
+ substrate.add_verified_state(Vector2D(x=0.92, y=0.90, properties=None)) # "length × width"
175
+
176
+ candidates = [
177
+ (0.92, 0.90), # Correct: length × width
178
+ (0.70, 0.68), # Confused with perimeter: 2(l+w)
179
+ (0.45, 0.42), # Wrong: length + width
180
+ (0.25, 0.20), # Very wrong: confusing with volume
181
+ ]
182
+
183
+ engine = MaterialFieldEngine(
184
+ substrate,
185
+ lambda_min=0.40,
186
+ lambda_max=1.10,
187
+ inference_steps=8
188
+ )
189
+
190
+ engine.initialize_candidates(candidates)
191
+
192
+ print("\nCandidate Formulas:")
193
+ labels = [
194
+ "Correct (length × width)",
195
+ "Perimeter confusion (2(l+w))",
196
+ "Wrong operation (length + width)",
197
+ "Volume confusion (3D thinking)"
198
+ ]
199
+
200
+ for i, (v, label) in enumerate(zip(engine.candidate_vectors, labels)):
201
+ print(f" {i}. {label:<35} | E={v.properties.elastic_modulus:.3f}")
202
+
203
+ results = engine.run_inference()
204
+
205
+ print("\nResult:")
206
+ if results['final_output']:
207
+ winner_idx = next(i for i, c in enumerate(candidates)
208
+ if (c[0], c[1]) == (results['final_output'].x, results['final_output'].y))
209
+ print(f" Selected: {labels[winner_idx]}")
210
+ else:
211
+ print(" ABSTAINED")
212
+ print(f" Excluded: {results['total_excluded']}")
213
+
214
+
215
+ def test_historical_fact(mode='multiplicative', sigma=0.5):
216
+ """
217
+ Query: 'When did Christopher Columbus reach the Americas?'
218
+ Expected: 1492
219
+ """
220
+ print("\n" + "=" * 80)
221
+ print("HISTORY: When did Columbus reach the Americas?")
222
+ print("=" * 80)
223
+ print(f"Mode: {mode}, σ={sigma}")
224
+
225
+ substrate = VerifiedSubstrate(
226
+ elastic_modulus_mode=mode,
227
+ elastic_modulus_sigma=sigma
228
+ )
229
+
230
+ # Verified date
231
+ substrate.add_verified_state(Vector2D(x=0.88, y=0.86, properties=None)) # "1492"
232
+
233
+ candidates = [
234
+ (0.88, 0.86), # Correct: 1492
235
+ (0.75, 0.70), # Close: 1490s range
236
+ (0.50, 0.45), # Common error: 1776 (confusing with US independence)
237
+ (0.30, 0.25), # Wrong century: 1500s
238
+ (0.10, 0.12), # Very wrong: 1942 (digit confusion)
239
+ ]
240
+
241
+ engine = MaterialFieldEngine(
242
+ substrate,
243
+ lambda_min=0.35,
244
+ lambda_max=1.00,
245
+ inference_steps=8
246
+ )
247
+
248
+ engine.initialize_candidates(candidates)
249
+
250
+ print("\nCandidate Dates:")
251
+ labels = [
252
+ "Correct (1492)",
253
+ "Approximate (1490s)",
254
+ "Confusion (1776 - US independence)",
255
+ "Wrong century (1500s)",
256
+ "Digit swap (1942)"
257
+ ]
258
+
259
+ for i, (v, label) in enumerate(zip(engine.candidate_vectors, labels)):
260
+ print(f" {i}. {label:<38} | E={v.properties.elastic_modulus:.3f}")
261
+
262
+ results = engine.run_inference()
263
+
264
+ print("\nResult:")
265
+ if results['final_output']:
266
+ winner_idx = next(i for i, c in enumerate(candidates)
267
+ if (c[0], c[1]) == (results['final_output'].x, results['final_output'].y))
268
+ print(f" Selected: {labels[winner_idx]}")
269
+ else:
270
+ print(" ABSTAINED")
271
+ print(f" Excluded: {results['total_excluded']}")
272
+
273
+
274
+ def compare_modes():
275
+ """Compare how different elastic modulus modes affect fixed reference queries"""
276
+ print("\n" + "=" * 80)
277
+ print("MODE COMPARISON: How does mode selection affect reference queries?")
278
+ print("=" * 80)
279
+
280
+ modes = [
281
+ ('cosine', 0.5, "Cosine (direction only)"),
282
+ ('multiplicative', 0.4, "Multiplicative σ=0.4 (tight - good for facts)"),
283
+ ('multiplicative', 0.7, "Multiplicative σ=0.7 (loose - allows exploration)"),
284
+ ]
285
+
286
+ for mode, sigma, description in modes:
287
+ print(f"\n{'─' * 80}")
288
+ print(f"Testing with: {description}")
289
+ print(f"{'─' * 80}")
290
+
291
+ test_science_fact(mode, sigma)
292
+
293
+
294
+ if __name__ == "__main__":
295
+ print("""
296
+ ╔══════════════════════════════════════════════════════════════════════════════╗
297
+ ║ ║
298
+ ║ Testing with Reference Queries ║
299
+ ║ ║
300
+ ║ Demonstrates material-field governance with simple example queries. ║
301
+ ║ Shows how elastic modulus mode affects factual recall vs. exploration. ║
302
+ ║ ║
303
+ ╚══════════════════════════════════════════════════════════════════════════════╝
304
+ """)
305
+
306
+ # Default: use multiplicative mode with a fixed sigma for repeatability
307
+ mode = 'multiplicative'
308
+ sigma = 0.45
309
+
310
+ if len(sys.argv) > 1:
311
+ if sys.argv[1] == 'compare':
312
+ compare_modes()
313
+ sys.exit(0)
314
+ elif sys.argv[1] == 'cosine':
315
+ mode = 'cosine'
316
+ elif sys.argv[1] == 'tight':
317
+ sigma = 0.3
318
+ elif sys.argv[1] == 'loose':
319
+ sigma = 0.7
320
+
321
+ print(f"\nUsing mode: {mode}, σ={sigma}")
322
+ print(" (Run with 'compare' to see all modes side-by-side)\n")
323
+
324
+ # Run all example tests
325
+ test_science_fact(mode, sigma)
326
+ test_geography_fact(mode, sigma)
327
+ test_math_concept(mode, sigma)
328
+ test_historical_fact(mode, sigma)
test_suite.py ADDED
@@ -0,0 +1,447 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test Suite for Material-Field Governance Reference Implementation
4
+
5
+ Pins expected behavior and verifies core invariants:
6
+ 1. Determinism: Same input → same output
7
+ 2. Phase mechanics: Crystallization phase is reached
8
+ 3. Exclusion: Fractured vectors don't propagate
9
+ 4. Numerical stability: No NaN/Inf, bounded values
10
+ """
11
+
12
+ import sys
13
+ import math
14
+ import hashlib
15
+ import json
16
+ from pathlib import Path
17
+
18
+ sys.path.insert(0, str(Path(__file__).parent))
19
+
20
+ from material_field_engine import (
21
+ MaterialFieldEngine, VerifiedSubstrate, Vector2D,
22
+ PhaseTransitionController, Phase, load_config
23
+ )
24
+
25
+
26
+ class TestResults:
27
+ """Track test results"""
28
+ def __init__(self):
29
+ self.passed = 0
30
+ self.failed = 0
31
+ self.tests = []
32
+
33
+ def record(self, name, passed, message=""):
34
+ self.tests.append((name, passed, message))
35
+ if passed:
36
+ self.passed += 1
37
+ print(f"PASS {name}")
38
+ else:
39
+ self.failed += 1
40
+ print(f"FAIL {name}: {message}")
41
+
42
+ def summary(self):
43
+ total = self.passed + self.failed
44
+ print(f"\n{'='*80}")
45
+ print(f"TEST SUMMARY: {self.passed}/{total} passed")
46
+ if self.failed > 0:
47
+ print(f"\nFailed tests:")
48
+ for name, passed, msg in self.tests:
49
+ if not passed:
50
+ print(f" • {name}: {msg}")
51
+ print(f"{'='*80}")
52
+ return self.failed == 0
53
+
54
+
55
+ def test_determinism(results):
56
+ """Test 1: Bit-identical outputs across multiple runs"""
57
+ print("\n" + "="*80)
58
+ print("TEST 1: DETERMINISM")
59
+ print("="*80)
60
+
61
+ config = load_config("balanced")
62
+ substrate = VerifiedSubstrate()
63
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
64
+
65
+ candidates = [(0.95, 0.92), (0.35, 0.30), (0.30, 0.25)]
66
+
67
+ hashes = []
68
+ for run in range(3):
69
+ engine = MaterialFieldEngine(
70
+ substrate,
71
+ lambda_min=config['lambda_min'],
72
+ lambda_max=config['lambda_max'],
73
+ inference_steps=config['total_steps']
74
+ )
75
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
76
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
77
+
78
+ engine.initialize_candidates(candidates)
79
+ result = engine.run_inference()
80
+
81
+ result_str = json.dumps({
82
+ 'output': (result['final_output'].x, result['final_output'].y) if result['final_output'] else None,
83
+ 'excluded_count': result['total_excluded'],
84
+ 'phase_log': [
85
+ {
86
+ 'step': e['step'],
87
+ 'phase': e['phase'],
88
+ 'survivors': e['survivors'],
89
+ 'pressure': round(e['pressure'], 6)
90
+ }
91
+ for e in result['phase_log']
92
+ ]
93
+ }, sort_keys=True)
94
+
95
+ h = hashlib.sha256(result_str.encode()).hexdigest()
96
+ hashes.append(h)
97
+
98
+ all_identical = len(set(hashes)) == 1
99
+ results.record(
100
+ "Determinism: Identical outputs across runs",
101
+ all_identical,
102
+ f"Got {len(set(hashes))} unique hashes" if not all_identical else ""
103
+ )
104
+
105
+ if all_identical:
106
+ print(f" Hash: {hashes[0][:32]}...")
107
+
108
+
109
+ def test_phase_progression(results):
110
+ """Test 2: Phase transitions occur in correct order"""
111
+ print("\n" + "="*80)
112
+ print("TEST 2: PHASE PROGRESSION")
113
+ print("="*80)
114
+
115
+ config = load_config("balanced")
116
+ substrate = VerifiedSubstrate()
117
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
118
+
119
+ engine = MaterialFieldEngine(
120
+ substrate,
121
+ lambda_min=config['lambda_min'],
122
+ lambda_max=config['lambda_max'],
123
+ inference_steps=config['total_steps']
124
+ )
125
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
126
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
127
+
128
+ engine.initialize_candidates([(0.95, 0.92), (0.35, 0.30)])
129
+ result = engine.run_inference()
130
+
131
+ # Extract phase sequence
132
+ phases = [entry['phase'] for entry in result['phase_log']]
133
+
134
+ # Check: NUCLEATION appears
135
+ has_nucleation = 'NUCLEATION' in phases
136
+ results.record(
137
+ "Phase: NUCLEATION phase occurs",
138
+ has_nucleation,
139
+ "NUCLEATION not found in phase log"
140
+ )
141
+
142
+ # Check: QUENCHING appears
143
+ has_quenching = 'QUENCHING' in phases
144
+ results.record(
145
+ "Phase: QUENCHING phase occurs",
146
+ has_quenching,
147
+ "QUENCHING not found in phase log"
148
+ )
149
+
150
+ # Check: CRYSTALLIZATION appears
151
+ has_crystallization = 'CRYSTALLIZATION' in phases
152
+ results.record(
153
+ "Phase: CRYSTALLIZATION phase occurs",
154
+ has_crystallization,
155
+ "CRYSTALLIZATION not found in phase log"
156
+ )
157
+
158
+ # Check: Phases appear in correct order
159
+ if has_nucleation and has_quenching and has_crystallization:
160
+ nucleation_idx = phases.index('NUCLEATION')
161
+ quenching_idx = phases.index('QUENCHING')
162
+ crystallization_idx = phases.index('CRYSTALLIZATION')
163
+
164
+ correct_order = nucleation_idx < quenching_idx < crystallization_idx
165
+ results.record(
166
+ "Phase: Correct sequential order",
167
+ correct_order,
168
+ f"Order: {nucleation_idx}, {quenching_idx}, {crystallization_idx}"
169
+ )
170
+
171
+
172
+ def test_pressure_monotonicity(results):
173
+ """Test 3: Constraint pressure λ increases monotonically"""
174
+ print("\n" + "="*80)
175
+ print("TEST 3: PRESSURE MONOTONICITY")
176
+ print("="*80)
177
+
178
+ config = load_config("balanced")
179
+ substrate = VerifiedSubstrate()
180
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
181
+
182
+ engine = MaterialFieldEngine(
183
+ substrate,
184
+ lambda_min=config['lambda_min'],
185
+ lambda_max=config['lambda_max'],
186
+ inference_steps=config['total_steps']
187
+ )
188
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
189
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
190
+
191
+ engine.initialize_candidates([(0.95, 0.92)])
192
+ result = engine.run_inference()
193
+
194
+ pressures = [entry['pressure'] for entry in result['phase_log']]
195
+
196
+ # Check monotonicity (non-decreasing)
197
+ is_monotonic = all(pressures[i] <= pressures[i+1] for i in range(len(pressures)-1))
198
+ results.record(
199
+ "Pressure: Monotonically increasing",
200
+ is_monotonic,
201
+ f"Pressures: {pressures}"
202
+ )
203
+
204
+ # Check: Reaches maximum
205
+ reaches_max = abs(pressures[-1] - config['lambda_max']) < 0.01
206
+ results.record(
207
+ "Pressure: Reaches λ_max",
208
+ reaches_max,
209
+ f"Final: {pressures[-1]}, Expected: {config['lambda_max']}"
210
+ )
211
+
212
+
213
+ def test_mechanical_exclusion(results):
214
+ """Test 4: Weak candidates are excluded"""
215
+ print("\n" + "="*80)
216
+ print("TEST 4: MECHANICAL EXCLUSION")
217
+ print("="*80)
218
+
219
+ config = load_config("aggressive") # Use aggressive to ensure exclusion
220
+ substrate = VerifiedSubstrate()
221
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
222
+
223
+ engine = MaterialFieldEngine(
224
+ substrate,
225
+ lambda_min=config['lambda_min'],
226
+ lambda_max=config['lambda_max'],
227
+ inference_steps=config['total_steps']
228
+ )
229
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
230
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
231
+
232
+ # Add substrate-aligned and far candidates
233
+ engine.initialize_candidates([
234
+ (0.95, 0.92), # Near substrate
235
+ (0.50, 0.50), # Medium distance
236
+ (0.30, 0.25), # Far from substrate
237
+ (0.10, 0.10), # Very far from substrate
238
+ ])
239
+ result = engine.run_inference()
240
+
241
+ # Check: At least one exclusion occurred
242
+ has_exclusions = result['total_excluded'] > 0
243
+ results.record(
244
+ "Exclusion: Weak candidates excluded",
245
+ has_exclusions,
246
+ f"Expected >0 exclusions, got {result['total_excluded']}"
247
+ )
248
+
249
+ # Check: Survivor count decreases or stays at 1 (if exclusions happen early)
250
+ initial_survivors = result['phase_log'][0]['survivors']
251
+ final_survivors = result['phase_log'][-1]['survivors']
252
+ survivors_decreased_or_single = final_survivors <= initial_survivors
253
+ results.record(
254
+ "Exclusion: Survivor count ≤ initial",
255
+ survivors_decreased_or_single,
256
+ f"Initial: {initial_survivors}, Final: {final_survivors}"
257
+ )
258
+
259
+
260
+ def test_numerical_stability(results):
261
+ """Test 5: No NaN/Inf values in outputs"""
262
+ print("\n" + "="*80)
263
+ print("TEST 5: NUMERICAL STABILITY")
264
+ print("="*80)
265
+
266
+ config = load_config("balanced")
267
+ substrate = VerifiedSubstrate()
268
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
269
+
270
+ engine = MaterialFieldEngine(
271
+ substrate,
272
+ lambda_min=config['lambda_min'],
273
+ lambda_max=config['lambda_max'],
274
+ inference_steps=config['total_steps']
275
+ )
276
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
277
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
278
+
279
+ # Test with edge cases
280
+ edge_cases = [
281
+ (0.0, 0.0), # Zero vector
282
+ (1.0, 1.0), # Unit diagonal
283
+ (0.95, 0.92), # Near substrate
284
+ ]
285
+
286
+ engine.initialize_candidates(edge_cases)
287
+ result = engine.run_inference()
288
+
289
+ # Check for NaN/Inf in output
290
+ if result['final_output']:
291
+ has_nan_inf = (
292
+ math.isnan(result['final_output'].x) or
293
+ math.isnan(result['final_output'].y) or
294
+ math.isinf(result['final_output'].x) or
295
+ math.isinf(result['final_output'].y)
296
+ )
297
+ results.record(
298
+ "Numerical: No NaN/Inf in output",
299
+ not has_nan_inf,
300
+ "Found NaN or Inf in output coordinates"
301
+ )
302
+ else:
303
+ results.record(
304
+ "Numerical: Abstention (no output)",
305
+ True,
306
+ "System abstained (acceptable)"
307
+ )
308
+
309
+ # Check: Elastic modulus in [0, 1]
310
+ for i, v in enumerate(engine.candidate_vectors + engine.excluded_vectors):
311
+ E = v.properties.elastic_modulus
312
+ in_range = 0.0 <= E <= 1.0
313
+ if not in_range:
314
+ results.record(
315
+ f"Numerical: E bounded for vector {i}",
316
+ False,
317
+ f"E={E} outside [0, 1]"
318
+ )
319
+ break
320
+ else:
321
+ results.record(
322
+ "Numerical: All E values in [0, 1]",
323
+ True
324
+ )
325
+
326
+
327
+ def test_yield_strength_stability(results):
328
+ """Test 6: Yield strength computation is stable"""
329
+ print("\n" + "="*80)
330
+ print("TEST 6: YIELD STRENGTH STABILITY")
331
+ print("="*80)
332
+
333
+ substrate = VerifiedSubstrate()
334
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
335
+
336
+ config = load_config("balanced")
337
+
338
+ # Compute yield strength for same vector multiple times
339
+ test_vector = (0.50, 0.50)
340
+ yield_strengths = []
341
+
342
+ for _ in range(3):
343
+ engine = MaterialFieldEngine(
344
+ substrate,
345
+ lambda_min=config['lambda_min'],
346
+ lambda_max=config['lambda_max'],
347
+ inference_steps=config['total_steps']
348
+ )
349
+ engine.initialize_candidates([test_vector])
350
+ sigma_y = engine.candidate_vectors[0].properties.yield_strength
351
+ yield_strengths.append(sigma_y)
352
+
353
+ # Check: All identical
354
+ all_identical = len(set(yield_strengths)) == 1
355
+ results.record(
356
+ "Yield strength: Stable across runs",
357
+ all_identical,
358
+ f"Got different values: {yield_strengths}"
359
+ )
360
+
361
+ if all_identical:
362
+ print(f" σ_y = {yield_strengths[0]:.6f}")
363
+
364
+
365
+ def test_hallucination_free_logic(results):
366
+ """Test 7: Grounding/abstention flag is consistent"""
367
+ print("\n" + "="*80)
368
+ print("TEST 7: GROUNDING FLAG")
369
+ print("="*80)
370
+
371
+ config = load_config("balanced")
372
+ substrate = VerifiedSubstrate()
373
+ substrate.add_verified_state(Vector2D(x=0.95, y=0.92, properties=None))
374
+
375
+ # Test 1: Grounded output should mark `hallucination_free` True
376
+ engine = MaterialFieldEngine(
377
+ substrate,
378
+ lambda_min=config['lambda_min'],
379
+ lambda_max=config['lambda_max'],
380
+ inference_steps=config['total_steps']
381
+ )
382
+ engine.phase_controller.nucleation_threshold = config['nucleation_threshold']
383
+ engine.phase_controller.quenching_threshold = config['quenching_threshold']
384
+ engine.initialize_candidates([(0.95, 0.92)]) # Near substrate
385
+ result = engine.run_inference()
386
+
387
+ results.record(
388
+ "Grounding flag: Grounded output marked correctly",
389
+ result['hallucination_free'] and result['final_output'] is not None,
390
+ f"Expected True, got {result['hallucination_free']}"
391
+ )
392
+
393
+ # Test 2: Abstention should mark `hallucination_free` True
394
+ engine2 = MaterialFieldEngine(
395
+ substrate,
396
+ lambda_min=0.9, # Very high pressure
397
+ lambda_max=3.0,
398
+ inference_steps=4
399
+ )
400
+ engine2.phase_controller.nucleation_threshold = 0.1
401
+ engine2.phase_controller.quenching_threshold = 0.3
402
+ engine2.initialize_candidates([(0.01, 0.01)]) # Very far
403
+ result2 = engine2.run_inference()
404
+
405
+ # If abstained, should still be hallucination-free
406
+ if result2['abstained']:
407
+ results.record(
408
+ "Grounding flag: Abstention marked correctly",
409
+ result2['hallucination_free'],
410
+ "Abstention should set hallucination_free=True"
411
+ )
412
+
413
+
414
+ def main():
415
+ print("""
416
+ ╔══════════════════════════════════════════════════════════════════════════════╗
417
+ ║ ║
418
+ ║ MATERIAL-FIELD GOVERNANCE TEST SUITE ║
419
+ ║ Verifying Core Invariants and Pinning Behavior ║
420
+ ║ ║
421
+ ╚══════════════════════════════════════════════════════════════════════════════╝
422
+ """)
423
+
424
+ results = TestResults()
425
+
426
+ # Run all tests
427
+ test_determinism(results)
428
+ test_phase_progression(results)
429
+ test_pressure_monotonicity(results)
430
+ test_mechanical_exclusion(results)
431
+ test_numerical_stability(results)
432
+ test_yield_strength_stability(results)
433
+ test_hallucination_free_logic(results)
434
+
435
+ # Print summary
436
+ success = results.summary()
437
+
438
+ if success:
439
+ print("\nALL TESTS PASSED")
440
+ return 0
441
+ else:
442
+ print("\nSOME TESTS FAILED")
443
+ return 1
444
+
445
+
446
+ if __name__ == "__main__":
447
+ sys.exit(main())
verify_fixes.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import sys
3
+ import os
4
+ from pathlib import Path
5
+
6
+ # Add project root to path
7
+ sys.path.insert(0, str(Path(__file__).parent))
8
+
9
+ from material_field_engine import MaterialFieldEngine, VerifiedSubstrate, Vector2D, fp_to_float, fp_from_float
10
+ from llm_adapter import DeterministicHashEmbedderND
11
+
12
+ def test_16d_stability():
13
+ print("Testing 16D Stability and Stress Reporting...")
14
+
15
+ # Setup 16D environment
16
+ embedder = DeterministicHashEmbedderND(dims=16)
17
+
18
+ # Create substrate (1 verified fact)
19
+ substrate_text = "The sky is blue"
20
+ sub_vec_coords = embedder.embed(substrate_text)
21
+ substrate_vector = Vector2D(
22
+ x=sub_vec_coords[0],
23
+ y=sub_vec_coords[1],
24
+ properties=None,
25
+ coords=sub_vec_coords
26
+ )
27
+
28
+ substrate = VerifiedSubstrate(
29
+ verified_states=[substrate_vector],
30
+ elastic_modulus_mode='multiplicative',
31
+ elastic_modulus_sigma=0.5
32
+ )
33
+
34
+ # Create engine
35
+ engine = MaterialFieldEngine(substrate, lambda_min=0.3, lambda_max=0.9, inference_steps=8)
36
+
37
+ # Test 1: Near match (should survive or fracture late, definitely NOT at step 0)
38
+ # We simulate a "near match" by adding tiny noise to the substrate vector
39
+ near_coords = [c + 0.01 for c in sub_vec_coords]
40
+
41
+ engine.initialize_candidates([near_coords])
42
+
43
+ # Check initial properties
44
+ print("\nInitial Candidate Properties:")
45
+ for v in engine.candidate_vectors:
46
+ print(f"E: {v.properties.elastic_modulus:.4f}, Strain: {v.properties.strain:.4f}")
47
+
48
+ start_stress = engine.candidate_vectors[0].properties.stress
49
+ print(f"Initial Stress: {start_stress}")
50
+
51
+ # Run Inference
52
+ results = engine.run_inference()
53
+
54
+ final_output = results.get('final_output')
55
+ print(f"\nFinal Output: {'Survived' if final_output else 'Excluded'}")
56
+
57
+ # Check Stress Reporting
58
+ max_stress = results.get('max_stress')
59
+ final_stress = results.get('final_stress')
60
+
61
+ print(f"Max Stress: {max_stress}")
62
+ print(f"Final Reported Stress: {final_stress}")
63
+
64
+ if final_output is None:
65
+ # If excluded, ensure final_stress matches max_stress and is > 0 (unless it started > yield)
66
+ if final_stress != max_stress:
67
+ print("FAILURE: final_stress does not match max_stress for excluded candidate.")
68
+ else:
69
+ print("SUCCESS: Stress reporting logic works for exclusions.")
70
+
71
+ # Check 16D Stability
72
+ # If E is tiny (<0.1) despite being close (distance ~ 0.04 in 16D), then normalization failed.
73
+ # Distance of 0.01 in 16 dims: sqrt(16 * 0.01^2) = sqrt(0.0016) = 0.04.
74
+ # RBF with sigma=0.5: exp(-0.04^2 / (2*0.5^2)) = exp(-0.0016 / 0.5) ~ 1.0.
75
+ # Without normalization? 16D "close" usually means distance ~1.0-2.0 if not identical.
76
+ # Let's check a "misaligned" but "close-ish" one.
77
+
78
+ # Real test: Random vector (avg distance in 16D is high).
79
+ # Expected: E should not be 0.0 just due to dims.
80
+
81
+ print("\nTest passed if no crashes and stress is reported.")
82
+
83
+ if __name__ == "__main__":
84
+ test_16d_stability()