use super::*;
use crate::calibration::create_ideal_calibration as create_ideal_calibration_fn;
use scirs2_core::random::prelude::*;
pub fn create_standard_topology(
topology_type: &str,
num_qubits: usize,
) -> DeviceResult<HardwareTopology> {
match topology_type {
"linear" => Ok(create_linear_topology(num_qubits)),
"grid" => Ok(create_grid_topology(num_qubits)),
"star" => Ok(create_star_topology(num_qubits)),
"complete" => Ok(create_complete_topology(num_qubits)),
_ => Err(DeviceError::InvalidTopology(format!(
"Unknown topology: {}",
topology_type
))),
}
}
fn create_linear_topology(num_qubits: usize) -> HardwareTopology {
HardwareTopology::linear_topology(num_qubits)
}
fn create_grid_topology(num_qubits: usize) -> HardwareTopology {
let side_length = (num_qubits as f64).sqrt().ceil() as usize;
let rows = side_length;
let cols = num_qubits.div_ceil(side_length);
HardwareTopology::grid_topology(rows, cols)
}
fn create_star_topology(num_qubits: usize) -> HardwareTopology {
use crate::topology::{GateProperties, QubitProperties};
let mut topology = HardwareTopology::new(num_qubits);
for i in 0..num_qubits {
topology.add_qubit(QubitProperties {
id: i as u32,
index: i as u32,
t1: 50.0,
t2: 70.0,
single_qubit_gate_error: 0.001,
gate_error_1q: 0.001,
readout_error: 0.01,
frequency: 5.0 + 0.1 * i as f64,
});
}
for i in 1..num_qubits {
topology.add_connection(
0,
i as u32,
GateProperties {
error_rate: 0.01,
duration: 200.0,
gate_type: "CZ".to_string(),
},
);
}
topology
}
fn create_complete_topology(num_qubits: usize) -> HardwareTopology {
use crate::topology::{GateProperties, QubitProperties};
let mut topology = HardwareTopology::new(num_qubits);
for i in 0..num_qubits {
topology.add_qubit(QubitProperties {
id: i as u32,
index: i as u32,
t1: 50.0,
t2: 70.0,
single_qubit_gate_error: 0.001,
gate_error_1q: 0.001,
readout_error: 0.01,
frequency: 5.0 + 0.1 * i as f64,
});
}
for i in 0..num_qubits {
for j in i + 1..num_qubits {
topology.add_connection(
i as u32,
j as u32,
GateProperties {
error_rate: 0.01,
duration: 200.0,
gate_type: "CZ".to_string(),
},
);
}
}
topology
}
pub fn create_ideal_calibration(device_name: String, num_qubits: usize) -> DeviceCalibration {
create_ideal_calibration_fn(device_name, num_qubits)
}
pub fn validate_mapping(
mapping: &HashMap<usize, usize>,
num_logical_qubits: usize,
num_physical_qubits: usize,
) -> DeviceResult<()> {
for i in 0..num_logical_qubits {
if !mapping.contains_key(&i) {
return Err(DeviceError::InvalidMapping(format!(
"Logical qubit {} not mapped",
i
)));
}
}
for &physical in mapping.values() {
if physical >= num_physical_qubits {
return Err(DeviceError::InvalidMapping(format!(
"Physical qubit {} exceeds device capacity",
physical
)));
}
}
let mut used_physical = HashSet::new();
for &physical in mapping.values() {
if !used_physical.insert(physical) {
return Err(DeviceError::InvalidMapping(format!(
"Physical qubit {} mapped multiple times",
physical
)));
}
}
Ok(())
}
pub fn calculate_mapping_quality(
mapping: &HashMap<usize, usize>,
logical_graph: &Graph<usize, f64>,
topology: &HardwareTopology,
) -> DeviceResult<f64> {
let mut total_distance = 0.0;
let mut edge_count = 0;
for edge in logical_graph.edges() {
let source = edge.source;
let target = edge.target;
if let (Some(&phys_source), Some(&phys_target)) =
(mapping.get(&source), mapping.get(&target))
{
let distance = topology
.shortest_path_distance(phys_source, phys_target)
.unwrap_or(f64::INFINITY);
total_distance += distance;
edge_count += 1;
}
}
if edge_count > 0 {
Ok(1.0 / (1.0 + total_distance / edge_count as f64))
} else {
Ok(1.0)
}
}
pub fn generate_random_circuit<const N: usize>(
gate_count: usize,
two_qubit_ratio: f64,
) -> Circuit<N> {
let mut circuit = Circuit::<N>::new();
let mut rng = thread_rng();
for _ in 0..gate_count {
if rng.random::<f64>() < two_qubit_ratio {
let q1 = rng.random_range(0..N);
let mut q2 = rng.random_range(0..N);
while q2 == q1 {
q2 = rng.random_range(0..N);
}
let _ = circuit.cnot(QubitId(q1 as u32), QubitId(q2 as u32));
} else {
let q = rng.random_range(0..N);
let _ = circuit.x(QubitId(q as u32));
}
}
circuit
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_linear_topology_creation() {
let topology = create_linear_topology(4);
assert_eq!(topology.num_qubits(), 4);
assert!(topology.are_connected(0, 1));
assert!(topology.are_connected(1, 2));
assert!(topology.are_connected(2, 3));
assert!(!topology.are_connected(0, 3));
}
#[test]
fn test_grid_topology_creation() {
let topology = create_grid_topology(4);
assert_eq!(topology.num_qubits(), 4);
assert!(topology.are_connected(0, 1));
assert!(topology.are_connected(0, 2));
}
#[test]
fn test_star_topology_creation() {
let topology = create_star_topology(5);
assert_eq!(topology.num_qubits(), 5);
for i in 1..5 {
assert!(topology.are_connected(0, i));
}
assert!(!topology.are_connected(1, 2));
}
#[test]
fn test_mapping_validation() {
let mut mapping = HashMap::new();
mapping.insert(0, 0);
mapping.insert(1, 1);
mapping.insert(2, 2);
assert!(validate_mapping(&mapping, 3, 4).is_ok());
mapping.insert(3, 2); assert!(validate_mapping(&mapping, 4, 4).is_err());
}
#[test]
fn test_mapping_quality_calculation() {
let topology = create_linear_topology(4);
let mut graph = Graph::new();
let _nodes: Vec<_> = (0..4).map(|i| graph.add_node(i)).collect();
let _ = graph.add_edge(0, 3, 1.0);
let mut mapping = HashMap::new();
mapping.insert(0, 0);
mapping.insert(1, 1);
mapping.insert(2, 2);
mapping.insert(3, 3);
let quality = calculate_mapping_quality(&mapping, &graph, &topology)
.expect("should calculate mapping quality");
assert!(quality > 0.0 && quality <= 1.0);
}
#[test]
fn test_random_circuit_generation() {
let circuit = generate_random_circuit::<4>(10, 0.5);
assert!(circuit.gates().len() <= 10);
}
#[test]
fn test_standard_topology_creation() {
assert!(create_standard_topology("linear", 4).is_ok());
assert!(create_standard_topology("grid", 4).is_ok());
assert!(create_standard_topology("star", 4).is_ok());
assert!(create_standard_topology("complete", 4).is_ok());
assert!(create_standard_topology("invalid", 4).is_err());
}
#[test]
fn test_complete_topology() {
let topology = create_complete_topology(4);
assert_eq!(topology.num_qubits(), 4);
for i in 0..4 {
for j in i + 1..4 {
assert!(topology.are_connected(i, j));
}
}
}
#[test]
fn test_ideal_calibration_creation() {
let _calibration = create_ideal_calibration("test_device".to_string(), 4);
}
#[test]
fn test_mapping_validation_edge_cases() {
let mapping = HashMap::new();
assert!(validate_mapping(&mapping, 0, 4).is_ok());
let mut mapping = HashMap::new();
mapping.insert(0, 10);
assert!(validate_mapping(&mapping, 1, 4).is_err());
let mut mapping = HashMap::new();
mapping.insert(0, 0);
assert!(validate_mapping(&mapping, 2, 4).is_err());
}
}