use crate::{
components::{
pauli_string::SumOp,
state::State,
},
errors::Error,
};
use num_complex::Complex;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TrotterOrder {
First,
Second,
}
pub fn first_order_trotter_step(
hamiltonian: &SumOp,
initial_state: &State,
dt: f64,
) -> Result<State, Error> {
if hamiltonian.num_terms() == 0 {
return Err(Error::InvalidNumberOfQubits(0));
}
let factor = Complex::new(0.0, -dt);
let mut current_state = initial_state.clone();
for term in &hamiltonian.terms {
current_state = term.apply_exp_factor(¤t_state, factor)?;
}
Ok(current_state)
}
pub fn second_order_trotter_step(
hamiltonian: &SumOp,
initial_state: &State,
dt: f64,
) -> Result<State, Error> {
if hamiltonian.num_terms() == 0 {
return Err(Error::InvalidNumberOfQubits(0));
}
let half_factor = Complex::new(0.0, -dt / 2.0);
let mut current_state = initial_state.clone();
for term in &hamiltonian.terms {
current_state = term.apply_exp_factor(¤t_state, half_factor)?;
}
for term in hamiltonian.terms.iter().rev() {
current_state = term.apply_exp_factor(¤t_state, half_factor)?;
}
Ok(current_state)
}
pub fn trotter_evolve_state(
hamiltonian: &SumOp,
initial_state: &State,
dt: f64,
num_steps: usize,
order: TrotterOrder,
) -> Result<State, Error> {
if hamiltonian.num_terms() == 0 {
return Err(Error::InvalidNumberOfQubits(0));
}
let mut current_state = initial_state.clone();
for _ in 0..num_steps {
current_state = match order {
TrotterOrder::First => {
first_order_trotter_step(hamiltonian, ¤t_state, dt)?
},
TrotterOrder::Second => {
second_order_trotter_step(hamiltonian, ¤t_state, dt)?
},
};
}
Ok(current_state)
}