Question
We own a generative twin that turns a floorplan + a crowd into ray-traced CSI (c-multifloor-fsm-observatory). Point it at a question about the building: given this floor, where do I place the access points so they (a) COVER the space, (b) SEE moving people well enough to COUNT them, and (c) ideally do both — and let the walking simulator generate the crowds that answer it. Output: a placement tool that ranks AP layouts for operation (deployable, cost-bounded), for experiment (maximally count-informative capture), or for the constrained both-worlds sweet spot. Run it across 56 ResPlan floors of different topology, with realistic persona-driven crowds, and compute the counting-vs-coverage Pareto per floor.
The novelty wedge (be precise). Placement-for-sensing is not virgin territory;
wang2025_2c42 ↗
(IEEE IoT-J 2025) scores hand-designed layouts with a geometric surrogate (SSNR→RSQ)
fit to static seated targets, and never optimises against exhaustive search because
it has no generative crowd. The defensible contribution is the evaluation model: we
score a layout by the count-estimation informativeness I(C;Φ) of CSI our twin actually
ray-traces, marginalised over crowds the walking simulator actually generates —
dynamic flows through doors and corridors, not seated grids. This is wang2025's Open
Question 6 verbatim ("can RSQ extend from static-seated to dynamic/flowing crowds, and
does the metric predict counting error for moving individuals?"), answered generatively.
RSQ is the geometric baseline we beat — or honestly fail to beat, an outcome worth stating
up front. Nobody couples pedestrian-dynamics → ray-traced CSI → placement optimisation
in one loop over real multi-floor geometry with a dual operational/experimental deliverable
and a computed counting-vs-coverage Pareto. That composite is the wedge.
Framing discipline. Sim-authored evidence, on the same knife-edge as every sim result in this project (campaign-rigor-audit). The tool RANKS placements; it is a hypothesis generator until one real-hardware floor confirms the ranking. Stage 2 coverage is first-order LOS; Stage 3+ coverage is ray-traced but clean-tensor (Sionna PHY has no impairment classes — the impaired path is a bolt-on, ip110-sionna-rt-upgrade). No measured detection-rate claim anywhere.
Why now — ~80% built, never wired into a placement loop
| Piece | Asset | Gives us |
|---|---|---|
| Crowd generator | walk-notebook + IP-107 agenda/FSM engine |
persona OD flows door↔room↔corridor on real geometry |
| CSI generator | sionna-csi-runner (IP-110 Sionna-RT) |
ray-traced CSI and coverage/signal maps for arbitrary emitter placement |
| Coverage optimiser | coverage_submodular.py |
greedy set-cover, 1−1/e bound, counting-vs-coverage Pareto |
| Placement kernel | placement_oracle.py (this campaign) |
measured I(C;Φ) + surrogate + 3-variant constrained selection |
| Floor substrate | 110 ResPlan floors in PostGIS | walls, doors, occupiable, candidate grids |
| Visual surface | monad_knowledge_qgis, /map/ atlas, walk trajectory.html |
render + replay the 5 decision layers |
IP-110's unlock makes it cheap enough to attempt: Sionna-RT emits coverage/signal maps as
native output, so the propagation-honest coverage layer comes for free per candidate set,
replacing the LOS proxy coverage_submodular flags in its own docstring.
The formal object
Candidate site set V (a grid over occupiable space), placement S ⊆ V, |S| ≤ k. The
walking simulator induces P(X) over crowd states X (positions + count C), driven by
persona OD flows. Two objectives, one honest tension:
- Coverage (breadth)
F_cov(S)= footfall-weighted fraction of the floor with ≥1 propagation-covered link fromS. Weighted set-cover → monotone submodular → greedy gets 1−1/e (Pillar 4b, spectral-count-and-submodular-coverage). - Counting (depth)
F_cnt(S)=I(C ; Φ(H_S)), the mutual information between crowd count and the CSI feature at the chosen links, expectation overP(X), estimated by running the twin. Information is NOT submodular — a second link at a busy hub can be more-than-additively useful or redundant depending on multipath. So greedy is a heuristic here, checked against exhaustivek-subsets where feasible.
The clean guarantee lives on coverage; on counting the interesting science is where the two disagree — covering the corridors people walk (breadth) is a different placement from concentrating links on the busy hub for count SNR (depth). Three deliverables from one front: operational (front knee under deployment constraints + comms co-objective), experimental (count-informativeness maximiser under research constraints), both-worlds (the deployable-yet-scientific intersection).
What the supervisor does — five stages, multi-agentic
- Substrate & candidate grid — stage each floor's
floor_geometry.json(envelope + wall WKT) from PostGIS; build the candidate gridV(auto-grid over occupiable, mountable flag = within reach of a wall). Topology-stratify the 56 floors by room count / area. - Persona crowds (
sim-runnerfan-out, cheap ~6 s/floor) —walk-notebookkind: agendaswith the five personas, seeds {0,1,2}. Honour walkable QC; drop hard-fails as geometry findings. Producestrajectory.parquet(→ footfall + per-frame count) + replayabletrajectory.html. - Cheap Pareto, corpus-wide (
coverage_submodular, pure numpy) — coverage LOS proxy, counting-depth proxy, submodularity audit, greedy vs optimal, Pareto + corner Jaccard across all 56 floors. The go/no-go economics live here: if counting-optimal never tracks the flow, or the gap is nil everywhere, the expensive stages are not worth firing. - Propagation-real kernel, SPARSE (
sionna-csi-runner, expensive, verify floors only —test-lab-synth-floor-0,resplan-1374-floor-0,resplan-12439-floor-0) — ray-traced coverage/signal maps replace the LOS proxy; per-candidate CSI feeds theplacement_oraclemeasuredI(C;Φ)with bootstrap CIs. The diary's cheap gate: does the kernel separate good from bad links at all? - Surrogate + verify — fit RSQ-style geometric surrogate + learned correction to the sampled
I(C;Φ); report held-out rank fidelity; run greedy/Pareto over the full-grid surrogate; then re-run the top-k layouts with a full coupled ray-trace to confirm the ranking. Never trust the surrogate unverified. - Deliverables + replay — the three placements per floor →
placement_result.parquet; the five-panel figure per floor; the cross-floor operational-vs-experimental Jaccard; a/map/3-D replay of a chosen layout with agents walking through it (analysis-writersynthesis under the sim-storytelling-contract).
Personas (the realistic movement the counting objective needs)
Seven floor-agnostic archetypes — a cafeteria/library story over a busy period — each an IP-107
agenda that enters near a floor edge, does something, and leaves (after: leave), so the count
ramps/spikes/drains. Configs:
exp_csi_crowd/config/oracle-agendas.yaml— CANONICAL coupled crowd (walk → CSI + BLE), with aseated → network_traffichook so seated devices advertise/burst (emitters.parquet).exp_csi_crowd/config/oracle-agendas-placement.yaml— the placement variant, hooks OFF (clean reference-Tx → candidate-Rx links; BLE still from the same CFR) — see the fork note under Execution.walk_notebook/config/personas-placement-oracle.yaml— walk-only mirror for replay/inspection.
| Persona | Behaviour | Traffic |
|---|---|---|
| long_stay_worker | enter → claim desk → long focused session → leave | seated ⇒ BLE + WiFi |
| study_group (cohesive) | arrive together → adjacent seats at one table → study → leave together | seated ⇒ traffic |
| cafeteria_patron | queue → order area → sit + eat → leave | seated ⇒ traffic |
| browser | shelf → shelf → brief skim-seat → leave | light/intermittent |
| through_busy | cross floor edge-to-edge, never seats | radio-quiet |
| through_quiet | orthogonal passer-by stream | radio-quiet |
| quick_visitor | pop in to one area → straight back out | none |
The "with or without traffic" distinction falls out of behaviour, not a flag: only seated
personas fire the network_traffic hook. The count MUST vary for I(C;Φ) to exist — a
static full-occupancy cast pins the count (H(C)=0) and collapses the estimand to a silent-null
zero; hence every persona has ingress + egress and staggered arrivals. Per-floor door-precise
agendas (spawn_door + kind: room/door legs) are a crowd-choreographer refinement for the
verify floors; the region/seat library is the corpus-wide default.
Figure render request
placement_oracle five-panel per floor: (1) candidate grid (mountable vs mid-room), (2) persona
footfall surface, (3) coverage layer (LOS or Sionna signal map), (4) per-candidate I(C;Φ) heat,
(5) chosen APs for operational/experimental/both. Cross-floor: the corner-Jaccard distribution and
the blindspot/off-objective-sacrifice-vs-topology scatter.
Out of scope
- Hardware detection rate — the field defeater is IP-106 / the IP-112 AX210-Pi5 anchor. This campaign licenses which floor to instrument, not the operational claim.
- The flagship FIIT floor —
fiit-library-floor-0is not sim-ready (fiit-library-floor-not-sim-ready); ResPlan +test-lab-synthonly until the QGIS reconcile. - Full 56×full-grid ray-trace — combinatorial and deliberately never run; the surrogate+verify design is the tractability contract.
Expected interpretation
- Counting-optimal tracks the doors/corridors, coverage-optimal spreads to the geometric centre → the dynamic-flow answer to wang2025's static-seated result; the corner Jaccard is materially < 1 and the gap widens with corridor-heavy topology. Feeds the System-Design placement chain.
- The gap is nil / counting-optimal == coverage-optimal everywhere → a clarifying negative: placement is an area/anchor-budget problem, not a counting-geometry one; simplifies the story and kills the expensive stages cheap.
- A floor fails walkable QC → geometry-import finding for that ResPlan floor; report and drop.
- Surrogate held-out rho is poor → the loop is "expensive RSQ"; fall back to the measured sparse set and report the amortisation as not-yet-solved.
Risks / honest limits
- Sim-authored evidence — hypothesis generator until one real-hardware floor confirms the ranking. Frame every claim that way (campaign-rigor-audit, synthetic-csi-sim-to-real-transfer).
- Non-submodular counting — greedy guarantee is coverage-only; counting axis checked against
exhaustion on small
k. - Compute — ray-tracing is the cost; surrogate+verify is the tractability plan. Poor surrogate ⇒ degrade to expensive-RSQ, reported honestly.
- Fidelity gap — Sionna PHY has no impairment classes; placement optimised on clean tensors may not match impaired hardware. The anchored floor tests exactly this.
- Geometry readiness — ResPlan floors usable now; FIIT blocked.
Execution
Execution log — C4/C5 dense grid + rich personas, run fully locally (2026-07-13, M1 Max)
Run as direct sim run executions (not campaign sessions), driven by helper modules under
monad_knowledge/notebooks/python/: oracle_grid_register.py (dense candidate grid → PostGIS
experiment csi-oracle-grid-<floor>), oracle_grid_reduce2.py (multi-seed reduce → I(C;Φ) +
Pareto + surrogate), oracle_grid_materialize.py (chosen APs → PostGIS), oracle_grid_gallery2.py.
- Stage 0-2 (earlier): cheap coverage↔count Pareto corpus-wide — divergence 0.718, CI [0.680,0.754], n=57; counting-opt ≠ coverage-opt on 57/57. GO.
- C4/C5 dense grid, 6 floors (12439 [16 cand, 3 seeds] · 1374 · 16157 · 2605 · 12853 · 1046):
count ranges 1–10 … 1–22; per-candidate
I(C;Φ)spreads 0.11–0.60 nats; coverage-greedy = 1.00 ≥ 1−1/e on all; operational vs experimental placements disjoint (Jaccard 0.00–0.50). - #3 multi-seed: 12439 at 3 seeds → per-candidate MI ranking only moderately stable (Spearman ρ = 0.41); average over seeds before trusting a rank.
- #4 Pareto: swept k∈{2..5} × λ∈{0..1}; front + knee computed per floor.
- #2b cross-floor surrogate: leave-one-floor-out ridge, 61 candidates/6 floors → mean ρ = 0.24, wildly variable (−0.52 … +0.72). Geometry does NOT predict ray-traced MI across floors — the physics sim is load-bearing (the "expensive RSQ" risk, confirmed). #2a Sionna signal-map coverage DEFERRED (exp-csi-crowd emits no radio map; LOS proxy kept pending a runner change).
- #5 materialised:
placement-<floor>-{operational,experimental,both}PostGIS experiments (18 experiments, 57 APs) →/map/+ QGIS render via existing device layers.
Runs synced to experiments/runs/; figures + rec.json + Pareto tables + cross-floor surrogate
under _attachments/placement-oracle/agendas/; results narrated in the seed diary. Gallery:
_attachments/placement-oracle/agendas_gallery.html.
Execution log — public-building day showcase, real institutional floors + real-crowd anchor (2026-07-14, M1 Max)
Extends the campaign off ResPlan onto real S3DIS institutional geometry with a multi-hour
crowd and a real-crowd footfall anchor, and adds the furniture-as-scatterer counterfactual.
Run fully locally as direct sim run executions; helper modules under
monad_knowledge/notebooks/python/public_day_*.py. Deliverable bundle + executed notebook:
_attachments/placement-oracle/public-day/ (public_day_results.ipynb).
Question (this run). On a real public floor, with a real-scale flowing crowd, does the coverage-optimal AP set equal the count-optimal set — and does the room's furniture move the answer? Two rooms of different shape (an office corridor, a public lobby) test whether any separation is a property of the objective or an artefact of geometry.
Hypotheses (falsifiable). H1 coverage-optimal ≠ count-optimal (Jaccard < 1, rank ρ low). Furniture reorders the count-informative ranking / count-optimal set.
How to read it. Per candidate AP we compute coverage (footfall-weighted LOS, submodular greedy)
and count-informativeness I(C;Φ) = MI between the instantaneous room count and the ray-traced CSI
feature (mean sub-carrier amplitude), over the coupled exp-csi-crowd frames; empty vs furnished
scenes differ only in whether the room's furniture is injected as box scatterers.
Runs.
- Real-crowd anchor — ATC shopping-mall (18,145 persons, 10.9 h) reconstructed occupancy +
footfall; a naive 15-AP coverage grid leaves 46% of actual footfall in blind spots (the
real-world motivation;
_attachments/.../public-day/atc/). - Flagship day (area_5 office corridor) — full-day agenda crowd walk
01KXGKATQC7ZGQYM7ESXG9HHKN(242 agents, peak 89 on floor, replay + occupancy/footfall/speed plots). CSI kernel (60 ray-traced frames × 16 candidates, LOS-confined to the corridor): empty01KXGMGTENDZZD5QZH6NQSSEN2, furnished01KXGMWJ9XKC0NT4XY92KCZ1T8. - Room 2 (area_4 public lobby) — busy-period lobby crowd
01KXGNDQHH7DA88W5QN7H8KJ2H(46 agents, in-lobby count 3→29, median walk 1.20 m/s). CSI kernel (15 candidates over the open lobby): empty01KXGNFD4SFWS2TE565AESXWYK, furnished01KXGNJK42QB7G34D0CNEESSQ4.
Result.
| Room | count range | H1 Jaccard (cov∩cnt) | H1 rank ρ | furniture MI ρ | count-opt moved by furniture |
|---|---|---|---|---|---|
| area_5 corridor | 1–28 | 0.00 (disjoint) | −0.23 | 0.62 | {1,5,15}→{2,9,15} ✓ |
| area_4 lobby | 3–46 | 0.50 (partial) | 0.04 | 0.48 | {1,9,14}→{1,8,14} ✓ |
- H1 supported in both rooms. Coverage-optimal is never count-optimal: fully disjoint in the corridor (Jaccard 0.00), only half-overlapping in the lobby (0.50). In both, the per-AP coverage rank is essentially uncorrelated with count-informativeness (ρ ≈ 0), so a coverage site survey does not rank APs for counting.
- The gap is geometry-dependent. Separation is stronger in the long corridor (coverage wants even spacing; counting wants the high-flux ends) than in the small open lobby (where most candidates see most of the room, so the two objectives partly coincide) — a physically sensible, honest nuance.
- Furniture is not neutral. Injecting furniture as scatterers reorders the count-informative ranking (empty↔furnished MI ρ 0.48–0.62) and moves the count-optimal set in both rooms — a placement chosen on an empty CAD shell is not the placement you would choose furnished.
Meaning. This operationalises wang2025_2c42 ↗'s Open Question 6 for dynamic/flowing crowds on real institutional geometry: coverage and counting are distinct placement objectives, the divergence widens with corridor-like topology, and the furnished geometry — not the room shell — sets count sensitivity. Simulator evidence: a hypothesis generator, not deployment guidance — the channel is ray-traced and the impairment model uncalibrated; every claim is a falsifiable prediction awaiting the real AX210/Pi5 anchor (IP-106 / IP-112). One crowd seed per room for the headline; MI on a single amplitude feature.
Not yet done
- Real-hardware anchor (the licensing gate): one AX210/Pi5 floor (IP-106 / IP-112) to confirm the sim ranking.
- #2a propagation coverage from a Sionna signal-map (needs a
sionna-csi-runnerchange). - Full 56-floor measured grid (deliberately gated on the surrogate, which under-performs).