quantrs2_circuit/builder/
mod.rs1use std::collections::HashMap;
7use std::fmt;
8use std::sync::Arc;
9
10pub type CircuitBuilder<const N: usize> = Circuit<N>;
12
13use quantrs2_core::{
14 decomposition::{utils as decomp_utils, CompositeGate},
15 error::QuantRS2Result,
16 gate::{
17 multi::{
18 Fredkin,
19 ISwap,
20 Toffoli,
21 CH,
22 CNOT,
23 CRX,
24 CRY,
25 CRZ,
26 CS,
27 CY,
28 CZ,
29 DCX,
31 ECR,
32 RXX,
33 RYY,
34 RZX,
35 RZZ,
36 SWAP,
37 },
38 single::{
39 Hadamard,
40 Identity,
42 PGate,
43 PauliX,
44 PauliY,
45 PauliZ,
46 Phase,
47 PhaseDagger,
48 RotationX,
49 RotationY,
50 RotationZ,
51 SqrtX,
52 SqrtXDagger,
53 TDagger,
54 UGate,
55 T,
56 },
57 GateOp,
58 },
59 qubit::QubitId,
60 register::Register,
61};
62
63use scirs2_core::Complex64;
64use std::any::Any;
65use std::collections::HashSet;
66
67#[derive(Debug, Clone)]
69pub struct CircuitStats {
70 pub total_gates: usize,
72 pub gate_counts: HashMap<String, usize>,
74 pub depth: usize,
76 pub two_qubit_gates: usize,
78 pub multi_qubit_gates: usize,
80 pub gate_density: f64,
82 pub used_qubits: usize,
84 pub total_qubits: usize,
86}
87
88#[derive(Debug, Clone)]
90pub struct GatePool {
91 gates: HashMap<String, Arc<dyn GateOp + Send + Sync>>,
93}
94
95impl GatePool {
96 #[must_use]
98 pub fn new() -> Self {
99 let mut gates = HashMap::with_capacity(16);
100
101 for qubit_id in 0..32 {
103 let qubit = QubitId::new(qubit_id);
104
105 gates.insert(
107 format!("H_{qubit_id}"),
108 Arc::new(Hadamard { target: qubit }) as Arc<dyn GateOp + Send + Sync>,
109 );
110 gates.insert(
111 format!("X_{qubit_id}"),
112 Arc::new(PauliX { target: qubit }) as Arc<dyn GateOp + Send + Sync>,
113 );
114 gates.insert(
115 format!("Y_{qubit_id}"),
116 Arc::new(PauliY { target: qubit }) as Arc<dyn GateOp + Send + Sync>,
117 );
118 gates.insert(
119 format!("Z_{qubit_id}"),
120 Arc::new(PauliZ { target: qubit }) as Arc<dyn GateOp + Send + Sync>,
121 );
122 gates.insert(
123 format!("S_{qubit_id}"),
124 Arc::new(Phase { target: qubit }) as Arc<dyn GateOp + Send + Sync>,
125 );
126 gates.insert(
127 format!("T_{qubit_id}"),
128 Arc::new(T { target: qubit }) as Arc<dyn GateOp + Send + Sync>,
129 );
130 }
131
132 Self { gates }
133 }
134
135 pub fn get_gate<G: GateOp + Clone + Send + Sync + 'static>(
142 &mut self,
143 gate: G,
144 ) -> Arc<dyn GateOp + Send + Sync> {
145 if gate.is_parameterized() {
147 return Arc::new(gate) as Arc<dyn GateOp + Send + Sync>;
148 }
149
150 let key = format!("{}_{:?}", gate.name(), gate.qubits());
151
152 if let Some(cached_gate) = self.gates.get(&key) {
153 cached_gate.clone()
154 } else {
155 let arc_gate = Arc::new(gate) as Arc<dyn GateOp + Send + Sync>;
156 self.gates.insert(key, arc_gate.clone());
157 arc_gate
158 }
159 }
160}
161
162impl Default for GatePool {
163 fn default() -> Self {
164 Self::new()
165 }
166}
167
168#[derive(Debug, Clone)]
170pub struct Measure {
171 pub target: QubitId,
172}
173
174impl GateOp for Measure {
175 fn name(&self) -> &'static str {
176 "measure"
177 }
178
179 fn qubits(&self) -> Vec<QubitId> {
180 vec![self.target]
181 }
182
183 fn is_parameterized(&self) -> bool {
184 false
185 }
186
187 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
188 Err(quantrs2_core::error::QuantRS2Error::UnsupportedOperation(
195 "Measure has no unitary matrix representation".to_string(),
196 ))
197 }
198
199 fn as_any(&self) -> &dyn Any {
200 self
201 }
202
203 fn clone_gate(&self) -> Box<dyn GateOp> {
204 Box::new(self.clone())
205 }
206}
207
208struct BoxGateWrapper(Box<dyn GateOp>);
212
213impl std::fmt::Debug for BoxGateWrapper {
214 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215 self.0.fmt(f)
216 }
217}
218
219unsafe impl Send for BoxGateWrapper {}
221unsafe impl Sync for BoxGateWrapper {}
222
223impl GateOp for BoxGateWrapper {
224 fn name(&self) -> &'static str {
225 self.0.name()
226 }
227 fn qubits(&self) -> Vec<QubitId> {
228 self.0.qubits()
229 }
230 fn num_qubits(&self) -> usize {
231 self.0.num_qubits()
232 }
233 fn is_parameterized(&self) -> bool {
234 self.0.is_parameterized()
235 }
236 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
237 self.0.matrix()
238 }
239 fn as_any(&self) -> &dyn std::any::Any {
240 self.0.as_any()
241 }
242 fn clone_gate(&self) -> Box<dyn GateOp> {
243 self.0.clone_gate()
244 }
245}
246
247#[derive(Debug, Clone)]
251pub struct BarrierInfo {
252 pub after_gate_index: usize,
255 pub qubits: Vec<QubitId>,
257}
258
259pub struct Circuit<const N: usize> {
277 gates: Vec<Arc<dyn GateOp + Send + Sync>>,
279 gate_pool: GatePool,
281 pub barriers: Vec<BarrierInfo>,
285}
286
287impl<const N: usize> Clone for Circuit<N> {
288 fn clone(&self) -> Self {
289 Self {
291 gates: self.gates.clone(),
292 gate_pool: self.gate_pool.clone(),
293 barriers: self.barriers.clone(),
294 }
295 }
296}
297
298impl<const N: usize> fmt::Debug for Circuit<N> {
299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300 f.debug_struct("Circuit")
301 .field("num_qubits", &N)
302 .field("num_gates", &self.gates.len())
303 .finish()
304 }
305}
306
307impl<const N: usize> Circuit<N> {
308 #[must_use]
318 pub fn new() -> Self {
319 Self {
320 gates: Vec::with_capacity(64), gate_pool: GatePool::new(),
322 barriers: Vec::new(),
323 }
324 }
325
326 #[must_use]
328 pub fn with_capacity(capacity: usize) -> Self {
329 Self {
330 gates: Vec::with_capacity(capacity),
331 gate_pool: GatePool::new(),
332 barriers: Vec::new(),
333 }
334 }
335
336 pub fn add_gate<G: GateOp + Clone + Send + Sync + 'static>(
338 &mut self,
339 gate: G,
340 ) -> QuantRS2Result<&mut Self> {
341 for qubit in gate.qubits() {
343 if qubit.id() as usize >= N {
344 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
345 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
346 gate.name(),
347 qubit.id(),
348 N,
349 N - 1
350 )));
351 }
352 }
353
354 let gate_arc = self.gate_pool.get_gate(gate);
356 self.gates.push(gate_arc);
357 Ok(self)
358 }
359
360 pub fn from_gates(gates: Vec<Box<dyn GateOp>>) -> QuantRS2Result<Self> {
366 let mut circuit = Self::with_capacity(gates.len());
367 for gate in gates {
368 let in_range = gate.qubits().iter().all(|q| (q.id() as usize) < N);
370 if in_range {
371 let arc: Arc<dyn GateOp + Send + Sync> = Arc::new(BoxGateWrapper(gate));
375 circuit.gates.push(arc);
376 }
377 }
378 Ok(circuit)
379 }
380
381 pub fn add_gate_arc(
383 &mut self,
384 gate: Arc<dyn GateOp + Send + Sync>,
385 ) -> QuantRS2Result<&mut Self> {
386 for qubit in gate.qubits() {
388 if qubit.id() as usize >= N {
389 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
390 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
391 gate.name(),
392 qubit.id(),
393 N,
394 N - 1
395 )));
396 }
397 }
398
399 self.gates.push(gate);
400 Ok(self)
401 }
402
403 #[must_use]
405 pub fn gates(&self) -> &[Arc<dyn GateOp + Send + Sync>] {
406 &self.gates
407 }
408
409 #[must_use]
411 pub fn gates_as_boxes(&self) -> Vec<Box<dyn GateOp>> {
412 self.gates
413 .iter()
414 .map(|arc_gate| arc_gate.clone_gate())
415 .collect()
416 }
417
418 #[must_use]
422 pub fn count_gates_by_type(&self) -> HashMap<String, usize> {
423 let mut counts = HashMap::new();
424 for gate in &self.gates {
425 *counts.entry(gate.name().to_string()).or_insert(0) += 1;
426 }
427 counts
428 }
429
430 #[must_use]
432 pub fn calculate_depth(&self) -> usize {
433 if self.gates.is_empty() {
434 return 0;
435 }
436
437 let mut qubit_last_used = vec![0; N];
439 let mut max_depth = 0;
440
441 for (gate_idx, gate) in self.gates.iter().enumerate() {
442 let gate_qubits = gate.qubits();
443
444 let gate_start_depth = gate_qubits
446 .iter()
447 .map(|q| qubit_last_used[q.id() as usize])
448 .max()
449 .unwrap_or(0);
450
451 let gate_end_depth = gate_start_depth + 1;
452
453 for qubit in gate_qubits {
455 qubit_last_used[qubit.id() as usize] = gate_end_depth;
456 }
457
458 max_depth = max_depth.max(gate_end_depth);
459 }
460
461 max_depth
462 }
463
464 #[must_use]
466 pub fn count_two_qubit_gates(&self) -> usize {
467 self.gates
468 .iter()
469 .filter(|gate| gate.qubits().len() == 2)
470 .count()
471 }
472
473 #[must_use]
475 pub fn count_multi_qubit_gates(&self) -> usize {
476 self.gates
477 .iter()
478 .filter(|gate| gate.qubits().len() >= 3)
479 .count()
480 }
481
482 #[must_use]
484 pub fn calculate_critical_path(&self) -> usize {
485 self.calculate_depth()
486 }
487
488 #[must_use]
490 pub fn calculate_gate_density(&self) -> f64 {
491 if N == 0 {
492 0.0
493 } else {
494 self.gates.len() as f64 / N as f64
495 }
496 }
497
498 #[must_use]
500 pub fn get_used_qubits(&self) -> HashSet<QubitId> {
501 let mut used_qubits = HashSet::new();
502 for gate in &self.gates {
503 for qubit in gate.qubits() {
504 used_qubits.insert(qubit);
505 }
506 }
507 used_qubits
508 }
509
510 #[must_use]
512 pub fn uses_all_qubits(&self) -> bool {
513 self.get_used_qubits().len() == N
514 }
515
516 #[must_use]
518 pub fn gates_on_qubit(&self, target_qubit: QubitId) -> Vec<&Arc<dyn GateOp + Send + Sync>> {
519 self.gates
520 .iter()
521 .filter(|gate| gate.qubits().contains(&target_qubit))
522 .collect()
523 }
524
525 #[must_use]
527 pub fn gates_in_range(&self, start: usize, end: usize) -> &[Arc<dyn GateOp + Send + Sync>] {
528 let end = end.min(self.gates.len().saturating_sub(1));
529 let start = start.min(end);
530 &self.gates[start..=end]
531 }
532
533 #[must_use]
535 pub fn is_empty(&self) -> bool {
536 self.gates.is_empty()
537 }
538
539 #[must_use]
541 pub fn get_stats(&self) -> CircuitStats {
542 let gate_counts = self.count_gates_by_type();
543 let depth = self.calculate_depth();
544 let two_qubit_gates = self.count_two_qubit_gates();
545 let multi_qubit_gates = self.count_multi_qubit_gates();
546 let gate_density = self.calculate_gate_density();
547 let used_qubits = self.get_used_qubits().len();
548
549 CircuitStats {
550 total_gates: self.gates.len(),
551 gate_counts,
552 depth,
553 two_qubit_gates,
554 multi_qubit_gates,
555 gate_density,
556 used_qubits,
557 total_qubits: N,
558 }
559 }
560
561 #[must_use]
563 pub const fn num_qubits(&self) -> usize {
564 N
565 }
566
567 #[must_use]
569 pub fn num_gates(&self) -> usize {
570 self.gates.len()
571 }
572
573 #[must_use]
575 pub fn get_gate_names(&self) -> Vec<String> {
576 self.gates
577 .iter()
578 .map(|gate| gate.name().to_string())
579 .collect()
580 }
581
582 pub(crate) fn find_gate_by_type_and_index(
584 &self,
585 gate_type: &str,
586 index: usize,
587 ) -> Option<&dyn GateOp> {
588 let mut count = 0;
589 for gate in &self.gates {
590 if gate.name() == gate_type {
591 if count == index {
592 return Some(gate.as_ref());
593 }
594 count += 1;
595 }
596 }
597 None
598 }
599
600 pub fn run<S: Simulator<N>>(&self, simulator: S) -> QuantRS2Result<Register<N>> {
602 simulator.run(self)
603 }
604
605 pub fn decompose(&self) -> QuantRS2Result<Self> {
610 let mut decomposed = Self::new();
611
612 let boxed_gates = self.gates_as_boxes();
614
615 let simple_gates = decomp_utils::decompose_circuit(&boxed_gates)?;
617
618 for gate in simple_gates {
620 decomposed.add_gate_box(gate)?;
621 }
622
623 Ok(decomposed)
624 }
625
626 #[must_use]
628 pub const fn build(self) -> Self {
629 self
630 }
631
632 pub fn optimize(&self) -> QuantRS2Result<Self> {
639 let mut optimized = Self::new();
640
641 let boxed_gates = self.gates_as_boxes();
643
644 let simplified_gates_result = decomp_utils::optimize_gate_sequence(&boxed_gates);
646
647 if let Ok(simplified_gates) = simplified_gates_result {
649 for g in simplified_gates {
650 optimized.add_gate_box(g)?;
651 }
652 }
653
654 let new_gate_count = optimized.gates.len();
657 optimized.barriers = self
658 .barriers
659 .iter()
660 .map(|b| BarrierInfo {
661 after_gate_index: b.after_gate_index.min(new_gate_count),
662 qubits: b.qubits.clone(),
663 })
664 .collect();
665
666 Ok(optimized)
667 }
668
669 pub(crate) fn add_gate_box(&mut self, gate: Box<dyn GateOp>) -> QuantRS2Result<&mut Self> {
672 for qubit in gate.qubits() {
674 if qubit.id() as usize >= N {
675 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
676 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
677 gate.name(),
678 qubit.id(),
679 N,
680 N - 1
681 )));
682 }
683 }
684
685 let cloned_gate = gate.clone_gate();
688
689 if let Some(g) = cloned_gate.as_any().downcast_ref::<Hadamard>() {
694 self.gates
695 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
696 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliX>() {
697 self.gates
698 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
699 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliY>() {
700 self.gates
701 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
702 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliZ>() {
703 self.gates
704 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
705 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CNOT>() {
706 self.gates
707 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
708 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CZ>() {
709 self.gates
710 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
711 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<SWAP>() {
712 self.gates
713 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
714 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CY>() {
715 self.gates
716 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
717 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CH>() {
718 self.gates
719 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
720 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CS>() {
721 self.gates
722 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
723 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Toffoli>() {
724 self.gates
725 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
726 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Fredkin>() {
727 self.gates
728 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
729 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CRX>() {
730 self.gates
731 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
732 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CRY>() {
733 self.gates
734 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
735 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CRZ>() {
736 self.gates
737 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
738 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<ISwap>() {
739 self.gates
740 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
741 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<ECR>() {
742 self.gates
743 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
744 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RXX>() {
745 self.gates
746 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
747 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RYY>() {
748 self.gates
749 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
750 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RZZ>() {
751 self.gates
752 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
753 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RZX>() {
754 self.gates
755 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
756 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<DCX>() {
757 self.gates
758 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
759 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RotationX>() {
760 self.gates
761 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
762 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RotationY>() {
763 self.gates
764 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
765 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RotationZ>() {
766 self.gates
767 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
768 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Phase>() {
769 self.gates
770 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
771 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PhaseDagger>() {
772 self.gates
773 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
774 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<T>() {
775 self.gates
776 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
777 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<TDagger>() {
778 self.gates
779 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
780 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<SqrtX>() {
781 self.gates
782 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
783 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<SqrtXDagger>() {
784 self.gates
785 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
786 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<UGate>() {
787 self.gates
788 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
789 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PGate>() {
790 self.gates
791 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
792 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Identity>() {
793 self.gates
794 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
795 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Measure>() {
796 self.gates
797 .push(Arc::new(g.clone()) as Arc<dyn GateOp + Send + Sync>);
798 } else {
799 self.gates
806 .push(Arc::new(BoxGateWrapper(cloned_gate)) as Arc<dyn GateOp + Send + Sync>);
807 }
808
809 Ok(self)
810 }
811
812 pub fn create_composite(
817 &self,
818 start_idx: usize,
819 end_idx: usize,
820 name: &str,
821 ) -> QuantRS2Result<CompositeGate> {
822 if start_idx >= self.gates.len() || end_idx > self.gates.len() || start_idx >= end_idx {
823 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
824 "Invalid start/end indices ({}/{}) for circuit with {} gates",
825 start_idx,
826 end_idx,
827 self.gates.len()
828 )));
829 }
830
831 let mut gates: Vec<Box<dyn GateOp>> = Vec::new();
834 for gate in &self.gates[start_idx..end_idx] {
835 gates.push(decomp_utils::clone_gate(gate.as_ref())?);
836 }
837
838 let mut qubits = Vec::new();
840 for gate in &gates {
841 for qubit in gate.qubits() {
842 if !qubits.contains(&qubit) {
843 qubits.push(qubit);
844 }
845 }
846 }
847
848 Ok(CompositeGate {
849 gates,
850 qubits,
851 name: name.to_string(),
852 })
853 }
854
855 pub fn add_composite(&mut self, composite: &CompositeGate) -> QuantRS2Result<&mut Self> {
857 for gate in &composite.gates {
859 let gate_clone = decomp_utils::clone_gate(gate.as_ref())?;
864 self.add_gate_box(gate_clone)?;
865 }
866
867 Ok(self)
868 }
869
870 #[must_use]
872 pub fn with_classical_control(self) -> crate::classical::ClassicalCircuit<N> {
873 let mut classical_circuit = crate::classical::ClassicalCircuit::new();
874
875 let _ = classical_circuit.add_classical_register("c", N);
877
878 for gate in self.gates {
880 let boxed_gate = gate.clone_gate();
881 classical_circuit
882 .operations
883 .push(crate::classical::CircuitOp::Quantum(boxed_gate));
884 }
885
886 classical_circuit
887 }
888
889 pub fn bell_state(&mut self, qubit1: u32, qubit2: u32) -> QuantRS2Result<&mut Self> {
899 self.h(QubitId::new(qubit1))?;
900 self.cnot(QubitId::new(qubit1), QubitId::new(qubit2))?;
901 Ok(self)
902 }
903
904 pub fn ghz_state(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
912 if qubits.is_empty() {
913 return Ok(self);
914 }
915
916 self.h(QubitId::new(qubits[0]))?;
918
919 for i in 1..qubits.len() {
921 self.cnot(QubitId::new(qubits[0]), QubitId::new(qubits[i]))?;
922 }
923
924 Ok(self)
925 }
926
927 pub fn w_state(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
933 if qubits.is_empty() {
934 return Ok(self);
935 }
936
937 let n = qubits.len() as f64;
938
939 self.ry(QubitId::new(qubits[0]), 2.0 * (1.0 / n.sqrt()).acos())?;
942
943 for i in 1..qubits.len() {
944 let angle = 2.0 * (1.0 / (n - i as f64).sqrt()).acos();
945 self.cry(QubitId::new(qubits[i - 1]), QubitId::new(qubits[i]), angle)?;
946 }
947
948 for i in 0..qubits.len() - 1 {
950 self.cnot(QubitId::new(qubits[i + 1]), QubitId::new(qubits[i]))?;
951 }
952
953 Ok(self)
954 }
955
956 pub fn plus_state_all(&mut self) -> QuantRS2Result<&mut Self> {
964 for i in 0..N {
965 self.h(QubitId::new(i as u32))?;
966 }
967 Ok(self)
968 }
969
970 pub fn cnot_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
978 if qubits.len() < 2 {
979 return Ok(self);
980 }
981
982 for i in 0..qubits.len() - 1 {
983 self.cnot(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
984 }
985
986 Ok(self)
987 }
988
989 pub fn cnot_ring(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
993 if qubits.len() < 2 {
994 return Ok(self);
995 }
996
997 self.cnot_ladder(qubits)?;
999
1000 let last_idx = qubits.len() - 1;
1002 self.cnot(QubitId::new(qubits[last_idx]), QubitId::new(qubits[0]))?;
1003
1004 Ok(self)
1005 }
1006
1007 pub fn swap_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
1015 if qubits.len() < 2 {
1016 return Ok(self);
1017 }
1018
1019 for i in 0..qubits.len() - 1 {
1020 self.swap(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
1021 }
1022
1023 Ok(self)
1024 }
1025
1026 pub fn cz_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
1034 if qubits.len() < 2 {
1035 return Ok(self);
1036 }
1037
1038 for i in 0..qubits.len() - 1 {
1039 self.cz(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
1040 }
1041
1042 Ok(self)
1043 }
1044}
1045
1046impl<const N: usize> Default for Circuit<N> {
1047 fn default() -> Self {
1048 Self::new()
1049 }
1050}
1051
1052pub trait Simulator<const N: usize> {
1054 fn run(&self, circuit: &Circuit<N>) -> QuantRS2Result<Register<N>>;
1056}
1057
1058#[cfg(test)]
1059mod tests;