use std::collections::HashMap;
use super::Device;
use super::GenericDevice;
use crate::RoqoqoError;
use ndarray::Array2;
#[derive(Clone, Debug, PartialEq, Default)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct AllToAllDevice {
number_qubits: usize,
generic_device: GenericDevice,
}
impl AllToAllDevice {
pub fn new(
number_qubits: usize,
single_qubit_gates: &[String],
two_qubit_gates: &[String],
default_gate_time: f64,
) -> Self {
let generic = GenericDevice {
number_qubits,
single_qubit_gates: HashMap::with_capacity(single_qubit_gates.len()),
two_qubit_gates: HashMap::with_capacity(two_qubit_gates.len()),
multi_qubit_gates: HashMap::new(),
decoherence_rates: HashMap::with_capacity(number_qubits),
};
let mut new = Self {
number_qubits,
generic_device: generic,
};
for gate_name in single_qubit_gates {
new = new.set_all_single_qubit_gate_times(gate_name, default_gate_time);
}
for gate_name in two_qubit_gates {
new = new.set_all_two_qubit_gate_times(gate_name, default_gate_time);
}
new = new
.set_all_qubit_decoherence_rates(Array2::zeros((3, 3)))
.expect("Internal bug in roqoqo devices.");
new
}
pub fn set_all_single_qubit_gate_times(mut self, gate: &str, gate_time: f64) -> Self {
if let Some(gate_times) = self.generic_device.single_qubit_gates.get_mut(gate) {
for gatetime in gate_times.values_mut() {
*gatetime = gate_time
}
} else {
let mut gatetimes: HashMap<usize, f64> = HashMap::with_capacity(self.number_qubits);
for qubit in 0..self.number_qubits {
gatetimes.insert(qubit, gate_time);
}
self.generic_device
.single_qubit_gates
.insert(gate.to_string(), gatetimes);
}
self
}
pub fn set_all_two_qubit_gate_times(mut self, gate: &str, gate_time: f64) -> Self {
if let Some(gate_times) = self.generic_device.two_qubit_gates.get_mut(gate) {
for gatetime in gate_times.values_mut() {
*gatetime = gate_time
}
} else {
let mut gatetimes: HashMap<(usize, usize), f64> =
HashMap::with_capacity(self.number_qubits.pow(2));
for control in 0..self.number_qubits {
for target in 0..self.number_qubits {
if control != target {
gatetimes.insert((control, target), gate_time);
}
}
}
self.generic_device
.two_qubit_gates
.insert(gate.to_string(), gatetimes);
}
self
}
pub fn set_single_qubit_gate_time(
&mut self,
gate: &str,
qubit: usize,
gate_time: f64,
) -> Result<(), RoqoqoError> {
self.generic_device
.set_single_qubit_gate_time(gate, qubit, gate_time)
}
pub fn set_two_qubit_gate_time(
&mut self,
gate: &str,
control: usize,
target: usize,
gate_time: f64,
) -> Result<(), RoqoqoError> {
self.generic_device
.set_two_qubit_gate_time(gate, control, target, gate_time)
}
pub fn set_three_qubit_gate_time(
&mut self,
gate: &str,
control_0: usize,
control_1: usize,
target: usize,
gate_time: f64,
) -> Result<(), RoqoqoError> {
self.generic_device
.set_three_qubit_gate_time(gate, control_0, control_1, target, gate_time)
}
pub fn set_multi_qubit_gate_time(
&mut self,
gate: &str,
qubits: Vec<usize>,
gate_time: f64,
) -> Result<(), RoqoqoError> {
self.generic_device
.set_multi_qubit_gate_time(gate, qubits, gate_time)
}
pub fn set_qubit_decoherence_rates(
&mut self,
qubit: usize,
rates: Array2<f64>,
) -> Result<(), RoqoqoError> {
self.generic_device
.set_qubit_decoherence_rates(qubit, rates)
}
pub fn set_all_qubit_decoherence_rates(
mut self,
rates: Array2<f64>,
) -> Result<Self, RoqoqoError> {
let shape = rates.shape();
if shape == [3, 3] {
for qubit in 0..self.number_qubits() {
self.generic_device
.set_qubit_decoherence_rates(qubit, rates.clone())?;
}
Ok(self)
} else {
Err(RoqoqoError::GenericError {
msg: "The input parameter `rates` needs to be a (3x3)-matrix.".to_string(),
})
}
}
pub fn add_damping(&mut self, qubit: usize, damping: f64) -> Result<(), RoqoqoError> {
self.generic_device.add_damping(qubit, damping)
}
pub fn add_dephasing(&mut self, qubit: usize, dephasing: f64) -> Result<(), RoqoqoError> {
self.generic_device.add_dephasing(qubit, dephasing)
}
pub fn add_depolarising(&mut self, qubit: usize, depolarising: f64) -> Result<(), RoqoqoError> {
self.generic_device.add_depolarising(qubit, depolarising)
}
pub fn add_damping_all(mut self, damping: f64) -> Self {
for qubit in 0..self.number_qubits {
self.generic_device
.add_damping(qubit, damping)
.expect("Checked insertion fails");
}
self
}
pub fn add_dephasing_all(mut self, dephasing: f64) -> Self {
for qubit in 0..self.number_qubits {
self.generic_device
.add_dephasing(qubit, dephasing)
.expect("Checked insertion fails");
}
self
}
pub fn add_depolarising_all(mut self, depolarising: f64) -> Self {
for qubit in 0..self.number_qubits {
self.generic_device
.add_depolarising(qubit, depolarising)
.expect("Checked insertion fails");
}
self
}
}
impl Device for AllToAllDevice {
fn number_qubits(&self) -> usize {
self.generic_device.number_qubits
}
fn single_qubit_gate_time(&self, hqslang: &str, qubit: &usize) -> Option<f64> {
self.generic_device.single_qubit_gate_time(hqslang, qubit)
}
fn two_qubit_gate_time(&self, hqslang: &str, control: &usize, target: &usize) -> Option<f64> {
self.generic_device
.two_qubit_gate_time(hqslang, control, target)
}
fn three_qubit_gate_time(
&self,
hqslang: &str,
control_0: &usize,
control_1: &usize,
target: &usize,
) -> Option<f64> {
self.generic_device
.three_qubit_gate_time(hqslang, control_0, control_1, target)
}
fn multi_qubit_gate_time(&self, hqslang: &str, qubits: &[usize]) -> Option<f64> {
self.generic_device.multi_qubit_gate_time(hqslang, qubits)
}
fn qubit_decoherence_rates(&self, qubit: &usize) -> Option<Array2<f64>> {
self.generic_device.qubit_decoherence_rates(qubit)
}
fn to_generic_device(&self) -> GenericDevice {
self.generic_device.clone()
}
fn two_qubit_edges(&self) -> Vec<(usize, usize)> {
let mut vector: Vec<(usize, usize)> = Vec::new();
for row in 0..self.number_qubits() {
for column in row + 1..self.number_qubits() {
vector.push((row, column));
}
}
vector
}
fn single_qubit_gate_names(&self) -> Vec<String> {
self.generic_device
.single_qubit_gates
.keys()
.cloned()
.collect()
}
fn two_qubit_gate_names(&self) -> Vec<String> {
self.generic_device
.two_qubit_gates
.keys()
.cloned()
.collect()
}
fn multi_qubit_gate_names(&self) -> Vec<String> {
self.generic_device
.multi_qubit_gates
.keys()
.cloned()
.collect()
}
}
impl crate::operations::SupportedVersion for AllToAllDevice {}