diff options
| author | hachem <im@hachem.wtf> | 2025-12-10 06:27:29 +0100 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2025-12-10 06:27:29 +0100 |
| commit | 140daa490485812ef50756796435538b9f6d9428 (patch) | |
| tree | 635d792ae7d4db123d538ef30304bc65cde739b2 /tester/src | |
| parent | e77aef153c8676ff90659433ac0ca157a3c585c2 (diff) | |
[add]: add support for non-clifford gates
Diffstat (limited to 'tester/src')
| -rw-r--r-- | tester/src/benchmarks.rs | 90 | ||||
| -rw-r--r-- | tester/src/clifford.rs | 126 | ||||
| -rw-r--r-- | tester/src/common.rs | 171 | ||||
| -rw-r--r-- | tester/src/custom_gates.rs | 121 | ||||
| -rw-r--r-- | tester/src/main.rs | 524 | ||||
| -rw-r--r-- | tester/src/non_clifford.rs | 137 |
6 files changed, 701 insertions, 468 deletions
diff --git a/tester/src/benchmarks.rs b/tester/src/benchmarks.rs new file mode 100644 index 0000000..0a88502 --- /dev/null +++ b/tester/src/benchmarks.rs @@ -0,0 +1,90 @@ +use crate::common::{benchmark_circuit, print_section, BenchmarkResult}; +use libpsi_core::QuantumCircuit; +use libpsi_visualizer::HorizontalRenderer; + +pub fn run_all(results: &mut Vec<BenchmarkResult>) { + println!("═══════════════════════════════════════════════════════════════"); + println!(" BENCHMARK CIRCUITS"); + println!("═══════════════════════════════════════════════════════════════\n"); + + test_8_qubit(results); + test_10_qubit(results); + test_12_qubit(results); + test_14_qubit(results); +} + +pub fn test_8_qubit(results: &mut Vec<BenchmarkResult>) { + print_section("8-qubit Entangled Circuit"); + + let builder = || { + let mut circuit = QuantumCircuit::new(8); + for i in 0..8 { + circuit.h(i); + } + for i in 0..7 { + circuit.cnot(i, i + 1); + } + circuit + }; + + println!("{}", HorizontalRenderer::new(&builder())); + results.push(benchmark_circuit("8-qubit entangled", builder)); +} + +pub fn test_10_qubit(results: &mut Vec<BenchmarkResult>) { + print_section("10-qubit Entangled Circuit"); + + let builder = || { + let mut circuit = QuantumCircuit::new(10); + for i in 0..10 { + circuit.h(i); + } + for i in 0..9 { + circuit.cnot(i, i + 1); + } + circuit.cz(0, 9); + circuit + }; + + println!("{}", HorizontalRenderer::new(&builder())); + results.push(benchmark_circuit("10-qubit entangled", builder)); +} + +pub fn test_12_qubit(results: &mut Vec<BenchmarkResult>) { + print_section("12-qubit Entangled Circuit"); + + let builder = || { + let mut circuit = QuantumCircuit::new(12); + for i in 0..12 { + circuit.h(i); + } + for i in 0..11 { + circuit.cnot(i, i + 1); + } + circuit.cz(0, 11); + circuit.swap(5, 6); + circuit + }; + + println!("{}", HorizontalRenderer::new(&builder())); + results.push(benchmark_circuit("12-qubit entangled", builder)); +} + +pub fn test_14_qubit(results: &mut Vec<BenchmarkResult>) { + print_section("14-qubit Entangled Circuit"); + + let builder = || { + let mut circuit = QuantumCircuit::new(14); + for i in 0..14 { + circuit.h(i); + } + for i in 0..13 { + circuit.cnot(i, i + 1); + } + circuit + }; + + println!("{}", HorizontalRenderer::new(&builder())); + results.push(benchmark_circuit("14-qubit entangled", builder)); +} + diff --git a/tester/src/clifford.rs b/tester/src/clifford.rs new file mode 100644 index 0000000..5c0b453 --- /dev/null +++ b/tester/src/clifford.rs @@ -0,0 +1,126 @@ +use crate::common::{benchmark_circuit, print_circuit, print_section, BenchmarkResult}; +use libpsi_core::QuantumCircuit; + +pub fn run_all(results: &mut Vec<BenchmarkResult>) { + println!("═══════════════════════════════════════════════════════════════"); + println!(" CLIFFORD GATES TESTS"); + println!("═══════════════════════════════════════════════════════════════\n"); + + test_bell_state(results); + test_ghz_state(results); + test_swap_via_cnots(results); + test_toffoli(results); + test_hadamard_measure(results); + test_complex_circuit(results); +} + +pub fn test_bell_state(results: &mut Vec<BenchmarkResult>) { + print_section("Bell State with Measurement"); + + let builder = || { + let mut circuit = QuantumCircuit::with_classical(2, 2); + circuit.h(0).cnot(0, 1).measure(0, 0).measure(1, 1); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("Bell State (2 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_ghz_state(results: &mut Vec<BenchmarkResult>) { + print_section("GHZ State"); + + let builder = || { + let mut circuit = QuantumCircuit::new(3); + circuit.h(0).cnot(0, 1).cnot(0, 2); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("GHZ State (3 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_swap_via_cnots(results: &mut Vec<BenchmarkResult>) { + print_section("SWAP via 3 CNOTs"); + + let builder = || { + let mut circuit = QuantumCircuit::new(2); + circuit.x(0).cnot(0, 1).cnot(1, 0).cnot(0, 1); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("SWAP via CNOTs (2 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_toffoli(results: &mut Vec<BenchmarkResult>) { + print_section("Toffoli Gate"); + + let builder = || { + let mut circuit = QuantumCircuit::new(3); + circuit.x(0).x(1).toffoli(0, 1, 2); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("Toffoli (3 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_hadamard_measure(results: &mut Vec<BenchmarkResult>) { + print_section("Full Circuit with Measurements"); + + let builder = || { + let mut circuit = QuantumCircuit::with_classical(3, 3); + circuit.h(0).h(1).h(2).measure_all(); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("3-qubit Hadamard + Measure", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_complex_circuit(results: &mut Vec<BenchmarkResult>) { + print_section("Complex Circuit"); + + let builder = || { + let mut circuit = QuantumCircuit::with_classical(4, 2); + circuit + .h(0) + .h(1) + .cnot(0, 2) + .cnot(1, 3) + .cz(2, 3) + .swap(0, 1) + .measure(0, 0) + .measure(1, 1); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("Complex (4 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + diff --git a/tester/src/common.rs b/tester/src/common.rs new file mode 100644 index 0000000..90eabd8 --- /dev/null +++ b/tester/src/common.rs @@ -0,0 +1,171 @@ +use libpsi_core::{QuantumCircuit, QuantumState, Runtime, Vector}; +use libpsi_visualizer::{HorizontalRenderer, VerticalRenderer}; +use std::time::{Duration, Instant}; + +pub struct BenchmarkResult { + pub name: String, + pub basic_time: Duration, + pub mt_time: Duration, + pub results_match: bool, +} + +pub fn benchmark_circuit<F>(name: &str, circuit_builder: F) -> BenchmarkResult +where + F: Fn() -> QuantumCircuit, +{ + let mut circuit_st = circuit_builder(); + let mut circuit_mt = circuit_builder(); + + let start_st = Instant::now(); + circuit_st.compute_with(Runtime::BasicRT); + let basic_time = start_st.elapsed(); + + let start_mt = Instant::now(); + circuit_mt.compute_with(Runtime::BasicRTMT); + let mt_time = start_mt.elapsed(); + + let state_st = circuit_st.state(); + let state_mt = circuit_mt.state(); + + let results_match = states_equal(state_st, state_mt); + + BenchmarkResult { + name: name.to_string(), + basic_time, + mt_time, + results_match, + } +} + +pub fn states_equal(a: &QuantumState, b: &QuantumState) -> bool { + if a.size() != b.size() { + return false; + } + for i in 0..a.size() { + let amp_a = a.get(i); + let amp_b = b.get(i); + let diff_real = (amp_a.real - amp_b.real).abs(); + let diff_imag = (amp_a.imaginary - amp_b.imaginary).abs(); + if diff_real > 1e-10 || diff_imag > 1e-10 { + return false; + } + } + true +} + +pub fn format_duration(d: Duration) -> String { + if d.as_secs() > 0 { + format!("{:.3}s", d.as_secs_f64()) + } else if d.as_millis() > 0 { + format!("{:.3}ms", d.as_secs_f64() * 1000.0) + } else { + format!("{:.3}us", d.as_secs_f64() * 1_000_000.0) + } +} + +pub fn print_section(title: &str) { + let width = 61; + let padding = width - title.len() - 2; + println!("┌{}┐", "─".repeat(width)); + println!("│ {}{} │", title, " ".repeat(padding)); + println!("└{}┘\n", "─".repeat(width)); +} + +pub fn print_circuit(circuit: &QuantumCircuit) { + println!("Horizontal:\n{}", HorizontalRenderer::new(circuit)); + println!("Vertical:\n{}", VerticalRenderer::new(circuit)); +} + +pub fn print_benchmark_table(results: &[BenchmarkResult]) { + const C1: usize = 30; + const C2: usize = 12; + const C3: usize = 12; + const C4: usize = 10; + const C5: usize = 5; + + let top = format!( + "╔{}═{}═{}═{}═{}╗", + "═".repeat(C1 + 2), + "═".repeat(C2 + 2), + "═".repeat(C3 + 2), + "═".repeat(C4 + 2), + "═".repeat(C5 + 2) + ); + let title = format!( + "╠{}╤{}╤{}╤{}╤{}╣", + "═".repeat(C1 + 2), + "═".repeat(C2 + 2), + "═".repeat(C3 + 2), + "═".repeat(C4 + 2), + "═".repeat(C5 + 2) + ); + let header = format!( + "╠{}╪{}╪{}╪{}╪{}╣", + "═".repeat(C1 + 2), + "═".repeat(C2 + 2), + "═".repeat(C3 + 2), + "═".repeat(C4 + 2), + "═".repeat(C5 + 2) + ); + let bottom = format!( + "╚{}╧{}╧{}╧{}╧{}╝", + "═".repeat(C1 + 2), + "═".repeat(C2 + 2), + "═".repeat(C3 + 2), + "═".repeat(C4 + 2), + "═".repeat(C5 + 2) + ); + + let total_width = C1 + C2 + C3 + C4 + C5 + 14; + + println!("\n{}", top); + println!( + "║{:^width$}║", + "RUNTIME BENCHMARK RESULTS", + width = total_width + ); + println!("{}", title); + println!( + "║ {:<C1$} │ {:^C2$} │ {:^C3$} │ {:^C4$} │ {:^C5$} ║", + "Circuit", "BasicRT", "BasicRTMT", "Speedup", "Match", + ); + println!("{}", header); + + for r in results { + let speedup = r.basic_time.as_secs_f64() / r.mt_time.as_secs_f64(); + let speedup_str = format!("{:.2}x", speedup); + let match_str = if r.results_match { "✓" } else { "✗" }; + + println!( + "║ {:<C1$} │ {:>C2$} │ {:>C3$} │ {:>C4$} │ {:^C5$} ║", + r.name, + format_duration(r.basic_time), + format_duration(r.mt_time), + speedup_str, + match_str, + ); + } + + println!("{}", bottom); +} + +pub fn print_summary(results: &[BenchmarkResult]) { + let all_match = results.iter().all(|r| r.results_match); + println!("\n"); + if all_match { + println!("✓ All circuits produced identical results with both runtimes!"); + } else { + println!("✗ WARNING: Some circuits produced different results!"); + } + + let total_basic: Duration = results.iter().map(|r| r.basic_time).sum(); + let total_mt: Duration = results.iter().map(|r| r.mt_time).sum(); + let overall_speedup = total_basic.as_secs_f64() / total_mt.as_secs_f64(); + + println!( + "\nTotal time - BasicRT: {} | BasicRTMT: {} | Overall speedup: {:.2}x", + format_duration(total_basic), + format_duration(total_mt), + overall_speedup + ); +} diff --git a/tester/src/custom_gates.rs b/tester/src/custom_gates.rs new file mode 100644 index 0000000..0e21614 --- /dev/null +++ b/tester/src/custom_gates.rs @@ -0,0 +1,121 @@ +use crate::common::{benchmark_circuit, print_circuit, print_section, BenchmarkResult}; +use libpsi_core::{complex, matrix, CustomGate, CustomGateBuilder, QuantumCircuit}; + +pub fn run_all(results: &mut Vec<BenchmarkResult>) { + println!("═══════════════════════════════════════════════════════════════"); + println!(" CUSTOM GATES TESTS"); + println!("═══════════════════════════════════════════════════════════════\n"); + + test_bell_gate(results); + test_swap_gate(results); + test_sqrt_x_gate(results); +} + +pub fn test_bell_gate(results: &mut Vec<BenchmarkResult>) { + print_section("Custom Gate: Bell Pair Creator"); + + let bell_gate = CustomGateBuilder::new("BELL", 2).h(0).cnot(0, 1).build(); + let gate_clone = bell_gate.clone(); + + let builder = move || { + let mut circuit = QuantumCircuit::new(4); + circuit + .apply_custom(gate_clone.clone(), &[0, 1]) + .apply_custom(gate_clone.clone(), &[2, 3]); + circuit + }; + + let display_circuit = { + let mut circuit = QuantumCircuit::new(4); + circuit + .apply_custom(bell_gate.clone(), &[0, 1]) + .apply_custom(bell_gate.clone(), &[2, 3]); + circuit + }; + print_circuit(&display_circuit); + results.push(benchmark_circuit("Custom BELL (4 qubits)", builder)); + + let mut display = { + let mut circuit = QuantumCircuit::new(4); + circuit + .apply_custom(bell_gate.clone(), &[0, 1]) + .apply_custom(bell_gate.clone(), &[2, 3]); + circuit + }; + display.compute(); + println!("{}\n", display); +} + +pub fn test_swap_gate(results: &mut Vec<BenchmarkResult>) { + print_section("Custom Gate: Swap via CNOTs"); + + let swap_gate = CustomGateBuilder::new("MYSWAP", 2) + .cnot(0, 1) + .cnot(1, 0) + .cnot(0, 1) + .build(); + let gate_clone = swap_gate.clone(); + + let builder = move || { + let mut circuit = QuantumCircuit::new(2); + circuit.x(0).apply_custom(gate_clone.clone(), &[0, 1]); + circuit + }; + + let display_circuit = { + let mut circuit = QuantumCircuit::new(2); + circuit.x(0).apply_custom(swap_gate.clone(), &[0, 1]); + circuit + }; + print_circuit(&display_circuit); + results.push(benchmark_circuit("Custom SWAP (2 qubits)", builder)); + + let mut display = { + let mut circuit = QuantumCircuit::new(2); + circuit.x(0).apply_custom(swap_gate.clone(), &[0, 1]); + circuit + }; + display.compute(); + println!("{}\n", display); +} + +pub fn test_sqrt_x_gate(results: &mut Vec<BenchmarkResult>) { + print_section("Custom Gate: Matrix-defined √X gate"); + + let sqrt_x_matrix = matrix!( + [complex!(0.5, 0.5), complex!(0.5, -0.5)]; + [complex!(0.5, -0.5), complex!(0.5, 0.5)] + ); + let sqrt_x = CustomGate::from_matrix("√X", sqrt_x_matrix); + let gate_clone = sqrt_x.clone(); + + let builder = move || { + let mut circuit = QuantumCircuit::new(1); + circuit + .apply_custom(gate_clone.clone(), &[0]) + .apply_custom(gate_clone.clone(), &[0]); + circuit + }; + + let display_circuit = { + let mut circuit = QuantumCircuit::new(1); + circuit + .apply_custom(sqrt_x.clone(), &[0]) + .apply_custom(sqrt_x.clone(), &[0]); + circuit + }; + print_circuit(&display_circuit); + results.push(benchmark_circuit("√X gate (1 qubit)", builder)); + + let mut display = { + let mut circuit = QuantumCircuit::new(1); + circuit + .apply_custom(sqrt_x.clone(), &[0]) + .apply_custom(sqrt_x.clone(), &[0]); + circuit + }; + display.compute(); + println!("{}", display); + println!("(Two √X gates should equal X, so |0⟩ becomes |1⟩)\n"); +} + diff --git a/tester/src/main.rs b/tester/src/main.rs index 660dc2b..ac0a61f 100644 --- a/tester/src/main.rs +++ b/tester/src/main.rs @@ -1,487 +1,75 @@ -use libpsi_core::*; -use libpsi_visualizer::*; -use std::time::{Duration, Instant}; +mod benchmarks; +mod clifford; +mod common; +mod custom_gates; +mod non_clifford; -struct BenchmarkResult { - name: String, - basic_time: Duration, - mt_time: Duration, - results_match: bool, -} - -fn benchmark_circuit<F>(name: &str, circuit_builder: F) -> BenchmarkResult -where - F: Fn() -> QuantumCircuit, -{ - let mut circuit_st = circuit_builder(); - let mut circuit_mt = circuit_builder(); - - let start_st = Instant::now(); - circuit_st.compute_with(Runtime::BasicRT); - let basic_time = start_st.elapsed(); - - let start_mt = Instant::now(); - circuit_mt.compute_with(Runtime::BasicRTMT); - let mt_time = start_mt.elapsed(); - - let state_st = circuit_st.state(); - let state_mt = circuit_mt.state(); - - let results_match = states_equal(state_st, state_mt); - - BenchmarkResult { - name: name.to_string(), - basic_time, - mt_time, - results_match, - } -} +use common::{print_benchmark_table, print_summary, BenchmarkResult}; +use std::env; -fn states_equal(a: &QuantumState, b: &QuantumState) -> bool { - use crate::maths::vector::Vector; - if a.size() != b.size() { - return false; - } - for i in 0..a.size() { - let amp_a = a.get(i); - let amp_b = b.get(i); - let diff_real = (amp_a.real - amp_b.real).abs(); - let diff_imag = (amp_a.imaginary - amp_b.imaginary).abs(); - if diff_real > 1e-10 || diff_imag > 1e-10 { - return false; - } - } - true +fn print_header() { + println!("═══════════════════════════════════════════════════════════════"); + println!(" PSI Quantum Simulator"); + println!("═══════════════════════════════════════════════════════════════\n"); } -fn format_duration(d: Duration) -> String { - if d.as_secs() > 0 { - format!("{:.3}s", d.as_secs_f64()) - } else if d.as_millis() > 0 { - format!("{:.3}ms", d.as_secs_f64() * 1000.0) - } else { - format!("{:.3}us", d.as_secs_f64() * 1_000_000.0) - } +fn print_usage() { + println!("Usage: tester [OPTIONS]"); + println!(); + println!("Options:"); + println!(" all Run all tests (default)"); + println!(" clifford Run Clifford gate tests only"); + println!(" non-clifford Run non-Clifford gate tests only"); + println!(" custom Run custom gate tests only"); + println!(" bench Run benchmark tests only"); + println!(" help Show this help message"); + println!(); + println!("Examples:"); + println!(" tester # Run all tests"); + println!(" tester clifford # Run only Clifford gate tests"); + println!(" tester non-clifford # Run only rotation/parametric gate tests"); + println!(" tester custom bench # Run custom gates and benchmarks"); } -fn print_benchmark_table(results: &[BenchmarkResult]) { - // Column widths (content only, not including borders) - const C1: usize = 30; // Circuit name - const C2: usize = 12; // BasicRT - const C3: usize = 12; // BasicRTMT - const C4: usize = 10; // Speedup - const C5: usize = 5; // Match - - let top = format!( - "╔{}═{}═{}═{}═{}╗", - "═".repeat(C1 + 2), - "═".repeat(C2 + 2), - "═".repeat(C3 + 2), - "═".repeat(C4 + 2), - "═".repeat(C5 + 2) - ); - let title = format!( - "╠{}╤{}╤{}╤{}╤{}╣", - "═".repeat(C1 + 2), - "═".repeat(C2 + 2), - "═".repeat(C3 + 2), - "═".repeat(C4 + 2), - "═".repeat(C5 + 2) - ); - let header = format!( - "╠{}╪{}╪{}╪{}╪{}╣", - "═".repeat(C1 + 2), - "═".repeat(C2 + 2), - "═".repeat(C3 + 2), - "═".repeat(C4 + 2), - "═".repeat(C5 + 2) - ); - let bottom = format!( - "╚{}╧{}╧{}╧{}╧{}╝", - "═".repeat(C1 + 2), - "═".repeat(C2 + 2), - "═".repeat(C3 + 2), - "═".repeat(C4 + 2), - "═".repeat(C5 + 2) - ); - - let total_width = C1 + C2 + C3 + C4 + C5 + 14; - - println!("\n{}", top); - println!( - "║{:^width$}║", - "RUNTIME BENCHMARK RESULTS", - width = total_width - ); - println!("{}", title); - println!( - "║ {:<C1$} │ {:^C2$} │ {:^C3$} │ {:^C4$} │ {:^C5$} ║", - "Circuit", - "BasicRT", - "BasicRTMT", - "Speedup", - "Match", - C1 = C1, - C2 = C2, - C3 = C3, - C4 = C4, - C5 = C5 - ); - println!("{}", header); - - for r in results { - let speedup = r.basic_time.as_secs_f64() / r.mt_time.as_secs_f64(); - let speedup_str = format!("{:.2}x", speedup); - let match_str = if r.results_match { "✓" } else { "✗" }; +fn main() { + let args: Vec<String> = env::args().skip(1).collect(); - println!( - "║ {:<C1$} │ {:>C2$} │ {:>C3$} │ {:>C4$} │ {:^C5$} ║", - r.name, - format_duration(r.basic_time), - format_duration(r.mt_time), - speedup_str, - match_str, - C1 = C1, - C2 = C2, - C3 = C3, - C4 = C4, - C5 = C5 - ); + if args + .iter() + .any(|a| a == "help" || a == "--help" || a == "-h") + { + print_usage(); + return; } - println!("{}", bottom); -} - -fn main() { - println!("═══════════════════════════════════════════════════════════════"); - println!(" PSI Quantum Simulator"); - println!("═══════════════════════════════════════════════════════════════\n"); + print_header(); let mut results: Vec<BenchmarkResult> = Vec::new(); - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Bell State with Measurement │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let bell_builder = || { - let mut circuit = QuantumCircuit::with_classical(2, 2); - circuit.h(0).cnot(0, 1).measure(0, 0).measure(1, 1); - circuit - }; - - let bell = bell_builder(); - println!("Horizontal:\n{}", HorizontalRenderer::new(&bell)); - println!("Vertical:\n{}", VerticalRenderer::new(&bell)); - - results.push(benchmark_circuit("Bell State (2 qubits)", bell_builder)); - let mut bell_display = bell_builder(); - bell_display.compute(); - println!("{}\n", bell_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ GHZ State │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let ghz_builder = || { - let mut circuit = QuantumCircuit::new(3); - circuit.h(0).cnot(0, 1).cnot(0, 2); - circuit - }; - - let ghz = ghz_builder(); - println!("Horizontal:\n{}", HorizontalRenderer::new(&ghz)); - println!("Vertical:\n{}", VerticalRenderer::new(&ghz)); - - results.push(benchmark_circuit("GHZ State (3 qubits)", ghz_builder)); - let mut ghz_display = ghz_builder(); - ghz_display.compute(); - println!("{}\n", ghz_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ SWAP via 3 CNOTs │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let swap_builder = || { - let mut circuit = QuantumCircuit::new(2); - circuit.x(0).cnot(0, 1).cnot(1, 0).cnot(0, 1); - circuit - }; - - let swap_circuit = swap_builder(); - println!("Horizontal:\n{}", HorizontalRenderer::new(&swap_circuit)); - println!("Vertical:\n{}", VerticalRenderer::new(&swap_circuit)); + let run_all = args.is_empty() || args.iter().any(|a| a == "all"); + let run_clifford = run_all || args.iter().any(|a| a == "clifford"); + let run_non_clifford = run_all || args.iter().any(|a| a == "non-clifford"); + let run_custom = run_all || args.iter().any(|a| a == "custom"); + let run_bench = run_all || args.iter().any(|a| a == "bench"); - results.push(benchmark_circuit("SWAP via CNOTs (2 qubits)", swap_builder)); - let mut swap_display = swap_builder(); - swap_display.compute(); - println!("{}\n", swap_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Toffoli Gate │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let toffoli_builder = || { - let mut circuit = QuantumCircuit::new(3); - circuit.x(0).x(1).toffoli(0, 1, 2); - circuit - }; - - let toffoli = toffoli_builder(); - println!("Horizontal:\n{}", HorizontalRenderer::new(&toffoli)); - println!("Vertical:\n{}", VerticalRenderer::new(&toffoli)); - - results.push(benchmark_circuit("Toffoli (3 qubits)", toffoli_builder)); - let mut toffoli_display = toffoli_builder(); - toffoli_display.compute(); - println!("{}\n", toffoli_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Full Circuit with Measurements │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let full_builder = || { - let mut circuit = QuantumCircuit::with_classical(3, 3); - circuit.h(0).h(1).h(2).measure_all(); - circuit - }; - - let full = full_builder(); - println!("Horizontal:\n{}", HorizontalRenderer::new(&full)); - println!("Vertical:\n{}", VerticalRenderer::new(&full)); - - results.push(benchmark_circuit( - "3-qubit Hadamard + Measure", - full_builder, - )); - let mut full_display = full_builder(); - full_display.compute(); - println!("{}\n", full_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Complex Circuit │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let complex_builder = || { - let mut circuit = QuantumCircuit::with_classical(4, 2); - circuit - .h(0) - .h(1) - .cnot(0, 2) - .cnot(1, 3) - .cz(2, 3) - .swap(0, 1) - .measure(0, 0) - .measure(1, 1); - circuit - }; - - let complex = complex_builder(); - println!("Horizontal:\n{}", HorizontalRenderer::new(&complex)); - println!("Vertical:\n{}", VerticalRenderer::new(&complex)); - - results.push(benchmark_circuit("Complex (4 qubits)", complex_builder)); - let mut complex_display = complex_builder(); - complex_display.compute(); - println!("{}\n", complex_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Custom Gate: Bell Pair Creator │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let bell_gate = CustomGateBuilder::new("BELL", 2).h(0).cnot(0, 1).build(); - let bell_gate_clone = bell_gate.clone(); - - let custom_bell_builder = move || { - let mut circuit = QuantumCircuit::new(4); - circuit - .apply_custom(bell_gate_clone.clone(), &[0, 1]) - .apply_custom(bell_gate_clone.clone(), &[2, 3]); - circuit - }; - - let custom_bell = { - let mut circuit = QuantumCircuit::new(4); - circuit - .apply_custom(bell_gate.clone(), &[0, 1]) - .apply_custom(bell_gate.clone(), &[2, 3]); - circuit - }; - println!("Horizontal:\n{}", HorizontalRenderer::new(&custom_bell)); - println!("Vertical:\n{}", VerticalRenderer::new(&custom_bell)); - - results.push(benchmark_circuit( - "Custom BELL (4 qubits)", - custom_bell_builder, - )); - let mut custom_bell_display = { - let mut circuit = QuantumCircuit::new(4); - circuit - .apply_custom(bell_gate.clone(), &[0, 1]) - .apply_custom(bell_gate.clone(), &[2, 3]); - circuit - }; - custom_bell_display.compute(); - println!("{}\n", custom_bell_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Custom Gate: Swap via CNOTs │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let swap_gate = CustomGateBuilder::new("MYSWAP", 2) - .cnot(0, 1) - .cnot(1, 0) - .cnot(0, 1) - .build(); - let swap_gate_clone = swap_gate.clone(); - - let custom_swap_builder = move || { - let mut circuit = QuantumCircuit::new(2); - circuit.x(0).apply_custom(swap_gate_clone.clone(), &[0, 1]); - circuit - }; - - let custom_swap = { - let mut circuit = QuantumCircuit::new(2); - circuit.x(0).apply_custom(swap_gate.clone(), &[0, 1]); - circuit - }; - println!("Horizontal:\n{}", HorizontalRenderer::new(&custom_swap)); - println!("Vertical:\n{}", VerticalRenderer::new(&custom_swap)); - - results.push(benchmark_circuit( - "Custom SWAP (2 qubits)", - custom_swap_builder, - )); - let mut custom_swap_display = { - let mut circuit = QuantumCircuit::new(2); - circuit.x(0).apply_custom(swap_gate.clone(), &[0, 1]); - circuit - }; - custom_swap_display.compute(); - println!("{}\n", custom_swap_display); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Custom Gate: Matrix-defined √X gate │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let sqrt_x_matrix = matrix!( - [complex!(0.5, 0.5), complex!(0.5, -0.5)]; - [complex!(0.5, -0.5), complex!(0.5, 0.5)] - ); - let sqrt_x = CustomGate::from_matrix("√X", sqrt_x_matrix); - let sqrt_x_clone = sqrt_x.clone(); - - let sqrt_x_builder = move || { - let mut circuit = QuantumCircuit::new(1); - circuit - .apply_custom(sqrt_x_clone.clone(), &[0]) - .apply_custom(sqrt_x_clone.clone(), &[0]); - circuit - }; - - let sqrt_x_circuit = { - let mut circuit = QuantumCircuit::new(1); - circuit - .apply_custom(sqrt_x.clone(), &[0]) - .apply_custom(sqrt_x.clone(), &[0]); - circuit - }; - println!("Horizontal:\n{}", HorizontalRenderer::new(&sqrt_x_circuit)); - println!("Vertical:\n{}", VerticalRenderer::new(&sqrt_x_circuit)); - - results.push(benchmark_circuit("√X gate (1 qubit)", sqrt_x_builder)); - let mut sqrt_x_display = { - let mut circuit = QuantumCircuit::new(1); - circuit - .apply_custom(sqrt_x.clone(), &[0]) - .apply_custom(sqrt_x.clone(), &[0]); - circuit - }; - sqrt_x_display.compute(); - println!("{}", sqrt_x_display); - println!("(Two √X gates should equal X, so |0⟩ becomes |1⟩)\n"); - - println!("┌─────────────────────────────────────────────────────────────┐"); - println!("│ Larger Circuits (for benchmark comparison) │"); - println!("└─────────────────────────────────────────────────────────────┘\n"); - - let large_8_builder = || { - let mut circuit = QuantumCircuit::new(8); - for i in 0..8 { - circuit.h(i); - } - for i in 0..7 { - circuit.cnot(i, i + 1); - } - circuit - }; - println!("8-qubit entangled:"); - println!("{}", HorizontalRenderer::new(&large_8_builder())); - results.push(benchmark_circuit("8-qubit entangled", large_8_builder)); - - let large_10_builder = || { - let mut circuit = QuantumCircuit::new(10); - for i in 0..10 { - circuit.h(i); - } - for i in 0..9 { - circuit.cnot(i, i + 1); - } - circuit.cz(0, 9); - circuit - }; - println!("10-qubit entangled:"); - println!("{}", HorizontalRenderer::new(&large_10_builder())); - results.push(benchmark_circuit("10-qubit entangled", large_10_builder)); - - let large_12_builder = || { - let mut circuit = QuantumCircuit::new(12); - for i in 0..12 { - circuit.h(i); - } - for i in 0..11 { - circuit.cnot(i, i + 1); - } - circuit.cz(0, 11); - circuit.swap(5, 6); - circuit - }; - println!("12-qubit entangled:"); - println!("{}", HorizontalRenderer::new(&large_12_builder())); - results.push(benchmark_circuit("12-qubit entangled", large_12_builder)); - - let large_14_builder = || { - let mut circuit = QuantumCircuit::new(14); - for i in 0..14 { - circuit.h(i); - } - for i in 0..13 { - circuit.cnot(i, i + 1); - } - circuit - }; - println!("14-qubit entangled:"); - println!("{}", HorizontalRenderer::new(&large_14_builder())); - results.push(benchmark_circuit("14-qubit entangled", large_14_builder)); + if run_clifford { + clifford::run_all(&mut results); + } - print_benchmark_table(&results); + if run_non_clifford { + non_clifford::run_all(&mut results); + } - let all_match = results.iter().all(|r| r.results_match); - println!("\n"); - if all_match { - println!("✓ All circuits produced identical results with both runtimes!"); - } else { - println!("✗ WARNING: Some circuits produced different results!"); + if run_custom { + custom_gates::run_all(&mut results); } - let total_basic: Duration = results.iter().map(|r| r.basic_time).sum(); - let total_mt: Duration = results.iter().map(|r| r.mt_time).sum(); - let overall_speedup = total_basic.as_secs_f64() / total_mt.as_secs_f64(); + if run_bench { + benchmarks::run_all(&mut results); + } - println!( - "\nTotal time - BasicRT: {} | BasicRTMT: {} | Overall speedup: {:.2}x", - format_duration(total_basic), - format_duration(total_mt), - overall_speedup - ); + if !results.is_empty() { + print_benchmark_table(&results); + print_summary(&results); + } } diff --git a/tester/src/non_clifford.rs b/tester/src/non_clifford.rs new file mode 100644 index 0000000..8545d01 --- /dev/null +++ b/tester/src/non_clifford.rs @@ -0,0 +1,137 @@ +use crate::common::{benchmark_circuit, print_circuit, print_section, BenchmarkResult}; +use libpsi_core::QuantumCircuit; +use std::f64::consts::PI; + +pub fn run_all(results: &mut Vec<BenchmarkResult>) { + println!("═══════════════════════════════════════════════════════════════"); + println!(" NON-CLIFFORD GATES TESTS"); + println!("═══════════════════════════════════════════════════════════════\n"); + + test_fixed_gates(results); + test_rotation_gates(results); + test_phase_gates(results); + test_general_unitaries(results); + test_controlled_rotations(results); + test_variational_circuit(results); +} + +pub fn test_fixed_gates(results: &mut Vec<BenchmarkResult>) { + print_section("Non-Clifford Gates: T, T†, √X, S†"); + + let builder = || { + let mut circuit = QuantumCircuit::new(2); + circuit.h(0).t(0).tdg(0).sx(1).sxdg(1).h(0).s(0).sdg(0); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("Non-Clifford fixed gates", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_rotation_gates(results: &mut Vec<BenchmarkResult>) { + print_section("Rotation Gates: Rx, Ry, Rz"); + + let builder = || { + let mut circuit = QuantumCircuit::new(3); + circuit + .rx(0, PI / 4.0) + .ry(1, PI / 2.0) + .rz(2, PI) + .rx(0, -PI / 4.0); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("Rotation gates (3 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_phase_gates(results: &mut Vec<BenchmarkResult>) { + print_section("Phase Gate: P(θ)"); + + let builder = || { + let mut circuit = QuantumCircuit::new(2); + circuit.h(0).p(0, PI / 4.0).h(1).p(1, PI / 2.0); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("Phase gates (2 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_general_unitaries(results: &mut Vec<BenchmarkResult>) { + print_section("General Unitaries: U1, U2, U3"); + + let builder = || { + let mut circuit = QuantumCircuit::new(3); + circuit + .u1(0, PI / 4.0) + .u2(1, 0.0, PI) + .u3(2, PI / 2.0, 0.0, PI); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("General unitaries (3 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_controlled_rotations(results: &mut Vec<BenchmarkResult>) { + print_section("Controlled Rotation Gates: CRx, CRy, CRz, CP"); + + let builder = || { + let mut circuit = QuantumCircuit::new(4); + circuit + .x(0) + .crx(0, 1, PI / 2.0) + .x(2) + .cry(2, 3, PI / 4.0) + .crz(0, 2, PI) + .cp(1, 3, PI / 2.0); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit( + "Controlled rotations (4 qubits)", + builder, + )); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} + +pub fn test_variational_circuit(results: &mut Vec<BenchmarkResult>) { + print_section("Variational Circuit (VQE-like)"); + + let builder = || { + let mut circuit = QuantumCircuit::new(3); + circuit.ry(0, 0.5).ry(1, 0.3).ry(2, 0.7); + circuit.cnot(0, 1).cnot(1, 2); + circuit.rx(0, 0.2).rx(1, 0.4).rx(2, 0.6); + circuit.cz(0, 2); + circuit + }; + + print_circuit(&builder()); + results.push(benchmark_circuit("Variational circuit (3 qubits)", builder)); + + let mut display = builder(); + display.compute(); + println!("{}\n", display); +} |
