pub mod compression;
pub mod fusion;
pub mod lazy_evaluation;
pub mod peephole;
pub mod zx_optimizer;
use crate::error::QuantRS2Result;
use crate::gate::GateOp;
use crate::qubit::QubitId;
pub trait OptimizationPass {
fn optimize(&self, gates: Vec<Box<dyn GateOp>>) -> QuantRS2Result<Vec<Box<dyn GateOp>>>;
fn name(&self) -> &str;
fn is_applicable(&self, gates: &[Box<dyn GateOp>]) -> bool {
!gates.is_empty()
}
}
pub struct OptimizationChain {
passes: Vec<Box<dyn OptimizationPass>>,
}
impl OptimizationChain {
pub fn new() -> Self {
Self { passes: Vec::new() }
}
#[must_use]
pub fn add_pass(mut self, pass: Box<dyn OptimizationPass>) -> Self {
self.passes.push(pass);
self
}
pub fn optimize(
&self,
mut gates: Vec<Box<dyn GateOp>>,
) -> QuantRS2Result<Vec<Box<dyn GateOp>>> {
for pass in &self.passes {
if pass.is_applicable(&gates) {
gates = pass.optimize(gates)?;
}
}
Ok(gates)
}
}
#[derive(Debug, Clone)]
pub struct GateInfo {
pub gate: Box<dyn GateOp>,
pub index: usize,
pub qubits: Vec<QubitId>,
pub is_parameterized: bool,
}
pub fn gates_are_disjoint(gate1: &dyn GateOp, gate2: &dyn GateOp) -> bool {
let qubits1 = gate1.qubits();
let qubits2 = gate2.qubits();
for q1 in &qubits1 {
for q2 in &qubits2 {
if q1 == q2 {
return false;
}
}
}
true
}
pub fn gates_can_commute(gate1: &dyn GateOp, gate2: &dyn GateOp) -> bool {
if gates_are_disjoint(gate1, gate2) {
return true;
}
if gate1.qubits().len() == 1 && gate2.qubits().len() == 1 && gate1.qubits() == gate2.qubits() {
match (gate1.name(), gate2.name()) {
("Z" | "S" | "S†" | "T" | "T†" | "RZ", "Z" | "S" | "T")
| ("Z" | "S" | "S†" | "T" | "T†", "S†" | "T†")
| ("RZ", "RZ")
| ("X" | "RX", "X" | "RX") | ("Y" | "RY", "Y" | "RY") => true,
_ => false,
}
} else {
false
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::gate::single::{Hadamard, PauliX, PauliZ};
use crate::qubit::QubitId;
#[test]
fn test_gates_are_disjoint() {
let gate1 = Box::new(PauliX { target: QubitId(0) }) as Box<dyn GateOp>;
let gate2 = Box::new(PauliZ { target: QubitId(1) }) as Box<dyn GateOp>;
let gate3 = Box::new(Hadamard { target: QubitId(0) }) as Box<dyn GateOp>;
assert!(gates_are_disjoint(gate1.as_ref(), gate2.as_ref()));
assert!(!gates_are_disjoint(gate1.as_ref(), gate3.as_ref()));
}
#[test]
fn test_gates_can_commute() {
let z1 = Box::new(PauliZ { target: QubitId(0) }) as Box<dyn GateOp>;
let z2 = Box::new(PauliZ { target: QubitId(0) }) as Box<dyn GateOp>;
let x1 = Box::new(PauliX { target: QubitId(0) }) as Box<dyn GateOp>;
assert!(gates_can_commute(z1.as_ref(), z2.as_ref()));
assert!(!gates_can_commute(z1.as_ref(), x1.as_ref()));
}
}