simquantum-tuning-lab / INTEGRATION.md
100enigma's picture
SimQuantum — AMD Developer Hackathon
da98415
|
Raw
History Blame Contribute Delete
15.5 kB

A newer version of the Streamlit SDK is available: 1.58.0

Upgrade

Phase 0/1/2 Integration Guide

This document explains how the three phases of the agentic quantum dot tuning system integrate together.


Architecture Overview

┌─────────────────────────────────────────────────────────────────────┐
│                      EXECUTIVE AGENT (Phase 2)                       │
│                    Main orchestration loop (Fig. 2)                  │
└─────────────────────────────────────────────────────────────────────┘
                                    │
                  ┌─────────────────┼─────────────────┐
                  │                 │                 │
                  ▼                 ▼                 ▼
         ┌────────────────┐  ┌────────────┐  ┌─────────────┐
         │  PERCEPTION    │  │  PLANNING  │  │  HARDWARE   │
         │   (Phase 1)    │  │ (Phase 2)  │  │  (Phase 0)  │
         └────────────────┘  └────────────┘  └─────────────┘
         │                   │              │
         │ - DQCGatekeeper   │ - BeliefUpdater      │ - DeviceAdapter
         │ - InspectionAgent │ - ActiveSensingPolicy│ - SafetyCritic
         │ - EnsembleCNN     │ - MultiResBO         │ - HITLManager
         │ - OOD Detector    │ - StateMachine       │ - GovernanceLogger
         │                   │ - TranslationAgent   │
         └───────────────────┴──────────────────────┴─────────────┘
                                    │
                                    ▼
                         ┌─────────────────────┐
                         │  EXPERIMENT STATE   │
                         │     (Phase 0)       │
                         │  Single source of   │
                         │       truth         │
                         └─────────────────────┘

Data Flow: One Complete Loop

1. Active Sensing (Phase 2 Planning)

ActiveSensingPolicy.select() examines ExperimentState.belief and proposes a measurement:

plan = sensing_policy.select(state.belief, v1_range, v2_range)
# → MeasurementPlan(modality=COARSE_2D, v1_range=(-0.5, 0.5), ...)

2. Translation (Phase 2 Agent)

TranslationAgent.execute() converts the plan to a DeviceAdapter call:

result = translator.execute(plan)
measurement = result.measurement  # Measurement from CIMSimulatorAdapter
state.add_measurement(measurement)

3. Data Quality Check (Phase 1 Perception)

DQCGatekeeper.assess() runs physics-based quality checks:

dqc_result = dqc.assess(measurement)
state.add_dqc_result(dqc_result)

if dqc_result.quality == DQCQuality.LOW:
    # STOP — do not pass to InspectionAgent
    return failure_result

4. Classification (Phase 1 Perception)

InspectionAgent.inspect() runs the full perception pipeline:

if measurement.is_2d:
    classification, ood_result = inspector.inspect(measurement, dqc_result)
    state.add_classification(classification)
    state.add_ood_result(ood_result)

InspectionAgent internally:

  • Log-preprocesses the array
  • Runs EnsembleCNN (5-model ensemble)
  • Extracts physics features (FFT peak ratio, diagonal strength)
  • Checks for physics override
  • Runs OOD detector on penultimate features
  • Generates structured NL summary

5. Belief Update (Phase 2 Planning)

BeliefUpdater updates the POMDP belief using CIM observation model:

belief_updater.update_from_2d(measurement, classification)
# Updates state.belief.charge_probs in-place

For line scans (bypass InspectionAgent per blueprint §5.1):

if measurement.modality == MeasurementModality.LINE_SCAN:
    belief_updater.update_from_1d(measurement)

6. Bayesian Optimization (Phase 2 Planning)

MultiResBO.propose() uses GP with CIM-informed priors:

bo.update(state.bo_history)
proposal = bo.propose(current=state.current_voltage, l1_max=0.10)
# → ActionProposal(delta_v=VoltagePoint(vg1=0.05, vg2=0.02), ...)

7. Safety Critic (Phase 0 Hardware)

SafetyCritic enforces hard constraints:

proposal = safety_critic.clip(proposal, state.current_voltage)
verdict = safety_critic.verify(state.current_voltage, proposal)

if not verdict.all_passed:
    state.record_safety_violation()
    return failure_result

8. Risk Assessment + HITL (Phase 0 Governance)

HITLManager.compute_risk_score() aggregates 12 trigger conditions:

risk = hitl_manager.compute_risk_score(
    proposal=proposal,
    safety_verdict=verdict,
    dqc_flag=dqc_result.quality.value,
    ood_score=ood_result.score,
    ensemble_disagreement=classification.ensemble_disagreement,
    consecutive_backtracks=state.consecutive_backtracks,
    step=state.step + 1,
)

if risk >= 0.70:
    event = hitl_manager.queue_request(...)
    event = hitl_manager.await_decision(event)  # BLOCKS
    state.add_hitl_event(event)

9. Execute Move (Phase 2 Agent + Phase 0 Hardware)

If all checks pass:

translator.execute_voltage_move(
    vg1=state.current_voltage.vg1 + safe_dv.vg1,
    vg2=state.current_voltage.vg2 + safe_dv.vg2,
)
state.apply_move(safe_dv)

10. Governance (Phase 0)

GovernanceLogger records every action:

decision = Decision(
    run_id=state.run_id,
    step=state.step,
    intent="voltage_move",
    stage=state.stage,
    observation_summary={...},
    action_summary={...},
    rationale="...",
)
state.add_decision(decision)
governance_logger.log(decision)

11. State Machine (Phase 2 Planning)

StateMachine.process_result() manages stage transitions:

result = navigation_result(target_reached=True, belief_confidence=0.85)
new_stage, rationale, hitl_triggered = state_machine.process_result(result)

if new_stage != state.stage:
    state.advance_stage(new_stage)

Backtracking on failure:

if retries_exhausted:
    event = BacktrackEvent(from_stage=NAVIGATION, to_stage=CHARGE_ID, ...)
    state.record_backtrack(event)

Key Integration Points

BeliefState (Phase 0 stub → Phase 2 implementation)

Phase 0 defined the interface:

@dataclass
class BeliefState:
    charge_probs: Dict[tuple, float] = field(default_factory=dict)
    uncertainty_map: Optional[Any] = None
    device_params: Dict[str, float] = field(default_factory=lambda: {...})
    
    def entropy(self) -> float: ...
    def most_likely_state(self) -> Optional[tuple]: ...
    def initialise_uniform(self, charge_states: Optional[List[tuple]] = None) -> None: ...

Phase 2 implemented the particle filter:

class BeliefUpdater:
    def __init__(self, belief: BeliefState, ...):
        self.belief = belief  # Operates on Phase 0 stub directly
        self._particles = _ParticleSet(...)  # Internal engine
    
    def update_from_2d(self, measurement, classification):
        # Updates self.belief.charge_probs in-place
        self.belief.charge_probs = self._particles.to_charge_probs()

Classification Flow (Phase 1 → Phase 2)

InspectionAgent output:

classification = Classification(
    measurement_id=...,
    label=ChargeLabel.DOUBLE_DOT,
    confidence=0.85,
    ensemble_disagreement=0.12,
    features={...},
    physics_override=False,
    nl_summary="...",
)

Used by multiple Phase 2 components:

  • BeliefUpdater: Uses label and confidence to boost particle weights; physics_override=True → inflates uncertainty
  • MultiResBO: Creates BOPoints from classifications; confidence becomes the reward signal
  • StateMachine: Uses confidence to determine if stage success threshold is met
  • HITLManager: Uses ensemble_disagreement in risk score computation

Safety Integration (Phase 0 → Phase 2)

ExecutiveAgent always calls SafetyCritic before any move:

proposal = bo.propose(...)                              # Phase 2 proposes
proposal = safety_critic.clip(proposal, current)        # Phase 0 clips
verdict = safety_critic.verify(current, proposal)       # Phase 0 verifies

if verdict.all_passed:
    translator.execute_voltage_move(...)                # Phase 2 executes
    state.apply_move(proposal.safe_delta_v)             # Phase 0 records
else:
    state.record_safety_violation()

No component can bypass SafetyCritic — it's architecturally enforced.

HITL Integration (Phase 0 → Phase 2)

HITLManager is called at two points:

  1. Risk score computation (every voltage move):

    risk = hitl_manager.compute_risk_score(...)
    if risk >= 0.70:
        event = hitl_manager.queue_request(...)
        event = hitl_manager.await_decision(event)  # BLOCKS
    
  2. State machine backtracking (condition 8):

    if state.consecutive_backtracks >= 2:
        # StateMachine returns hitl_triggered=True
        # ExecutiveAgent queues HITL event
    

No timeout auto-approval — agent blocks until human decides.


Running the Integrated System

Without Trained Models (CI/Development)

# Uses InspectionAgent in stub mode (untrained ensemble, no OOD)
pytest tests/test_integration_phase012.py -v

# Run benchmark without checkpoints
python experiments/benchmark_phase2.py --fast --skip-missing-checkpoints

With Trained Models (Full System)

# 1. Train Phase 1 models
python experiments/train_phase1.py --out experiments/checkpoints/phase1

# 2. Run benchmark
python experiments/benchmark_phase2.py --n-trials 100 --budget 2048

Manual Inspection

from qdot.core.state import ExperimentState
from qdot.simulator.cim import CIMSimulatorAdapter
from qdot.agent.executive import ExecutiveAgent
from qdot.perception.inspector import InspectionAgent
from qdot.core.hitl import HITLManager, HITLOutcome

# Setup
state = ExperimentState.new(device_id="manual_test")
adapter = CIMSimulatorAdapter(device_id="manual_test", seed=42)
inspector = InspectionAgent(ensemble=None, ood_detector=None)  # Or load trained

hitl = HITLManager()
hitl.set_test_mode(auto_outcome=HITLOutcome.APPROVED)  # No blocking for demo

# Create agent
agent = ExecutiveAgent(
    state=state,
    adapter=adapter,
    inspection_agent=inspector,
    hitl_manager=hitl,
    max_steps=50,
    measurement_budget=2048,
)

# Run
summary = agent.run()
print(f"Success: {summary['success']}")
print(f"Measurements: {summary['total_measurements']}")
print(f"Reduction: {summary['measurement_reduction']:.1%}")

File Organization

qdot/
├── core/                          # Phase 0 — Foundation
│   ├── types.py                   # All canonical types
│   ├── state.py                   # ExperimentState + BeliefState stub
│   ├── governance.py              # GovernanceLogger
│   └── hitl.py                    # HITLManager
│
├── hardware/                      # Phase 0 — Device interface
│   ├── adapter.py                 # DeviceAdapter ABC
│   └── safety.py                  # SafetyCritic
│
├── simulator/                     # Phase 0 — CIM simulator
│   └── cim.py                     # ConstantInteractionDevice + CIMSimulatorAdapter
│
├── perception/                    # Phase 1 — Perception pipeline
│   ├── dqc.py                     # DQCGatekeeper
│   ├── inspector.py               # InspectionAgent
│   ├── classifier.py              # EnsembleCNN
│   ├── features.py                # Physics validators
│   ├── ood.py                     # MahalanobisOOD
│   └── dataset.py                 # CIMDataset for training
│
├── planning/                      # Phase 2 — POMDP + BO
│   ├── belief.py                  # BeliefUpdater + CIMObservationModel
│   ├── sensing.py                 # ActiveSensingPolicy
│   ├── bayesian_opt.py            # MultiResBO + GaussianProcess
│   └── state_machine.py           # StateMachine (5 stages)
│
└── agent/                         # Phase 2 — Main loop
    ├── executive.py               # ExecutiveAgent (orchestrator)
    └── translator.py              # TranslationAgent (NL → API)

Testing Strategy

Unit Tests (per module)

  • tests/test_types.py — Phase 0 types
  • tests/test_state.py — ExperimentState, BeliefState stub
  • tests/test_safety.py — SafetyCritic + fuzz test (5000 iterations)
  • tests/test_simulator.py — CIM physics
  • tests/test_perception.py — DQC, CNN, OOD, InspectionAgent
  • tests/test_planning.py — Belief, sensing, BO, state machine
  • tests/test_agent.py — TranslationAgent, ExecutiveAgent

Integration Tests

  • tests/test_integration_phase012.py — Full pipeline smoke tests

Benchmarks

  • experiments/train_phase1.py --fast — Phase 1 smoke test (CI)
  • experiments/benchmark_phase2.py --fast — Phase 2 quick eval (10 trials)
  • experiments/benchmark_phase2.py --n-trials 100 — Full benchmark

Next Steps (Phase 3)

  1. LLM Integration (IBM Granite 3-8B-Instruct)

    • Replace template rationales with LLM calls
    • ONE call per stage transition + ONE per HITL trigger
    • Budget: ~200 tokens per call
  2. Disorder Learning

    • OOD flag → fit device-specific disorder map
    • Inject into CIMObservationModel.device
    • Close sim-to-real gap
  3. Meta-Learning

    • Learn CIM parameter priors from device family
    • Fast adaptation to new devices
  4. Hardware Validation

    • Integrate real Si/SiGe adapter
    • Run on QFlow hardware testbed
    • Validate ≥50% reduction on real devices

Troubleshooting

"No tests collected" in test_agent.py

Cause: File didn't exist or pytest can't find it.
Fix: Ensure tests/test_agent.py is in the repo root tests/ directory.

"ModuleNotFoundError: No module named 'qdot.planning'"

Cause: Phase 2 modules not in Python path.
Fix: Run pip install -e . from repo root to install in editable mode.

InspectionAgent predictions are random

Cause: Running without trained checkpoints (ensemble=None).
Fix: Either (a) train models with experiments/train_phase1.py, or (b) use --skip-missing-checkpoints flag for testing without models.

HITL blocks forever

Cause: HITLManager not in test mode.
Fix: Call hitl_manager.set_test_mode(auto_outcome=HITLOutcome.APPROVED) for non-blocking testing.

SafetyCritic rejects all moves

Cause: Voltage bounds or l1_max cap too tight.
Fix: Check state.voltage_bounds and state.step_caps["l1_max"] are reasonable for your device.


Phase 0/1/2 integration complete. All components tested individually and end-to-end. Ready for Phase 3.