pub mod bloch;
pub mod diagram;
mod fabric;
mod validation;
use burn_quantum::{Circuit, Error, Result};
pub use fabric::*;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct ComplexValue {
pub re: f64,
pub im: f64,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct SubsystemState {
pub wire: usize,
pub dimension: usize,
pub probabilities: Vec<f64>,
pub density: Vec<ComplexValue>,
pub bloch: Option<[f64; 3]>,
pub purity: f64,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct TimelineFrame {
pub step: usize,
pub label: String,
pub probabilities: Vec<f64>,
pub amplitudes: Option<Vec<ComplexValue>>,
pub subsystems: Vec<SubsystemState>,
pub norm: f64,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ExperimentTrace {
pub kind: TraceKind,
pub frames: Vec<TimelineFrame>,
pub backend: String,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub enum TraceKind {
Circuit,
Optimization,
Protocol,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct OptimizationPoint {
pub iteration: usize,
pub parameters: Vec<f64>,
pub loss: f64,
pub metric: Vec<f64>,
pub bloch: Vec<Option<[f64; 3]>>,
pub probabilities: Vec<f64>,
pub loss_evaluations: usize,
pub fidelity_evaluations: usize,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ProtocolRecord {
pub program: burn_quantum::protocol::Protocol,
pub outcomes: Vec<usize>,
pub probabilities: Vec<f64>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct VisualizationDocument {
pub schema_version: u32,
pub title: String,
pub description: String,
pub circuit: Circuit,
pub parameters: Vec<f64>,
pub inputs: Vec<f64>,
pub operation_labels: Vec<String>,
pub trace: ExperimentTrace,
pub fabric: Option<FabricSnapshot>,
pub optimization: Vec<OptimizationPoint>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub protocol: Option<ProtocolRecord>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct ProbabilityBin {
pub start: usize,
pub end: usize,
pub probability: f64,
}
pub fn aggregate_probabilities(values: &[f64], max_bins: usize) -> Result<Vec<ProbabilityBin>> {
if max_bins == 0
|| values.is_empty()
|| values.iter().any(|v| !v.is_finite() || *v < 0.)
|| !values.iter().sum::<f64>().is_finite()
{
return Err(Error::InvalidValue(
"invalid probability aggregation".into(),
));
}
let width = values.len().div_ceil(max_bins);
Ok(values
.chunks(width)
.enumerate()
.map(|(i, chunk)| ProbabilityBin {
start: i * width,
end: i * width + chunk.len(),
probability: chunk.iter().sum(),
})
.collect())
}