quant_iron/
circuit.rs

1use crate::{
2    compiler::{compilable::CompilableCircuit, qasm::QasmCircuit},
3    components::{
4        gate::Gate,
5        measurement::MeasurementBasis,
6        operator::Operator,
7        parametric::{
8            parameter::Parameter,
9            parametric_gate::{ParametricMatchgate, ParametricRyPhase},
10        },
11        state::State,
12    },
13    errors::{CompilerError, Error},
14    subroutine::Subroutine,
15};
16
17use std::fs;
18use std::io::Write;
19use std::path::Path;
20
21use num_complex::Complex;
22
23/// Represents a quantum circuit as a vector of gates.
24///
25/// # Fields
26///
27/// * `gates` - A vector of gates in the circuit.
28/// * `num_qubits` - The number of qubits in the circuit.
29#[derive(Debug)]
30pub struct Circuit {
31    /// A vector of gates in the circuit.
32    pub gates: Vec<Gate>,
33    /// The number of qubits in the circuit.
34    pub num_qubits: usize,
35}
36
37impl Circuit {
38    // Helper function to validate gate qubits
39    fn _validate_gate_qubits(gate: &Gate, circuit_num_qubits: usize) -> Result<(), Error> {
40        // Check if the gate's target qubits are within the circuit's qubit range
41        for &qubit in gate.get_target_qubits() {
42            if qubit >= circuit_num_qubits {
43                return Err(Error::InvalidQubitIndex(qubit, circuit_num_qubits));
44            }
45        }
46
47        // Check if the gate's control qubits are within the circuit's qubit range
48        if let Some(control_qubits) = gate.get_control_qubits() {
49            for &qubit in control_qubits {
50                if qubit >= circuit_num_qubits {
51                    return Err(Error::InvalidQubitIndex(qubit, circuit_num_qubits));
52                }
53            }
54        }
55        Ok(())
56    }
57
58    /// Creates a new circuit with the specified number of qubits.
59    ///
60    /// # Arguments
61    ///
62    /// * `num_qubits` - The number of qubits in the circuit.
63    ///
64    /// # Returns
65    ///
66    /// * `Circuit` - A new instance of the Circuit struct.
67    pub fn new(num_qubits: usize) -> Self {
68        Circuit {
69            gates: Vec::new(),
70            num_qubits,
71        }
72    }
73
74    /// Creates a new circuit with the specified gates and number of qubits.
75    ///
76    /// # Arguments
77    ///
78    /// * `gates` - A vector of gates in the circuit.
79    /// * `num_qubits` - The number of qubits in the circuit.
80    ///
81    /// # Returns
82    ///
83    /// * `Result<Circuit, Error>` - A new instance of the Circuit struct or an error if the circuit cannot be created.
84    pub fn with_gates(gates: Vec<Gate>, num_qubits: usize) -> Result<Circuit, Error> {
85        for gate in &gates {
86            Self::_validate_gate_qubits(gate, num_qubits)?;
87        }
88
89        Ok(Circuit { gates, num_qubits })
90    }
91
92    /// Adds a gate to the circuit.
93    ///
94    /// # Arguments
95    ///
96    /// * `gate` - The gate to be added to the circuit.
97    ///
98    /// # Returns
99    ///
100    /// * `Result<(), Error>` - An empty result if the gate is added successfully, or an error if the gate cannot be added.
101    pub fn add_gate(&mut self, gate: Gate) -> Result<(), Error> {
102        Self::_validate_gate_qubits(&gate, self.num_qubits)?;
103        self.gates.push(gate);
104        Ok(())
105    }
106
107    /// Adds multiple gates to the circuit.
108    ///
109    /// # Arguments
110    ///
111    /// * `gates` - A vector of gates to be added to the circuit.
112    ///
113    /// # Returns
114    ///
115    /// * `Result<(), Error>` - An empty result if the gates are added successfully, or an error if any gate cannot be added.
116    pub fn add_gates(&mut self, gates: Vec<Gate>) -> Result<(), Error> {
117        for gate in &gates {
118            Self::_validate_gate_qubits(gate, self.num_qubits)?;
119        }
120        self.gates.extend(gates);
121        Ok(())
122    }
123
124    /// Gets the number of qubits in the circuit.
125    ///
126    /// # Returns
127    ///
128    /// * `usize` - The number of qubits in the circuit.
129    pub fn get_num_qubits(&self) -> usize {
130        self.num_qubits
131    }
132
133    /// Gets the gates in the circuit.
134    ///
135    /// # Returns
136    ///
137    /// * `&Vec<Gate>` - A reference to the vector of gates in the circuit.
138    pub fn get_gates(&self) -> &Vec<Gate> {
139        &self.gates
140    }
141
142    /// Executes the circuit with the given initial state, and returns the final state.
143    ///
144    /// # Arguments
145    ///
146    /// * `initial_state` - The initial state of the qubits in the circuit.
147    ///
148    /// # Returns
149    ///
150    /// * `Result<State, Error>` - The final state of the qubits after executing the circuit.
151    ///
152    /// # Errors
153    ///
154    /// * Returns an error if the number of qubits in the initial state does not match the number of qubits in the circuit.
155    /// * Returns an error if the circuit cannot be executed due to invalid gate operations.
156    pub fn execute(&self, initial_state: &State) -> Result<State, Error> {
157        if initial_state.num_qubits() != self.num_qubits {
158            return Err(Error::InvalidNumberOfQubits(initial_state.num_qubits()));
159        }
160
161        let mut current_state = initial_state.clone();
162
163        for gate in &self.gates {
164            current_state = gate.apply(&current_state)?;
165        }
166
167        Ok(current_state)
168    }
169
170    /// Executes the circuit with the given initial state, and returns all the intermediate states and the final state.
171    ///
172    /// # Arguments
173    ///
174    /// * `initial_state` - The initial state of the qubits in the circuit.
175    ///
176    /// # Returns
177    ///
178    /// * `Result<Vec<State>, Error>` - A vector of intermediate states and the final state after executing the circuit.
179    ///
180    /// # Errors
181    ///
182    /// * Returns an error if the number of qubits in the initial state does not match the number of qubits in the circuit.
183    /// * Returns an error if the circuit cannot be executed due to invalid gate operations.
184    pub fn trace_execution(&self, initial_state: &State) -> Result<Vec<State>, Error> {
185        if initial_state.num_qubits() != self.num_qubits {
186            return Err(Error::InvalidNumberOfQubits(initial_state.num_qubits()));
187        }
188
189        let mut current_state = initial_state.clone();
190        let mut states = vec![current_state.clone()];
191
192        for gate in &self.gates {
193            current_state = gate.apply(&current_state)?;
194            states.push(current_state.clone());
195        }
196
197        Ok(states)
198    }
199
200    /// Converts a parametric circuit into a circuit with concrete gates.
201    pub(crate) fn to_concrete_circuit(&self) -> Self {
202        let concrete_gates = self.gates.iter().flat_map(|g| {
203            match g {
204                Gate::Parametric(p_gate, targets, controls) => {
205                    p_gate.to_concrete_gates(targets, controls)
206                }
207                _ => vec![g.clone()],
208            }
209        }).collect();
210
211        Circuit {
212            gates: concrete_gates,
213            num_qubits: self.num_qubits,
214        }
215    }
216
217    /// Converts the circuit to its internal QASM circuit if the circuit is compilable, and return an error if it is not, or if the conversion fails.
218    pub(crate) fn to_qasm_circuit(&self) -> Result<QasmCircuit, CompilerError> {
219        let concrete_circuit = self.to_concrete_circuit();
220        let compilable_circuit = CompilableCircuit::try_from(&concrete_circuit)?;
221        let qasm_instructions =
222            compilable_circuit
223                .to_ir()
224                .iter()
225                .try_fold(Vec::new(), |mut acc, instr| {
226                    acc.extend(instr.to_qasm()?);
227                    Ok(acc)
228                })?;
229
230        Ok(QasmCircuit::new(
231            qasm_instructions,
232            compilable_circuit.num_qubits,
233        ))
234    }
235
236    /// Converts the circuit to its OpenQASM 3.0 (Quantum Assembly 3.0) representation.
237    pub fn to_qasm(&self, to_dir: Option<impl AsRef<Path>>) -> Result<String, CompilerError> {
238        let qasm_circuit: QasmCircuit = self.to_qasm_circuit()?;
239        let qasm_string = qasm_circuit.to_qasm_string();
240
241        if let Some(path) = to_dir {
242            let dir_path = path.as_ref();
243
244            if !dir_path.is_dir() {
245                return Err(CompilerError::IOError(format!(
246                    "Provided path is not a directory: {}",
247                    dir_path.display()
248                )));
249            }
250
251            let output_path = dir_path.join("circuit.qasm");
252
253            let mut file = fs::File::create(&output_path).map_err(|e| {
254                CompilerError::IOError(format!(
255                    "Error creating file '{}': {}",
256                    output_path.display(),
257                    e
258                ))
259            })?;
260
261            file.write_all(qasm_string.as_bytes()).map_err(|e| {
262                CompilerError::IOError(format!(
263                    "Error writing to file '{}': {}",
264                    output_path.display(),
265                    e
266                ))
267            })?;
268        }
269
270        Ok(qasm_string)
271    }
272}
273
274/// A builder for creating a quantum circuit.
275///
276/// # Fields
277///
278/// * `gates` - A vector of gates in the circuit.
279///
280/// * `num_qubits` - The number of qubits in the circuit.
281pub struct CircuitBuilder {
282    /// A vector of gates in the circuit builder.
283    /// A temporary vector to hold gates before building the circuit.
284    pub gates: Vec<Gate>,
285    /// The number of qubits in the circuit builder.
286    pub num_qubits: usize,
287}
288
289impl CircuitBuilder {
290    /// Creates a new circuit builder with the specified number of qubits.
291    ///
292    /// # Arguments
293    ///
294    /// * `num_qubits` - The number of qubits in the circuit builder.
295    ///
296    /// # Returns
297    ///
298    /// * `CircuitBuilder` - A new instance of the CircuitBuilder struct.
299    pub fn new(num_qubits: usize) -> Self {
300        CircuitBuilder {
301            gates: Vec::new(),
302            num_qubits,
303        }
304    }
305
306    /// Adds a gate to the circuit builder.
307    ///
308    /// # Arguments
309    ///
310    /// * `gate` - The gate to be added to the circuit builder.
311    pub fn add_gate(&mut self, gate: Gate) -> &mut Self {
312        self.gates.push(gate);
313        self
314    }
315
316    /// Adds multiple gates to the circuit builder.
317    ///
318    /// # Arguments
319    ///
320    /// * `gates` - A vector of gates to be added to the circuit builder.
321    pub fn add_gates(&mut self, gates: Vec<Gate>) -> &mut Self {
322        self.gates.extend(gates);
323        self
324    }
325
326    /// Builds the circuit from the gates in the circuit builder.
327    /// The builder's internal gate list is not cleared, allowing the builder to be reused.
328    /// If this is the final circuit, use `build_final` instead.
329    ///
330    /// # Returns
331    ///
332    /// * `Result<Circuit, Error>` - A new instance of the Circuit struct or an error if the circuit cannot be built.
333    pub fn build(&mut self) -> Result<Circuit, Error> {
334        let gates_cloned = self.gates.clone();
335        Circuit::with_gates(gates_cloned, self.num_qubits)
336    }
337
338    /// Builds the circuit from the gates in the circuit builder.
339    /// The builder's internal gate list is cleared, allowing the builder to be reused.
340    /// If this is an intermediate circuit, use `build` instead to retain the gates for further modifications.
341    ///
342    /// # Returns
343    ///
344    /// * `Result<Circuit, Error>` - A new instance of the Circuit struct or an error if the circuit cannot be built.
345    pub fn build_final(&mut self) -> Result<Circuit, Error> {
346        let gates = std::mem::take(&mut self.gates);
347        Circuit::with_gates(gates, self.num_qubits)
348    }
349
350    /// Builds a subroutine from the gates in the circuit builder.
351    /// The builder's internal gate list is cleared, allowing the builder to be reused.
352    ///
353    /// # Returns
354    ///
355    /// * `Subroutine` - A new instance of the Subroutine struct.
356    pub fn build_subroutine(&mut self) -> Subroutine {
357        let gates = std::mem::take(&mut self.gates);
358        Subroutine::with_gates(gates, self.num_qubits)
359    }
360
361    /// Adds a subroutine to the circuit builder.
362    ///
363    /// # Arguments
364    ///
365    /// * `subroutine` - The subroutine to be added to the circuit builder.
366    pub fn add_subroutine(&mut self, subroutine: Subroutine) -> &mut Self {
367        self.gates.extend(subroutine.gates);
368        self
369    }
370
371    // -- SINGLE QUBIT GATES --
372
373    /// Adds a Hadamard gate to the circuit builder.
374    ///
375    /// # Arguments
376    ///
377    /// * `qubit` - The index of the qubit to which the Hadamard gate will be applied.
378    pub fn h_gate(&mut self, qubit: usize) -> &mut Self {
379        let gate: Gate = Gate::h_gate(qubit);
380        self.add_gate(gate);
381        self
382    }
383
384    /// Adds multiple Hadamard gates to the circuit builder.
385    ///
386    /// # Arguments
387    ///
388    /// * `qubits` - A vector of indices of the qubits to which the Hadamard gates will be applied.
389    pub fn h_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
390        let gates: Vec<Gate> = Gate::h_multi_gate(qubits);
391        self.add_gates(gates);
392        self
393    }
394
395    /// Adds controlled Hadamard gates to the circuit builder.
396    ///
397    /// # Arguments
398    ///
399    /// * `target_qubits` - A vector of indices of the target qubits.
400    /// * `control_qubits` - A vector of indices of the control qubits.
401    pub fn ch_gates(&mut self, target_qubits: Vec<usize>, control_qubits: Vec<usize>) -> &mut Self {
402        let gates: Vec<Gate> = Gate::h_controlled_gates(target_qubits, control_qubits);
403        self.add_gates(gates);
404        self
405    }
406
407    /// Adds a Pauli-X gate to the circuit builder.
408    ///
409    /// # Arguments
410    ///
411    /// * `qubit` - The index of the qubit to which the Pauli-X gate will be applied.
412    pub fn x_gate(&mut self, qubit: usize) -> &mut Self {
413        let gate: Gate = Gate::x_gate(qubit);
414        self.add_gate(gate);
415        self
416    }
417
418    /// Adds multiple Pauli-X gates to the circuit builder.
419    ///
420    /// # Arguments
421    ///
422    /// * `qubits` - A vector of indices of the qubits to which the Pauli-X gates will be applied.
423    pub fn x_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
424        let gates: Vec<Gate> = Gate::x_multi_gate(qubits);
425        self.add_gates(gates);
426        self
427    }
428
429    /// Adds controlled Pauli-X gates to the circuit builder.
430    ///
431    /// # Arguments
432    ///
433    /// * `target_qubits` - A vector of indices of the target qubits.
434    /// * `control_qubits` - A vector of indices of the control qubits.
435    pub fn cx_gates(&mut self, target_qubits: Vec<usize>, control_qubits: Vec<usize>) -> &mut Self {
436        let gates: Vec<Gate> = Gate::x_controlled_gates(target_qubits, control_qubits);
437        self.add_gates(gates);
438        self
439    }
440
441    /// Adds a Pauli-Y gate to the circuit builder.
442    ///
443    /// # Arguments
444    ///
445    /// * `qubit` - The index of the qubit to which the Pauli-Y gate will be applied.
446    pub fn y_gate(&mut self, qubit: usize) -> &mut Self {
447        let gate: Gate = Gate::y_gate(qubit);
448        self.add_gate(gate);
449        self
450    }
451
452    /// Adds multiple Pauli-Y gates to the circuit builder.
453    ///
454    /// # Arguments
455    ///
456    /// * `qubits` - A vector of indices of the qubits to which the Pauli-Y gates will be applied.
457    pub fn y_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
458        let gates: Vec<Gate> = Gate::y_multi_gate(qubits);
459        self.add_gates(gates);
460        self
461    }
462
463    /// Adds controlled Pauli-Y gates to the circuit builder.
464    ///
465    /// # Arguments
466    ///
467    /// * `target_qubits` - A vector of indices of the target qubits.
468    /// * `control_qubits` - A vector of indices of the control qubits.
469    pub fn cy_gates(&mut self, target_qubits: Vec<usize>, control_qubits: Vec<usize>) -> &mut Self {
470        let gates: Vec<Gate> = Gate::y_controlled_gates(target_qubits, control_qubits);
471        self.add_gates(gates);
472        self
473    }
474
475    /// Adds a Pauli-Z gate to the circuit builder.
476    ///
477    /// # Arguments
478    ///
479    /// * `qubit` - The index of the qubit to which the Pauli-Z gate will be applied.
480    pub fn z_gate(&mut self, qubit: usize) -> &mut Self {
481        let gate: Gate = Gate::z_gate(qubit);
482        self.add_gate(gate);
483        self
484    }
485
486    /// Adds multiple Pauli-Z gates to the circuit builder.
487    ///
488    /// # Arguments
489    ///
490    /// * `qubits` - A vector of indices of the qubits to which the Pauli-Z gates will be applied.
491    pub fn z_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
492        let gates: Vec<Gate> = Gate::z_multi_gate(qubits);
493        self.add_gates(gates);
494        self
495    }
496
497    /// Adds controlled Pauli-Z gates to the circuit builder.
498    ///
499    /// # Arguments
500    ///
501    /// * `target_qubits` - A vector of indices of the target qubits.
502    /// * `control_qubits` - A vector of indices of the control qubits.
503    pub fn cz_gates(&mut self, target_qubits: Vec<usize>, control_qubits: Vec<usize>) -> &mut Self {
504        let gates: Vec<Gate> = Gate::z_controlled_gates(target_qubits, control_qubits);
505        self.add_gates(gates);
506        self
507    }
508
509    /// Adds an Identity gate to the circuit builder.
510    ///
511    /// # Arguments
512    ///
513    /// * `qubit` - The index of the qubit to which the Identity gate will be applied.
514    pub fn id_gate(&mut self, qubit: usize) -> &mut Self {
515        let gate: Gate = Gate::i_gate(qubit);
516        self.add_gate(gate);
517        self
518    }
519
520    /// Adds multiple Identity gates to the circuit builder.
521    ///
522    /// # Arguments
523    ///
524    /// * `qubits` - A vector of indices of the qubits to which the Identity gates will be applied.
525    pub fn id_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
526        let gates: Vec<Gate> = Gate::i_multi_gate(qubits);
527        self.add_gates(gates);
528        self
529    }
530
531    /// Adds controlled Identity gates to the circuit builder.
532    ///
533    /// # Arguments
534    ///
535    /// * `target_qubits` - A vector of indices of the target qubits.
536    /// * `control_qubits` - A vector of indices of the control qubits.
537    pub fn ci_gates(&mut self, target_qubits: Vec<usize>, control_qubits: Vec<usize>) -> &mut Self {
538        let gates: Vec<Gate> = Gate::i_controlled_gates(target_qubits, control_qubits);
539        self.add_gates(gates);
540        self
541    }
542
543    /// Adds a Phase S gate to the circuit builder.
544    ///
545    /// # Arguments
546    ///
547    /// * `qubit` - The index of the qubit to which the Phase S gate will be applied.
548    pub fn s_gate(&mut self, qubit: usize) -> &mut Self {
549        let gate: Gate = Gate::s_gate(qubit);
550        self.add_gate(gate);
551        self
552    }
553
554    /// Adds multiple Phase S gates to the circuit builder.
555    ///
556    /// # Arguments
557    ///
558    /// * `qubits` - A vector of indices of the qubits to which the Phase S gates will be applied.
559    pub fn s_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
560        let gates: Vec<Gate> = Gate::s_multi_gate(qubits);
561        self.add_gates(gates);
562        self
563    }
564
565    /// Adds controlled Phase S gates to the circuit builder.
566    ///
567    /// # Arguments
568    ///
569    /// * `target_qubits` - A vector of indices of the target qubits.
570    /// * `control_qubits` - A vector of indices of the control qubits.
571    pub fn cs_gates(&mut self, target_qubits: Vec<usize>, control_qubits: Vec<usize>) -> &mut Self {
572        let gates: Vec<Gate> = Gate::s_controlled_gates(target_qubits, control_qubits);
573        self.add_gates(gates);
574        self
575    }
576
577    /// Adds a Phase S Dagger gate to the circuit builder.
578    ///
579    /// # Arguments
580    ///
581    /// * `qubit` - The index of the qubit to which the Phase S Dagger gate will be applied.
582    pub fn sdag_gate(&mut self, qubit: usize) -> &mut Self {
583        let gate: Gate = Gate::s_dag_gate(qubit);
584        self.add_gate(gate);
585        self
586    }
587
588    /// Adds multiple Phase S Dagger gates to the circuit builder.
589    ///
590    /// # Arguments
591    ///
592    /// * `qubits` - A vector of indices of the qubits to which the Phase S Dagger gates will be applied.
593    pub fn sdag_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
594        let gates: Vec<Gate> = Gate::s_dag_multi_gate(qubits);
595        self.add_gates(gates);
596        self
597    }
598
599    /// Adds controlled Phase S Dagger gates to the circuit builder.
600    ///
601    /// # Arguments
602    ///
603    /// * `target_qubits` - A vector of indices of the target qubits.
604    /// * `control_qubits` - A vector of indices of the control qubits.
605    pub fn csdag_gates(
606        &mut self,
607        target_qubits: Vec<usize>,
608        control_qubits: Vec<usize>,
609    ) -> &mut Self {
610        let gates: Vec<Gate> = Gate::s_dag_controlled_gates(target_qubits, control_qubits);
611        self.add_gates(gates);
612        self
613    }
614
615    /// Adds a Phase T gate to the circuit builder.
616    ///
617    /// # Arguments
618    ///
619    /// * `qubit` - The index of the qubit to which the Phase T gate will be applied.
620    pub fn t_gate(&mut self, qubit: usize) -> &mut Self {
621        let gate: Gate = Gate::t_gate(qubit);
622        self.add_gate(gate);
623        self
624    }
625
626    /// Adds multiple Phase T gates to the circuit builder.
627    ///
628    /// # Arguments
629    ///
630    /// * `qubits` - A vector of indices of the qubits to which the Phase T gates will be applied.
631    pub fn t_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
632        let gates: Vec<Gate> = Gate::t_multi_gate(qubits);
633        self.add_gates(gates);
634        self
635    }
636
637    /// Adds controlled Phase T gates to the circuit builder.
638    ///
639    /// # Arguments
640    ///
641    /// * `target_qubits` - A vector of indices of the target qubits.
642    /// * `control_qubits` - A vector of indices of the control qubits.
643    pub fn ct_gates(&mut self, target_qubits: Vec<usize>, control_qubits: Vec<usize>) -> &mut Self {
644        let gates: Vec<Gate> = Gate::t_controlled_gates(target_qubits, control_qubits);
645        self.add_gates(gates);
646        self
647    }
648
649    /// Adds a Phase T Dagger gate to the circuit builder.
650    ///
651    /// # Arguments
652    ///
653    /// * `qubit` - The index of the qubit to which the Phase T Dagger gate will be applied.
654    pub fn tdag_gate(&mut self, qubit: usize) -> &mut Self {
655        let gate: Gate = Gate::t_dag_gate(qubit);
656        self.add_gate(gate);
657        self
658    }
659
660    /// Adds multiple Phase T Dagger gates to the circuit builder.
661    ///
662    /// # Arguments
663    ///
664    /// * `qubits` - A vector of indices of the qubits to which the Phase T Dagger gates will be applied.
665    pub fn tdag_gates(&mut self, qubits: Vec<usize>) -> &mut Self {
666        let gates: Vec<Gate> = Gate::t_dag_multi_gate(qubits);
667        self.add_gates(gates);
668        self
669    }
670
671    /// Adds controlled Phase T Dagger gates to the circuit builder.
672    ///
673    /// # Arguments
674    ///
675    /// * `target_qubits` - A vector of indices of the target qubits.
676    /// * `control_qubits` - A vector of indices of the control qubits.
677    pub fn ctdag_gates(
678        &mut self,
679        target_qubits: Vec<usize>,
680        control_qubits: Vec<usize>,
681    ) -> &mut Self {
682        let gates: Vec<Gate> = Gate::t_dag_controlled_gates(target_qubits, control_qubits);
683        self.add_gates(gates);
684        self
685    }
686
687    /// Adds a Phase Shift gate to the circuit builder.
688    ///
689    /// # Arguments
690    ///
691    /// * `qubit` - The index of the qubit to which the Phase Shift gate will be applied.
692    /// * `angle` - The phase shift angle in radians.
693    pub fn p_gate(&mut self, qubit: usize, angle: f64) -> &mut Self {
694        let gate: Gate = Gate::p_gate(qubit, angle);
695        self.add_gate(gate);
696        self
697    }
698
699    /// Adds multiple Phase Shift gates to the circuit builder.
700    ///
701    /// # Arguments
702    ///
703    /// * `qubits` - A vector of indices of the qubits to which the Phase Shift gates will be applied.
704    /// * `angle` - The phase shift angle in radians for all gates.
705    pub fn p_gates(&mut self, qubits: Vec<usize>, angle: f64) -> &mut Self {
706        let gates: Vec<Gate> = Gate::p_multi_gate(qubits, angle);
707        self.add_gates(gates);
708        self
709    }
710
711    /// Adds controlled Phase Shift gates to the circuit builder.
712    ///
713    /// # Arguments
714    ///
715    /// * `target_qubits` - A vector of indices of the target qubits.
716    /// * `control_qubits` - A vector of indices of the control qubits.
717    /// * `angle` - The phase shift angle in radians for all gates.
718    pub fn cp_gates(
719        &mut self,
720        target_qubits: Vec<usize>,
721        control_qubits: Vec<usize>,
722        angle: f64,
723    ) -> &mut Self {
724        let gates: Vec<Gate> = Gate::p_controlled_gates(target_qubits, control_qubits, angle);
725        self.add_gates(gates);
726        self
727    }
728
729    /// Adds a Rotate X gate to the circuit builder.
730    ///
731    /// # Arguments
732    ///
733    /// * `qubit` - The index of the qubit to which the Rotate X gate will be applied.
734    /// * `angle` - The rotation angle in radians.
735    pub fn rx_gate(&mut self, qubit: usize, angle: f64) -> &mut Self {
736        let gate: Gate = Gate::rx_gate(qubit, angle);
737        self.add_gate(gate);
738        self
739    }
740
741    /// Adds multiple Rotate X gates to the circuit builder.
742    ///
743    /// # Arguments
744    ///
745    /// * `qubits` - A vector of indices of the qubits to which the Rotate X gates will be applied.
746    /// * `angle` - The rotation angle in radians for all gates.
747    pub fn rx_gates(&mut self, qubits: Vec<usize>, angle: f64) -> &mut Self {
748        let gates: Vec<Gate> = Gate::rx_multi_gate(qubits, angle);
749        self.add_gates(gates);
750        self
751    }
752
753    /// Adds controlled Rotate X gates to the circuit builder.
754    ///
755    /// # Arguments
756    ///
757    /// * `target_qubits` - A vector of indices of the target qubits.
758    /// * `control_qubits` - A vector of indices of the control qubits.
759    /// * `angle` - The rotation angle in radians for all gates.
760    pub fn crx_gates(
761        &mut self,
762        target_qubits: Vec<usize>,
763        control_qubits: Vec<usize>,
764        angle: f64,
765    ) -> &mut Self {
766        let gates: Vec<Gate> = Gate::rx_controlled_gates(target_qubits, control_qubits, angle);
767        self.add_gates(gates);
768        self
769    }
770
771    /// Adds a Rotate Y gate to the circuit builder.
772    ///
773    /// # Arguments
774    ///
775    /// * `qubit` - The index of the qubit to which the Rotate Y gate will be applied.
776    /// * `angle` - The rotation angle in radians.
777    pub fn ry_gate(&mut self, qubit: usize, angle: f64) -> &mut Self {
778        let gate: Gate = Gate::ry_gate(qubit, angle);
779        self.add_gate(gate);
780        self
781    }
782
783    /// Adds multiple Rotate Y gates to the circuit builder.
784    ///
785    /// # Arguments
786    ///
787    /// * `qubits` - A vector of indices of the qubits to which the Rotate Y gates will be applied.
788    /// * `angle` - The rotation angle in radians for all gates.
789    pub fn ry_gates(&mut self, qubits: Vec<usize>, angle: f64) -> &mut Self {
790        let gates: Vec<Gate> = Gate::ry_multi_gate(qubits, angle);
791        self.add_gates(gates);
792        self
793    }
794
795    /// Adds controlled Rotate Y gates to the circuit builder.
796    ///
797    /// # Arguments
798    ///
799    /// * `target_qubits` - A vector of indices of the target qubits.
800    /// * `control_qubits` - A vector of indices of the control qubits.
801    /// * `angle` - The rotation angle in radians for all gates.
802    pub fn cry_gates(
803        &mut self,
804        target_qubits: Vec<usize>,
805        control_qubits: Vec<usize>,
806        angle: f64,
807    ) -> &mut Self {
808        let gates: Vec<Gate> = Gate::ry_controlled_gates(target_qubits, control_qubits, angle);
809        self.add_gates(gates);
810        self
811    }
812
813    /// Adds a Rotate Z gate to the circuit builder.
814    ///
815    /// # Arguments
816    ///
817    /// * `qubit` - The index of the qubit to which the Rotate Z gate will be applied.
818    /// * `angle` - The rotation angle in radians.
819    pub fn rz_gate(&mut self, qubit: usize, angle: f64) -> &mut Self {
820        let gate: Gate = Gate::rz_gate(qubit, angle);
821        self.add_gate(gate);
822        self
823    }
824
825    /// Adds multiple Rotate Z gates to the circuit builder.
826    ///
827    /// # Arguments
828    ///
829    /// * `qubits` - A vector of indices of the qubits to which the Rotate Z gates will be applied.
830    /// * `angle` - The rotation angle in radians for all gates.
831    pub fn rz_gates(&mut self, qubits: Vec<usize>, angle: f64) -> &mut Self {
832        let gates: Vec<Gate> = Gate::rz_multi_gate(qubits, angle);
833        self.add_gates(gates);
834        self
835    }
836
837    /// Adds controlled Rotate Z gates to the circuit builder.
838    ///
839    /// # Arguments
840    ///
841    /// * `target_qubits` - A vector of indices of the target qubits.
842    /// * `control_qubits` - A vector of indices of the control qubits.
843    /// * `angle` - The rotation angle in radians for all gates.
844    pub fn crz_gates(
845        &mut self,
846        target_qubits: Vec<usize>,
847        control_qubits: Vec<usize>,
848        angle: f64,
849    ) -> &mut Self {
850        let gates: Vec<Gate> = Gate::rz_controlled_gates(target_qubits, control_qubits, angle);
851        self.add_gates(gates);
852        self
853    }
854
855    /// Adds an arbitrary unitary operator gate to the circuit builder.
856    ///
857    /// # Arguments
858    ///
859    /// * `qubit` - The index of the qubit to which the operator will be applied.
860    ///
861    /// * `unitary` - Matrix representing the unitary operator.
862    ///
863    /// # Warning
864    ///
865    /// This method is fallible due to the potential for invalid unitary matrices.
866    /// If the unitary matrix is not valid, it will return an error.
867    /// Therefore, the `Result` must be handled appropriately before chaining further operations.
868    pub fn unitary_gate(
869        &mut self,
870        qubit: usize,
871        unitary: [[Complex<f64>; 2]; 2],
872    ) -> Result<&mut Self, Error> {
873        let gate: Gate = Gate::unitary2_gate(qubit, unitary)?;
874        self.add_gate(gate);
875        Ok(self)
876    }
877
878    /// Adds multiple arbitrary unitary operator gates to the circuit builder.
879    ///
880    /// # Arguments
881    ///
882    /// * `qubits` - A vector of indices of the qubits to which the operator will be applied.
883    ///
884    /// * `unitary` - Matrix representing the unitary operator.
885    ///
886    /// # Warning
887    ///
888    /// This method is fallible due to the potential for invalid unitary matrices.
889    /// If the unitary matrix is not valid, it will return an error.
890    /// Therefore, the `Result` must be handled appropriately before chaining further operations.
891    pub fn unitary_gates(
892        &mut self,
893        qubits: Vec<usize>,
894        unitary: [[Complex<f64>; 2]; 2],
895    ) -> Result<&mut Self, Error> {
896        let gates: Vec<Gate> = Gate::unitary2_multi_gate(qubits, unitary)?;
897        self.add_gates(gates);
898        Ok(self)
899    }
900
901    /// Adds controlled arbitrary unitary operator gates to the circuit builder.
902    ///
903    /// # Arguments
904    ///
905    /// * `target_qubits` - A vector of indices of the target qubits.
906    ///
907    /// * `control_qubits` - A vector of indices of the control qubits.
908    ///
909    /// * `unitary` - Matrix representing the unitary operator.
910    ///
911    /// # Warning
912    ///
913    /// This method is fallible due to the potential for invalid unitary matrices.
914    /// If the unitary matrix is not valid, it will return an error.
915    /// Therefore, the `Result` must be handled appropriately before chaining further operations.
916    pub fn cunitary_gates(
917        &mut self,
918        target_qubits: Vec<usize>,
919        control_qubits: Vec<usize>,
920        unitary: [[Complex<f64>; 2]; 2],
921    ) -> Result<&mut Self, Error> {
922        let gates = Gate::unitary2_controlled_gates(target_qubits, control_qubits, unitary)?;
923        self.add_gates(gates);
924        Ok(self)
925    }
926
927    /// Creates and adds a new Unitary2 operator gate from a rotation angle theta and phase shift angle phi.
928    ///
929    /// This operator can be decomposed into a rotation around the Y axis followed by a phase shift.
930    /// The enclosed unitary matrix is guaranteed to be unitary.
931    ///
932    /// Special cases include:
933    ///
934    /// * U(theta, 0) = RY(theta)
935    /// * U(0, phi) = PhaseShift(phi)
936    /// * U(Pi/2, Pi) = Hadamard
937    /// * U(Pi, Pi) = Pauli-X
938    ///
939    /// # Arguments
940    ///
941    /// * `qubit` - The index of the qubit to which the operator will be applied.
942    ///
943    /// * `theta` - The rotation angle in radians.
944    ///
945    /// * `phi` - The phase shift angle in radians.
946    pub fn ry_phase_gate(&mut self, qubit: usize, theta: f64, phi: f64) -> &mut Self {
947        let gate: Gate = Gate::ry_phase_gate(qubit, theta, phi);
948        self.add_gate(gate);
949        self
950    }
951
952    /// Creates and adds multiple new Unitary2 operator gates from a rotation angle theta and phase shift angle phi.
953    ///
954    /// This operator can be decomposed into a rotation around the Y axis followed by a phase shift.
955    /// The enclosed unitary matrix is guaranteed to be unitary.
956    ///
957    /// Special cases include:
958    /// * U(theta, 0) = RY(theta)
959    /// * U(0, phi) = PhaseShift(phi)
960    /// * U(Pi/2, Pi) = Hadamard
961    /// * U(Pi, Pi) = Pauli-X
962    ///
963    /// # Arguments
964    /// * `qubits` - A vector of indices of the qubits to which the operator will be applied.
965    /// * `theta` - The rotation angle in radians for all gates.
966    /// * `phi` - The phase shift angle in radians for all gates.
967    pub fn ry_phase_gates(&mut self, qubits: Vec<usize>, theta: f64, phi: f64) -> &mut Self {
968        let gates: Vec<Gate> = Gate::ry_phase_multi_gate(qubits, theta, phi);
969        self.add_gates(gates);
970        self
971    }
972
973    /// Creates and adds controlled Unitary2 operator gates from a rotation angle theta and phase shift angle phi.
974    ///
975    /// This operator can be decomposed into a rotation around the Y axis followed by a phase shift.
976    /// The enclosed unitary matrix is guaranteed to be unitary.
977    ///
978    /// Special cases include:
979    /// * U(theta, 0) = RY(theta)
980    /// * U(0, phi) = PhaseShift(phi)
981    /// * U(Pi/2, Pi) = Hadamard
982    /// * U(Pi, Pi) = Pauli-X
983    ///
984    /// # Arguments
985    ///
986    /// * `target_qubits` - A vector of indices of the target qubits.
987    ///
988    /// * `control_qubits` - A vector of indices of the control qubits.
989    ///
990    /// * `theta` - The rotation angle in radians for all gates.
991    ///
992    /// * `phi` - The phase shift angle in radians for all gates.
993    pub fn cry_phase_gates(
994        &mut self,
995        target_qubits: Vec<usize>,
996        control_qubits: Vec<usize>,
997        theta: f64,
998        phi: f64,
999    ) -> &mut Self {
1000        let gates: Vec<Gate> =
1001            Gate::ry_phase_controlled_gates(target_qubits, control_qubits, theta, phi);
1002        self.add_gates(gates);
1003        self
1004    }
1005
1006    // -- MULTI-QUBIT GATES --
1007
1008    /// Adds a CNOT gate to the circuit builder.
1009    ///
1010    /// # Arguments
1011    ///
1012    /// * `target_qubit` - The index of the target qubit.
1013    /// * `control_qubit` - The index of the control qubit.
1014    pub fn cnot_gate(&mut self, target_qubit: usize, control_qubit: usize) -> &mut Self {
1015        let gate: Gate = Gate::cnot_gate(target_qubit, control_qubit);
1016        self.add_gate(gate);
1017        self
1018    }
1019
1020    /// Adds a SWAP gate to the circuit builder.
1021    ///
1022    /// # Arguments
1023    ///
1024    /// * `qubit1` - The index of the first qubit to swap.
1025    /// * `qubit2` - The index of the second qubit to swap.
1026    pub fn swap_gate(&mut self, qubit1: usize, qubit2: usize) -> &mut Self {
1027        let gate: Gate = Gate::swap_gate(qubit1, qubit2);
1028        self.add_gate(gate);
1029        self
1030    }
1031
1032    /// Adds a controlled SWAP gate to the circuit builder.
1033    ///
1034    /// # Arguments
1035    ///
1036    /// * `target_qubit1` - The index of the first qubit to swap.
1037    /// * `target_qubit2` - The index of the second qubit to swap.
1038    /// * `control_qubits` - A vector of indices of the control qubits.
1039    pub fn cswap_gate(
1040        &mut self,
1041        target_qubit1: usize,
1042        target_qubit2: usize,
1043        control_qubits: Vec<usize>,
1044    ) -> &mut Self {
1045        let gate: Gate = Gate::Operator(
1046            Box::new(crate::components::operator::SWAP),
1047            vec![target_qubit1, target_qubit2],
1048            control_qubits,
1049        );
1050        self.add_gate(gate);
1051        self
1052    }
1053
1054    /// Adds a Toffoli (CCNOT) gate to the circuit builder.
1055    ///
1056    /// # Arguments
1057    ///
1058    /// * `target_qubit` - The index of the target qubit.
1059    /// * `control_qubit1` - The index of the first control qubit.
1060    /// * `control_qubit2` - The index of the second control qubit.
1061    pub fn toffoli_gate(
1062        &mut self,
1063        control_qubit1: usize,
1064        control_qubit2: usize,
1065        target_qubit: usize,
1066    ) -> &mut Self {
1067        let gate: Gate = Gate::toffoli_gate(target_qubit, vec![control_qubit1, control_qubit2]);
1068        self.add_gate(gate);
1069        self
1070    }
1071
1072    /// Adds a Matchgate to the circuit builder.
1073    ///
1074    /// # Arguments
1075    ///
1076    /// * `target_qubit` - The index of the first target qubit. The second target qubit is assumed to be the next qubit.
1077    /// * `theta` - The angle of rotation in radians.
1078    /// * `phi1` - The first phase shift in radians.
1079    /// * `phi2` - The second phase shift in radians.
1080    ///
1081    /// # Warning
1082    ///
1083    /// This gate is not yet compilable to OpenQASM, since it requires advanced decomposition techniques.
1084    pub fn matchgate(
1085        &mut self,
1086        target_qubit: usize,
1087        theta: f64,
1088        phi1: f64,
1089        phi2: f64,
1090    ) -> &mut Self {
1091        let gate: Gate = Gate::matchgate(target_qubit, theta, phi1, phi2);
1092        self.add_gate(gate);
1093        self
1094    }
1095
1096    /// Adds a controlled Matchgate to the circuit builder.
1097    ///
1098    /// # Arguments
1099    ///
1100    /// * `target_qubit` - The index of the first target qubit. The second target qubit is assumed to be the next qubit.
1101    /// * `control_qubits` - A vector of indices of the control qubits.
1102    /// * `theta` - The angle of rotation in radians.
1103    /// * `phi1` - The first phase shift in radians.
1104    /// * `phi2` - The second phase shift in radians.
1105    /// 
1106    /// # Warning
1107    ///
1108    /// This gate is not yet compilable to OpenQASM, since it requires advanced decomposition techniques.
1109    pub fn cmatchgate(
1110        &mut self,
1111        target_qubit: usize,
1112        control_qubits: Vec<usize>,
1113        theta: f64,
1114        phi1: f64,
1115        phi2: f64,
1116    ) -> &mut Self {
1117        let gate: Gate =
1118            Gate::controlled_matchgate(target_qubit, control_qubits, theta, phi1, phi2);
1119        self.add_gate(gate);
1120        self
1121    }
1122
1123    /// Adds a custom operator gate to the circuit builder.
1124    ///
1125    /// # Arguments
1126    ///
1127    /// * `operator` - The operator to be added to the circuit builder.
1128    /// * `target_qubits` - A vector of indices of the target qubits.
1129    /// * `control_qubits` - An vector of indices of the control qubits.
1130    pub fn add_operator_gate(
1131        &mut self,
1132        operator: Box<dyn Operator>,
1133        target_qubits: Vec<usize>,
1134        control_qubits: Vec<usize>,
1135    ) -> &mut Self {
1136        let gate: Gate = Gate::Operator(operator, target_qubits, control_qubits);
1137        self.add_gate(gate);
1138        self
1139    }
1140
1141    // -- PARAMETRIC GATES --
1142
1143    /// Adds a parametric Ry phase gate to the circuit builder.
1144    /// 
1145    /// # Arguments
1146    ///
1147    /// * `target_index` - The index of the target qubit.
1148    /// * `parameter` - The parameter of size 2 to be used in the gate.
1149    pub fn parametric_ry_phase_gate(&mut self, target_index: usize, parameter: Parameter<2>) -> &mut Self {
1150        let p_gate = ParametricRyPhase { parameter };
1151        let gate = Gate::Parametric(Box::new(p_gate), vec![target_index], vec![]);
1152        self.add_gate(gate);
1153        self
1154    }
1155
1156    /// Adds multiple parametric Ry phase gates to the circuit builder, each with its own parameter.
1157    ///
1158    /// # Arguments
1159    ///
1160    /// * `target_indices` - A vector of indices of the target qubits.
1161    /// * `parameters` - A vector of parameters of size 2 to be used in the gates.
1162    /// 
1163    /// # Warning
1164    /// 
1165    /// This method is fallible due to the potential for a mismatch in the number of parameters.
1166    /// If the number of parameters is not equal to the number of target indices, it will return an error.
1167    /// Therefore, the `Result` must be handled appropriately before chaining further operations.
1168    pub fn parametric_ry_phase_gates(&mut self, target_indices: Vec<usize>, parameters: Vec<Parameter<2>>) -> Result<&mut Self, Error> {
1169        if target_indices.len() != parameters.len() {
1170            return Err(Error::MismatchedNumberOfParameters {
1171                expected: target_indices.len(),
1172                actual: parameters.len(),
1173            });
1174        }
1175
1176        for (target_index, parameter) in target_indices.into_iter().zip(parameters.into_iter()) {
1177            self.parametric_ry_phase_gate(target_index, parameter);
1178        }
1179        Ok(self)
1180    }
1181
1182    /// Adds multiple controlled parametric Ry phase gates to the circuit builder, each with its own parameter.
1183    /// 
1184    /// # Arguments
1185    ///
1186    /// * `target_indices` - A vector of indices of the target qubits.
1187    /// * `control_indices` - A vector of indices of the control qubits.
1188    /// * `parameters` - A vector of parameters of size 2 to be used in the gates.
1189    ///
1190    /// # Warning
1191    ///
1192    /// This method is fallible due to the potential for a mismatch in the number of parameters.
1193    /// If the number of parameters is not equal to the number of target indices, it will return an error.
1194    /// Therefore, the `Result` must be handled appropriately before chaining further operations.
1195    pub fn parametric_cry_phase_gates(&mut self, target_indices: Vec<usize>, control_indices: Vec<usize>, parameters: Vec<Parameter<2>>) -> Result<&mut Self, Error> {
1196        if target_indices.len() != parameters.len() {
1197            return Err(Error::MismatchedNumberOfParameters {
1198                expected: target_indices.len(),
1199                actual: parameters.len(),
1200            });
1201        }
1202
1203        for (target_index, parameter) in target_indices.into_iter().zip(parameters.into_iter()) {
1204            let p_gate = ParametricRyPhase { parameter: parameter.clone() };
1205            let gate = Gate::Parametric(Box::new(p_gate), vec![target_index], control_indices.clone());
1206            self.add_gate(gate);
1207        }
1208        Ok(self)
1209    }
1210
1211    /// Adds a parametric matchgate to the circuit builder.
1212    ///
1213    /// # Arguments
1214    ///
1215    /// * `target_index` - The index of the target qubit.
1216    /// * `parameter` - The parameter of size 3 to be used in the gate.
1217    pub fn parametric_matchgate(&mut self, target_index: usize, parameter: Parameter<3>) -> &mut Self {
1218        let p_gate = ParametricMatchgate { parameter };
1219        let gate = Gate::Parametric(Box::new(p_gate), vec![target_index], vec![]);
1220        self.add_gate(gate);
1221        self
1222    }
1223
1224    /// Adds a controlled parametric matchgate to the circuit builder.
1225    ///
1226    /// # Arguments
1227    ///
1228    /// * `target_index` - The index of the target qubit.
1229    /// * `control_indices` - A vector of indices of the control qubits.
1230    /// * `parameter` - The parameter of size 3 to be used in the gate.
1231    pub fn parametric_cmatchgate(&mut self, target_index: usize, control_indices: Vec<usize>, parameter: Parameter<3>) -> &mut Self {
1232        let p_gate = ParametricMatchgate { parameter };
1233        let gate = Gate::Parametric(Box::new(p_gate), vec![target_index], control_indices);
1234        self.add_gate(gate);
1235        self
1236    }
1237
1238    // -- MEASUREMENT GATES --
1239
1240    /// Adds a measurement gate to the circuit builder.
1241    ///
1242    /// # Arguments
1243    ///
1244    /// * `basis` - The measurement basis (e.g., computational).
1245    ///
1246    /// * `qubits` - A vector of indices of the qubits to be measured.
1247    pub fn measure_gate(&mut self, basis: MeasurementBasis, qubits: Vec<usize>) -> &mut Self {
1248        let gate: Gate = Gate::Measurement(basis, qubits);
1249        self.add_gate(gate);
1250        self
1251    }
1252}