Back to Ruview

Quantum-Inspired & Autonomous Modules -- WiFi-DensePose Edge Intelligence

docs/edge-modules/autonomous.md

0.7.021.3 KB
Original Source

Quantum-Inspired & Autonomous Modules -- WiFi-DensePose Edge Intelligence

Advanced algorithms inspired by quantum computing, neuroscience, and AI planning. These modules let the ESP32 make autonomous decisions, heal its own mesh network, interpret high-level scene semantics, and explore room states using quantum-inspired search.

Quantum-Inspired

ModuleFileWhat It DoesEvent IDsBudget
Quantum Coherenceqnt_quantum_coherence.rsMaps CSI phases onto a Bloch sphere to detect sudden environmental changes850-852H (<10 ms)
Interference Searchqnt_interference_search.rsGrover-inspired multi-hypothesis room state classifier855-857H (<10 ms)

Quantum Coherence (qnt_quantum_coherence.rs)

What it does: Maps each subcarrier's phase onto a point on the quantum Bloch sphere and computes an aggregate coherence metric from the mean Bloch vector magnitude. When all subcarrier phases are aligned, the system is "coherent" (like a quantum pure state). When phases scatter randomly, it is "decoherent" (like a maximally mixed state). Sudden decoherence -- a rapid entropy spike -- indicates an environmental disturbance such as a door opening, a person entering, or furniture being moved.

Algorithm: Each subcarrier phase is mapped to a 3D Bloch vector:

  • theta = |phase| (polar angle)
  • phi = sign(phase) * pi/2 (azimuthal angle)

Since phi is always +/- pi/2, cos(phi) = 0 and sin(phi) = +/- 1. This eliminates 2 trig calls per subcarrier (saving 64+ cosf/sinf calls per frame for 32 subcarriers). The x-component of the mean Bloch vector is always zero.

Von Neumann entropy: S = -p*log(p) - (1-p)*log(1-p) where p = (1 + |bloch|) / 2. S=0 when perfectly coherent (|bloch|=1), S=ln(2) when maximally mixed (|bloch|=0). EMA smoothing with alpha=0.15.

Public API

rust
use wifi_densepose_wasm_edge::qnt_quantum_coherence::QuantumCoherenceMonitor;

let mut mon = QuantumCoherenceMonitor::new();             // const fn
let events = mon.process_frame(&phases);                  // per-frame
let coh = mon.coherence();                                // [0, 1], 1=pure state
let ent = mon.entropy();                                  // [0, ln(2)]
let norm_ent = mon.normalized_entropy();                   // [0, 1]
let bloch = mon.bloch_vector();                           // [f32; 3]
let frames = mon.frame_count();                           // total frames

Events

Event IDConstantValueFrequency
850EVENT_ENTANGLEMENT_ENTROPYEMA-smoothed Von Neumann entropy [0, ln(2)]Every 10 frames
851EVENT_DECOHERENCE_EVENTEntropy jump magnitude (> 0.3)On detection
852EVENT_BLOCH_DRIFTEuclidean distance between consecutive Bloch vectorsEvery 5 frames

Configuration Constants

ConstantValuePurpose
MAX_SC32Maximum subcarriers
ALPHA0.15EMA smoothing factor
DECOHERENCE_THRESHOLD0.3Entropy jump threshold
ENTROPY_EMIT_INTERVAL10Frames between entropy reports
DRIFT_EMIT_INTERVAL5Frames between drift reports
LN20.693147Maximum binary entropy

Example: Door Opening Detection via Decoherence

Frames 1-50: Empty room, phases stable at ~0.1 rad
  Bloch vector: (0, 0.10, 0.99) -> coherence = 0.995
  Entropy ~ 0.005 (near zero, pure state)

Frame 51: Door opens, multipath changes suddenly
  Phases scatter: [-2.1, 0.8, 1.5, -0.3, ...]
  Bloch vector: (0, 0.12, 0.34) -> coherence = 0.36
  Entropy jumps to 0.61
  -> EVENT_DECOHERENCE_EVENT = 0.605 (jump magnitude)
  -> EVENT_BLOCH_DRIFT = 0.65 (large Bloch vector displacement)

Frames 52-100: New stable multipath
  Phases settle at new values
  Entropy gradually decays via EMA
  No more decoherence events

Bloch Sphere Intuition

Think of each subcarrier as a compass needle. When the room is stable, all needles point roughly the same direction (high coherence, low entropy). When something changes the WiFi multipath -- a person enters, a door opens, furniture moves -- the needles scatter in different directions (low coherence, high entropy). The Bloch sphere formalism quantifies this in a way that is mathematically precise and computationally cheap.


Interference Search (qnt_interference_search.rs)

What it does: Maintains 16 amplitude-weighted hypotheses for the current room state (empty, person in zone A/B/C/D, two persons, exercising, sleeping, etc.) and uses a Grover-inspired oracle+diffusion process to converge on the most likely state.

Algorithm: Inspired by Grover's quantum search algorithm, adapted for classical computation:

  1. Oracle: CSI evidence (presence, motion, person count) multiplies hypothesis amplitudes by boost (1.3) or dampen (0.7) factors depending on consistency.
  2. Grover diffusion: Reflects all amplitudes about their mean (a_i = 2*mean - a_i), concentrating probability mass on oracle-boosted hypotheses. Negative amplitudes are clamped to zero (classical approximation).
  3. Normalization: Amplitudes are renormalized so sum-of-squares = 1.0 (probability conservation).

After enough iterations, the winner emerges with probability > 0.5 (convergence threshold).

The 16 Hypotheses

IndexHypothesisOracle Evidence
0Emptypresence=0
1-4Person in Zone A/B/C/Dpresence=1, 1 person
5Two Personsn_persons=2
6Three Personsn_persons>=3
7Moving Lefthigh motion, moving state
8Moving Righthigh motion, moving state
9Sittinglow motion, present
10Standinglow motion, present
11Fallinghigh motion (transient)
12Exercisinghigh motion, present
13Sleepinglow motion, present
14Cookingmoderate motion + moving
15Workinglow motion, present

Public API

rust
use wifi_densepose_wasm_edge::qnt_interference_search::{InterferenceSearch, Hypothesis};

let mut search = InterferenceSearch::new();               // const fn, uniform amplitudes
let events = search.process_frame(presence, motion_energy, n_persons);
let winner = search.winner();                             // Hypothesis enum
let prob = search.winner_probability();                   // [0, 1]
let converged = search.is_converged();                    // prob > 0.5
let amp = search.amplitude(Hypothesis::Sleeping);         // raw amplitude
let p = search.probability(Hypothesis::Exercising);       // amplitude^2
let iters = search.iterations();                          // total iterations
search.reset();                                           // back to uniform

Events

Event IDConstantValueFrequency
855EVENT_HYPOTHESIS_WINNERWinning hypothesis index (0-15)Every 10 frames or on change
856EVENT_HYPOTHESIS_AMPLITUDEWinning hypothesis probabilityEvery 20 frames
857EVENT_SEARCH_ITERATIONSTotal Grover iterationsEvery 50 frames

Configuration Constants

ConstantValuePurpose
N_HYPO16Number of room-state hypotheses
CONVERGENCE_PROB0.5Threshold for declaring convergence
ORACLE_BOOST1.3Amplitude multiplier for supported hypotheses
ORACLE_DAMPEN0.7Amplitude multiplier for contradicted hypotheses
MOTION_HIGH_THRESH0.5Motion energy threshold for "high motion"
MOTION_LOW_THRESH0.15Motion energy threshold for "low motion"

Example: Room State Classification

Initial state: All 16 hypotheses at probability 1/16 = 0.0625

Frames 1-30: presence=0, motion=0, n_persons=0
  Oracle boosts Empty (index 0), dampens all others
  Diffusion concentrates probability mass on Empty
  After 30 iterations: P(Empty) = 0.72, P(others) < 0.03
  -> EVENT_HYPOTHESIS_WINNER = 0 (Empty)

Frames 31-60: presence=1, motion=0.8, n_persons=1
  Oracle boosts Exercising, MovingLeft, MovingRight
  Oracle dampens Empty, Sitting, Sleeping
  After 30 more iterations: P(Exercising) = 0.45
  -> EVENT_HYPOTHESIS_WINNER = 12 (Exercising)
  Winner changed -> event emitted immediately

Frames 61-90: presence=1, motion=0.05, n_persons=1
  Oracle boosts Sitting, Sleeping, Working, Standing
  Oracle dampens Exercising, MovingLeft, MovingRight
  -> Convergence shifts to static hypotheses

Autonomous Systems

ModuleFileWhat It DoesEvent IDsBudget
Psycho-Symbolicaut_psycho_symbolic.rsContext-aware inference using forward-chaining symbolic rules880-883H (<10 ms)
Self-Healing Meshaut_self_healing_mesh.rsMonitors mesh node health and auto-reconfigures via min-cut analysis885-888S (<5 ms)

Psycho-Symbolic Inference (aut_psycho_symbolic.rs)

What it does: Interprets raw CSI-derived features into high-level semantic conclusions using a knowledge base of 16 forward-chaining rules. Given presence, motion energy, breathing rate, heart rate, person count, coherence, and time of day, it determines conclusions like "person resting", "possible intruder", "medical distress", or "social activity".

Algorithm: Forward-chaining rule evaluation. Each rule has 4 condition slots (feature_id, comparison_op, threshold). A rule fires when all non-disabled conditions match. Confidence propagation: the final confidence is the rule's base confidence multiplied by per-condition match-quality scores (how far above/below threshold the feature is, clamped to [0.5, 1.0]). Contradiction detection resolves mutually exclusive conclusions by keeping the higher-confidence one.

The 16 Rules

RuleConclusionConditionsBase Confidence
R0Possible IntruderPresence + high motion (>=200) + night0.80
R1Person RestingPresence + low motion (<30) + breathing 10-22 BPM0.90
R2Pet or EnvironmentNo presence + motion (>=15)0.60
R3Social ActivityMulti-person (>=2) + high motion (>=100)0.70
R4Exercise1 person + high motion (>=150) + elevated HR (>=100)0.80
R5Possible FallPresence + sudden stillness (motion<10, prev_motion>=150)0.70
R6InterferenceLow coherence (<0.4) + presence0.50
R7SleepingPresence + very low motion (<5) + night + breathing (>=8)0.90
R8Cooking ActivityPresence + moderate motion (40-120) + evening0.60
R9Leaving HomeNo presence + previous motion (>=50) + morning0.65
R10Arriving HomePresence + motion (>=60) + low prev_motion (<15) + evening0.70
R11Child PlayingMulti-person (>=2) + very high motion (>=250) + daytime0.60
R12Working at Desk1 person + low motion (<20) + good coherence (>=0.6) + morning0.75
R13Medical DistressPresence + very high HR (>=130) + low motion (<15)0.85
R14Room Empty (Stable)No presence + no motion (<5) + good coherence (>=0.6)0.95
R15Crowd GatheringMany persons (>=4) + high motion (>=120)0.70

Contradiction Pairs

These conclusions are mutually exclusive. When both fire, only the one with higher confidence survives:

Pair APair B
SleepingExercise
SleepingSocial Activity
Room Empty (Stable)Possible Intruder
Person RestingExercise

Input Features

IndexFeatureSourceRange
0PresenceTier 2 DSP0 (absent) or 1 (present)
1Motion EnergyTier 2 DSP0 to ~1000
2Breathing BPMTier 2 vitals0-60
3Heart Rate BPMTier 2 vitals0-200
4Person CountTier 2 occupancy0-8
5CoherenceQuantumCoherenceMonitor or upstream0-1
6Time BucketHost clock0=morning, 1=afternoon, 2=evening, 3=night
7Previous MotionInternal (auto-tracked)0 to ~1000

Public API

rust
use wifi_densepose_wasm_edge::aut_psycho_symbolic::PsychoSymbolicEngine;

let mut engine = PsychoSymbolicEngine::new();             // const fn
engine.set_coherence(0.8);                                // from upstream module
let events = engine.process_frame(
    presence, motion, breathing, heartrate, n_persons, time_bucket
);
let rules = engine.fired_rules();                         // u16 bitmap
let count = engine.fired_count();                         // number of rules that fired
let prev = engine.prev_conclusion();                      // last winning conclusion ID
let contras = engine.contradiction_count();                // total contradictions
engine.reset();                                           // clear state

Events

Event IDConstantValueFrequency
880EVENT_INFERENCE_RESULTConclusion ID (1-16)When any rule fires
881EVENT_INFERENCE_CONFIDENCEConfidence [0, 1] of the winning conclusionPaired with result
882EVENT_RULE_FIREDRule index (0-15)For each rule that fired
883EVENT_CONTRADICTIONEncoded pair: conclusion_a * 100 + conclusion_bOn contradiction

Example: Fall Detection Sequence

Frame 1: Person walking briskly
  Features: presence=1, motion=200, breathing=20, HR=90, persons=1, time=1
  R4 (Exercise) fires: confidence = 0.80 * 0.75 = 0.60
  -> EVENT_INFERENCE_RESULT = 5 (Exercise)
  -> EVENT_INFERENCE_CONFIDENCE = 0.60

Frame 2: Sudden stillness (prev_motion=200, current motion=3)
  R5 (Possible Fall) fires: confidence = 0.70 * 0.85 = 0.595
  R1 (Person Resting) also fires: confidence = 0.90 * 0.50 = 0.45
  No contradiction between these two
  -> EVENT_RULE_FIRED = 5 (Fall rule)
  -> EVENT_RULE_FIRED = 1 (Resting rule)
  -> EVENT_INFERENCE_RESULT = 6 (Possible Fall, highest confidence)
  -> EVENT_INFERENCE_CONFIDENCE = 0.595

Self-Healing Mesh (aut_self_healing_mesh.rs)

What it does: Monitors the health of an 8-node sensor mesh and automatically detects when the network topology becomes fragile. Uses the Stoer-Wagner minimum graph cut algorithm to find the weakest link in the mesh. When the min-cut value drops below a threshold, it identifies the degraded node and triggers a reconfiguration event.

Algorithm: Stoer-Wagner min-cut on a weighted graph of up to 8 nodes. Edge weights are the minimum quality score of the two endpoints (min(q_i, q_j)). Quality scores are EMA-smoothed (alpha=0.15) per-node CSI coherence values. O(n^3) complexity, which is only 512 operations for n=8. State machine transitions between healthy and healing modes.

Public API

rust
use wifi_densepose_wasm_edge::aut_self_healing_mesh::SelfHealingMesh;

let mut mesh = SelfHealingMesh::new();                    // const fn
mesh.update_node_quality(0, coherence);                   // update single node
let events = mesh.process_frame(&node_qualities);         // process all nodes
let q = mesh.node_quality(2);                             // EMA quality for node 2
let n = mesh.active_nodes();                              // count
let mc = mesh.prev_mincut();                              // last min-cut value
let healing = mesh.is_healing();                          // fragile state?
let weak = mesh.weakest_node();                           // node ID or 0xFF
mesh.reset();                                             // clear state

Events

Event IDConstantValueFrequency
885EVENT_NODE_DEGRADEDIndex of the degraded node (0-7)When min-cut < 0.3
886EVENT_MESH_RECONFIGUREMin-cut value (measure of fragility)Paired with degraded
887EVENT_COVERAGE_SCOREMean quality across all active nodes [0, 1]Every frame
888EVENT_HEALING_COMPLETEMin-cut value (now healthy)When min-cut recovers >= 0.6

Configuration Constants

ConstantValuePurpose
MAX_NODES8Maximum mesh nodes
QUALITY_ALPHA0.15EMA smoothing for node quality
MINCUT_FRAGILE0.3Below this, mesh is considered fragile
MINCUT_HEALTHY0.6Above this, healing is considered complete

State Machine

                 mincut < 0.3
  [Healthy] ----------------------> [Healing]
      ^                                 |
      |         mincut >= 0.6           |
      +---------------------------------+

Stoer-Wagner Min-Cut Details

The algorithm finds the minimum weight of edges that, if removed, would disconnect the graph into two components. For an 8-node mesh:

  1. Start with the full weighted adjacency matrix
  2. For each phase (n-1 phases total):
    • Grow a set A by repeatedly adding the node with the highest total edge weight to A
    • The last two nodes added (prev, last) define a "cut of the phase" = weight to last
    • Track the global minimum cut across all phases
    • Merge the last two nodes (combine their edge weights)
  3. Return (global_min_cut, node_on_lighter_side)

Example: Node Failure and Recovery

Frame 1: All 4 nodes healthy
  qualities = [0.9, 0.85, 0.88, 0.92]
  Coverage = 0.89
  Min-cut = 0.85 (well above 0.6)
  -> EVENT_COVERAGE_SCORE = 0.89

Frame 50: Node 1 starts degrading
  qualities = [0.9, 0.20, 0.88, 0.92]
  EMA-smoothed quality[1] drops gradually
  Min-cut drops to 0.20 (edge weights use min(q_i, q_j))
  Min-cut < 0.3 -> FRAGILE!
  -> EVENT_NODE_DEGRADED = 1
  -> EVENT_MESH_RECONFIGURE = 0.20
  -> Mesh enters healing mode

  Host firmware can now:
  - Increase node 1's transmit power
  - Route traffic around node 1
  - Wake up a backup node
  - Alert the operator

Frame 100: Node 1 recovers (antenna repositioned)
  qualities = [0.9, 0.85, 0.88, 0.92]
  Min-cut climbs back to 0.85
  Min-cut >= 0.6 -> HEALTHY!
  -> EVENT_HEALING_COMPLETE = 0.85

How Quantum-Inspired Algorithms Help WiFi Sensing

These modules use quantum computing metaphors -- not because the ESP32 is a quantum computer, but because the mathematical frameworks from quantum mechanics map naturally onto CSI signal analysis:

Bloch Sphere / Coherence: WiFi subcarrier phases behave like quantum phases. When multipath is stable, all phases align (pure state). When the environment changes, phases randomize (mixed state). The Von Neumann entropy quantifies this exactly, providing a single scalar "change detector" that is more robust than tracking individual subcarrier phases.

Grover's Algorithm / Hypothesis Search: The oracle+diffusion loop is a principled way to combine evidence from multiple noisy sensors. Instead of hard-coding "if motion > 0.5 then exercising", the Grover-inspired search lets multiple hypotheses compete. Evidence gradually amplifies the correct hypothesis while suppressing incorrect ones. This is more robust to noisy CSI data than a single threshold.

Why not just use classical statistics? You could. But the quantum-inspired formulations have three practical advantages on embedded hardware:

  1. Fixed memory: The Bloch vector is always 3 floats. The hypothesis array is always 16 floats. No dynamic allocation needed.
  2. Graceful degradation: If CSI data is noisy, the Grover search does not crash or give a wrong answer immediately -- it just converges more slowly.
  3. Composability: The coherence score from the Bloch sphere module feeds directly into the Temporal Logic Guard (rule 3: "no vital signs when coherence < 0.3") and the Psycho-Symbolic engine (feature 5: coherence). This creates a pipeline where quantum-inspired metrics inform classical reasoning.

Memory Layout

ModuleState Size (approx)Static Event Buffer
Quantum Coherence~40 bytes (3D Bloch vector + 2 entropy floats + counter)3 entries
Interference Search~80 bytes (16 amplitudes + counters)3 entries
Psycho-Symbolic~24 bytes (bitmap + counters + prev_motion)8 entries
Self-Healing Mesh~360 bytes (8x8 adjacency + 8 qualities + state)6 entries

All modules use fixed-size arrays and static event buffers. No heap allocation. Fully no_std compliant for WASM3 deployment on ESP32-S3.


Cross-Module Integration

These modules are designed to work together in a pipeline:

CSI Frame (Tier 2 DSP)
    |
    v
[Quantum Coherence] --coherence--> [Psycho-Symbolic Engine]
    |                                     |
    v                                     v
[Interference Search]              [Inference Result]
    |                                     |
    v                                     v
[Room State Hypothesis]            [GOAP Planner]
                                         |
                                         v
                                   [Module Activate/Deactivate]
                                         |
                                         v
                                   [Self-Healing Mesh]
                                         |
                                         v
                                   [Reconfiguration Events]

The Quantum Coherence monitor feeds its coherence score to:

  • Psycho-Symbolic Engine: As feature 5 (coherence), enabling rules R3 (interference) and R6 (low coherence)
  • Temporal Logic Guard: Rule 3 checks "no vital signs when coherence < 0.3"
  • Self-Healing Mesh: Node quality can be derived from coherence

The GOAP Planner uses inference results to decide which modules to activate (e.g., activate vitals monitoring when a person is present, enter low-power mode when the room is empty).