Files
wifi-densepose/rust-port/wifi-densepose-rs/crates/wifi-densepose-ruvector/benches/crv_bench.rs
ruv 60e0e6d3c4 feat: ADR-033 CRV signal-line integration + ruvector-crv 6-stage pipeline
Implement full CRV (Coordinate Remote Viewing) signal-line protocol
mapping to WiFi CSI sensing via ruvector-crv:

- Stage I: CsiGestaltClassifier (6 gestalt types from amplitude/phase)
- Stage II: CsiSensoryEncoder (texture/color/temperature/sound/luminosity/dimension)
- Stage III: Mesh topology encoding (AP nodes/links → GNN graph)
- Stage IV: Coherence gate → AOL detection (signal vs noise separation)
- Stage V: Pose interrogation via differentiable search
- Stage VI: Person partitioning via MinCut clustering
- Cross-session convergence for cross-room identity

New files:
- crv/mod.rs: 1,430 lines, 43 tests
- crv_bench.rs: 8 criterion benchmarks (gestalt, sensory, pipeline, convergence)
- ADR-033: 740-line architecture decision with 30+ acceptance criteria
- patches/ruvector-crv: Fix ruvector-gnn 2.0.5 API mismatch

Dependencies: ruvector-crv 0.1.1, ruvector-gnn 2.0.5

Co-Authored-By: claude-flow <ruv@ruv.net>
2026-03-01 22:21:59 -05:00

406 lines
13 KiB
Rust

//! Benchmarks for CRV (Coordinate Remote Viewing) integration.
//!
//! Measures throughput of gestalt classification, sensory encoding,
//! full session pipelines, cross-session convergence, and embedding
//! dimension scaling using the `ruvector-crv` crate directly.
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use ruvector_crv::{
CrvConfig, CrvSessionManager, GestaltType, SensoryModality, StageIData, StageIIData,
StageIIIData, StageIVData,
};
use ruvector_crv::types::{
GeometricKind, SketchElement, SpatialRelationType, SpatialRelationship,
};
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
/// Build a synthetic CSI-like ideogram stroke with `n` subcarrier points.
fn make_stroke(n: usize) -> Vec<(f32, f32)> {
(0..n)
.map(|i| {
let t = i as f32 / n as f32;
(t, (t * std::f32::consts::TAU).sin() * 0.5 + 0.5)
})
.collect()
}
/// Build a Stage I data frame representing a single CSI gestalt sample.
fn make_stage_i(gestalt: GestaltType) -> StageIData {
StageIData {
stroke: make_stroke(64),
spontaneous_descriptor: "angular rising".to_string(),
classification: gestalt,
confidence: 0.85,
}
}
/// Build a Stage II sensory data frame.
fn make_stage_ii() -> StageIIData {
StageIIData {
impressions: vec![
(SensoryModality::Texture, "rough metallic".to_string()),
(SensoryModality::Temperature, "warm".to_string()),
(SensoryModality::Color, "silver-gray".to_string()),
(SensoryModality::Luminosity, "reflective".to_string()),
(SensoryModality::Sound, "low hum".to_string()),
],
feature_vector: None,
}
}
/// Build a Stage III spatial sketch.
fn make_stage_iii() -> StageIIIData {
StageIIIData {
sketch_elements: vec![
SketchElement {
label: "tower".to_string(),
kind: GeometricKind::Rectangle,
position: (0.5, 0.8),
scale: Some(3.0),
},
SketchElement {
label: "base".to_string(),
kind: GeometricKind::Rectangle,
position: (0.5, 0.2),
scale: Some(5.0),
},
SketchElement {
label: "antenna".to_string(),
kind: GeometricKind::Line,
position: (0.5, 0.95),
scale: Some(1.0),
},
],
relationships: vec![
SpatialRelationship {
from: "tower".to_string(),
to: "base".to_string(),
relation: SpatialRelationType::Above,
strength: 0.9,
},
SpatialRelationship {
from: "antenna".to_string(),
to: "tower".to_string(),
relation: SpatialRelationType::Above,
strength: 0.85,
},
],
}
}
/// Build a Stage IV emotional / AOL data frame.
fn make_stage_iv() -> StageIVData {
StageIVData {
emotional_impact: vec![
("awe".to_string(), 0.7),
("curiosity".to_string(), 0.6),
("unease".to_string(), 0.3),
],
tangibles: vec!["metal structure".to_string(), "concrete".to_string()],
intangibles: vec!["transmission".to_string(), "power".to_string()],
aol_detections: vec![],
}
}
/// Create a manager with one session pre-loaded with 4 stages of data.
fn populated_manager(dims: usize) -> (CrvSessionManager, String) {
let config = CrvConfig {
dimensions: dims,
..CrvConfig::default()
};
let mut mgr = CrvSessionManager::new(config);
let sid = "bench-sess".to_string();
mgr.create_session(sid.clone(), "coord-001".to_string())
.unwrap();
mgr.add_stage_i(&sid, &make_stage_i(GestaltType::Manmade))
.unwrap();
mgr.add_stage_ii(&sid, &make_stage_ii()).unwrap();
mgr.add_stage_iii(&sid, &make_stage_iii()).unwrap();
mgr.add_stage_iv(&sid, &make_stage_iv()).unwrap();
(mgr, sid)
}
// ---------------------------------------------------------------------------
// Benchmarks
// ---------------------------------------------------------------------------
/// Benchmark: classify a single CSI frame through Stage I (64 subcarriers).
fn gestalt_classify_single(c: &mut Criterion) {
let config = CrvConfig {
dimensions: 64,
..CrvConfig::default()
};
let mut manager = CrvSessionManager::new(config);
manager
.create_session("gc-single".to_string(), "coord-gc".to_string())
.unwrap();
let data = make_stage_i(GestaltType::Manmade);
c.bench_function("gestalt_classify_single", |b| {
b.iter(|| {
manager
.add_stage_i("gc-single", black_box(&data))
.unwrap();
})
});
}
/// Benchmark: classify a batch of 100 CSI frames through Stage I.
fn gestalt_classify_batch(c: &mut Criterion) {
let config = CrvConfig {
dimensions: 64,
..CrvConfig::default()
};
let gestalts = GestaltType::all();
let frames: Vec<StageIData> = (0..100)
.map(|i| make_stage_i(gestalts[i % gestalts.len()]))
.collect();
c.bench_function("gestalt_classify_batch_100", |b| {
b.iter(|| {
let mut manager = CrvSessionManager::new(CrvConfig {
dimensions: 64,
..CrvConfig::default()
});
manager
.create_session("gc-batch".to_string(), "coord-gcb".to_string())
.unwrap();
for frame in black_box(&frames) {
manager.add_stage_i("gc-batch", frame).unwrap();
}
})
});
}
/// Benchmark: extract sensory features from a single CSI frame (Stage II).
fn sensory_encode_single(c: &mut Criterion) {
let config = CrvConfig {
dimensions: 64,
..CrvConfig::default()
};
let mut manager = CrvSessionManager::new(config);
manager
.create_session("se-single".to_string(), "coord-se".to_string())
.unwrap();
let data = make_stage_ii();
c.bench_function("sensory_encode_single", |b| {
b.iter(|| {
manager
.add_stage_ii("se-single", black_box(&data))
.unwrap();
})
});
}
/// Benchmark: full session pipeline -- create session, add 10 mixed-stage
/// frames, run Stage V interrogation, and run Stage VI partitioning.
fn pipeline_full_session(c: &mut Criterion) {
let stage_i_data = make_stage_i(GestaltType::Manmade);
let stage_ii_data = make_stage_ii();
let stage_iii_data = make_stage_iii();
let stage_iv_data = make_stage_iv();
c.bench_function("pipeline_full_session", |b| {
let mut counter = 0u64;
b.iter(|| {
counter += 1;
let config = CrvConfig {
dimensions: 64,
..CrvConfig::default()
};
let mut manager = CrvSessionManager::new(config);
let sid = format!("pfs-{}", counter);
manager
.create_session(sid.clone(), "coord-pfs".to_string())
.unwrap();
// 10 frames across stages I-IV
for _ in 0..3 {
manager
.add_stage_i(&sid, black_box(&stage_i_data))
.unwrap();
}
for _ in 0..3 {
manager
.add_stage_ii(&sid, black_box(&stage_ii_data))
.unwrap();
}
for _ in 0..2 {
manager
.add_stage_iii(&sid, black_box(&stage_iii_data))
.unwrap();
}
for _ in 0..2 {
manager
.add_stage_iv(&sid, black_box(&stage_iv_data))
.unwrap();
}
// Stage V: interrogate with a probe embedding
let probe_emb = vec![0.1f32; 64];
let probes: Vec<(&str, u8, Vec<f32>)> = vec![
("structure query", 1, probe_emb.clone()),
("texture query", 2, probe_emb.clone()),
];
let _ = manager.run_stage_v(&sid, &probes, 3);
// Stage VI: partition
let _ = manager.run_stage_vi(&sid);
})
});
}
/// Benchmark: cross-session convergence analysis with 2 independent
/// sessions of 10 frames each, targeting the same coordinate.
fn convergence_two_sessions(c: &mut Criterion) {
let gestalts = [GestaltType::Manmade, GestaltType::Natural, GestaltType::Energy];
let stage_ii_data = make_stage_ii();
c.bench_function("convergence_two_sessions", |b| {
let mut counter = 0u64;
b.iter(|| {
counter += 1;
let config = CrvConfig {
dimensions: 64,
convergence_threshold: 0.5,
..CrvConfig::default()
};
let mut manager = CrvSessionManager::new(config);
let coord = format!("conv-coord-{}", counter);
// Session A: 10 frames
let sid_a = format!("viewer-a-{}", counter);
manager
.create_session(sid_a.clone(), coord.clone())
.unwrap();
for i in 0..5 {
let data = make_stage_i(gestalts[i % gestalts.len()]);
manager.add_stage_i(&sid_a, black_box(&data)).unwrap();
}
for _ in 0..5 {
manager
.add_stage_ii(&sid_a, black_box(&stage_ii_data))
.unwrap();
}
// Session B: 10 frames (similar but not identical)
let sid_b = format!("viewer-b-{}", counter);
manager
.create_session(sid_b.clone(), coord.clone())
.unwrap();
for i in 0..5 {
let data = make_stage_i(gestalts[(i + 1) % gestalts.len()]);
manager.add_stage_i(&sid_b, black_box(&data)).unwrap();
}
for _ in 0..5 {
manager
.add_stage_ii(&sid_b, black_box(&stage_ii_data))
.unwrap();
}
// Convergence analysis
let _ = manager.find_convergence(&coord, black_box(0.5));
})
});
}
/// Benchmark: session creation overhead alone.
fn crv_session_create(c: &mut Criterion) {
c.bench_function("crv_session_create", |b| {
b.iter(|| {
let config = CrvConfig {
dimensions: 32,
..CrvConfig::default()
};
let mut manager = CrvSessionManager::new(black_box(config));
manager
.create_session(
black_box("sess-1".to_string()),
black_box("coord-1".to_string()),
)
.unwrap();
})
});
}
/// Benchmark: embedding dimension scaling (32, 128, 384).
///
/// Measures Stage I + Stage II encode time across different embedding
/// dimensions to characterize how cost grows with dimensionality.
fn crv_embedding_dimension_scaling(c: &mut Criterion) {
let stage_i_data = make_stage_i(GestaltType::Manmade);
let stage_ii_data = make_stage_ii();
let mut group = c.benchmark_group("crv_embedding_dimension_scaling");
for dims in [32, 128, 384] {
group.bench_with_input(BenchmarkId::from_parameter(dims), &dims, |b, &dims| {
let mut counter = 0u64;
b.iter(|| {
counter += 1;
let config = CrvConfig {
dimensions: dims,
..CrvConfig::default()
};
let mut manager = CrvSessionManager::new(config);
let sid = format!("dim-{}-{}", dims, counter);
manager
.create_session(sid.clone(), "coord-dim".to_string())
.unwrap();
// Encode one Stage I + one Stage II at this dimensionality
let emb_i = manager
.add_stage_i(&sid, black_box(&stage_i_data))
.unwrap();
let emb_ii = manager
.add_stage_ii(&sid, black_box(&stage_ii_data))
.unwrap();
assert_eq!(emb_i.len(), dims);
assert_eq!(emb_ii.len(), dims);
})
});
}
group.finish();
}
/// Benchmark: Stage VI partitioning on a pre-populated session
/// (4 stages of accumulated data).
fn crv_stage_vi_partition(c: &mut Criterion) {
c.bench_function("crv_stage_vi_partition", |b| {
let mut counter = 0u64;
b.iter(|| {
counter += 1;
// Re-create the populated manager each iteration because
// run_stage_vi mutates the session (appends an entry).
let (mut mgr, sid) = populated_manager(64);
let _ = mgr.run_stage_vi(black_box(&sid));
})
});
}
// ---------------------------------------------------------------------------
// Criterion groups
// ---------------------------------------------------------------------------
criterion_group!(
benches,
gestalt_classify_single,
gestalt_classify_batch,
sensory_encode_single,
pipeline_full_session,
convergence_two_sessions,
crv_session_create,
crv_embedding_dimension_scaling,
crv_stage_vi_partition,
);
criterion_main!(benches);