tasq/node_modules/agentic-flow/docs/quantum-research/QUANTUM_RESEARCH_LITERATURE_REVIEW.md

57 KiB
Raw Blame History

Observer-Agnostic Quantum Measurement: Comprehensive Literature Review

Research Date: 2025-10-14 Researcher: Research Agent Context: Implementation requirements for Observer-Agnostic Measurement and No-Retrocausal Marginals Theorem Purpose: Deep research to support falsifiable quantum mechanics experiment testing consciousness effects on quantum measurement outcomes


Executive Summary

This comprehensive literature review examines five critical areas for implementing the Observer-Agnostic Measurement experiment in Rust:

  1. Quantum Measurement Theory - POVM formalism, Born rule, delayed-choice quantum eraser experiments
  2. Rust Quantum Computing Libraries - nalgebra, num-complex, quantum simulation frameworks, SIMD optimization
  3. Experimental Design - Photonic quantum eraser setups, entangled photon generation, interferometry
  4. Best Practices - Pre-registration protocols, reproducibility standards, falsification criteria
  5. Implementation Considerations - Scientific Rust project structure, testing strategies, visualization

Key Finding: The existing research document provides an excellent theoretical foundation. This review adds critical implementation details, library recommendations, and best practices from 2024's quantum computing ecosystem.


1. Quantum Measurement Theory

1.1 POVM (Positive Operator-Valued Measure) Formalism

Theoretical Foundation:

  • POVMs represent the most general class of quantum measurements
  • An n-outcome POVM is a set of n positive semi-definite Hermitian operators {E_k} that sum to identity: Σ E_k = I
  • Given a d-dimensional quantum state ρ, the probability of observing outcome k is given by Born's rule: p(k) = Tr(E_k ρ)
  • POVMs extend standard projective measurements (PVMs) and are essential for describing realistic, imperfect measurements

Recent Developments (2024):

  • The POVM theorem has been systematically presented in Bohmian mechanics context, grounding measurement formalism in quantum equilibrium hypothesis
  • POVM formalism is extensively used in quantum information, quantum field theory, and quantum computing
  • Qiskit now includes POVM Toolbox for practical implementations

Computational Representation:

use nalgebra::{DMatrix, Complex};
use num_complex::Complex64 as C64;

/// POVM element (positive semi-definite operator)
pub struct POVMElement {
    operator: DMatrix<C64>,
}

impl POVMElement {
    /// Create from projector |ψ⟩⟨ψ|
    pub fn from_projector(psi: &DVector<C64>) -> Self {
        let n = psi.len();
        let mut op = DMatrix::zeros(n, n);
        for i in 0..n {
            for j in 0..n {
                op[(i, j)] = psi[i] * psi[j].conj();
            }
        }
        Self { operator: op }
    }

    /// Verify positive semi-definiteness
    pub fn is_valid(&self) -> bool {
        // Check eigenvalues are non-negative
        let eigs = self.operator.complex_eigenvalues();
        eigs.iter().all(|e| e.re >= -1e-10)
    }
}

/// Complete POVM measurement set
pub struct POVM {
    elements: Vec<POVMElement>,
}

impl POVM {
    /// Verify POVM completeness: Σ E_k = I
    pub fn verify_completeness(&self) -> bool {
        let sum = self.elements.iter()
            .fold(DMatrix::zeros(2, 2), |acc, e| acc + e.operator.clone());

        let identity = DMatrix::identity(2, 2);
        (sum - identity).norm() < 1e-10
    }

    /// Calculate Born rule probability
    pub fn probability(&self, outcome: usize, rho: &DMatrix<C64>) -> f64 {
        let result = &self.elements[outcome].operator * rho;
        result.trace().re
    }
}

1.2 Born Rule and Measurement Probabilities

Theoretical Foundation:

  • Born rule: p(outcome) = Tr(M_outcome ρ) where M is measurement operator and ρ is density matrix
  • For pure states |ψ⟩: p(outcome) = |⟨ψ|M|ψ⟩|²
  • The rule is linear in ρ, meaning measurement statistics depend only on quantum state and measurement setup, NOT on observer identity

Computational Implementation:

/// Calculate measurement probability using Born rule
pub fn born_probability(
    state: &DMatrix<C64>,     // Density matrix ρ
    measurement: &DMatrix<C64>, // Measurement operator M
) -> f64 {
    let result = measurement * state;
    result.trace().re.max(0.0).min(1.0) // Clamp to [0,1] for numerical stability
}

/// For pure states: p = |⟨ψ|M|ψ⟩|²
pub fn born_pure_state(
    psi: &DVector<C64>,
    measurement: &DMatrix<C64>,
) -> f64 {
    let m_psi = measurement * psi;
    let amplitude = psi.dotc(&m_psi);
    (amplitude * amplitude.conj()).re
}

1.3 Delayed-Choice Quantum Eraser Experiments

Experimental Context:

  • Elaboration on Wheeler's delayed-choice experiment incorporating quantum eraser concepts
  • Tests wave-particle duality and complementarity principle
  • Heart of the experiment: mutually exclusive quantum features that appear to violate cause-effect relations

Key Components:

  1. Entangled Photon Pairs: Generated via spontaneous parametric down-conversion (SPDC)
  2. Signal Path: Signal photon passes through double-slit interferometer
  3. Idler Path: Idler photon measured in different bases (which-path vs eraser)
  4. Delayed Choice: Decision about idler measurement can be made after signal detection

2024 Experimental Demonstrations:

  • Recent experiments using coherent photons from attenuated CW lasers
  • Proposal for electron-light entanglement via cathodoluminescence in transmission electron microscope
  • Scientific Reports (2023-2024): Observations with frequency-entangled photon pairs

Critical Predictions:

  • Singles on signal photon are ALWAYS flat (50-50 distribution) regardless of idler measurement choice
  • Conditional statistics (coincidence counts) show interference fringes only when conditioning on eraser basis outcomes
  • NO retrocausal signaling: later measurement choice cannot alter already-registered singles

Computational Model:

/// Delayed-choice quantum eraser simulation
pub struct QuantumEraser {
    phi: f64,  // Phase parameter
}

impl QuantumEraser {
    /// Create Bell state with phase: (|00⟩ + e^(iφ)|11⟩)/√2
    pub fn bell_state_with_phase(&self) -> DVector<C64> {
        let s = 1.0 / 2.0_f64.sqrt();
        DVector::from_vec(vec![
            C64::new(s, 0.0),
            C64::new(0.0, 0.0),
            C64::new(0.0, 0.0),
            C64::from_polar(s, self.phi),
        ])
    }

    /// Singles probability (MUST be 0.5, 0.5 regardless of idler measurement)
    pub fn singles_probability(&self) -> [f64; 2] {
        let psi = self.bell_state_with_phase();
        let rho = density_matrix(&psi);
        let rho_signal = partial_trace_second(&rho);

        let p0 = born_probability(&rho_signal, &projector(&ket0()));
        let p1 = born_probability(&rho_signal, &projector(&ket1()));

        [p0, p1]
    }

    /// Conditional probability p(signal|idler, basis)
    pub fn conditional_probability(
        &self,
        idler_basis: IdlerBasis,
    ) -> [[f64; 2]; 2] {
        // Implementation shows phase-dependent fringes for eraser basis
        // but NOT in singles statistics
        todo!("See existing research.md for full implementation")
    }
}

1.4 Wave-Particle Duality and Complementarity

Englert's Duality Relation:

  • For any quantum interferometer: V² + D² ≤ 1
  • V = visibility (wave-like behavior), D = distinguishability (particle-like behavior)
  • Perfect implementation: V² + D² = 1 for pure states
  • Partial which-path information: 0 < V² + D² < 1

Computational Verification:

pub fn verify_duality_bound(
    visibility: f64,
    distinguishability: f64,
) -> bool {
    let sum = visibility.powi(2) + distinguishability.powi(2);
    sum <= 1.0 + 1e-10 // Allow small numerical error
}

/// Calculate visibility from off-diagonal density matrix elements
pub fn calculate_visibility(rho_signal: &DMatrix<C64>) -> f64 {
    2.0 * rho_signal[(0, 1)].norm()
}

/// Calculate distinguishability from diagonal elements
pub fn calculate_distinguishability(rho_signal: &DMatrix<C64>) -> f64 {
    (rho_signal[(0, 0)].re - rho_signal[(1, 1)].re).abs()
}

2. Rust Quantum Computing Libraries

2.1 Core Mathematical Libraries

nalgebra (v0.32+)

Purpose: Linear algebra operations, matrix manipulations, quantum state representations

Justification:

  • Most mature linear algebra library in Rust ecosystem
  • Excellent performance with compile-time optimizations
  • Supports complex numbers via num-complex integration
  • Used extensively in scientific computing projects
  • Strong type safety with dimension checking

Key Features for Quantum Simulation:

  • DMatrix<Complex64>: Dynamic matrices for density matrices and operators
  • DVector<Complex64>: State vectors |ψ⟩
  • Matrix operations: multiplication, trace, eigenvalues
  • Kronecker products for tensor products of quantum systems

Example Usage:

[dependencies]
nalgebra = "0.32"
num-complex = "0.4"

use nalgebra::{DMatrix, DVector};
use num_complex::Complex64 as C64;

// Quantum state
let psi = DVector::from_vec(vec![
    C64::new(1.0/f64::sqrt(2.0), 0.0),
    C64::new(0.0, 1.0/f64::sqrt(2.0)),
]);

// Operator
let sigma_x = DMatrix::from_row_slice(2, 2, &[
    C64::new(0.0, 0.0), C64::new(1.0, 0.0),
    C64::new(1.0, 0.0), C64::new(0.0, 0.0),
]);

num-complex (v0.4+)

Purpose: Complex number arithmetic

Justification:

  • Standard complex number implementation in Rust
  • Integrates seamlessly with nalgebra
  • Efficient operations with SIMD potential
  • Supports polar form for phase representation

Key Features:

use num_complex::Complex64;

// Rectangular form
let z1 = Complex64::new(1.0, 2.0);

// Polar form (for phase factors e^(iφ))
let z2 = Complex64::from_polar(1.0, std::f64::consts::PI / 4.0);

// Operations
let sum = z1 + z2;
let conj = z1.conj();
let norm = z1.norm();

2.2 Quantum Simulation Frameworks

GitHub: https://github.com/Renmusxd/RustQIP

Justification:

  • Most feature-complete quantum simulation library
  • Leverages Rust's borrow checker to enforce no-cloning theorem
  • Graph-based circuit building for optimization
  • Active maintenance and community

Key Features:

  • Quantum circuit builder with type-safe gate operations
  • State vector simulation with efficient memory management
  • Support for measurements and conditional operations
  • Noise models for realistic simulations

Example:

use qip::prelude::*;

let n_qubits = 2;
let mut b = OpBuilder::new();
let q = b.qubit(); // |0⟩

// Build quantum circuit
let q = b.hadamard(q);
let q = b.phase(q, std::f64::consts::PI / 4.0);

// Measure
let (_, measured) = b.measure(q);

q1tsim (Alternative)

Crates.io: https://crates.io/crates/q1tsim

Justification:

  • Simpler API, easier learning curve
  • Efficient for small-scale simulations
  • Good for educational purposes and prototyping

Trade-offs:

  • Less feature-rich than RustQIP
  • Smaller community
  • Better for straightforward simulations

Spinoza (High Performance)

GitHub: https://github.com/QuState/spinoza

Justification:

  • Pure Rust implementation with Python bindings
  • Designed for performance
  • Flexible and fast for classical simulation

Use Cases:

  • Large-scale state vector simulations
  • Performance-critical applications
  • Hybrid quantum-classical algorithms

2.3 SIMD Optimization Strategies

Context: Quantum state vectors scale as 2^n for n qubits. SIMD can provide 2-8× speedup for vector operations.

rayon (v1.8+) - Data Parallelism

[dependencies]
rayon = "1.8"

use rayon::prelude::*;

// Parallel state vector operations
fn apply_gate_parallel(
    state: &mut Vec<Complex64>,
    gate: &Gate,
) {
    state.par_chunks_mut(2)
        .for_each(|chunk| {
            gate.apply_to_pair(chunk);
        });
}

packed_simd2 - Explicit SIMD

[dependencies]
packed_simd_2 = "0.3"

use packed_simd_2::*;

// SIMD complex multiplication
#[inline]
fn complex_mul_simd(a: f64x4, b: f64x4) -> f64x4 {
    // a = [a.re, a.im, c.re, c.im]
    // b = [b.re, b.im, d.re, d.im]
    // Implements 2 complex multiplications in parallel
    todo!("SIMD implementation")
}

SimSIMD - Mixed Precision SIMD

Library: https://lib.rs/crates/simsimd

Features:

  • 350+ SIMD-optimized kernels
  • Dot products for complex vectors
  • Ideal for quantum computing workloads
  • Used in AI, search, and DBMS

Application to Quantum:

// Inner products for quantum state overlap
// ⟨ψ|φ⟩ = Σ ψ_i* φ_i
fn quantum_inner_product(
    psi: &[Complex64],
    phi: &[Complex64],
) -> Complex64 {
    // Use SimSIMD for 4-8× speedup
    todo!("SimSIMD integration")
}

2.4 Performance Comparison (2024 Data)

Based on available benchmarks and community reports:

Library State Vector Size Performance Memory Use Case
RustQIP Up to 20 qubits Efficient General purpose
q1tsim Up to 15 qubits Good Education
Spinoza Up to 25 qubits Optimized HPC
Raw nalgebra Unlimited Manual Custom algorithms

Recommendation for Observer-Agnostic Experiment:

  • Primary: Raw nalgebra + num-complex (full control, matches research.md)
  • Validation: RustQIP (cross-check against established library)
  • Optimization: rayon for parallelism, consider SimSIMD for production

3. Experimental Design: Photonic Quantum Eraser

3.1 Entangled Photon Generation via SPDC

Spontaneous Parametric Down-Conversion (SPDC):

Process:

  • High-power UV pump laser (typically 405 nm) focused on nonlinear crystal
  • Crystal material: Beta-Barium Borate (BBO) or Lithium Niobate (LN)
  • Single pump photon → two lower-energy photons (signal + idler)
  • Energy conservation: ω_pump = ω_signal + ω_idler
  • Momentum conservation: k_pump = k_signal + k_idler

Types of SPDC:

  1. Type-I SPDC:

    • Signal and idler have same polarization
    • Perpendicular to pump polarization
    • Simpler to implement
    • Good for basic quantum eraser experiments
  2. Type-II SPDC:

    • Signal and idler have orthogonal polarizations
    • More complex setup
    • Natural polarization entanglement
    • Preferred for Observer-Agnostic experiment

Laboratory Setup (2024 Standards):

Pump Laser (405 nm, 50-100 mW)
    ↓
Focusing Optics (f = 50-100 mm)
    ↓
BBO Crystal (Type-II, 1-2 mm thick)
    ↓
Collimating Optics
    ↓
Dichroic Mirror (separate pump from down-converted photons)
    ↓
Signal (810 nm) ← HOM Beam Splitter → Idler (810 nm)

BBO Crystal Specifications:

  • Material: β-BaB₂O₄
  • Type: Type-II phase matching
  • Thickness: 1-2 mm (optimal for 405 nm → 810 nm)
  • Cutting angle: Optimized for collinear or non-collinear emission
  • AR coating: 405 nm and 810 nm

Commercial Sources (2024):

  • Thorlabs: SPDC crystals and complete kits
  • qutools: Integrated SPDC sources with alignment fixtures
  • Typical cost: $5,000-$15,000 for complete SPDC source

Entanglement Quality:

  • Coincidence rate: 1000-10,000 pairs/second (typical)
  • Heralding efficiency: 50-80%
  • Entanglement fidelity: >95% achievable
  • Coherence time: Limited by pump laser coherence (~ns to μs)

3.2 Interferometer Configurations

Signal Interferometer:

Signal Photon
    ↓
Beam Splitter 1 (50:50)
    ↓
Path A → Phase Shifter φ
Path B → (Reference)
    ↓
Beam Splitter 2 (50:50)
    ↓
Detector D_0, D_1

Idler Measurement:

Idler Photon
    ↓
[Switchable Measurement Basis]
    ├─ Which-Path: Measure in |0⟩, |1⟩ basis
    └─ Eraser: Insert Beam Splitter → Measure in |+⟩, |−⟩ basis
    ↓
Detector D_A, D_B

Key Components:

  1. Beam Splitters:

    • 50:50 non-polarizing cube beam splitters
    • Quality: >99% splitting ratio stability
    • AR coated for 810 nm
  2. Phase Shifter:

    • Piezo-mounted mirror or electrooptic modulator
    • Range: 0 to 2π
    • Resolution: <λ/100
    • Stability: <λ/50 drift over measurement time
  3. Detectors:

    • Single-photon avalanche diodes (SPADs)
    • Quantum efficiency: >50% at 810 nm
    • Dark count rate: <100 counts/second
    • Timing resolution: <500 ps
    • Examples: PerkinElmer SPCM-AQRH, Excelitas SPCM-AQ4C
  4. Coincidence Electronics:

    • Time-tagging module or coincidence counter
    • Resolution: ≤1 ns
    • Examples: PicoQuant HydraHarp, Swabian Time Tagger

3.3 Observer Control Mechanism

Critical Feature for Observer-Agnostic Test:

The experiment MUST implement three types of controllers for the idler basis choice:

Controller Type 1: Human Observer

┌─────────────────────────────┐
│  Human presses button       │
│  "Which-Path" or "Eraser"   │
└────────────┬────────────────┘
             ↓
    Optical Switch / Flip Mirror
             ↓
    Idler Measurement Path

Controller Type 2: Hardware Random Number Generator

┌─────────────────────────────┐
│  Quantum RNG (e.g., IDQ)    │
│  or Cryptographic RNG       │
└────────────┬────────────────┘
             ↓
    Microcontroller Decision
             ↓
    Motorized Flip Mirror
             ↓
    Idler Measurement Path

Controller Type 3: Deterministic Timer

┌─────────────────────────────┐
│  Scheduled Pattern:         │
│  t < 30s: Which-Path        │
│  t ≥ 30s: Eraser            │
└────────────┬────────────────┘
             ↓
    Computer-Controlled Switch
             ↓
    Idler Measurement Path

Implementation Requirements:

  • Controller identity must be BLINDED in data file
  • Timestamp all events (signal detection, idler detection, controller decision)
  • Record all metadata (temperature, alignment, laser power)
  • Randomize controller order across runs

3.4 Statistical Analysis Methods

Primary Test: Chi-Squared Test

Purpose: Test if signal singles distribution differs across controller types

Hypothesis:

  • H₀: p(signal=0) = 0.5 for all controller types (observer-agnostic)
  • H₁: p(signal=0) ≠ 0.5 for at least one controller type

Implementation:

use statrs::distribution::{ChiSquared, ContinuousCDF};

pub fn chi_squared_test(
    observed: &[u64],  // [counts_0, counts_1] for each controller
    expected: &[u64],  // Expected counts under H₀
) -> (f64, f64) {
    let chi_squared = observed.iter()
        .zip(expected.iter())
        .map(|(&obs, &exp)| {
            let diff = obs as f64 - exp as f64;
            diff * diff / exp as f64
        })
        .sum::<f64>();

    let df = (observed.len() - 1) as f64;
    let dist = ChiSquared::new(df).unwrap();
    let p_value = 1.0 - dist.cdf(chi_squared);

    (chi_squared, p_value)
}

Secondary Test: TOST (Two One-Sided Tests) for Equivalence

Purpose: Prove that controller types produce equivalent results within ε = 5×10⁻⁴

Hypothesis:

  • H₀: |Δp| ≥ ε (distributions differ)
  • H₁: |Δp| < ε (distributions equivalent)

Implementation:

pub fn tost_equivalence_test(
    p_human: f64,
    n_human: u64,
    p_rng: f64,
    n_rng: u64,
    epsilon: f64,  // Equivalence margin (e.g., 5e-4)
) -> (f64, f64) {
    // Standard error
    let se = ((p_human * (1.0 - p_human) / n_human as f64) +
              (p_rng * (1.0 - p_rng) / n_rng as f64)).sqrt();

    // Test 1: p_human - p_rng < epsilon
    let t1 = ((p_human - p_rng) - epsilon) / se;

    // Test 2: p_human - p_rng > -epsilon
    let t2 = ((p_human - p_rng) + epsilon) / se;

    // Both must be significant for equivalence
    let p1 = normal_cdf(t1);
    let p2 = 1.0 - normal_cdf(t2);

    (t1.max(t2), p1.max(p2))
}

Power Analysis:

To detect Δp = 10⁻³ at α = 0.01 with power 0.9:

pub fn required_sample_size(
    effect_size: f64,  // Δp
    alpha: f64,        // Type I error rate
    power: f64,        // 1 - β
) -> u64 {
    // Simplified formula for equal sample sizes
    let z_alpha = normal_quantile(1.0 - alpha / 2.0);
    let z_beta = normal_quantile(power);

    let n = 2.0 * (z_alpha + z_beta).powi(2) / effect_size.powi(2);
    n.ceil() as u64
}

// For Δp = 0.001, α = 0.01, power = 0.9:
// n ≈ 850,000 events per controller type

4. Best Practices: Pre-Registration and Reproducibility

4.1 Pre-Registration Protocols

Why Pre-Register?

  • Prevents p-hacking and HARKing (Hypothesizing After Results are Known)
  • Establishes credibility of null results
  • Standard practice in psychology, medicine; emerging in physics

2024 Status in Physics:

  • Condensed matter physics: International Conference on Reproducibility (NSF-supported)
  • Quantum mechanics: Some groups pre-registering for controversial tests
  • High-energy physics: Pre-registration implicit in theory → experiment workflow

Pre-Registration Template for Observer-Agnostic Experiment:

title: "Observer-Agnostic Measurement and No-Retrocausal Marginals Theorem"
preregistration_date: "YYYY-MM-DD"
expected_completion: "YYYY-MM-DD"

hypotheses:
  primary:
    h0: "Singles probability p(signal|controller) is independent of controller type"
    h1: "Singles probability differs across controller types"
    prediction: "Null result: |Δp| < 5×10⁻⁴"

  secondary:
    h0: "Duality relation V² + D² ≤ 1 holds for all controller types"
    h1: "Duality violation for at least one controller type"

experimental_design:
  apparatus: "Photonic quantum eraser with SPDC, Type-II BBO crystal"
  controllers:
    - type: "human"
      implementation: "Button press interface"
    - type: "hardware_rng"
      implementation: "IDQ Quantis QRNG"
    - type: "deterministic"
      implementation: "Timer-based schedule"

  blinding:
    data_collection: "Controller identity encoded, revealed only after analysis"
    analysis: "Automated scripts with pre-defined thresholds"

  randomization: "Controller order randomized per run, balanced across sessions"

sample_size:
  calculation:
    effect_size: 0.001
    alpha: 0.01
    power: 0.9
    required_n_per_controller: 850000

  stopping_rule:
    type: "fixed_n"
    justification: "Pre-computed sample size, no interim analyses"

statistical_analysis:
  primary_test:
    method: "Chi-squared test"
    significance_level: 0.01
    adjustment: "Bonferroni for 3 pairwise comparisons"

  secondary_test:
    method: "TOST equivalence test"
    equivalence_margin: 5e-4
    justification: "Instrument resolution limit"

exclusion_criteria:
  - "Coincidence window > 2 ns (temporal mismatch)"
  - "Dark count rate > 200 counts/s (detector malfunction)"
  - "Laser power drift > 5% (stability issue)"
  - "Temperature change > 2°C (thermal drift)"

falsification_criteria:
  - "χ² test p-value < 0.01 AND |Δp| > 5×10⁻⁴ (reproducible across 3+ runs)"
  - "Duality violation: V² + D² > 1.01 with error bars excluding 1.0"
  - "Retrocausal signal: Correlation between delayed choice and earlier singles"

data_sharing:
  repository: "Zenodo / OSF / arXiv"
  format: "HDF5 with metadata, CSV summaries"
  code: "GitHub repository with analysis scripts"
  license: "MIT / CC-BY-4.0"

4.2 Reproducibility Standards

Data Formats:

// HDF5 for raw data
[dependencies]
hdf5 = "0.8"

pub struct ExperimentalData {
    pub timestamp: Vec<f64>,           // Event time (ns)
    pub signal_detector: Vec<u8>,      // 0 or 1
    pub idler_detector: Vec<u8>,       // 0 or 1
    pub controller_type: Vec<u8>,      // Blinded: 1, 2, or 3
    pub phase_setting: Vec<f64>,       // Phase φ (radians)
    pub laser_power: Vec<f32>,         // mW
    pub temperature: Vec<f32>,         // °C
}

impl ExperimentalData {
    pub fn save_hdf5(&self, path: &Path) -> Result<()> {
        let file = hdf5::File::create(path)?;
        file.new_dataset::<f64>()
            .create("timestamp", self.timestamp.len())?
            .write(&self.timestamp)?;
        // ... save other fields
        Ok(())
    }
}

Code Archiving:

# Cargo.toml for reproducible builds
[package]
name = "observer-invariance"
version = "1.0.0"
edition = "2021"

# Pin all dependencies for reproducibility
[dependencies]
nalgebra = "=0.32.3"
num-complex = "=0.4.4"
statrs = "=0.16.0"
hdf5 = "=0.8.1"
plotters = "=0.3.5"

# Include data processing scripts
[[bin]]
name = "analyze"
path = "src/bin/analyze.rs"

Docker Container:

# Reproducible analysis environment
FROM rust:1.75

RUN apt-get update && apt-get install -y \
    libhdf5-dev \
    python3-pip

COPY . /experiment
WORKDIR /experiment

RUN cargo build --release
RUN pip3 install numpy matplotlib jupyter

CMD ["cargo", "run", "--release", "--bin", "analyze"]

4.3 Error Analysis and Uncertainty Quantification

Sources of Uncertainty:

  1. Photon Statistics (Poisson):
pub fn poisson_error(counts: u64) -> f64 {
    (counts as f64).sqrt()
}
  1. Detector Efficiency:
  • Systematic: Calibrate against known source (±1-2%)
  • Statistical: Bootstrap resampling
  1. Alignment Drift:
  • Thermal: Monitor temperature, correct for drift
  • Mechanical: Stabilize on optical table, vibration isolation
  1. Background Counts:
pub fn signal_to_noise_ratio(signal: u64, background: u64, time: f64) -> f64 {
    signal as f64 / (background as f64 * time).sqrt()
}

Monte Carlo Uncertainty Propagation:

use rand::thread_rng;
use rand_distr::{Normal, Distribution};

pub fn monte_carlo_error_propagation(
    measured_p: f64,
    n_samples: u64,
    systematic_error: f64,
    n_simulations: usize,
) -> f64 {
    let mut rng = thread_rng();
    let dist = Normal::new(measured_p, systematic_error).unwrap();

    let simulated: Vec<f64> = (0..n_simulations)
        .map(|_| {
            let p = dist.sample(&mut rng).max(0.0).min(1.0);
            // Simulate binomial sampling
            let successes: u64 = (0..n_samples)
                .filter(|_| rng.gen::<f64>() < p)
                .count() as u64;
            successes as f64 / n_samples as f64
        })
        .collect();

    // Standard deviation of simulated values
    let mean = simulated.iter().sum::<f64>() / simulated.len() as f64;
    let variance = simulated.iter()
        .map(|&x| (x - mean).powi(2))
        .sum::<f64>() / simulated.len() as f64;

    variance.sqrt()
}

4.4 Falsification Criteria

What Would Falsify the Theorem?

  1. Reproducible Controller Effect:

    • Condition: χ² test p < 0.01 AND |Δp| > 5×10⁻⁴
    • Requirement: Replicated in 3+ independent runs
    • Controls: Same apparatus, different operators
  2. Duality Violation:

    • Condition: V² + D² > 1.0 + 3σ
    • Requirement: Systematic, not due to misalignment
    • Calibration: Verify with known coherent/incoherent sources
  3. Retrocausal Signal:

    • Condition: Correlation between delayed idler choice and already-recorded signal singles
    • Test: Time-resolved analysis with varying delay
    • Control: Verify with dummy "random" controller (recorded, not causal)

What Would NOT Falsify:

  • Single anomalous run (could be systematic error)
  • Small effects comparable to drift (need better apparatus)
  • Effects that disappear with better blinding (expectation bias)

5. Implementation Considerations: Scientific Rust Projects

5.1 Project Structure

Recommended Layout:

observer-invariance/
├── Cargo.toml                 # Main manifest
├── Cargo.lock                 # Lock file (commit for reproducibility)
├── README.md                  # Project overview
├── LICENSE                    # MIT or Apache-2.0
│
├── src/
│   ├── lib.rs                 # Public API
│   ├── math.rs                # Linear algebra utilities
│   ├── quantum.rs             # Quantum state operations
│   ├── eraser.rs              # Delayed-choice eraser simulation
│   ├── duality.rs             # V² + D² ≤ 1 verification
│   ├── statistics.rs          # Chi-squared, TOST, power analysis
│   ├── io.rs                  # Data import/export (HDF5, CSV)
│   └── bin/
│       ├── simulate.rs        # Main simulation CLI
│       ├── analyze.rs         # Data analysis CLI
│       └── visualize.rs       # Plotting CLI
│
├── tests/
│   ├── integration_tests.rs  # End-to-end tests
│   ├── invariance_tests.rs   # Observer-agnostic tests
│   ├── duality_tests.rs      # Complementarity tests
│   └── statistical_tests.rs  # Statistics validation
│
├── benches/
│   ├── simulation.rs          # Benchmark state evolution
│   └── analysis.rs            # Benchmark statistical tests
│
├── examples/
│   ├── basic_eraser.rs        # Simple quantum eraser
│   ├── scan_phase.rs          # φ sweep for fringes
│   └── controller_comparison.rs # Compare controller types
│
├── data/
│   ├── raw/                   # Experimental data (gitignored if large)
│   ├── processed/             # Analysis outputs
│   └── simulated/             # Simulation outputs
│
├── docs/
│   ├── theory.md              # Theorem and predictions
│   ├── implementation.md      # Code documentation
│   └── analysis_protocol.md  # Statistical analysis plan
│
└── scripts/
    ├── preprocess.py          # Optional: Python preprocessing
    ├── plot_results.py        # Matplotlib visualizations
    └── generate_report.sh     # Automated reporting

Cargo.toml Example:

[package]
name = "observer-invariance"
version = "0.1.0"
edition = "2021"
authors = ["Your Name <email@example.com>"]
license = "MIT OR Apache-2.0"
description = "Observer-Agnostic Quantum Measurement Simulation and Analysis"
repository = "https://github.com/user/observer-invariance"
keywords = ["quantum", "measurement", "delayed-choice", "quantum-eraser"]
categories = ["science", "simulation"]

[lib]
name = "observer_invariance"
path = "src/lib.rs"

[[bin]]
name = "simulate"
path = "src/bin/simulate.rs"

[[bin]]
name = "analyze"
path = "src/bin/analyze.rs"

[dependencies]
# Core math
nalgebra = "0.32"
num-complex = "0.4"

# Random number generation
rand = "0.8"
rand_chacha = "0.3"  # Deterministic RNG for tests

# Statistics
statrs = "0.16"

# CLI
clap = { version = "4.5", features = ["derive"] }

# Data formats
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
csv = "1.3"
hdf5 = { version = "0.8", optional = true }  # Large data

# Visualization
plotters = "0.3"

# Utilities
anyhow = "1.0"
thiserror = "1.0"

[dev-dependencies]
approx = "0.5"  # Floating-point comparisons
proptest = "1.4"  # Property-based testing
criterion = { version = "0.5", features = ["html_reports"] }

[features]
default = ["hdf5-io"]
hdf5-io = ["hdf5"]

[profile.release]
opt-level = 3
lto = "fat"
codegen-units = 1

[profile.bench]
inherits = "release"

5.2 Testing Strategies for Quantum Simulations

Unit Tests: Verify Mathematical Correctness

#[cfg(test)]
mod tests {
    use super::*;
    use approx::assert_abs_diff_eq;

    #[test]
    fn test_born_rule_normalization() {
        let psi = DVector::from_vec(vec![
            C64::new(0.6, 0.0),
            C64::new(0.8, 0.0),
        ]);
        let rho = density_matrix(&psi);

        let p0 = born_probability(&rho, &projector(&ket0()));
        let p1 = born_probability(&rho, &projector(&ket1()));

        // Probabilities must sum to 1
        assert_abs_diff_eq!(p0 + p1, 1.0, epsilon = 1e-12);
    }

    #[test]
    fn test_partial_trace_identity() {
        // Tr_B(|00⟩⟨00|) = |0⟩⟨0|
        let psi = kron(&ket0(), &ket0());
        let rho = density_matrix(&psi);
        let rho_a = partial_trace_second(&rho);

        let expected = projector(&ket0());
        assert_matrix_approx_eq(&rho_a, &expected, 1e-12);
    }

    #[test]
    fn test_duality_relation() {
        for gamma in [0.0, 0.3, 0.5, 0.8, 1.0] {
            let (v, d) = visibility_distinguishability(gamma);
            assert!(v >= 0.0 && v <= 1.0);
            assert!(d >= 0.0 && d <= 1.0);
            assert_abs_diff_eq!(v.powi(2) + d.powi(2), 1.0, epsilon = 1e-10);
        }
    }
}

Property-Based Tests: Verify Physical Laws

use proptest::prelude::*;

proptest! {
    #[test]
    fn prop_unitary_preserves_norm(
        theta in 0.0..std::f64::consts::TAU,
        phi in 0.0..std::f64::consts::TAU,
    ) {
        let psi_initial = arbitrary_qubit_state(theta, phi);
        let u = arbitrary_unitary();
        let psi_final = u * &psi_initial;

        let norm_initial = psi_initial.norm();
        let norm_final = psi_final.norm();

        prop_assert!((norm_initial - norm_final).abs() < 1e-10);
    }

    #[test]
    fn prop_measurement_probabilities_sum_to_one(
        theta in 0.0..std::f64::consts::TAU,
        phi in 0.0..std::f64::consts::TAU,
    ) {
        let psi = arbitrary_qubit_state(theta, phi);
        let rho = density_matrix(&psi);

        let p0 = born_probability(&rho, &projector(&ket0()));
        let p1 = born_probability(&rho, &projector(&ket1()));

        prop_assert!((p0 + p1 - 1.0).abs() < 1e-10);
    }

    #[test]
    fn prop_singles_invariant_under_idler_basis(
        phi in 0.0..std::f64::consts::TAU,
    ) {
        let eraser = QuantumEraser { phi };

        let singles = eraser.singles_probability();

        // Must be 0.5, 0.5 regardless of φ
        prop_assert!((singles[0] - 0.5).abs() < 1e-10);
        prop_assert!((singles[1] - 0.5).abs() < 1e-10);
    }
}

Integration Tests: End-to-End Simulation

// tests/integration_tests.rs
use observer_invariance::*;

#[test]
fn test_complete_quantum_eraser_workflow() {
    // Setup
    let n_runs = 10000;
    let phi_values = linspace(0.0, 2.0 * PI, 32);

    // Simulate with different controllers
    let controllers = vec![
        Controller::Human,
        Controller::HardwareRNG,
        Controller::Deterministic,
    ];

    for controller in controllers {
        let mut singles_histogram = vec![0u64; 2];

        for _ in 0..n_runs {
            let phi = *phi_values.choose(&mut rand::thread_rng()).unwrap();
            let eraser = QuantumEraser::new(phi);

            // Simulate measurement
            let signal_outcome = eraser.measure_signal();
            singles_histogram[signal_outcome] += 1;
        }

        // Verify singles are 50-50
        let p0 = singles_histogram[0] as f64 / n_runs as f64;
        let p1 = singles_histogram[1] as f64 / n_runs as f64;

        assert!((p0 - 0.5).abs() < 0.01, "Controller {:?} failed", controller);
        assert!((p1 - 0.5).abs() < 0.01, "Controller {:?} failed", controller);
    }
}

Benchmark Tests: Performance Validation

// benches/simulation.rs
use criterion::{black_box, criterion_group, criterion_main, Criterion};

fn bench_quantum_state_evolution(c: &mut Criterion) {
    let mut group = c.benchmark_group("state_evolution");

    group.bench_function("bell_state_creation", |b| {
        b.iter(|| {
            let eraser = QuantumEraser::new(black_box(1.0));
            black_box(eraser.bell_state_with_phase());
        });
    });

    group.bench_function("partial_trace", |b| {
        let eraser = QuantumEraser::new(1.0);
        let psi = eraser.bell_state_with_phase();
        let rho = density_matrix(&psi);

        b.iter(|| {
            black_box(partial_trace_second(&rho));
        });
    });

    group.finish();
}

criterion_group!(benches, bench_quantum_state_evolution);
criterion_main!(benches);

5.3 Visualization Tools

plotters Crate (Recommended)

use plotters::prelude::*;

pub fn plot_interference_pattern(
    phi_values: &[f64],
    probabilities: &[f64],
    output_path: &Path,
) -> Result<()> {
    let root = BitMapBackend::new(output_path, (800, 600)).into_drawing_area();
    root.fill(&WHITE)?;

    let mut chart = ChartBuilder::on(&root)
        .caption("Quantum Eraser: Conditional Probabilities", ("sans-serif", 40))
        .margin(10)
        .x_label_area_size(40)
        .y_label_area_size(50)
        .build_cartesian_2d(0.0..2.0 * PI, 0.0..1.0)?;

    chart.configure_mesh()
        .x_desc("Phase φ (radians)")
        .y_desc("Probability p(signal|idler)")
        .draw()?;

    chart.draw_series(LineSeries::new(
        phi_values.iter().zip(probabilities).map(|(x, y)| (*x, *y)),
        &BLUE,
    ))?;

    root.present()?;
    Ok(())
}

pub fn plot_duality_relation(
    visibility: &[f64],
    distinguishability: &[f64],
    output_path: &Path,
) -> Result<()> {
    // Plot V² + D² vs parameter
    // Expected: constant line at 1.0
    todo!("Implementation")
}

Alternative: Python Integration

// Generate CSV, plot with matplotlib (more features)
pub fn export_for_python(data: &SimulationResults, path: &Path) -> Result<()> {
    let mut wtr = csv::Writer::from_path(path)?;
    wtr.write_record(&["phi", "p0", "p1", "controller"])?;

    for (phi, p0, p1, controller) in data.iter() {
        wtr.write_record(&[
            phi.to_string(),
            p0.to_string(),
            p1.to_string(),
            controller.to_string(),
        ])?;
    }

    wtr.flush()?;
    Ok(())
}
# scripts/plot_results.py
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

def plot_quantum_eraser(csv_path):
    df = pd.read_csv(csv_path)

    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 5))

    # Singles distribution
    for controller in df['controller'].unique():
        subset = df[df['controller'] == controller]
        ax1.scatter(subset['phi'], subset['p0'],
                   label=f'Controller: {controller}', alpha=0.6)

    ax1.axhline(0.5, color='red', linestyle='--', label='Prediction')
    ax1.set_xlabel('Phase φ')
    ax1.set_ylabel('p(signal=0)')
    ax1.set_title('Singles Probability (Observer-Agnostic)')
    ax1.legend()

    # Conditional fringes
    # (requires separate data for conditioning)

    plt.tight_layout()
    plt.savefig('quantum_eraser_results.png', dpi=300)

5.4 Documentation Standards

Module-Level Documentation:

//! # Quantum Eraser Simulation
//!
//! This module implements the delayed-choice quantum eraser experiment
//! as described in the Observer-Agnostic Measurement Theorem.
//!
//! ## Theory
//!
//! The quantum eraser uses entangled photon pairs:
//! ```text
//! |ψ⟩ = (1/√2)(|00⟩ + e^(iφ)|11⟩)
//! ```
//!
//! ## Key Predictions
//!
//! 1. Singles probability p(signal) = 0.5 for all φ, regardless of idler measurement
//! 2. Conditional probability p(signal|idler) shows interference for eraser basis
//! 3. No retrocausal effects: delayed idler choice doesn't affect signal singles
//!
//! ## Example
//!
//! ```rust
//! use observer_invariance::QuantumEraser;
//!
//! let eraser = QuantumEraser::new(std::f64::consts::PI / 4.0);
//! let singles = eraser.singles_probability();
//! assert!((singles[0] - 0.5).abs() < 1e-10);
//! ```

pub mod eraser;

Function-Level Documentation:

/// Calculate the probability of measurement outcome using Born rule.
///
/// Given a quantum state ρ and a measurement operator M (POVM element),
/// computes p = Tr(M ρ).
///
/// # Arguments
///
/// * `state` - Density matrix ρ representing the quantum state
/// * `measurement` - POVM element M (positive semi-definite)
///
/// # Returns
///
/// Probability in [0, 1]. Values outside this range are clamped.
///
/// # Example
///
/// ```rust
/// let rho = density_matrix(&ket0());
/// let p0 = born_probability(&rho, &projector(&ket0()));
/// assert!((p0 - 1.0).abs() < 1e-10);
/// ```
///
/// # Panics
///
/// Panics if matrix dimensions are incompatible.
pub fn born_probability(
    state: &DMatrix<C64>,
    measurement: &DMatrix<C64>,
) -> f64 {
    // Implementation...
}

README.md Structure:

# Observer-Agnostic Measurement Simulation

Rust implementation of the Observer-Agnostic Measurement and No-Retrocausal Marginals Theorem.

## Installation

```bash
cargo build --release

Usage

Simulation

cargo run --release --bin simulate -- --phi-steps 64 --output eraser.csv

Analysis

cargo run --release --bin analyze -- --input experimental_data.hdf5

Visualization

python scripts/plot_results.py eraser.csv

Project Structure

  • src/math.rs - Linear algebra utilities
  • src/eraser.rs - Quantum eraser simulation
  • src/statistics.rs - Statistical tests

Testing

cargo test
cargo test --release  # For property-based tests (slower)
cargo bench  # Performance benchmarks

Citation

If you use this code, please cite:

@article{observer-agnostic-2024,
  title={Observer-Agnostic Measurement and No-Retrocausal Marginals},
  author={...},
  year={2024}
}

License

MIT OR Apache-2.0


---

## 6. Code Patterns for Quantum State Manipulation

### 6.1 State Vector Operations

```rust
use nalgebra::{DVector, DMatrix};
use num_complex::Complex64 as C64;

/// Computational basis states
pub fn ket0() -> DVector<C64> {
    DVector::from_vec(vec![C64::new(1.0, 0.0), C64::new(0.0, 0.0)])
}

pub fn ket1() -> DVector<C64> {
    DVector::from_vec(vec![C64::new(0.0, 0.0), C64::new(1.0, 0.0)])
}

/// Superposition states
pub fn ket_plus() -> DVector<C64> {
    let s = 1.0 / 2.0_f64.sqrt();
    DVector::from_vec(vec![C64::new(s, 0.0), C64::new(s, 0.0)])
}

pub fn ket_minus() -> DVector<C64> {
    let s = 1.0 / 2.0_f64.sqrt();
    DVector::from_vec(vec![C64::new(s, 0.0), C64::new(-s, 0.0)])
}

/// Arbitrary qubit state: |ψ⟩ = cos(θ/2)|0⟩ + e^(iφ)sin(θ/2)|1⟩
pub fn bloch_sphere_state(theta: f64, phi: f64) -> DVector<C64> {
    DVector::from_vec(vec![
        C64::new((theta / 2.0).cos(), 0.0),
        C64::from_polar((theta / 2.0).sin(), phi),
    ])
}

/// Normalize state vector
pub fn normalize(psi: &mut DVector<C64>) {
    let norm = psi.norm();
    if norm > 1e-15 {
        *psi /= norm;
    }
}

/// Inner product: ⟨ψ|φ⟩
pub fn inner_product(psi: &DVector<C64>, phi: &DVector<C64>) -> C64 {
    psi.dotc(phi)
}

/// Density matrix from pure state: ρ = |ψ⟩⟨ψ|
pub fn density_matrix(psi: &DVector<C64>) -> DMatrix<C64> {
    let n = psi.len();
    let mut rho = DMatrix::zeros(n, n);
    for i in 0..n {
        for j in 0..n {
            rho[(i, j)] = psi[i] * psi[j].conj();
        }
    }
    rho
}

/// Projector: P = |ψ⟩⟨ψ|
pub fn projector(psi: &DVector<C64>) -> DMatrix<C64> {
    density_matrix(psi)
}

6.2 Quantum Gates and Operators

/// Pauli matrices
pub fn sigma_x() -> DMatrix<C64> {
    DMatrix::from_row_slice(2, 2, &[
        C64::new(0.0, 0.0), C64::new(1.0, 0.0),
        C64::new(1.0, 0.0), C64::new(0.0, 0.0),
    ])
}

pub fn sigma_y() -> DMatrix<C64> {
    DMatrix::from_row_slice(2, 2, &[
        C64::new(0.0, 0.0), C64::new(0.0, -1.0),
        C64::new(0.0, 1.0), C64::new(0.0, 0.0),
    ])
}

pub fn sigma_z() -> DMatrix<C64> {
    DMatrix::from_row_slice(2, 2, &[
        C64::new(1.0, 0.0), C64::new(0.0, 0.0),
        C64::new(0.0, 0.0), C64::new(-1.0, 0.0),
    ])
}

/// Hadamard gate: H = (1/√2)[1  1; 1 -1]
pub fn hadamard() -> DMatrix<C64> {
    let s = 1.0 / 2.0_f64.sqrt();
    DMatrix::from_row_slice(2, 2, &[
        C64::new(s, 0.0), C64::new(s, 0.0),
        C64::new(s, 0.0), C64::new(-s, 0.0),
    ])
}

/// Phase gate: P(φ) = [1 0; 0 e^(iφ)]
pub fn phase_gate(phi: f64) -> DMatrix<C64> {
    DMatrix::from_row_slice(2, 2, &[
        C64::new(1.0, 0.0), C64::new(0.0, 0.0),
        C64::new(0.0, 0.0), C64::from_polar(1.0, phi),
    ])
}

/// Rotation gates
pub fn rotation_x(theta: f64) -> DMatrix<C64> {
    let c = (theta / 2.0).cos();
    let s = (theta / 2.0).sin();
    DMatrix::from_row_slice(2, 2, &[
        C64::new(c, 0.0), C64::new(0.0, -s),
        C64::new(0.0, -s), C64::new(c, 0.0),
    ])
}

pub fn rotation_y(theta: f64) -> DMatrix<C64> {
    let c = (theta / 2.0).cos();
    let s = (theta / 2.0).sin();
    DMatrix::from_row_slice(2, 2, &[
        C64::new(c, 0.0), C64::new(-s, 0.0),
        C64::new(s, 0.0), C64::new(c, 0.0),
    ])
}

pub fn rotation_z(theta: f64) -> DMatrix<C64> {
    DMatrix::from_row_slice(2, 2, &[
        C64::from_polar(1.0, -theta / 2.0), C64::new(0.0, 0.0),
        C64::new(0.0, 0.0), C64::from_polar(1.0, theta / 2.0),
    ])
}

6.3 Tensor Products and Entanglement

/// Kronecker product: A ⊗ B
pub fn kron(a: &DMatrix<C64>, b: &DMatrix<C64>) -> DMatrix<C64> {
    let (ar, ac) = a.shape();
    let (br, bc) = b.shape();
    let mut out = DMatrix::zeros(ar * br, ac * bc);

    for i in 0..ar {
        for j in 0..ac {
            let aij = a[(i, j)];
            for k in 0..br {
                for l in 0..bc {
                    out[(i * br + k, j * bc + l)] = aij * b[(k, l)];
                }
            }
        }
    }

    out
}

/// Bell states
pub fn bell_phi_plus() -> DVector<C64> {
    let s = 1.0 / 2.0_f64.sqrt();
    DVector::from_vec(vec![
        C64::new(s, 0.0), C64::new(0.0, 0.0),
        C64::new(0.0, 0.0), C64::new(s, 0.0),
    ])
}

pub fn bell_phi_minus() -> DVector<C64> {
    let s = 1.0 / 2.0_f64.sqrt();
    DVector::from_vec(vec![
        C64::new(s, 0.0), C64::new(0.0, 0.0),
        C64::new(0.0, 0.0), C64::new(-s, 0.0),
    ])
}

pub fn bell_psi_plus() -> DVector<C64> {
    let s = 1.0 / 2.0_f64.sqrt();
    DVector::from_vec(vec![
        C64::new(0.0, 0.0), C64::new(s, 0.0),
        C64::new(s, 0.0), C64::new(0.0, 0.0),
    ])
}

pub fn bell_psi_minus() -> DVector<C64> {
    let s = 1.0 / 2.0_f64.sqrt();
    DVector::from_vec(vec![
        C64::new(0.0, 0.0), C64::new(s, 0.0),
        C64::new(-s, 0.0), C64::new(0.0, 0.0),
    ])
}

/// Partial trace over second subsystem
/// Input: 4×4 density matrix for system A⊗B
/// Output: 2×2 density matrix for system A
pub fn partial_trace_second(rho_ab: &DMatrix<C64>) -> DMatrix<C64> {
    let mut rho_a = DMatrix::zeros(2, 2);

    // ρ_A = Tr_B(ρ_AB) = Σ_k ⟨k|_B ρ_AB |k⟩_B
    for i in 0..2 {
        for j in 0..2 {
            let mut sum = C64::new(0.0, 0.0);
            for k in 0..2 {
                let row = i * 2 + k;
                let col = j * 2 + k;
                sum += rho_ab[(row, col)];
            }
            rho_a[(i, j)] = sum;
        }
    }

    rho_a
}

/// Partial trace over first subsystem
pub fn partial_trace_first(rho_ab: &DMatrix<C64>) -> DMatrix<C64> {
    let mut rho_b = DMatrix::zeros(2, 2);

    for i in 0..2 {
        for j in 0..2 {
            let mut sum = C64::new(0.0, 0.0);
            for k in 0..2 {
                let row = k * 2 + i;
                let col = k * 2 + j;
                sum += rho_ab[(row, col)];
            }
            rho_b[(i, j)] = sum;
        }
    }

    rho_b
}

6.4 Measurement Simulation

use rand::Rng;

/// Simulate projective measurement in computational basis
pub fn measure_computational_basis<R: Rng>(
    psi: &DVector<C64>,
    rng: &mut R,
) -> (usize, DVector<C64>) {
    let n = psi.len();
    let probabilities: Vec<f64> = (0..n)
        .map(|i| (psi[i] * psi[i].conj()).re)
        .collect();

    // Sample outcome
    let r: f64 = rng.gen();
    let mut cumsum = 0.0;
    let mut outcome = 0;

    for (i, &p) in probabilities.iter().enumerate() {
        cumsum += p;
        if r < cumsum {
            outcome = i;
            break;
        }
    }

    // Post-measurement state (collapsed)
    let mut psi_post = DVector::zeros(n);
    psi_post[outcome] = C64::new(1.0, 0.0);

    (outcome, psi_post)
}

/// Simulate POVM measurement
pub fn measure_povm<R: Rng>(
    rho: &DMatrix<C64>,
    povm: &[DMatrix<C64>],
    rng: &mut R,
) -> usize {
    let probabilities: Vec<f64> = povm.iter()
        .map(|m| {
            let result = m * rho;
            result.trace().re.max(0.0)
        })
        .collect();

    // Normalize (may have small numerical errors)
    let total: f64 = probabilities.iter().sum();
    let probabilities: Vec<f64> = probabilities.iter()
        .map(|&p| p / total)
        .collect();

    // Sample
    let r: f64 = rng.gen();
    let mut cumsum = 0.0;

    for (i, &p) in probabilities.iter().enumerate() {
        cumsum += p;
        if r < cumsum {
            return i;
        }
    }

    povm.len() - 1  // Fallback (numerical edge case)
}

7. Common Pitfalls and How to Avoid Them

7.1 Numerical Stability Issues

Problem: Complex number arithmetic can accumulate errors

Solution:

/// Check if two complex matrices are approximately equal
pub fn matrix_approx_eq(a: &DMatrix<C64>, b: &DMatrix<C64>, epsilon: f64) -> bool {
    if a.shape() != b.shape() {
        return false;
    }

    let diff = a - b;
    diff.norm() < epsilon
}

/// Enforce hermiticity (for density matrices)
pub fn enforce_hermitian(mut rho: DMatrix<C64>) -> DMatrix<C64> {
    let n = rho.nrows();
    for i in 0..n {
        for j in 0..i {
            let avg = (rho[(i, j)] + rho[(j, i)].conj()) / 2.0;
            rho[(i, j)] = avg;
            rho[(j, i)] = avg.conj();
        }
        // Diagonal must be real
        rho[(i, i)] = C64::new(rho[(i, i)].re, 0.0);
    }
    rho
}

/// Enforce trace-1 normalization
pub fn normalize_density_matrix(mut rho: DMatrix<C64>) -> DMatrix<C64> {
    let tr = rho.trace().re;
    if tr > 1e-15 {
        rho /= tr;
    }
    rho
}

7.2 Phase Convention Ambiguities

Problem: Global phases are unphysical but can cause test failures

Solution:

/// Compare states up to global phase
pub fn states_equal_up_to_phase(psi: &DVector<C64>, phi: &DVector<C64>, epsilon: f64) -> bool {
    if psi.len() != phi.len() {
        return false;
    }

    // Find first non-zero element to fix phase
    let mut phase_factor = C64::new(1.0, 0.0);
    for i in 0..psi.len() {
        if psi[i].norm() > 1e-10 {
            phase_factor = phi[i] / psi[i];
            break;
        }
    }

    // Multiply one state by phase and compare
    let phi_adjusted: DVector<C64> = phi.map(|x| x / phase_factor);

    (psi - phi_adjusted).norm() < epsilon
}

7.3 Tensor Product Index Confusion

Problem: Indexing multi-qubit states is error-prone

Solution:

/// Convert multi-qubit index to binary string
pub fn index_to_binary(index: usize, n_qubits: usize) -> String {
    format!("{:0width$b}", index, width = n_qubits)
}

/// Example: Two-qubit system
/// |00⟩ → index 0
/// |01⟩ → index 1
/// |10⟩ → index 2
/// |11⟩ → index 3

#[test]
fn test_indexing() {
    assert_eq!(index_to_binary(0, 2), "00");
    assert_eq!(index_to_binary(1, 2), "01");
    assert_eq!(index_to_binary(2, 2), "10");
    assert_eq!(index_to_binary(3, 2), "11");
}

7.4 Measurement vs Observable Confusion

Problem: Mixing up measurement outcomes and expectation values

Solution:

/// Measurement: Sample discrete outcome according to Born rule
pub fn measure_observable<R: Rng>(
    psi: &DVector<C64>,
    observable: &DMatrix<C64>,
    rng: &mut R,
) -> (f64, DVector<C64>) {
    // 1. Diagonalize observable to get eigenvectors/eigenvalues
    let eigen = observable.hermitian_eigen();
    let eigenvalues = eigen.eigenvalues;
    let eigenvectors = eigen.eigenvectors;

    // 2. Calculate probabilities
    let probabilities: Vec<f64> = (0..eigenvalues.len())
        .map(|i| {
            let eigvec = eigenvectors.column(i);
            let amplitude = eigvec.dotc(psi);
            (amplitude * amplitude.conj()).re
        })
        .collect();

    // 3. Sample outcome
    let r: f64 = rng.gen();
    let mut cumsum = 0.0;
    let mut outcome_idx = 0;

    for (i, &p) in probabilities.iter().enumerate() {
        cumsum += p;
        if r < cumsum {
            outcome_idx = i;
            break;
        }
    }

    // 4. Return eigenvalue and collapsed state
    let eigenvalue = eigenvalues[outcome_idx].re;
    let collapsed_state = eigenvectors.column(outcome_idx).into_owned();

    (eigenvalue, collapsed_state)
}

/// Expectation value: ⟨O⟩ = ⟨ψ|O|ψ⟩
pub fn expectation_value(
    psi: &DVector<C64>,
    observable: &DMatrix<C64>,
) -> f64 {
    let o_psi = observable * psi;
    let result = psi.dotc(&o_psi);
    result.re
}

8. References to Similar Successful Projects

8.1 Academic Quantum Simulation Projects

QuEST (Quantum Exact Simulation Toolkit):

  • Language: C with Python/Julia bindings
  • Features: 30+ qubit simulations, GPU acceleration
  • Citation: Jones et al., Scientific Reports (2019)
  • Relevance: Demonstrates rigorous testing and validation protocols

ProjectQ:

  • Language: Python + C++
  • Features: Circuit optimization, resource estimation
  • Relevance: Good example of modular architecture

Qiskit:

  • Language: Python with Rust/C++ backends
  • Features: Hardware integration, POVM toolbox
  • Relevance: Industry-standard documentation practices

8.2 Rust Scientific Computing Exemplars

ndarray-linalg:

  • Domain: Linear algebra
  • Best Practice: Comprehensive benchmarking, BLAS integration
  • Relevant Pattern: Abstract backends for performance

petgraph:

  • Domain: Graph algorithms
  • Best Practice: Property-based testing with proptest
  • Relevant Pattern: Zero-cost abstractions

bio:

  • Domain: Bioinformatics
  • Best Practice: Scientific computing in Rust
  • Relevant Pattern: File format interoperability

8.3 Open Quantum Experiments

Delayed-Choice Quantum Eraser (Kim et al., 2000):

  • First realization with entangled photons
  • Data archived at: arXiv:quant-ph/9903047
  • Lesson: Importance of coincidence counting and timing resolution

Loophole-Free Bell Test (Hensen et al., Nature 2015):

  • Gold standard for experimental rigor
  • Pre-registered hypotheses, blinded analysis
  • Lesson: Eliminate all alternative explanations before claiming new physics

Quantum Eraser with Coherent Photons (Scientific Reports, 2023):

  • Recent demonstration with classical light
  • Open data repository
  • Lesson: Modern reproducibility standards

9. Implementation Roadmap

Phase 1: Core Simulation (Weeks 1-2)

  • Implement quantum state operations (math.rs)
  • Implement POVM formalism
  • Implement quantum eraser logic (eraser.rs)
  • Unit tests for all mathematical operations
  • Verify singles invariance with property tests

Phase 2: Statistical Analysis (Week 3)

  • Implement chi-squared test
  • Implement TOST equivalence test
  • Power analysis calculator
  • Monte Carlo error propagation
  • Integration tests for statistical correctness

Phase 3: Experimental Interface (Week 4)

  • Data import (HDF5, CSV)
  • Controller type encoding/blinding
  • Coincidence counting simulation
  • Export to plotting formats
  • End-to-end workflow test

Phase 4: Visualization & Documentation (Week 5)

  • Interference pattern plots
  • Duality relation visualization
  • Statistical test results summary
  • Complete API documentation
  • Example notebooks/scripts

Phase 5: Optimization & Benchmarking (Week 6)

  • Profile hot paths
  • SIMD optimization for matrix operations
  • Parallel Monte Carlo simulations
  • Benchmark against RustQIP
  • Performance regression tests

Phase 6: Validation & Pre-Registration (Week 7)

  • Cross-validate with existing QM libraries
  • Reproduce published quantum eraser results
  • Finalize pre-registration document
  • Code review and security audit
  • Prepare for experimental deployment

10. Coordination Memory Storage

This comprehensive research will be stored in the coordination memory system for other agents:

npx claude-flow@alpha memory store \
  --key "quantum-research/literature-review" \
  --namespace "coordination" \
  --value "$(cat /workspaces/agentic-flow/docs/QUANTUM_RESEARCH_LITERATURE_REVIEW.md)" \
  --ttl 2592000  # 30 days

Key Findings for Coordination:

  1. Primary Library: nalgebra + num-complex (matches existing research.md)
  2. Validation Library: RustQIP (cross-check)
  3. Optimization: rayon for parallelism, SimSIMD for production
  4. Statistical Testing: statrs for chi-squared/TOST, proptest for property-based testing
  5. Visualization: plotters (Rust-native) or matplotlib (Python export)
  6. Experimental Components: Type-II BBO crystal, SPADs, time-tagging module
  7. Critical Requirement: Blinded controller identity, pre-registration protocol

Conclusion

This literature review provides a complete foundation for implementing the Observer-Agnostic Measurement experiment. The existing research.md already contains excellent theoretical grounding and simulation scaffolding. This review adds:

  1. 2024 quantum computing ecosystem context - Latest library developments
  2. Experimental hardware specifics - SPDC, BBO crystals, detector requirements
  3. Statistical rigor - Chi-squared, TOST, power analysis implementations
  4. Software engineering best practices - Testing strategies, documentation, reproducibility
  5. Performance optimization paths - SIMD, parallelism, benchmarking

Next Steps:

  1. Coder agent: Implement Phase 1 (core simulation) using nalgebra
  2. Tester agent: Set up property-based tests with proptest
  3. Reviewer agent: Validate against existing quantum mechanics predictions
  4. Planner agent: Schedule experimental hardware procurement

Falsifiable Prediction: If |Δp| > 5×10⁻⁴ and reproducible across controller types, it would falsify standard quantum mechanics and suggest consciousness plays a causal role in measurement outcomes. This is testable, pre-registerable, and publishable.