1use env_logger::Builder;
6use log::LevelFilter;
7
8use crate::{error::Result, ir::qubit::LogicalQubit, prelude::QuantumGate, process::Process};
9
10#[cfg(feature = "plot")]
11use crate::process::{DumpData, Sample};
12#[cfg(feature = "plot")]
13use plotly::Plot;
14
15pub fn ajd<F>(process: &mut Process, mut f: F) -> Result<()>
16where
17 F: FnMut(&mut Process) -> Result<()>,
18{
19 process.adj_begin()?;
20 f(process)?;
21 process.adj_end()
22}
23
24pub fn ctrl<F>(process: &mut Process, control: &[LogicalQubit], mut f: F) -> Result<()>
25where
26 F: FnMut(&mut Process) -> Result<()>,
27{
28 process.ctrl_push(control)?;
29 f(process)?;
30 process.ctrl_pop()
31}
32
33pub fn c1gate(
34 process: &mut Process,
35 gate: QuantumGate,
36 control: LogicalQubit,
37 target: LogicalQubit,
38) -> Result<()> {
39 ctrl(process, &[control], |process| process.gate(gate, target))
40}
41
42pub fn cnot(process: &mut Process, control: LogicalQubit, target: LogicalQubit) -> Result<()> {
43 c1gate(process, QuantumGate::PauliX, control, target)
44}
45
46pub fn swap(process: &mut Process, qubit1: LogicalQubit, qubit2: LogicalQubit) -> Result<()> {
47 cnot(process, qubit1, qubit2)?;
48 cnot(process, qubit2, qubit1)?;
49 cnot(process, qubit1, qubit2)
50}
51
52pub fn around<O, I>(process: &mut Process, mut outer: O, mut inner: I) -> Result<()>
53where
54 I: FnMut(&mut Process) -> Result<()>,
55 O: FnMut(&mut Process) -> Result<()>,
56{
57 outer(process)?;
58 inner(process)?;
59 ajd(process, outer)
60}
61
62pub fn set_log_level(level: u32) {
63 let level = match level {
64 0 => LevelFilter::Off,
65 1 => LevelFilter::Error,
66 2 => LevelFilter::Warn,
67 3 => LevelFilter::Info,
68 4 => LevelFilter::Debug,
69 5 => LevelFilter::Trace,
70 _ => LevelFilter::max(),
71 };
72
73 Builder::new().filter_level(level).init();
74}
75
76#[cfg(feature = "plot")]
77pub fn plot_sample(data: &Sample) -> Plot {
78 use plotly::{layout::Axis, Bar, Layout};
79
80 let trace = Bar::new(data.0.clone(), data.1.clone());
81 let layout = Layout::new()
82 .x_axis(Axis::new().title("Measurement Results"))
83 .y_axis(Axis::new().title("Measurement Count"));
84 let mut plot = Plot::new();
85 plot.add_trace(trace);
86 plot.set_layout(layout);
87
88 plot
89}
90
91#[cfg(feature = "plot")]
92pub fn plot_dump(data: &DumpData) -> Plot {
93 use plotly::{common::Marker, layout::Axis, Bar, Layout};
94 use std::f64::consts::PI;
95
96 use crate::ir::gate::Cf64;
97
98 let amp: Vec<_> = data
99 .amplitudes_real
100 .iter()
101 .zip(data.amplitudes_imag.iter())
102 .map(|(re, im)| Cf64::new(*re, *im))
103 .collect();
104
105 let prob: Vec<_> = amp.iter().map(|x| x.norm_sqr()).collect();
106 let phase: Vec<_> = amp.iter().map(|x| x.arg()).collect();
107 let base: Vec<_> = data.basis_states.iter().map(|x| x[0]).collect();
108
109 let trace = Bar::new(base, prob).marker(
110 Marker::new()
111 .color_array(phase)
112 .cmin(-PI)
113 .cmax(PI)
114 .show_scale(true),
115 );
116
117 let layout = Layout::new()
118 .x_axis(Axis::new().title("Basis State"))
119 .y_axis(
120 Axis::new()
121 .title("Measurement Probability (%)")
122 .range(vec![0.0, 1.0]),
123 );
124
125 let mut plot = Plot::new();
126 plot.add_trace(trace);
127 plot.set_layout(layout);
128
129 plot
130}