ket/
util.rs

1// SPDX-FileCopyrightText: 2024 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use 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}