ruvector/docs/adr/ADR-260-photonlayer-optical-computing-simulator.md
rUv 2b7dbc7388
feat(photonlayer): optical simulation core — field, FFT, propagation, detector, receipts (ADR-260 Phase 1) (#587)
* feat(photonlayer): optical simulation core — field, FFT, propagation, detector, receipts (ADR-260 Phase 1)

Pure-Rust, dependency-light, deterministic learned-optical-frontend core:
- complex/fft: in-house radix-2 2D FFT (bit-reproducible, no external FFT lib)
- field/mask: image->scalar field, phase-only learned mask (identity/random/lens)
- propagate: Fresnel, Fraunhofer, angular-spectrum scalar diffraction
- detector: intensity capture + seeded shot/read noise, binning, quantization
- metrics: MSE/PSNR, compression ratio, frame-similarity, spectrum embedding
- receipt: BLAKE3-bound experiment receipts + verify (determinism invariant §21)
21 unit tests + doctest passing.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PjRKJMFe6yoNY3SMVEieHy

* feat(photonlayer): in-Rust mask learner, decoder, and benchmark harness (ADR-260 Phase 2/4)

- synthetic: deterministic 4-class shape dataset (no MNIST per ADR-260 §20.2)
- decoder: feature pooling + nearest-centroid digital backend (exact param count)
- learn: seeded block hill-climbing mask optimizer against task loss; learned
  mask provably dominates its random start (acceptance gate §17.2)
- baselines: digital/random/learned variants + compression showcase
- Result: at a 2x2 (4-pixel) sensor, learned mask 1.00 vs random 0.80 vs
  digital 0.65 test accuracy — same task, 64x fewer sensor pixels (§16.3)

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PjRKJMFe6yoNY3SMVEieHy

* chore(photonlayer): scaffold ruvector/cli/wasm crates for swarm implementation (ADR-260)

Stub crates registered as workspace members so each is independently
buildable/testable while the implementation swarm fills them in.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PjRKJMFe6yoNY3SMVEieHy

* feat(photonlayer): experiment memory, WASM playback, verification/privacy, CLI demos (ADR-260 Phases 2-4)

photonlayer-ruvector (22 tests): 32-dim experiment embeddings (mask histogram +
frame spectrum), cosine nearest-experiment recall, Fiedler-spectral pass/fail
boundary analysis, mask-family coherence gates, verifying receipt store.

photonlayer-wasm (17 tests): 5-view browser pipeline (incoming/mask/masked/
sensor + frame hash) with min-max u8 encoders; in-browser verify_receipt_json
(anti-swap); default_config_json.

photonlayer-bench (9 tests): + verification module (FAR/FRR/EER) and privacy
module (linear reconstruction-attack leakage). Learned mask EER 0.001 vs random
0.133; optical capture reduces reconstruction PSNR vs identity.

photonlayer-cli: bench / barcode / edge / privacy-gate / verify-receipt demos
with ASCII frame rendering. Barcode decodes all 4 classes from non-human-readable
frames; privacy-gate emits a verifying RVF receipt. Clean build, zero warnings.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PjRKJMFe6yoNY3SMVEieHy

* harden(photonlayer): validate untrusted optical configs at the boundary (ADR-260 security)

Add OpticalConfig::validate() + MAX_GRID_DIM cap as the security choke point:
reject non-power-of-two/oversized grids, non-finite or non-physical optical
params, and binning=0 before any allocation or FFT. Enforced in OpticalField::
from_image (pre-allocation) and in the WASM run_trace boundary (dimension guard
+ config.validate) to block allocation-DoS and 32-bit usize overflow from a
malicious config_json. +2 core tests (now 23).

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PjRKJMFe6yoNY3SMVEieHy

* docs(photonlayer): ADR-260 — learned-optical-frontend computing simulator

Formalizes the architecture, pipeline, crate layout, RuVector experiment-memory
schema, RVF receipt binding, benchmarks, acceptance gates, the determinism
invariant, and the application/positioning/ethics framing (front-end thesis;
industrial sensors -> drone preprocessing -> medical research -> consented
verification; non-goal: mass-surveillance face ID).

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PjRKJMFe6yoNY3SMVEieHy

* docs(photonlayer): ADR-261 (mask exchange + determinism), ADR-262 (privacy verification), SOTA research brief

ADR-261: canonical PhaseMask exchange format, determinism invariant (in-house
FFT + seeded RNG + BLAKE3), and import replay-verification.
ADR-262: privacy-preserving consented verification — FAR/FRR/EER, reconstruction-
attack leakage metric, receipt provenance, RuVector governance; documents the
measured numbers (learned EER 0.001 vs 0.133; optical reduces reconstruction PSNR)
and the mass-surveillance non-goal.
sota.md: D2NN, differentiable optics (TorchOptics/waveprop/diffractsim), hybrid
DOE+CNN compression, edge-enhanced D2NN, 2026 full-Stokes metasurface+U-Net;
credible-vs-overclaimed table; reference->component mapping; feasibility ranking.

Co-Authored-By: claude-flow <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_01PjRKJMFe6yoNY3SMVEieHy

* docs+bench(photonlayer): README, assessment/roadmap, more-data benchmark; fix wasm lint

- README (crate/repo face): positioning ("captures the answer"), the auditable
  optical-compression wedge, measured compression-sweep table, honest "do not
  claim yet" scope.
- docs/research/photonlayer/ASSESSMENT.md: full positioning, use-case risk table,
  prove-next roadmap (energy model, harder datasets, reconstruction-attack suite,
  hardware bridge), demos, products, scoring, acceptance test, references.
- tests/more_data_bench.rs: larger-N compression sweep (1/4/9/16-px sensors,
  40 samples/class, 300 iters) + WIN regression guard. Measured: at 64x reduction
  learned=0.988 vs random=0.738.
- Fix photonlayer-wasm useless-comparison lint -> meaningful monotonicity check.

* perf(photonlayer): M1 — cached + in-place Propagator (1.70x, bit-identical)

Hot-path optimization for the mask-learning loop, which propagates thousands
of fields through one fixed config. The config-only transfer function H was
recomputed on every call, and every propagate() cloned the field buffer.

- Propagator precomputes H once per (config,w,h); propagate_into() runs the
  forward FFT -> xH -> inverse FFT in place (no per-call clone).
- Output is bit-for-bit identical to the free propagate() (asserted in
  cached_propagator_is_bit_identical, always-on).
- Measured 1.70x over the naive path at 64x64 x3000 (release):
  naive=615ms -> cached+inplace=361ms. Proof is an --ignored timing test
  (debug wall-clock is meaningless); correctness gate runs in the default suite.

Also lands:
- ADR-263 PhotonLayer FiberGate (transmission-matrix MMF backend; receipt-
  verified, NOT zero-knowledge; non-square T; nalgebra column-major contract).
- docs/research/photonlayer/APPLICATIONS.md — task-trained-sensors positioning,
  application areas, viral demos, product path, platform acceptance test.

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(photonlayer): real-data MNIST optical-compression benchmark + differential ablation (M2)

Adds an honest, reproducible real-data benchmark for the learned optical
frontend (ADR-260 M2), replacing the synthetic-only 4-class evaluation that
ADR-260 itself flagged as a scientific-integrity risk.

New modules (photonlayer-bench):
- mnist.rs    : parses raw uncompressed IDX (verified magic 0x803/0x801),
                downsamples 28x28 -> 20x20 centered in a 32x32 power-of-two
                optical grid. Dataset is fetched once into a gitignored cache
                (NOT vendored); loader has zero network/decompression deps.
- diffdetect.rs: differential-detection readout (Li/Ozcan arXiv:1906.03417) -
                10 positive + 10 negative detector regions, score I+_k - I-_k.
- mnist_bench.rs: trains one phase mask (seeded block hill-climbing) and runs
                the full acceptance comparison + ablation on the IDENTICAL mask.

Integration test (mnist_differential_bench.rs, NOT a standalone bin to avoid
the CrowdStrike AV os-error-5 on fresh exes): fast always-on smoke guard +
#[ignore] heavy run with a documented command.

Measured (deterministic, seed 0x6e157, 4000 train / 2000 blind test, balanced):
  full-image baseline (1024 px, 10240-param centroid)  0.7540
  optical compressed  (  64 px,   640-param centroid)  0.7420
  delta vs baseline                                   -0.0120  (PASS, allows -0.02)
  sensor pixel reduction                               16.0x   (>= 16x)
  digital MAC reduction                                16.0x   (>= 10x)
  learned vs random mask (decoded)                     +0.0925
ACCEPTANCE (user's relative-to-baseline test): PASS.

Honest caveats reported in-table: this is a SINGLE hill-climbed phase mask +
tiny decoder (single-layer optical compression). The Li/Ozcan ~97% MNIST figure
is a 5-layer diffractive net trained end-to-end by backprop with differential
readout as the final layer; multi-layer + gradient is future work. The
optics-only argmax differential lever is reported as a transparency floor (the
mask is trained for the decoder readout, not the argmax readout). No absolute
SOTA claim is made.

cargo test -p photonlayer-core (23 pass) and -p photonlayer-bench --lib
(14 pass) green; clippy clean.

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(photonlayer): M3 — fold verified MNIST result + honest positioning + citations into ASSESSMENT

Adds the measured real-data MNIST table (optical 74.20% vs full-image baseline
75.40%, -1.20pp, 16x sensor + 16x MAC reduction; +9.25pp learned-vs-random),
the verbatim non-overclaiming positioning paragraph (competitive single-layer
optical compression, NOT a new accuracy SOTA), the must-avoid language list,
and the closest architectural citations (Wirth-Singh arXiv:2406.06534 primary,
Bezzam 2206.01429, Lin Science 2018, Li/Ozcan 1906.03417, Wang 2507.17374).

Co-Authored-By: claude-flow <ruv@ruv.net>

* perf(photonlayer-core): fold Fraunhofer fftshift into checkerboard premult + precompute FFT twiddle tables

OPT-A (bit-identical): replace `fft_2d + fftshift_2d` in both Fraunhofer
paths (free `fraunhofer()` and `Propagator::propagate_into`) with a ±1
checkerboard premultiply `(-1)^(x+y)` before the transform. By the DFT
shift theorem, FFT of the premultiplied input equals fftshift of the FFT,
eliminating the fftshift's full-buffer alloc + quadrant copy. True negate
(`Complex::ZERO - c`) is exact ±1.0 -> element-for-element identical to the
old sequence (new test `checkerboard_premult_equals_fft_then_fftshift`).

OPT-B (deliberately changes bits, determinism gain): precompute a per-
dimension `TwiddleTable` (`exp(sign·2π·j/n)` for j in 0..n/2) and INDEX it
by stride per butterfly instead of accumulating `w *= wlen`. Kills the f32
drift the accumulation injected and recomputes angles once per 2D FFT
instead of per row/column. Proven: FFT is bit-for-bit reproducible across
runs, and max-abs error vs an f64 reference DFT does NOT increase
(it decreases — drift removed). No hardcoded golden hashes/values in the
repo to update; re-run-determinism tests stay valid by construction.

Measured (release, 64x64 x3000, --ignored --nocapture):
  fraunhofer OPT-A+B: old(fft+fftshift,accum-twiddle)=210.5ms ->
  new(checkerboard+table)=116.1ms = 1.81x, max_diff_vs_old=5.7e-6 (f32 noise).
M1 cached-propagator benchmark still 2.00x and bit-identical.

All 27 photonlayer-core unit tests + propagation bit-identical gate green;
photonlayer-ruvector / photonlayer-bench / photonlayer-cli build and tests
green. Determinism invariant preserved (scalar cos/sin FFT, no FMA/SIMD/RFFT).

Co-Authored-By: claude-flow <ruv@ruv.net>

* feat(photonlayer): add Config B (argmax-diff-trained mask) to MNIST bench — isolates the differential lever

The M2 benchmark previously reported the differential-vs-plain argmax delta as a
small (+0.10pp) transparency footnote, because the single mask was trained for
the DECODER objective, not the argmax readout. That understated the Li/Ozcan
differential-detection mechanism. This adds a SECOND, clearly-labeled mask
trained directly for the argmax-differential objective, so the lever is shown in
isolation. Config A is unchanged and remains the product/acceptance headline.

Two masks, two objectives — A proves task-useful compression (the product
claim); B isolates the differential-detection lever (the mechanism). Both fully
deterministic (stated seeds), both reproduced by the integration test.

Measured (real MNIST, 4000 train / 2000 blind test, on current core HEAD):
  CONFIG A (decoder objective, seed 0x6e157) — product/acceptance:
    full-image baseline (1024 px)  0.7540
    optical compressed  (  64 px)  0.7305   (-2.35pp; 16x sensor + 16x MACs)
    learned vs random decoded      +0.0810  (WIN guard, asserted)
  CONFIG B (argmax-diff objective, seed 0x6e15c) — mechanism, NO decoder:
    plain argmax I+_k              0.1840
    differential argmax I+ - I-    0.3490
    differential lever delta       +0.1650  (asserted >= +0.05)
    NOTE: absolute accuracy is single-layer optics-only (no decoder) and modest
    by construction; the +0.1650 isolates the lever, NOT a headline accuracy.

No SOTA/beats language; no cherry-picking — both configs are in the printed table.

NOTE on Config A drift: an earlier measurement on commit 69424ecb read optical
0.7420 (-1.20pp, acceptance PASS). The core FFT crate changed underneath us
(cbcd0eb2, "precompute FFT twiddle tables") which slightly altered the
diffraction output for ALL FFT paths (AngularSpectrum included), shifting Config
A to 0.7305 (-2.35pp). Acceptance is REPORTED, not hard-asserted, so the test
stays green; the honest current-core number is -2.35pp. Flagged to the core
author — the twiddle-table change is not bit-identical to the pre-cbcd0eb2 FFT.

Scope: photonlayer-bench only (mnist_bench.rs + integration test). Core untouched.
cargo test -p photonlayer-bench --lib (14) + smoke green; full #[ignore] passes
(647s); clippy clean.

Co-Authored-By: claude-flow <ruv@ruv.net>

* test(photonlayer-bench): document the Config-A hill-climb optimizer ceiling

Adds run_mnist_config_a (fast Config-A-only harness) and a permanent #[ignore]
iteration sweep proving the -2pp acceptance line is NOT a training-budget issue
on the drift-corrected (post-cbcd0eb2) FFT core. Measured (seed 0x6e157,
4000 train / 2000 blind test):
  iters 1500 -> optical 73.05% (-2.35pp)
  iters 3000 -> optical 73.25% (-2.15pp)
  iters 4500 -> optical 73.20% (-2.20pp)
The block hill-climber has converged; the residual ~2pp gap is an OPTIMIZER
limit. Closing it (and reaching ~85-89%) requires analytic gradient descent
through the diffraction operator (Propagator::backward_into with conj(H)) — the
documented roadmap keystone, not a tonight change. No fabricated numbers; the
honest single-mask result is reported, not asserted to PASS.

Co-Authored-By: claude-flow <ruv@ruv.net>

* docs(photonlayer): M3 — refresh ASSESSMENT to shipped numbers + optimizer-ceiling honesty

The pre-OPT-B -1.20pp figure was stale after the twiddle-table FFT change.
Updates Config A to the true converged number on the optimized core
(73.05% / -2.35pp at 16x/16x; +8.10pp learned-vs-random), adds Config B
(+16.50pp differential lever), and states the honest framing: the gap is an
optimizer ceiling (sweep: 1500/3000/4500 -> -2.35/-2.15/-2.20pp), closeable
only by analytic gradient descent (backward_into with conj(H)) — the roadmap
keystone, with ~85-89% headroom. No PASS asserted that the method cannot reach.

Co-Authored-By: claude-flow <ruv@ruv.net>

* fix(photonlayer-bench): rustfmt + doc_lazy_continuation lint

- cargo fmt on all photonlayer crates
- Fix doc comment: `+` on continuation line parsed as markdown list
  marker causing clippy::doc_lazy_continuation. Changed to prose `and`.

Co-Authored-By: claude-flow <ruv@ruv.net>

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: ruv <ruvnet@users.noreply.github.com>
Co-authored-by: ruvnet <ruvnet@gmail.com>
2026-06-18 23:22:42 -04:00

32 KiB
Raw Permalink Blame History

ADR-260: PhotonLayer — Learned-Optical-Frontend Computing Simulator

Status: Proposed Date: 2026-06-18 Deciders: rUv Supersedes: None Related: ADR-029 (RVF Canonical Format), ADR-047 (Proof-Gated Mutation Protocol), ADR-117 (Canonical MinCut), ADR-197 (Differentiable MinCut Condensation)


Context

The Sensor Bandwidth and Compute Problem

Modern perception systems — edge cameras, drone sensors, industrial inspection rigs, medical imagers — push full-resolution pixel arrays through digital pipelines before any feature selection occurs. This is wasteful by design: the raw pixel stream contains far more information than is needed for any specific task, yet the full stream must be digitized, transmitted, and processed before the system can decide what mattered.

Diffractive optical elements (DOEs) offer a different model. A thin, passive (or actively controlled) phase plate placed in the optical path upstream of the sensor reshapes the light field before any electrons move. If that phase plate is designed by optimization, it can perform task-specific analogue pre-processing at the speed of light, concentrating class-discriminative energy into a small set of sensor pixels and discarding everything irrelevant before the first ADC conversion.

This idea has moved from theory to demonstrated hardware:

  • Lin et al. (2018, Science) showed that stacked diffractive layers designed by backpropagation can classify MNIST digits and reconstruct images at the speed of light, purely passively.
  • Hybrid DOE-CNN classifiers (Chen et al., 2023 and subsequent work, per project brief) report >7.8x electronic-layer compression when an optimized DOE precedes a shallow CNN.
  • Computational meta-optics reviews (2026, per project brief) document systems where >90% of the computation is performed by the optical front end, leaving only a lightweight digital decoder.
  • Edge-enhanced diffractive networks (June 2026, per project brief) improved single-diffractive-layer MNIST accuracy from 64.2% to 80.7% by adding optical edge extraction.
  • The 2026 full-Stokes reconstruction paper (per project brief) jointly optimized a differentiable single-layer metasurface with a U-Net backend to reconstruct RGB full-Stokes polarization images from a single monochrome sensor measurement — demonstrating the modern joint design blueprint.

RuVector already ships the primitives needed to simulate, train, evaluate, and store optical experiments in a reproducible, receipt-bound format:

  • crates/photonlayer-core: scalar field, FFT engine, phase mask, propagation (Fresnel / Fraunhofer / angular-spectrum), detector, metrics, RVF receipt.
  • crates/photonlayer-bench: synthetic data, nearest-centroid decoder, baseline variants, in-Rust hill-climbing learner, benchmark runner.
  • crates/photonlayer-ruvector: experiment embedding (32-dim) and cosine-similarity nearest-neighbour memory backed by ruvector-coherence.
  • crates/photonlayer-cli: command-line interface to the simulator and bench.
  • crates/photonlayer-wasm: wasm-bindgen bindings for browser simulation.

All five crates compile as of 2026-06-18 and 21 tests pass.

The PhotonLayer Claim (Precision Matters)

The precise, non-overclaiming thesis of PhotonLayer is:

Light performs the first trained transformation; a smaller digital backend reads the result.

This is not the same as "light is running a neural network." Light propagates through a trained phase plate and produces an intensity pattern on a sensor. The phase plate encodes a learned linear transformation (in the Fraunhofer regime, a weighted Fourier basis; in the Fresnel / angular-spectrum regime, a convolution with a learned coherent transfer function). The result is a lossy, task-specific analogue compression that the digital decoder reads. The neural computation, as traditionally understood, is in the training of the phase mask and in the digital decoder. Light provides the execution of the first (and most expensive in terms of flops-per-inference) stage at zero marginal electronic cost per pixel.


Decision

Adopt PhotonLayer as a first-class sub-system of RuVector

PhotonLayer occupies the crates/photonlayer-* namespace and the docs/research/photonlayer/ and docs/adr/ADR-26x-* documentation namespace. It is a simulator and experiment-memory system, not a fabrication or hardware driver system. All experiments are sealed with RVF-style receipts and stored in photonlayer-ruvector experiment memory for later retrieval and cross-experiment comparison.


Pipeline Architecture

§1 End-to-End Data Flow

┌──────────────┐
│  InputImage  │  Normalized f32 pixels, width × height
└──────┬───────┘
       │  field::OpticalField::from_image()
       ▼
┌──────────────────┐
│  OpticalField    │  Complex amplitude on spatial grid (padded)
└──────┬───────────┘
       │  mask::PhaseMask::apply()           ← THE LEARNED ELEMENT
       ▼
┌──────────────────────────┐
│  Modulated OpticalField  │  field * exp(i * θ(x,y))
└──────┬───────────────────┘
       │  propagate::propagate()
       │    Fresnel TF / Fraunhofer FFT / Angular Spectrum
       ▼
┌──────────────────────────┐
│  Propagated OpticalField │  Intensity = |amplitude|² before capture
└──────┬───────────────────┘
       │  detector::capture() / capture_with()
       │    shot noise · read noise · quantization · binning · saturation
       ▼
┌──────────────────┐
│  OpticalFrame    │  Sensor intensity map, frame_hash (BLAKE3)
└──────┬───────────┘
       │  metrics::frame_spectrum_embedding()
       │  decoder (NearestCentroid or external digital net)
       │  metrics::{accuracy, mse, psnr, compression_ratio, input_frame_similarity}
       ▼
┌──────────────────┐
│  MetricReport    │  Accuracy, MSE, PSNR, compression ratio, similarity, latency
└──────┬───────────┘
       │  receipt::build_receipt()
       ▼
┌──────────────────────┐
│  ExperimentReceipt   │  RVF-style receipt: 6 content hashes + rvf_receipt_hash
└──────┬───────────────┘
       │  photonlayer-ruvector::ExperimentMemory::remember()
       ▼
┌─────────────────────────────────────────────────────────────────┐
│  RuVector Experiment Memory                                      │
│  Cosine-similarity NN over 32-dim embeddings                    │
│  (mask phase histogram 16-dim + frame spectrum 16-dim)          │
└─────────────────────────────────────────────────────────────────┘

§2 MinCut Boundary Usage

The ruvector-mincut family (ADR-117, ADR-197) defines the boundary between computation domains. In the PhotonLayer pipeline this maps directly:

  • Optical domain (left of cut): OpticalField modulation and propagation. Computation is parallelizable, dependency-free across pixels, and in a real system executes in the optical path with no ADC cost.
  • Digital domain (right of cut)**: OpticalFrame readout and beyond. This is what the MinCut boundary formally partitions.

The sensor pixel count is the cut bandwidth: fewer sensor pixels = narrower cut = lower transmission from optical to digital domain. The PhotonLayer acceptance gate (§17) requires that a learned mask achieves higher task accuracy than the digital baseline at the same cut bandwidth.

§3 Coherence Gates

PhotonLayer does not directly use ruvector-coherence's energy gating for routing (that is CGT / ADR-015), but it borrows the coherence library for cosine-similarity search in experiment memory. A future extension can apply coherence gating to route the digital decoder between a reflex (centroid lookup) lane and a deep (neural network) lane based on the frame's entropy.


§4 Crate Layout

Crate Purpose Key modules
photonlayer-core Optical simulation kernel field, mask, fft, propagate, detector, metrics, receipt, hash, rng, complex, error, config, simulator
photonlayer-bench Benchmarks and learner synthetic, decoder, pipeline, baselines, learn, verification
photonlayer-ruvector Experiment memory integration embedding, memory
photonlayer-cli Command-line interface main
photonlayer-wasm Browser WASM bindings lib

All crates are pure Rust. photonlayer-core depends only on serde, serde_json, blake3, and thiserror. photonlayer-ruvector additionally depends on ruvector-coherence for cosine similarity.


§5 Data Types

§5.1 InputImage

pub struct InputImage {
    pub width: usize,
    pub height: usize,
    pub pixels: Vec<f32>,   // row-major, values in [0, 1]
}

§5.2 OpticalField

Complex amplitude on a 2D spatial grid. Internally Vec<Complex> where Complex { re: f32, im: f32 }. The field grid may be larger than the image (zero-padding for propagation accuracy).

§5.3 PhaseMask

pub struct PhaseMask {
    pub width: usize,
    pub height: usize,
    pub phase_radians: Vec<f32>,  // [0, 2π) per cell, row-major
    pub mask_id: String,          // "identity" | "random:0x…" | "lens:…" | "learned:0x…"
}

This is the trainable element. The mask-exchange format (ADR-261) serializes exactly this struct. Offline differentiable training (TorchOptics, waveprop, diffractsim) optimizes phase_radians by gradient descent; the simulator's in-Rust hill-climbing learner optimizes by seeded coordinate perturbation.

§5.4 OpticalConfig

pub struct OpticalConfig {
    pub width: usize,
    pub height: usize,
    pub wavelength_nm: f32,
    pub propagation_mm: f32,
    pub pixel_pitch_um: f32,
    pub propagation: PropagationMode,
    pub detector: DetectorConfig,
    pub seed: u64,
}

All fields participate in the determinism invariant (§21). The canonical JSON serialization of this struct is hashed into the receipt.

§5.5 PropagationMode

pub enum PropagationMode {
    Fresnel,          // Near-field transfer function
    Fraunhofer,       // Far-field single-FFT (Fourier transform magnitude)
    AngularSpectrum,  // Highest fidelity, valid across regimes
}

§5.6 DetectorConfig

pub struct DetectorConfig {
    pub shot_noise_photons: f32,   // 0 disables
    pub read_noise_std: f32,       // Additive Gaussian, intensity units
    pub quantization_levels: u32,  // 256 for 8-bit; 0 disables
    pub binning: usize,            // b×b block averaging; 1 disables
    pub saturation: f32,           // Clip ceiling; 0 disables
}

§5.7 OpticalFrame

pub struct OpticalFrame {
    pub width: usize,
    pub height: usize,
    pub intensity: Vec<f32>,  // Detector output, after noise/quant/binning
    pub frame_hash: String,   // BLAKE3 over (width, height, intensity bytes)
}

frame_hash is the primary reproducibility handle. Two simulations with identical inputs and config must produce identical frame_hash values.

§5.8 MetricReport

pub struct MetricReport {
    pub accuracy: f32,
    pub reconstruction_mse: f32,
    pub compression_ratio: f32,
    pub input_frame_similarity: f32,  // Pearson r: sensor vs. input pixels
    pub native_latency_us: f64,
}

input_frame_similarity is deliberately measured and bounded: for privacy-preserving optical verification (ADR-262) the sensor pattern must NOT look like the input image (Pearson |r| should be low).


§6 Propagation Modes — Physics Summary

§6.1 Fresnel (Near-Field)

Applies the paraxial Fresnel transfer function in the frequency domain:

H(fx, fy) = exp(-i π λ z (fx² + fy²))

where λ is wavelength (m), z is propagation distance (m), and (fx, fy) are spatial frequencies. Valid when the Fresnel number a²/(λz) >> 1 (aperture a large relative to wavelength times distance).

§6.2 Fraunhofer (Far-Field)

A single 2D FFT of the masked field; the intensity is the power spectrum. Valid when z >> a²/λ. Analytically the simplest mode and the one that most directly links the mask's spatial frequency content to the sensor pattern.

§6.3 Angular Spectrum (Exact Scalar)

Propagates each plane-wave component at its correct angle:

H(fx, fy) = exp(i 2π z sqrt(1/λ² - fx² - fy²))

Valid for all propagation distances within the scalar diffraction approximation. The simulator uses this as the default for production fidelity benchmarks.


§7 Detector Model

The detector stage models four physical effects in sequence:

  1. Intensity: I(x,y) = |E(x,y)|² where E is the propagated complex amplitude.
  2. Shot noise: Poisson noise with mean shot_noise_photons × I(x,y). Modelled as additive Gaussian N(0, sqrt(I/photons)) for computational efficiency; disabled when shot_noise_photons == 0.
  3. Read noise: Additive Gaussian N(0, read_noise_std) after shot noise.
  4. Quantization: Intensity binned to quantization_levels uniform levels in [0, max_intensity]; disabled when quantization_levels == 0.
  5. Binning: b×b pixel blocks averaged to a single output pixel; disabled when binning == 1. Binning is applied after quantization. The output frame dimensions are floor(width/b) × floor(height/b).
  6. Saturation: Intensities clipped to [0, saturation]; disabled when saturation == 0.

The seeded RNG (DeterministicRng, a 64-bit Xoshiro-256** variant) ensures that noise draws are deterministic given the seed embedded in OpticalConfig.


§8 RuVector Experiment-Memory Schema

Each finished experiment is stored as an ExperimentRecord:

pub struct ExperimentRecord {
    pub id: String,              // Unique experiment identifier
    pub label: String,           // Task outcome label ("pass", "fail", class name)
    pub config: OpticalConfig,   // Full optical configuration
    pub mask_id: String,         // From PhaseMask::mask_id
    pub embedding: Vec<f32>,     // 32-dim L2-normalised embedding
    pub receipt: ExperimentReceipt,
    pub metrics: MetricReport,
}

§8.1 Embedding Composition (32-dim)

The 32-dimensional embedding concatenates:

  • 16-dim mask phase histogram: normalized frequency distribution of phase_radians values across 16 uniform bins on [0, 2π).
  • 16-dim frame spectrum embedding: radial intensity distribution of OpticalFrame::intensity binned into 16 annular rings by distance from frame center, then L2-normalised.

Both components are L2-normalised independently before concatenation; the joint vector is L2-normalised again. This embedding is suitable for cosine-similarity nearest-neighbour search over experiment history.

§8.2 Nearest-Neighbour Recall

ExperimentMemory::nearest(query_embedding, limit) returns up to limit stored experiments sorted by descending cosine similarity. The current implementation is a linear scan over stored embeddings (exact NN). This is appropriate for the experiment-scale dataset; upgrade to HNSW when exceeding 10,000 stored experiments.


§9 RVF Receipt Binding (§15)

An ExperimentReceipt binds every experiment input to a single anti-swap hash:

pub struct ExperimentReceipt {
    pub experiment_id: String,
    pub input_hash: String,    // BLAKE3 over (width, height, pixels)
    pub mask_hash: String,     // BLAKE3 over (width, height, phase_radians)
    pub config_hash: String,   // BLAKE3 over canonical JSON of OpticalConfig
    pub output_hash: String,   // frame_hash from OpticalFrame
    pub metrics_hash: String,  // BLAKE3 over MetricReport fields
    pub git_commit: String,
    pub rustc_version: String,
    pub feature_flags: Vec<String>,
    pub seed: u64,
    pub rvf_receipt_hash: String,  // BLAKE3 over all of the above
}

rvf_receipt_hash is the primary tamper-detection value. verify_receipt(r) recomputes the binding digest and returns true iff the receipt fields are internally consistent. Importing a trained mask from an external source requires verifying that the imported mask's mask_hash matches the hash stored in the associated receipt.


§10 Benchmarks and Metrics (§16)

§10.1 Classification Benchmark

Three variants on a synthetic 4-class dataset (16×16 grid, configurable samples per class):

Variant Description
digital_baseline Pooled raw image pixels; no optics
random_mask Randomly initialized phase mask
learned_mask Phase mask trained by seeded block hill-climbing

The hill-climbing optimizer starts from a random mask and only accepts phase-perturbing moves that improve training accuracy (with separation margin as tiebreaker). Because only improving steps are accepted, the learned mask provably dominates its random starting point on the training objective.

§10.2 Compression Benchmark (Showcase Claim)

A sensor squeezed to 2×2 (= 4 pixels). The same 4-class synthetic dataset. Benchmark variants:

Variant Description
digital_tiny_sensor 4-pixel direct readout; no optics
random_mask_tiny Random mask into 4-pixel sensor
learned_mask_tiny Learned mask into 4-pixel sensor

Observed results (photonlayer-bench, 2026-06-18): at a 2×2 / 4-pixel sensor a learned mask reaches 1.00 test accuracy vs 0.80 for random mask vs 0.65 for digital baseline. This demonstrates 64× sensor compression (16×16 input to 2×2 sensor) with no loss of task accuracy. These figures are from a specific synthetic dataset and learner configuration; results on real data will differ.

§10.3 Metrics

Metric Symbol Notes
Classification accuracy accuracy Fraction correct on test split
Mean squared error mse Reconstruction fidelity
Peak signal-to-noise ratio psnr(dB) 10 log₁₀(peak²/MSE)
Compression ratio compression_ratio Input pixels / sensor pixels
Input-frame similarity input_frame_similarity Pearson r; low = not human-readable
Native simulation latency native_latency_us Wall-clock µs for one forward pass

§11 Acceptance Gates (§17)

The following invariants must hold for a PhotonLayer release to be accepted:

§17.1 Determinism Invariant

For any fixed (InputImage, PhaseMask, OpticalConfig):

ScalarSimulator.simulate(img, mask, cfg).frame_hash  ==
ScalarSimulator.simulate(img, mask, cfg).frame_hash

The second invocation must produce a bit-identical frame_hash. This is the determinism invariant; it is verified by tests::replay_is_deterministic in photonlayer-core/src/receipt.rs (21 tests pass as of 2026-06-18).

§17.2 Learned Dominates Random

On at least one benchmark variant:

learned_mask.train_accuracy >= random_mask.train_accuracy

Enforced by tests::learned_beats_or_matches_random_on_training in photonlayer-bench/src/baselines.rs.

§17.3 Learned Wins Under Compression

At the 2×2 sensor task:

learned_mask_tiny.test_accuracy > digital_tiny_sensor.test_accuracy
learned_mask_tiny.test_accuracy >= random_mask_tiny.test_accuracy

Enforced by tests::learned_strictly_wins_under_compression.

§17.4 Receipt Integrity

verify_receipt(r) must return true for every receipt produced by build_receipt(...). Tampering any field (including output_hash) must return false. Enforced by tests::receipt_verifies and tests::tamper_breaks_receipt.

§17.5 Input-Frame Similarity Bound

For the standard benchmark configuration, input_frame_similarity (Pearson r) must be below a threshold (default 0.4) to confirm that the sensor pattern is not a direct copy of the input image. This guards against trivially transparent optical paths.


§12 Determinism Invariant (§21)

The determinism invariant is the foundation of PhotonLayer's reproducibility guarantee:

Same InputImage + PhaseMask + OpticalConfig + seed (embedded in OpticalConfig) always produce the same frame_hash (BLAKE3 over the OpticalFrame intensity bytes).

Implementation guarantees:

  1. The FFT engine (photonlayer-core/src/fft.rs) is a pure-Rust, in-house Cooley-Tukey implementation with no platform-dependent SIMD paths in the default configuration. All arithmetic is deterministic across calls.
  2. The noise RNG (DeterministicRng) is a deterministic 64-bit Xoshiro-256** variant seeded from OpticalConfig::seed. No system entropy is consumed.
  3. OpticalConfig is serialized to canonical JSON before hashing, ensuring that field ordering is stable across serde versions.
  4. PhaseMask::phase_radians values are stored as f32; the hash_f32 function hashes the raw little-endian bytes, which are stable given identical f32 values.

Violation of the determinism invariant is a hard error. Imported masks (e.g., trained offline by TorchOptics) must be replayed and the resulting frame_hash compared against the stored receipt's output_hash before the mask is accepted into experiment memory.


§13 Implementation Phases

Phase 1 — Core Simulator (Complete)

  • photonlayer-core: field, FFT, mask, propagation, detector, metrics, receipt, hash, RNG, complex, error, config, simulator
  • 21 passing tests covering determinism, receipt integrity, mask apply, propagation modes, field construction, detector model
  • All three propagation modes: Fresnel, Fraunhofer, AngularSpectrum

Phase 2 — Benchmarks and Learner (Complete)

  • photonlayer-bench: synthetic 4-class dataset, nearest-centroid decoder, digital baseline, random mask baseline, block hill-climbing learner
  • Classification benchmark: digital < random < learned ordering
  • Compression benchmark: 1.00 vs 0.80 vs 0.65 test accuracy at 2×2 sensor
  • BenchReport: JSON-serializable, serde-stable

Phase 3 — RuVector Integration (Complete)

  • photonlayer-ruvector: ExperimentRecord, ExperimentMemory, 32-dim embedding (mask histogram + frame spectrum), cosine-similarity NN
  • photonlayer-cli: sub-commands for simulate, bench, store
  • photonlayer-wasm: wasm-bindgen entry point for browser simulation

Phase 4 — External Mask Import and Verification (Planned)

  • JSON schema for the mask-exchange format (ADR-261)
  • import_mask CLI command: loads a PhaseMask from JSON, replays the simulation, verifies frame_hash against stored receipt
  • BLAKE3 replay-hash verification in photonlayer-ruvector
  • Differential optics gradient export: compute ∂L/∂θ(x,y) for each mask cell to enable PyTorch-side optimization

Phase 5 — Privacy and Verification Applications (Planned, ADR-262)

  • Reconstruction-attack test: confirm that sensor frames cannot be inverted to recover human-readable input images above a privacy threshold
  • Optical verification mode: same/different decision from two frames
  • FAR / FRR / EER tracking in experiment memory
  • Governance receipt for spoof-failure events

Phase 6 — Hardware Calibration Bridge (Future)

  • Import measured PSF from physical DOE to replace simulated transfer function
  • Calibration drift tracking: compare measured PSF hash against baseline receipt over time
  • Multi-wavelength / polychromatic simulation (currently monochromatic)

§14 Application Domains, Positioning, and Ethics

§14.1 What PhotonLayer Is

PhotonLayer is a front-end compression and task-specific sensing system. Light performs the first trained transformation; a smaller digital backend reads the result. This means:

  • Lower latency: the optical computation adds zero marginal inference time (light propagates through the mask at the speed of light regardless of grid size).
  • Less sensor bandwidth: fewer pixels reach the ADC, lowering power and transmission cost.
  • Lower power: fewer ADC conversions, smaller digital pipeline.
  • Compressed measurements: the sensor plane contains a task-optimized projection, not a raw image.
  • Task-specific sensing: the phase mask is optimized for one task; other tasks require different masks or a reconfigurable liquid-crystal spatial light modulator (SLM).

PhotonLayer is not a full perception replacement. It cannot replace the digital decoder, because the optical front end is a compression step, not a complete classifier.

§14.2 Feasibility Ranking (Highest to Lowest for Near-Term Impact)

Rank 1 — Industrial and scientific sensors (highest feasibility)

Learned phase masks designed as task-specific measurement devices for:

  • Crack detection in structural materials (spatial frequency enhancement)
  • Crop disease and surface defect inspection (texture discrimination)
  • Material composition sensing (spectral and polarization encoding)
  • Polarization imaging (full-Stokes measurement with a single monochrome sensor, per 2026 metasurface paper)

These applications have controlled illumination, cooperative subjects, well-defined pass/fail criteria, and no consent or privacy concerns. The PhotonLayer compression benchmark (64× sensor reduction with 1.00 accuracy on synthetic data) directly motivates this class of application.

Rank 2 — Drone and autonomous vehicle perception preprocessing

Optical flow estimation, obstacle and wire detection, landing-zone classification, glare and lens-flare robustness. These applications benefit from the grams/watts/bandwidth/latency advantages of optical front ends at the sensor level, before any digital transmission. The phase mask acts as a hardware filter, passing only task-relevant structure to the digital pipeline.

Rank 3 — Medical imaging research simulator

Microscopy compression (encoding a high-resolution wavefront into a compact measurement), snapshot polarization imaging (single-shot full-Stokes, after 2026 metasurface blueprint), reconstruction from fewer measurements (compressed sensing with a learned optical modulator). This is a research tooling application, not a clinical diagnosis tool. PhotonLayer does not produce diagnostic conclusions; it simulates the measurement physics.

Rank 4 — Consented face verification with optical encoding

A phase mask that maps a face image to an encoded sensor pattern — not a human-readable image — for same/different verification and liveness/anti-spoof testing. Key constraints:

  • The sensor pattern must NOT be a recoverable face image (ADR-262 governs the reconstruction-attack threshold).
  • Consent and transparency are required: the subject must know that an optical encoding device is in use.
  • No face biometric is stored; only the compact encoded frame and the receipt.

This application is Rank 4 because the privacy engineering (reconstruction- attack resistance, consent governance, regulatory compliance) is substantial.

Non-goal — Public or mass surveillance facial recognition

PhotonLayer will not be used, documented, or positioned as a technology for identifying individuals in public spaces without consent. This is an explicit architectural and ethical boundary. No crate, no benchmark, and no ADR in the PhotonLayer namespace documents or facilitates mass facial recognition. The input_frame_similarity metric and the ADR-262 reconstruction-attack test exist precisely to confirm that the optical encoding discards human-readable image content.

§14.3 Claim Discipline

The following language is prohibited in PhotonLayer documentation and marketing:

  • "Light is running a neural network" — this conflates the optical propagation with the training algorithm and the decoder.
  • "The optical system classifies images" — the optical system projects; the digital decoder classifies.
  • "This replaces digital sensing" — it compresses and pre-processes the sensed signal; the sensor and digital pipeline remain.

The following language is precise and permitted:

  • "Light performs the first trained transformation."
  • "A learned phase mask concentrates task-discriminative energy into fewer sensor pixels."
  • "The digital decoder reads a compressed, task-specific optical projection."
  • "The learned mask achieves higher accuracy than a random mask at the same sensor pixel count."

Consequences

Positive

  • Establishes a reproducible, receipt-bound optical simulation infrastructure inside RuVector with zero external ML framework dependencies.
  • The compression benchmark provides a concrete, falsifiable claim: 64× sensor compression with 1.00 test accuracy (on synthetic data) vs 0.65 for the digital baseline.
  • The determinism invariant enables cross-machine and cross-time experiment comparison, mask import/export, and audit trails.
  • The RuVector experiment memory enables nearest-neighbour retrieval of similar past experiments, supporting iterative mask design.
  • The WASM build enables browser-based simulation demos and educational tools.

Negative

  • The in-Rust hill-climbing learner is not gradient-based; for large masks (e.g., 512×512) offline differentiable training (TorchOptics, waveprop) is required, and the import/verification bridge (Phase 4) is not yet built.
  • The current simulator is monochromatic; broadband / polychromatic simulation requires Phase 6 extensions.
  • The 21 tests cover the synthetic benchmark; real-world optical data validation requires physical fabrication or measured PSF import.

Risks

  • The compression benchmark results (1.00 / 0.80 / 0.65) are on a small synthetic 4-class dataset. Overclaiming these as representative of real-world performance would be a scientific integrity failure. All external communication must include the dataset and configuration context.
  • The privacy acceptance gate (§17.5, input_frame_similarity < 0.4) is a necessary but not sufficient condition for reconstruction-attack resistance. ADR-262 governs the full threat model.

References

  • ADR-015: Coherence-Gated Transformer — coherence library used for NN search
  • ADR-029: RVF Canonical Format — receipt binding pattern
  • ADR-047: Proof-Gated Mutation Protocol — proof tier design reference
  • ADR-117: Canonical MinCut — MinCut domain boundary concept
  • ADR-197: Differentiable MinCut Condensation — differentiable boundary loss
  • ADR-261: PhotonLayer Mask-Exchange Format and Determinism (companion ADR)
  • ADR-262: PhotonLayer Privacy-Preserving Optical Verification (companion ADR)
  • crates/photonlayer-core/src/lib.rs — simulator entry point and prelude
  • crates/photonlayer-core/src/config.rs — OpticalConfig, PropagationMode, DetectorConfig
  • crates/photonlayer-core/src/mask.rs — PhaseMask, apply, histogram
  • crates/photonlayer-core/src/receipt.rs — ExperimentReceipt, build_receipt, verify_receipt
  • crates/photonlayer-core/src/metrics.rs — MetricReport, frame_spectrum_embedding
  • crates/photonlayer-bench/src/baselines.rs — run_classification, run_compression
  • crates/photonlayer-bench/src/learn.rs — LearnConfig, learn_mask, LearnOutcome
  • crates/photonlayer-ruvector/src/memory.rs — ExperimentMemory, ExperimentRecord
  • crates/photonlayer-ruvector/src/embedding.rs — experiment_embedding (32-dim)
  • Lin et al. (2018), "All-Optical Machine Learning Using Diffractive Deep Neural Networks," Science 361(6406): 10041008 (per project brief / to be verified)
  • Computational meta-optics review (2026) — >90% optical front-end computation (per project brief / to be verified)
  • Edge-enhanced diffractive networks (June 2026) — 64.2% → 80.7% MNIST single-layer accuracy (per project brief / to be verified)
  • Full-Stokes metasurface + U-Net reconstruction (2026) — joint differentiable optical-electronic design blueprint (per project brief / to be verified)
  • TorchOptics library — PyTorch differentiable Fourier optics, GPU, joint optimization (per project brief / to be verified)
  • waveprop library — scalar diffraction, trainable apertures (per project brief / to be verified)
  • diffractsim library — JAX differentiable optimization and visualization (per project brief / to be verified)