Some checks failed
wai-audit collector and player integration / does this change touch it (push) Successful in 1m23s
WAI operation catalogue / does this change touch it (push) Successful in 1m5s
wai-quantum other formats / does this change touch it (push) Successful in 21s
wai-quantum-landscape-fpga reference design / does this change touch it (push) Successful in 26s
wai-quantum editors / does this change touch it (push) Successful in 28s
wai-quantum resource estimation / does this change touch it (push) Successful in 28s
wai-quantum error correction and mitigation / does this change touch it (push) Successful in 12s
wai-quantum extension points / does this change touch it (push) Successful in 25s
wai-quantum qudit jobs / does this change touch it (push) Successful in 34s
wai-quantum service / does this change touch it (push) Successful in 19s
wai-quantum studio and desktop / does this change touch it (push) Successful in 20s
wai-quantum service / service energy · linux packages (push) Failing after 12s
wai-quantum variational and algorithm library / does this change touch it (push) Successful in 18s
wai-quantum verdicts and repairs / does this change touch it (push) Successful in 29s
wai-quantum views in agent hosts / does this change touch it (push) Successful in 28s
wai-quantum on Windows / does this change touch it (push) Successful in 26s
wai-sink-android native sink library / does this change touch it (push) Successful in 35s
wai-sink-swift native sink package / does this change touch it (push) Successful in 32s
wai-quantum clippy / does this change touch it (push) Successful in 3m3s
wai-quantum OpenQASM reader / does this change touch it (push) Successful in 2m30s
wai-quantum docs, course and locales / does this change touch it (push) Successful in 2m48s
wai-quantum contract / does this change touch it (push) Successful in 2m53s
wai-quantum for JavaScript / does this change touch it (push) Successful in 2m40s
wai-quantum pulse and dynamics / does this change touch it (push) Successful in 2m31s
wai-quantum for Python / does this change touch it (push) Successful in 2m30s
wai-quantum command line / does this change touch it (push) Successful in 3m32s
WAI Studio / does this change touch it (push) Successful in 30s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 13s
WAI examples / WAI examples · does this change touch them (push) Successful in 14s
wai-quantum landscape energy to solution / does this change touch it (push) Successful in 13s
wai-quantum landscape stage 0, the sampler against the exact law / does this change touch it (push) Successful in 12s
wai-quantum energy-landscape jobs / does this change touch it (push) Successful in 11s
wai-quantum wasmQ / does this change touch it (push) Successful in 10s
wai-audit collector and player integration / collector · linux (push) Successful in 3m57s
wai-quantum other formats / the set under wasm32-wasip2 (wasmtime) (push) Successful in 3m13s
wai-quantum other formats / readers, writers and the set · linux (push) Successful in 7m22s
wai-quantum editors / editors · linux (push) Successful in 5m34s
wai-quantum qudit jobs / the module and the conformance set under wasm32-wasip2 (wasmtime) (push) Successful in 2m16s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 15m22s
wai-quantum extension points / the registry under wasm32-wasip2 (wasmtime) (push) Successful in 4m40s
wai-quantum error correction and mitigation / codes, decoders, texts and mitigation · linux, release (push) Successful in 9m5s
wai-quantum extension points / the registry and the example · linux (push) Successful in 9m0s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux, release (push) Successful in 2m59s
wai-quantum studio and desktop / studio · browser (push) Successful in 5m24s
wai-quantum qudit jobs / the module, the job, the conformance set, the referee and the verb · linux (push) Successful in 10m39s
wai-quantum verdicts and repairs / verdicts, repairs and the intent set · linux (push) Successful in 4m23s
wai-quantum verdicts and repairs / the intent set and the verdict under wasm32-wasip2 (wasmtime) (push) Successful in 3m37s
wai-quantum resource estimation / estimation and calibration · linux, release (push) Successful in 14m26s
wai-quantum views in agent hosts / views · the page and its engine (push) Successful in 6m21s
wai-quantum views in agent hosts / views · a scripted host (push) Successful in 6m36s
wai-quantum service / service · linux (push) Successful in 17m0s
wai-quantum studio and desktop / desktop app · linux (push) Successful in 16m40s
wai-quantum OpenQASM reader / corpus under wasm32-wasip2 (wasmtime) (push) Successful in 1m51s
wai-quantum contract / the policy is linked, and the deprecations page reads (push) Successful in 13s
wai-quantum OpenQASM reader / reader and corpus · linux (push) Successful in 5m37s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (push) Successful in 27s
wai-quantum clippy / clippy, warnings denied, every feature set · linux (push) Successful in 7m31s
wai-quantum pulse and dynamics / reader, simulator and pulse jobs under wasm32-wasip2 (wasmtime) (push) Successful in 2m0s
wai-quantum pulse and dynamics / reader, simulator and pulse jobs · linux, release (push) Successful in 4m19s
wai-quantum docs, course and locales / the course and the command line's languages · linux (push) Successful in 7m14s
wai-quantum contract / API compatibility · linux (push) Successful in 11m45s
WAI Studio / the catalogue's actions, the unit tests and the core · linux (push) Successful in 1m16s
wai-quantum-landscape-fpga reference design / the member against the model of the logic, and the logic against the model · linux, release (push) Successful in 43m41s
wai-quantum for JavaScript / javascript · linux (push) Successful in 11m32s
wai-quantum contract / schemas and the committed tool lists · linux (push) Successful in 17m19s
wai-quantum for Python / python · linux (push) Successful in 11m47s
WAI Studio / Studio in WebKit · linux (push) Successful in 25m18s
wai-quantum command line / command line · linux (push) Successful in 40m56s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (push) Failing after 51m56s
wai-quantum-landscape-fpga reference design / the board's code on the board's processor's architecture · linux-arm64, release (push) Successful in 1m43s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Successful in 8m45s
wai-audit collector and player integration / collector, player integration and the browser end to end · macos (push) Successful in 2m43s
wai-quantum editors / editors · macos (push) Successful in 2m46s
wai-quantum qudit jobs / the same bits · macos (push) Successful in 2m42s
wai-quantum extension points / the registry and the example · linux-arm64 (push) Successful in 6m44s
wai-quantum pulse and dynamics / the same bits · linux-arm64 (push) Successful in 4m3s
wai-quantum variational and algorithm library / parameters, gradients, optimisers, VQE, QAOA and builders · linux-arm64, release (push) Successful in 6m0s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 8m4s
wai-quantum studio and desktop / desktop app · macos (push) Successful in 5m30s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Successful in 7m17s
wai-quantum service / service · macos (push) Successful in 12m57s
wai-quantum landscape stage 0, the sampler against the exact law / the small tier, to the byte · linux (push) Successful in 1m6s
wai-quantum landscape energy to solution / the small tier, to the byte · linux (push) Successful in 3m6s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 4m9s
wai-quantum pulse and dynamics / the same bits · macos (push) Successful in 1m24s
wai-quantum wasmQ / the reference modules rebuild to their modules of record · linux (push) Successful in 36s
wai-quantum for Python / python · macos (push) Successful in 3m12s
wai-quantum command line / command line · macos (push) Successful in 2m41s
wai-quantum wasmQ / interpreter and vectors under wasm32-wasip2 (wasmtime) (push) Successful in 5m31s
wai-quantum wasmQ / profile, engines, reference modules, adversarial, vectors · linux (push) Successful in 7m1s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 12m56s
wai-quantum energy-landscape jobs / native against WebAssembly, over many seeds (push) Successful in 11m33s
WAI Studio / Studio in Chromium and Firefox · macos (push) Successful in 9m3s
wai-quantum energy-landscape jobs / reader, kernels, answers and the stated result · linux, release (push) Successful in 15m48s
wai-quantum energy-landscape jobs / the module under wasm32-wasip2 (wasmtime) (push) Successful in 19m24s
WAI examples / WAI examples · portable · linux (push) Successful in 25m12s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Failing after 37m26s
WAI examples / WAI examples · android-app · linux-arm64 (push) Successful in 16m3s
wai-quantum landscape stage 0, the sampler against the exact law / the small tier, to the byte · macos (push) Successful in 37s
wai-quantum energy-landscape jobs / the same bits · linux-arm64 (push) Successful in 17m52s
wai-quantum landscape energy to solution / the small tier, to the byte · macos (push) Successful in 3m14s
wai-quantum wasmQ / profile, engines, reference modules, adversarial, vectors · macos (push) Successful in 2m41s
wai-quantum energy-landscape jobs / the same bits · macos (push) Successful in 7m13s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (push) Successful in 21m17s
wai-quantum on Windows / engine · windows (push) Has been cancelled
wai-quantum on Windows / command line · windows (push) Has been cancelled
wai-quantum on Windows / job service · windows (push) Has been cancelled
wai-quantum on Windows / python · windows (push) Has been cancelled
wai-quantum studio and desktop / desktop app · windows (push) Has been cancelled
- tracker_ole mpo: the circuit's operator as a matrix-product state on row and column sites, grown outward from the perturbation's centre, the echo read as <<W|(O x O)|W>>. Held to the exact echo on small circuits at two junctions, and to sparse Pauli dynamics on sub-echoes of the 49-qubit circuit. On the full circuits its truncation drops the operator's whole departure from the identity (discarded weight about 0.53, 24 delta^2 = 0.54) and the value reads 1 at chi up to 64, on all three instances. - The operator chain now keeps each qubit's row and column in one slot and moves slots, not sites, to bring a two-qubit gate's qubits together, so no Bell pair is stretched across the chain; tracker_peaked scan grows a window around each of 39 junctions to find where a circuit's halves undo each other (none does in the 49-qubit peaked circuit at chi 16). - Receipts for every sweep run so far: sparse Pauli dynamics on the three echoes, the purified network on 49 qubits to chi 64 (and re-gauged), 49x1296 to chi 32, the operator echo on all three, and the peaked circuits 49x4020 and 49x5072 by state network and operator. The test re-runs the operator echo's cheapest receipt bit for bit. Co-Authored-By: Claude Opus 5.5 <[email protected]>
266 lines
11 KiB
Rust
266 lines
11 KiB
Rust
//! A circuit as an operator, grown from its middle outward: the method the
|
||
//! peaked circuits are read by (`tracker_peaked`, `mpo`).
|
||
|
||
#![allow(dead_code)]
|
||
|
||
use wai_quantum::gates::{C, Gate};
|
||
use wai_quantum::quantum_mpsim::{Chain, MpsConfig};
|
||
use wai_quantum::quantum_spd::{Op, Pauli, RotCircuit, sin_cos};
|
||
|
||
/// A gate's matrix on the qubits it names (the first the most significant bit).
|
||
pub fn matrix(op: &Op) -> (Vec<u32>, Vec<C>) {
|
||
let c = |re: f64, im: f64| C { re, im };
|
||
let pauli = |p: Pauli| -> [C; 4] {
|
||
match p {
|
||
Pauli::X => [c(0.0, 0.0), c(1.0, 0.0), c(1.0, 0.0), c(0.0, 0.0)],
|
||
Pauli::Y => [c(0.0, 0.0), c(0.0, -1.0), c(0.0, 1.0), c(0.0, 0.0)],
|
||
Pauli::Z => [c(1.0, 0.0), c(0.0, 0.0), c(0.0, 0.0), c(-1.0, 0.0)],
|
||
}
|
||
};
|
||
let kron = |a: &[C], b: &[C], da: usize, db: usize| -> Vec<C> {
|
||
let d = da * db;
|
||
let mut out = vec![c(0.0, 0.0); d * d];
|
||
for i in 0..d {
|
||
for j in 0..d {
|
||
let (x, y) = (a[(i / db) * da + j / db], b[(i % db) * db + j % db]);
|
||
out[i * d + j] = c(x.re * y.re - x.im * y.im, x.re * y.im + x.im * y.re);
|
||
}
|
||
}
|
||
out
|
||
};
|
||
// exp(−iθP/2) = cos(θ/2)·I − i·sin(θ/2)·P, for the string P on `qs`.
|
||
let rotation = |axis: &[(u32, Pauli)], cos: f64, sin: f64| -> (Vec<u32>, Vec<C>) {
|
||
let qs: Vec<u32> = axis.iter().map(|(q, _)| *q).collect();
|
||
let mut p = pauli(axis[0].1).to_vec();
|
||
let mut d = 2;
|
||
for &(_, f) in &axis[1..] {
|
||
p = kron(&p, &pauli(f), d, 2);
|
||
d *= 2;
|
||
}
|
||
let d = 1usize << qs.len();
|
||
let m = (0..d * d).map(|k| {
|
||
let id = if k / d == k % d { cos } else { 0.0 };
|
||
// −i·sin·P: (re, im) of P times (0, −sin).
|
||
c(id + sin * p[k].im, -sin * p[k].re)
|
||
});
|
||
(qs, m.collect())
|
||
};
|
||
let h = std::f64::consts::FRAC_1_SQRT_2;
|
||
match op {
|
||
Op::Rot { axis, theta } => {
|
||
let (s, co) = sin_cos(0.5 * theta);
|
||
rotation(axis, co, s)
|
||
}
|
||
Op::QuarterRot { axis, k } => {
|
||
let (co, s) = match k {
|
||
1 => (h, h),
|
||
2 => (0.0, 1.0),
|
||
_ => (-h, h),
|
||
};
|
||
rotation(axis, co, s)
|
||
}
|
||
Op::CZ(a, b) => (vec![*a, *b], (0..16).map(|k| if k % 5 == 0 { c(if k == 15 { -1.0 } else { 1.0 }, 0.0) } else { c(0.0, 0.0) }).collect()),
|
||
Op::CX(a, b) => {
|
||
let perm = [0usize, 1, 3, 2];
|
||
(vec![*a, *b], (0..16).map(|k| c(if perm[k / 4] == k % 4 { 1.0 } else { 0.0 }, 0.0)).collect())
|
||
}
|
||
Op::H(q) => (vec![*q], vec![c(h, 0.0), c(h, 0.0), c(h, 0.0), c(-h, 0.0)]),
|
||
Op::X(q) => (vec![*q], pauli(Pauli::X).to_vec()),
|
||
Op::Y(q) => (vec![*q], pauli(Pauli::Y).to_vec()),
|
||
Op::Z(q) => (vec![*q], pauli(Pauli::Z).to_vec()),
|
||
Op::S(q) => (vec![*q], vec![c(1.0, 0.0), c(0.0, 0.0), c(0.0, 0.0), c(0.0, 1.0)]),
|
||
Op::Sdg(q) => (vec![*q], vec![c(1.0, 0.0), c(0.0, 0.0), c(0.0, 0.0), c(0.0, -1.0)]),
|
||
Op::SX(q) => (vec![*q], vec![c(0.5, 0.5), c(0.5, -0.5), c(0.5, -0.5), c(0.5, 0.5)]),
|
||
Op::SXdg(q) => (vec![*q], vec![c(0.5, -0.5), c(0.5, 0.5), c(0.5, 0.5), c(0.5, -0.5)]),
|
||
Op::Swap(a, b) => (vec![*a, *b], Gate::swap(0, 1).matrix),
|
||
}
|
||
}
|
||
|
||
/// The transpose of a square row-major matrix.
|
||
pub fn transposed(m: &[C]) -> Vec<C> {
|
||
let d = (m.len() as f64).sqrt() as usize;
|
||
(0..d * d).map(|k| m[(k % d) * d + k / d]).collect()
|
||
}
|
||
|
||
/// What growing the operator from the middle gives.
|
||
pub struct Grown {
|
||
/// Each qubit's `⟨Z⟩` in the state the circuit prepares from `|0…0⟩`.
|
||
pub z: Vec<f64>,
|
||
/// The string the signs of `z` give, bit `q` qubit `q`.
|
||
pub string: Vec<u8>,
|
||
/// The string's probability.
|
||
pub probability: f64,
|
||
/// The chain's qubit order.
|
||
pub order: Vec<u32>,
|
||
pub max_bond: usize,
|
||
pub discarded: f64,
|
||
pub fidelity_estimate: f64,
|
||
}
|
||
|
||
/// The circuit as an operator, a matrix-product state on `2n` sites (each
|
||
/// qubit's row index beside its column index, the qubits in breadth-first
|
||
/// order of `edges`), started as the identity (a Bell pair a qubit) and grown
|
||
/// from the middle of the circuit outward: the gates after the midpoint on the
|
||
/// rows, in order, and each gate before it transposed on the columns, in
|
||
/// reverse, one two-qubit gate a side at a time. That is
|
||
/// `(A ⊗ Bᵀ)|Φ⟩ = (A·B ⊗ I)|Φ⟩` for the circuit `A·B`. The columns are then
|
||
/// projected on `|0⟩`, which leaves `2^{−n/2}·A·B|0…0⟩` on the rows.
|
||
pub fn grow_from_middle(circuit: &RotCircuit, edges: &[(u32, u32)], chi: usize) -> Grown {
|
||
grow_from(circuit, edges, chi, circuit.ops.len() / 2, usize::MAX).expect("the whole circuit")
|
||
}
|
||
|
||
/// A circuit's operator on a chain, as [`grow_chain`] leaves it.
|
||
pub struct Chained {
|
||
pub chain: Chain,
|
||
/// The qubit in each slot of the chain at the end, and each qubit's slot.
|
||
pub order: Vec<u32>,
|
||
pub pos: Vec<u32>,
|
||
/// Whether every gate was applied.
|
||
pub whole: bool,
|
||
}
|
||
|
||
impl Chained {
|
||
/// The site of qubit `q`'s row index, and of its column index.
|
||
pub fn row(&self, q: u32) -> u32 {
|
||
2 * self.pos[q as usize]
|
||
}
|
||
pub fn col(&self, q: u32) -> u32 {
|
||
2 * self.pos[q as usize] + 1
|
||
}
|
||
}
|
||
|
||
/// The circuit's operator `(A ⊗ Bᵀ)|Φ⟩`, `A` the gates from `mid` on and `B`
|
||
/// those before it, grown outward from `mid` by at most `window` two-qubit
|
||
/// gates a side, at bond dimension `chi`.
|
||
///
|
||
/// Each qubit's row and column sit side by side in a slot of the chain, the
|
||
/// slots first in breadth-first order of `edges`. A two-qubit gate on qubits in
|
||
/// slots apart first moves the second qubit's slot, both its sites together,
|
||
/// next to the first's, and the slots stay where they are moved: a qubit's row
|
||
/// never leaves its column, so routing stretches no pair across the chain.
|
||
pub fn grow_chain(circuit: &RotCircuit, edges: &[(u32, u32)], chi: usize, mid: usize, window: usize) -> Chained {
|
||
let n = circuit.n;
|
||
let order = super::common::bfs_chain(n, edges);
|
||
let mut pos = vec![0u32; n as usize];
|
||
for (i, &q) in order.iter().enumerate() {
|
||
pos[q as usize] = i as u32;
|
||
}
|
||
let mut at = order.clone();
|
||
let swap = Gate::swap(0, 1).matrix;
|
||
let ops = &circuit.ops;
|
||
let two = |op: &Op| matrix(op).0.len() == 2;
|
||
let mut chain = Chain::new(2 * n, MpsConfig { max_bond: chi, cutoff: 1e-14 }).expect("a chain");
|
||
for q in 0..n {
|
||
let s = 2 * pos[q as usize];
|
||
chain.apply(&Gate { qubits: vec![s], matrix: matrix(&Op::H(0)).1 }).expect("a gate");
|
||
chain.apply(&Gate { qubits: vec![s, s + 1], matrix: matrix(&Op::CX(0, 1)).1 }).expect("a gate");
|
||
}
|
||
// Exchange the pairs in slots `s` and `s + 1`: sites (r, c, r', c') become
|
||
// (r', c', r, c) by four swaps of neighbours.
|
||
let swap_slots = |chain: &mut Chain, pos: &mut [u32], at: &mut [u32], s: u32| {
|
||
let b = 2 * s;
|
||
for i in [b + 1, b, b + 2, b + 1] {
|
||
chain.apply(&Gate { qubits: vec![i, i + 1], matrix: swap.clone() }).expect("a swap");
|
||
}
|
||
let (x, y) = (at[s as usize], at[s as usize + 1]);
|
||
at.swap(s as usize, s as usize + 1);
|
||
pos[x as usize] = s + 1;
|
||
pos[y as usize] = s;
|
||
};
|
||
let apply = |chain: &mut Chain, pos: &mut [u32], at: &mut [u32], op: &Op, columns: bool| {
|
||
let (qs, m) = matrix(op);
|
||
if let [a, b] = qs[..] {
|
||
while pos[b as usize] > pos[a as usize] + 1 {
|
||
swap_slots(chain, pos, at, pos[b as usize] - 1);
|
||
}
|
||
while pos[b as usize] + 1 < pos[a as usize] {
|
||
swap_slots(chain, pos, at, pos[b as usize]);
|
||
}
|
||
}
|
||
let site = |q: u32| 2 * pos[q as usize] + u32::from(columns);
|
||
let m = if columns { transposed(&m) } else { m };
|
||
chain.apply(&Gate { qubits: qs.iter().map(|&q| site(q)).collect(), matrix: m }).expect("a gate");
|
||
};
|
||
let (mut f, mut b) = (mid, mid);
|
||
let mut sides = 0usize;
|
||
while (f < ops.len() || b > 0) && sides < window {
|
||
sides += 1;
|
||
while f < ops.len() {
|
||
apply(&mut chain, &mut pos, &mut at, &ops[f], false);
|
||
f += 1;
|
||
if two(&ops[f - 1]) {
|
||
break;
|
||
}
|
||
}
|
||
while b > 0 {
|
||
b -= 1;
|
||
apply(&mut chain, &mut pos, &mut at, &ops[b], true);
|
||
if two(&ops[b]) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
let whole = f == ops.len() && b == 0;
|
||
Chained { chain, order: at, pos, whole }
|
||
}
|
||
|
||
/// The echo `2⁻ⁿ Tr(O · W† O W)` of a circuit `W` for `O` the `Z`s on `sites`,
|
||
/// from its operator grown outward from gate `mid`: with `|W⟩⟩ = (W ⊗ I)|Φ⟩`,
|
||
/// it is `⟨⟨W|(O ⊗ O)|W⟩⟩`, since `O` is real and diagonal. For a circuit
|
||
/// written `U · V · U†`, `mid` at `V`'s centre starts the operator at `V`, a
|
||
/// product near the identity, and grows it by `V`'s dressing alone. Returns the
|
||
/// echo and the chain's report.
|
||
pub fn echo_by_operator(circuit: &RotCircuit, edges: &[(u32, u32)], chi: usize, mid: usize, sites: &[u32]) -> (f64, wai_quantum::quantum_mpsim::MpsReport) {
|
||
let g = grow_chain(circuit, edges, chi, mid, usize::MAX);
|
||
let mut z: Vec<(u32, char)> = Vec::new();
|
||
for &q in sites {
|
||
z.push((g.row(q), 'Z'));
|
||
z.push((g.col(q), 'Z'));
|
||
}
|
||
let f = g.chain.expectation(&z).expect("sites on the chain") / g.chain.norm2();
|
||
(f, g.chain.report())
|
||
}
|
||
|
||
/// The operator grown outward from gate `mid` by at most `window` two-qubit
|
||
/// gates a side: with the whole circuit, what [`grow_from_middle`] reads;
|
||
/// with less, the chain's report alone (no readout), to find where the
|
||
/// circuit's halves undo each other.
|
||
pub fn grow_from(circuit: &RotCircuit, edges: &[(u32, u32)], chi: usize, mid: usize, window: usize) -> Option<Grown> {
|
||
let n = circuit.n;
|
||
let Chained { mut chain, order, pos, whole } = grow_chain(circuit, edges, chi, mid, window);
|
||
let (row, col) = (|q: u32| 2 * pos[q as usize], |q: u32| 2 * pos[q as usize] + 1);
|
||
let report = chain.report();
|
||
if !whole {
|
||
return Some(Grown {
|
||
z: Vec::new(),
|
||
string: Vec::new(),
|
||
probability: f64::NAN,
|
||
order,
|
||
max_bond: report.max_bond_used,
|
||
discarded: report.discarded,
|
||
fidelity_estimate: report.fidelity_estimate,
|
||
});
|
||
}
|
||
let zero = C { re: 0.0, im: 0.0 };
|
||
let project = vec![C { re: 1.0, im: 0.0 }, zero, zero, zero];
|
||
for q in 0..n {
|
||
chain.apply(&Gate { qubits: vec![col(q)], matrix: project.clone() }).expect("a projection");
|
||
}
|
||
let norm = chain.norm2();
|
||
let z: Vec<f64> = (0..n).map(|q| chain.expectation(&[(row(q), 'Z')]).expect("a qubit") / norm).collect();
|
||
let string: Vec<u8> = z.iter().map(|&v| u8::from(v < 0.0)).collect();
|
||
let mut bits = vec![0u8; 2 * n as usize];
|
||
for q in 0..n {
|
||
bits[row(q) as usize] = string[q as usize];
|
||
}
|
||
let a = chain.amplitude(&bits).expect("a string");
|
||
Some(Grown {
|
||
z,
|
||
string,
|
||
probability: (a.re * a.re + a.im * a.im) / norm,
|
||
order,
|
||
max_bond: report.max_bond_used,
|
||
discarded: report.discarded,
|
||
fidelity_estimate: report.fidelity_estimate,
|
||
})
|
||
}
|