use crate::circuit::error::ParameterError;
use crate::circuit::symbolic_matrix::gate::circuit_to_symbolic_matrix;
use crate::circuit::symbolic_matrix::matrix::SymbolicMatrix;
use crate::circuit::{Circuit, CircuitError};
pub fn symbolic_matrices_equivalent(
lhs: &SymbolicMatrix,
rhs: &SymbolicMatrix,
) -> Result<bool, ParameterError> {
if lhs.shape() != rhs.shape() {
return Ok(false);
}
let mut pivot = None;
for ((row, col), lhs_value) in lhs.indexed_iter() {
let rhs_value = &rhs[[row, col]];
let lhs_zero = lhs_value.simplifies_to_zero()?;
let rhs_zero = rhs_value.simplifies_to_zero()?;
if lhs_zero != rhs_zero {
return Ok(false);
}
if !lhs_zero && pivot.is_none() {
pivot = Some((row, col));
}
}
let Some((pivot_row, pivot_col)) = pivot else {
return Ok(true);
};
let lhs_pivot = &lhs[[pivot_row, pivot_col]];
let rhs_pivot = &rhs[[pivot_row, pivot_col]];
for ((row, col), lhs_value) in lhs.indexed_iter() {
let rhs_value = &rhs[[row, col]];
if lhs_value.simplifies_to_zero()? && rhs_value.simplifies_to_zero()? {
continue;
}
let residual = lhs_value * rhs_pivot - rhs_value * lhs_pivot;
if !residual.simplifies_to_zero()? {
return Ok(false);
}
}
Ok(true)
}
pub fn circuits_equivalent(
lhs: &Circuit,
rhs: &Circuit,
qubits_order: Option<&[usize]>,
) -> Result<bool, CircuitError> {
let lhs_matrix = circuit_to_symbolic_matrix(lhs, qubits_order)?;
let rhs_matrix = circuit_to_symbolic_matrix(rhs, qubits_order)?;
symbolic_matrices_equivalent(&lhs_matrix, &rhs_matrix)
.map_err(|err| CircuitError::InvalidOperation(err.to_string()))
}
#[cfg(test)]
#[path = "./equivalence_test.rs"]
mod equivalence_test;