Files
wifi-densepose/crates/ruqu-core/src/optimizer.rs
ruv d803bfe2b1 Squashed 'vendor/ruvector/' content from commit b64c2172
git-subtree-dir: vendor/ruvector
git-subtree-split: b64c21726f2bb37286d9ee36a7869fef60cc6900
2026-02-28 14:39:40 -05:00

95 lines
3.0 KiB
Rust

//! Gate-fusion optimiser
//!
//! Scans a circuit for runs of consecutive single-qubit gates acting on the
//! same qubit and fuses them into a single `Unitary1Q` gate by multiplying
//! their 2x2 matrices.
use crate::circuit::QuantumCircuit;
use crate::gate::Gate;
use crate::types::Complex;
/// Multiply two 2x2 complex matrices: C = A * B.
pub fn mat_mul_2x2(a: &[[Complex; 2]; 2], b: &[[Complex; 2]; 2]) -> [[Complex; 2]; 2] {
[
[
a[0][0] * b[0][0] + a[0][1] * b[1][0],
a[0][0] * b[0][1] + a[0][1] * b[1][1],
],
[
a[1][0] * b[0][0] + a[1][1] * b[1][0],
a[1][0] * b[0][1] + a[1][1] * b[1][1],
],
]
}
/// Check whether two gates can be fused.
///
/// Both must be non-measurement single-qubit unitaries acting on the same qubit.
pub fn can_fuse(a: &Gate, b: &Gate) -> bool {
if a.is_non_unitary() || b.is_non_unitary() {
return false;
}
match (a.matrix_1q(), b.matrix_1q()) {
(Some(_), Some(_)) => {
let qa = a.qubits();
let qb = b.qubits();
qa.len() == 1 && qb.len() == 1 && qa[0] == qb[0]
}
_ => false,
}
}
/// Optimise a circuit by greedily fusing consecutive single-qubit gates
/// that act on the same qubit.
///
/// Returns a new, potentially shorter circuit.
pub fn fuse_gates(circuit: &QuantumCircuit) -> QuantumCircuit {
let mut result = QuantumCircuit::new(circuit.num_qubits());
let gates = circuit.gates();
let len = gates.len();
let mut i = 0;
while i < len {
// Attempt to start a fusion run if the current gate is a fusable 1Q gate.
if !gates[i].is_non_unitary() {
if let Some(first_matrix) = gates[i].matrix_1q() {
let q = gates[i].qubits()[0];
let mut fused = first_matrix;
let mut count = 1usize;
// Greedily absorb subsequent fusable 1Q gates on the same qubit.
while i + count < len {
let next = &gates[i + count];
if next.is_non_unitary() {
break;
}
if let Some(next_m) = next.matrix_1q() {
let nq = next.qubits();
if nq.len() == 1 && nq[0] == q {
// next_m is applied *after* fused, so C = next_m * fused.
fused = mat_mul_2x2(&next_m, &fused);
count += 1;
continue;
}
}
break;
}
if count > 1 {
result.add_gate(Gate::Unitary1Q(q, fused));
} else {
result.add_gate(gates[i].clone());
}
i += count;
continue;
}
}
// Non-fusable gate: pass through unchanged.
result.add_gate(gates[i].clone());
i += 1;
}
result
}