use holographic_memory::core::entangled::{hash_u64, EntangledHVec};
use std::collections::{HashMap, HashSet};
const DIM: usize = 16384;
const DENOM: usize = 256;
const N_CONCEPTS: usize = 100;
const MAX_FACTS: usize = 5000;
fn load_points() -> Vec<usize> {
vec![10, 50, 100, 200, 500, 1000, 2000, 5000]
}
fn density(bundle: &EntangledHVec) -> f64 {
bundle.indices().len() as f64 / DIM as f64
}
struct Fact {
country_idx: usize,
capital_idx: usize,
composed: EntangledHVec,
}
fn main() {
let concepts: Vec<EntangledHVec> = (0..N_CONCEPTS)
.map(|i| EntangledHVec::new_with_density(DIM, DENOM, i as u64 * 7 + 42))
.collect();
let relation = EntangledHVec::new_with_density(DIM, DENOM, 0xCAFE_BABE);
let mut facts: Vec<Fact> = Vec::with_capacity(MAX_FACTS);
'outer: for ci in 0..N_CONCEPTS {
for ki in 0..N_CONCEPTS {
if facts.len() >= MAX_FACTS {
break 'outer;
}
let composed = concepts[ci].bind(&relation).bind(&concepts[ki]);
facts.push(Fact {
country_idx: ci,
capital_idx: ki,
composed,
});
}
}
let all_composed: Vec<&EntangledHVec> = facts.iter().map(|f| &f.composed).collect();
let mut arm_a_pool: HashSet<u32> = HashSet::new();
for f in &facts {
for &idx in f.composed.indices() {
arm_a_pool.insert(idx);
}
}
let pool_indices: Vec<u32> = {
let mut v: Vec<u32> = arm_a_pool.into_iter().collect();
v.sort_unstable();
v
};
let pool_size = pool_indices.len();
let arm_a_active_counts: Vec<usize> =
facts.iter().map(|f| f.composed.indices().len()).collect();
let avg_active =
arm_a_active_counts.iter().sum::<usize>() as f64 / arm_a_active_counts.len() as f64;
let arm_b_items: Vec<EntangledHVec> = (0..MAX_FACTS)
.map(|i| {
let target_k = arm_a_active_counts[i];
let mut selected: Vec<u32> = Vec::with_capacity(target_k);
let seed = i as u64 * 31 + 0xB00B;
for p in 0..target_k {
let pool_idx = hash_u64(seed, p as u64) as usize % pool_size;
selected.push(pool_indices[pool_idx]);
}
selected.sort_unstable();
selected.dedup();
EntangledHVec::from_indices(selected, DIM)
})
.collect();
let arm_c_items: Vec<EntangledHVec> = (0..MAX_FACTS)
.map(|i| EntangledHVec::new_with_density(DIM, DENOM, i as u64 * 1_000_003 + 0xDEAD))
.collect();
let n_probes = 200usize;
let probes_b: Vec<EntangledHVec> = (0..n_probes)
.map(|i| {
let target_k = avg_active.round() as usize;
let seed = i as u64 * 97 + 0xF00D;
let mut selected: Vec<u32> = Vec::with_capacity(target_k);
for p in 0..target_k {
let pool_idx = hash_u64(seed, p as u64) as usize % pool_size;
selected.push(pool_indices[pool_idx]);
}
selected.sort_unstable();
selected.dedup();
EntangledHVec::from_indices(selected, DIM)
})
.collect();
let probes_c: Vec<EntangledHVec> = (0..n_probes)
.map(|i| {
EntangledHVec::new_with_density(
DIM,
DENOM,
(MAX_FACTS + n_probes + i) as u64 * 1_000_003 + 0xBEEF,
)
})
.collect();
println!("KILL CRITERION: Codebook recovery at n=5000 must exceed 80% top-1 AND arm A must beat arm B gap by clear margin.");
println!(
"If recovery < 80%: codebook stores concepts not facts, Category 4 is density artifact."
);
println!("If A and B gap tie: structure claim dead, only bounded-pool effect is real.");
println!();
println!(
"# Setup: D={}, denom={} (k={}), {} concepts, {} max facts",
DIM,
DENOM,
DIM / DENOM,
N_CONCEPTS,
MAX_FACTS
);
println!(
"# Arm-A index pool size: {} / {} = {:.4} of dimension",
pool_size,
DIM,
pool_size as f64 / DIM as f64
);
println!("# Arm-A avg active count per fact: {:.1}", avg_active);
println!();
println!("# ARM A: Codebook composition (100 concepts, structured)");
println!(
"# arm\tn_items\trecovery_accuracy\tn_ambiguous\tn_correct_but_ambig\tbundle_density\tgap"
);
let load_pts = load_points();
let mut arm_a_final_recovery = 0.0f64;
for &n in &load_pts {
let n = n.min(facts.len());
let bundle = EntangledHVec::bundle_bloom(&all_composed[..n]);
let d = density(&bundle);
let mut correct = 0usize;
let mut ambiguous = 0usize;
let mut correct_but_ambig = 0usize;
for fact in &facts[..n] {
let country_idx = fact.country_idx;
let capital_idx = fact.capital_idx;
let mut pass_count = 0usize;
let mut correct_passes = false;
for cand_j in 0..N_CONCEPTS {
let candidate_fact = concepts[country_idx]
.bind(&relation)
.bind(&concepts[cand_j]);
let cc = candidate_fact.corrected_containment(&bundle);
if cc >= 0.99 {
pass_count += 1;
if cand_j == capital_idx {
correct_passes = true;
}
}
}
if correct_passes && pass_count == 1 {
correct += 1;
} else if correct_passes && pass_count > 1 {
ambiguous += 1;
correct_but_ambig += 1;
}
}
let recovery = correct as f64 / n as f64;
if n == facts.len().min(MAX_FACTS) || n == 5000 {
arm_a_final_recovery = recovery;
}
let member_mins: Vec<f64> = (0..n.min(200))
.map(|fi| facts[fi].composed.corrected_containment(&bundle))
.collect();
let member_min = member_mins.iter().cloned().fold(f64::INFINITY, f64::min);
let mut nonmember_maxes: Vec<f64> = Vec::new();
for pi in 0..200usize {
let ci = (n + pi) % N_CONCEPTS;
let ki = ((n + pi) / N_CONCEPTS + 50) % N_CONCEPTS;
let probe = concepts[ci].bind(&relation).bind(&concepts[ki]);
let is_stored = facts[..n]
.iter()
.any(|f| f.country_idx == ci && f.capital_idx == ki);
if !is_stored {
nonmember_maxes.push(probe.corrected_containment(&bundle));
}
}
let nonmember_max = if nonmember_maxes.is_empty() {
f64::NEG_INFINITY
} else {
nonmember_maxes
.iter()
.cloned()
.fold(f64::NEG_INFINITY, f64::max)
};
let gap = member_min - nonmember_max;
println!(
"A\t{}\t{:.4}\t{}\t{}\t{:.4}\t{:.4}",
n, recovery, ambiguous, correct_but_ambig, d, gap
);
}
println!();
println!("# ARM B: Bounded pool, independent (same density growth, no structure)");
println!("# arm\tn_items\tbundle_density\tmember_min\tnonmember_max\tgap");
for &n in &load_pts {
let n = n.min(arm_b_items.len());
let slice: Vec<&EntangledHVec> = arm_b_items[..n].iter().collect();
let bundle = EntangledHVec::bundle_bloom(&slice);
let d = density(&bundle);
let member_ccs: Vec<f64> = arm_b_items[..n]
.iter()
.map(|v| v.corrected_containment(&bundle))
.collect();
let member_min = member_ccs.iter().cloned().fold(f64::INFINITY, f64::min);
let probe_ccs: Vec<f64> = probes_b
.iter()
.map(|v| v.corrected_containment(&bundle))
.collect();
let nonmember_max = probe_ccs.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
let gap = member_min - nonmember_max;
println!(
"B\t{}\t{:.4}\t{:.4}\t{:.4}\t{:.4}",
n, d, member_min, nonmember_max, gap
);
}
println!();
println!("# ARM C: Unbounded IID baseline");
println!("# arm\tn_items\tbundle_density\tmember_min\tnonmember_max\tgap");
for &n in &load_pts {
let n = n.min(arm_c_items.len());
let slice: Vec<&EntangledHVec> = arm_c_items[..n].iter().collect();
let bundle = EntangledHVec::bundle_bloom(&slice);
let d = density(&bundle);
let member_ccs: Vec<f64> = arm_c_items[..n]
.iter()
.map(|v| v.corrected_containment(&bundle))
.collect();
let member_min = member_ccs.iter().cloned().fold(f64::INFINITY, f64::min);
let probe_ccs: Vec<f64> = probes_c
.iter()
.map(|v| v.corrected_containment(&bundle))
.collect();
let nonmember_max = probe_ccs.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
let gap = member_min - nonmember_max;
println!(
"C\t{}\t{:.4}\t{:.4}\t{:.4}\t{:.4}",
n, d, member_min, nonmember_max, gap
);
}
println!();
println!("# DIAGNOSTIC: Recovery accuracy by concept sharing count (n=5000)");
println!("# sharing_bucket\tn_facts\trecovery_accuracy");
let n_diag = MAX_FACTS.min(facts.len());
let bundle_diag = EntangledHVec::bundle_bloom(&all_composed[..n_diag]);
let mut concept_usage: HashMap<usize, usize> = HashMap::new();
for f in &facts[..n_diag] {
*concept_usage.entry(f.country_idx).or_insert(0) += 1;
*concept_usage.entry(f.capital_idx).or_insert(0) += 1;
}
struct DiagFact {
max_sharing: usize,
recovered: bool,
}
let mut diag_facts: Vec<DiagFact> = Vec::with_capacity(n_diag);
for fact in &facts[..n_diag] {
let country_idx = fact.country_idx;
let capital_idx = fact.capital_idx;
let max_sharing = std::cmp::max(
*concept_usage.get(&country_idx).unwrap_or(&0),
*concept_usage.get(&capital_idx).unwrap_or(&0),
);
let mut pass_count = 0usize;
let mut correct_passes = false;
for cand_j in 0..N_CONCEPTS {
let candidate_fact = concepts[country_idx]
.bind(&relation)
.bind(&concepts[cand_j]);
let cc = candidate_fact.corrected_containment(&bundle_diag);
if cc >= 0.99 {
pass_count += 1;
if cand_j == capital_idx {
correct_passes = true;
}
}
}
let recovered = correct_passes && pass_count == 1;
diag_facts.push(DiagFact {
max_sharing,
recovered,
});
}
let mut buckets: HashMap<usize, (usize, usize)> = HashMap::new();
for df in &diag_facts {
let entry = buckets.entry(df.max_sharing).or_insert((0, 0));
entry.0 += 1;
if df.recovered {
entry.1 += 1;
}
}
let mut bucket_keys: Vec<usize> = buckets.keys().cloned().collect();
bucket_keys.sort();
for &k in &bucket_keys {
let (total, recovered) = buckets[&k];
let acc = recovered as f64 / total as f64;
println!("{}\t{}\t{:.4}", k, total, acc);
}
println!();
println!("# ═══════════════════════════════════════════════════════════");
println!("# VERDICT");
if arm_a_final_recovery >= 0.80 {
println!(
"# Recovery at n=5000: {:.1}% >= 80% => codebook stores FACTS, not just concepts.",
arm_a_final_recovery * 100.0
);
} else {
println!(
"# Recovery at n=5000: {:.1}% < 80% => KILL: codebook stores concepts not facts, Category 4 is density artifact.",
arm_a_final_recovery * 100.0
);
}
println!("# ═══════════════════════════════════════════════════════════");
}