1use 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 Ok(vec![
190 Complex64::new(1.0, 0.0),
191 Complex64::new(0.0, 0.0),
192 Complex64::new(0.0, 0.0),
193 Complex64::new(1.0, 0.0),
194 ])
195 }
196
197 fn as_any(&self) -> &dyn Any {
198 self
199 }
200
201 fn clone_gate(&self) -> Box<dyn GateOp> {
202 Box::new(self.clone())
203 }
204}
205
206struct BoxGateWrapper(Box<dyn GateOp>);
210
211impl std::fmt::Debug for BoxGateWrapper {
212 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
213 self.0.fmt(f)
214 }
215}
216
217unsafe impl Send for BoxGateWrapper {}
219unsafe impl Sync for BoxGateWrapper {}
220
221impl GateOp for BoxGateWrapper {
222 fn name(&self) -> &'static str {
223 self.0.name()
224 }
225 fn qubits(&self) -> Vec<QubitId> {
226 self.0.qubits()
227 }
228 fn num_qubits(&self) -> usize {
229 self.0.num_qubits()
230 }
231 fn is_parameterized(&self) -> bool {
232 self.0.is_parameterized()
233 }
234 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
235 self.0.matrix()
236 }
237 fn as_any(&self) -> &dyn std::any::Any {
238 self.0.as_any()
239 }
240 fn clone_gate(&self) -> Box<dyn GateOp> {
241 self.0.clone_gate()
242 }
243}
244
245#[derive(Debug, Clone)]
249pub struct BarrierInfo {
250 pub after_gate_index: usize,
253 pub qubits: Vec<QubitId>,
255}
256
257pub struct Circuit<const N: usize> {
275 gates: Vec<Arc<dyn GateOp + Send + Sync>>,
277 gate_pool: GatePool,
279 pub barriers: Vec<BarrierInfo>,
283}
284
285impl<const N: usize> Clone for Circuit<N> {
286 fn clone(&self) -> Self {
287 Self {
289 gates: self.gates.clone(),
290 gate_pool: self.gate_pool.clone(),
291 barriers: self.barriers.clone(),
292 }
293 }
294}
295
296impl<const N: usize> fmt::Debug for Circuit<N> {
297 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
298 f.debug_struct("Circuit")
299 .field("num_qubits", &N)
300 .field("num_gates", &self.gates.len())
301 .finish()
302 }
303}
304
305impl<const N: usize> Circuit<N> {
306 #[must_use]
316 pub fn new() -> Self {
317 Self {
318 gates: Vec::with_capacity(64), gate_pool: GatePool::new(),
320 barriers: Vec::new(),
321 }
322 }
323
324 #[must_use]
326 pub fn with_capacity(capacity: usize) -> Self {
327 Self {
328 gates: Vec::with_capacity(capacity),
329 gate_pool: GatePool::new(),
330 barriers: Vec::new(),
331 }
332 }
333
334 pub fn add_gate<G: GateOp + Clone + Send + Sync + 'static>(
336 &mut self,
337 gate: G,
338 ) -> QuantRS2Result<&mut Self> {
339 for qubit in gate.qubits() {
341 if qubit.id() as usize >= N {
342 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
343 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
344 gate.name(),
345 qubit.id(),
346 N,
347 N - 1
348 )));
349 }
350 }
351
352 let gate_arc = self.gate_pool.get_gate(gate);
354 self.gates.push(gate_arc);
355 Ok(self)
356 }
357
358 pub fn from_gates(gates: Vec<Box<dyn GateOp>>) -> QuantRS2Result<Self> {
364 let mut circuit = Self::with_capacity(gates.len());
365 for gate in gates {
366 let in_range = gate.qubits().iter().all(|q| (q.id() as usize) < N);
368 if in_range {
369 let arc: Arc<dyn GateOp + Send + Sync> = Arc::new(BoxGateWrapper(gate));
373 circuit.gates.push(arc);
374 }
375 }
376 Ok(circuit)
377 }
378
379 pub fn add_gate_arc(
381 &mut self,
382 gate: Arc<dyn GateOp + Send + Sync>,
383 ) -> QuantRS2Result<&mut Self> {
384 for qubit in gate.qubits() {
386 if qubit.id() as usize >= N {
387 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
388 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
389 gate.name(),
390 qubit.id(),
391 N,
392 N - 1
393 )));
394 }
395 }
396
397 self.gates.push(gate);
398 Ok(self)
399 }
400
401 #[must_use]
403 pub fn gates(&self) -> &[Arc<dyn GateOp + Send + Sync>] {
404 &self.gates
405 }
406
407 #[must_use]
409 pub fn gates_as_boxes(&self) -> Vec<Box<dyn GateOp>> {
410 self.gates
411 .iter()
412 .map(|arc_gate| arc_gate.clone_gate())
413 .collect()
414 }
415
416 #[must_use]
420 pub fn count_gates_by_type(&self) -> HashMap<String, usize> {
421 let mut counts = HashMap::new();
422 for gate in &self.gates {
423 *counts.entry(gate.name().to_string()).or_insert(0) += 1;
424 }
425 counts
426 }
427
428 #[must_use]
430 pub fn calculate_depth(&self) -> usize {
431 if self.gates.is_empty() {
432 return 0;
433 }
434
435 let mut qubit_last_used = vec![0; N];
437 let mut max_depth = 0;
438
439 for (gate_idx, gate) in self.gates.iter().enumerate() {
440 let gate_qubits = gate.qubits();
441
442 let gate_start_depth = gate_qubits
444 .iter()
445 .map(|q| qubit_last_used[q.id() as usize])
446 .max()
447 .unwrap_or(0);
448
449 let gate_end_depth = gate_start_depth + 1;
450
451 for qubit in gate_qubits {
453 qubit_last_used[qubit.id() as usize] = gate_end_depth;
454 }
455
456 max_depth = max_depth.max(gate_end_depth);
457 }
458
459 max_depth
460 }
461
462 #[must_use]
464 pub fn count_two_qubit_gates(&self) -> usize {
465 self.gates
466 .iter()
467 .filter(|gate| gate.qubits().len() == 2)
468 .count()
469 }
470
471 #[must_use]
473 pub fn count_multi_qubit_gates(&self) -> usize {
474 self.gates
475 .iter()
476 .filter(|gate| gate.qubits().len() >= 3)
477 .count()
478 }
479
480 #[must_use]
482 pub fn calculate_critical_path(&self) -> usize {
483 self.calculate_depth()
484 }
485
486 #[must_use]
488 pub fn calculate_gate_density(&self) -> f64 {
489 if N == 0 {
490 0.0
491 } else {
492 self.gates.len() as f64 / N as f64
493 }
494 }
495
496 #[must_use]
498 pub fn get_used_qubits(&self) -> HashSet<QubitId> {
499 let mut used_qubits = HashSet::new();
500 for gate in &self.gates {
501 for qubit in gate.qubits() {
502 used_qubits.insert(qubit);
503 }
504 }
505 used_qubits
506 }
507
508 #[must_use]
510 pub fn uses_all_qubits(&self) -> bool {
511 self.get_used_qubits().len() == N
512 }
513
514 #[must_use]
516 pub fn gates_on_qubit(&self, target_qubit: QubitId) -> Vec<&Arc<dyn GateOp + Send + Sync>> {
517 self.gates
518 .iter()
519 .filter(|gate| gate.qubits().contains(&target_qubit))
520 .collect()
521 }
522
523 #[must_use]
525 pub fn gates_in_range(&self, start: usize, end: usize) -> &[Arc<dyn GateOp + Send + Sync>] {
526 let end = end.min(self.gates.len().saturating_sub(1));
527 let start = start.min(end);
528 &self.gates[start..=end]
529 }
530
531 #[must_use]
533 pub fn is_empty(&self) -> bool {
534 self.gates.is_empty()
535 }
536
537 #[must_use]
539 pub fn get_stats(&self) -> CircuitStats {
540 let gate_counts = self.count_gates_by_type();
541 let depth = self.calculate_depth();
542 let two_qubit_gates = self.count_two_qubit_gates();
543 let multi_qubit_gates = self.count_multi_qubit_gates();
544 let gate_density = self.calculate_gate_density();
545 let used_qubits = self.get_used_qubits().len();
546
547 CircuitStats {
548 total_gates: self.gates.len(),
549 gate_counts,
550 depth,
551 two_qubit_gates,
552 multi_qubit_gates,
553 gate_density,
554 used_qubits,
555 total_qubits: N,
556 }
557 }
558
559 #[must_use]
561 pub const fn num_qubits(&self) -> usize {
562 N
563 }
564
565 #[must_use]
567 pub fn num_gates(&self) -> usize {
568 self.gates.len()
569 }
570
571 #[must_use]
573 pub fn get_gate_names(&self) -> Vec<String> {
574 self.gates
575 .iter()
576 .map(|gate| gate.name().to_string())
577 .collect()
578 }
579
580 pub(crate) fn find_gate_by_type_and_index(
582 &self,
583 gate_type: &str,
584 index: usize,
585 ) -> Option<&dyn GateOp> {
586 let mut count = 0;
587 for gate in &self.gates {
588 if gate.name() == gate_type {
589 if count == index {
590 return Some(gate.as_ref());
591 }
592 count += 1;
593 }
594 }
595 None
596 }
597
598 pub fn run<S: Simulator<N>>(&self, simulator: S) -> QuantRS2Result<Register<N>> {
600 simulator.run(self)
601 }
602
603 pub fn decompose(&self) -> QuantRS2Result<Self> {
608 let mut decomposed = Self::new();
609
610 let boxed_gates = self.gates_as_boxes();
612
613 let simple_gates = decomp_utils::decompose_circuit(&boxed_gates)?;
615
616 for gate in simple_gates {
618 decomposed.add_gate_box(gate)?;
619 }
620
621 Ok(decomposed)
622 }
623
624 #[must_use]
626 pub const fn build(self) -> Self {
627 self
628 }
629
630 pub fn optimize(&self) -> QuantRS2Result<Self> {
637 let mut optimized = Self::new();
638
639 let boxed_gates = self.gates_as_boxes();
641
642 let simplified_gates_result = decomp_utils::optimize_gate_sequence(&boxed_gates);
644
645 if let Ok(simplified_gates) = simplified_gates_result {
647 for g in simplified_gates {
648 optimized.add_gate_box(g)?;
649 }
650 }
651
652 let new_gate_count = optimized.gates.len();
655 optimized.barriers = self
656 .barriers
657 .iter()
658 .map(|b| BarrierInfo {
659 after_gate_index: b.after_gate_index.min(new_gate_count),
660 qubits: b.qubits.clone(),
661 })
662 .collect();
663
664 Ok(optimized)
665 }
666
667 pub(crate) fn add_gate_box(&mut self, gate: Box<dyn GateOp>) -> QuantRS2Result<&mut Self> {
670 for qubit in gate.qubits() {
672 if qubit.id() as usize >= N {
673 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
674 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
675 gate.name(),
676 qubit.id(),
677 N,
678 N - 1
679 )));
680 }
681 }
682
683 let cloned_gate = gate.clone_gate();
686
687 if let Some(g) = cloned_gate.as_any().downcast_ref::<Hadamard>() {
692 self.gates
693 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
694 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliX>() {
695 self.gates
696 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
697 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliY>() {
698 self.gates
699 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
700 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliZ>() {
701 self.gates
702 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
703 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CNOT>() {
704 self.gates
705 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
706 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CZ>() {
707 self.gates
708 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
709 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<SWAP>() {
710 self.gates
711 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
712 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CY>() {
713 self.gates
714 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
715 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CH>() {
716 self.gates
717 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
718 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CS>() {
719 self.gates
720 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
721 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Toffoli>() {
722 self.gates
723 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
724 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Fredkin>() {
725 self.gates
726 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
727 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CRX>() {
728 self.gates
729 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
730 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CRY>() {
731 self.gates
732 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
733 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CRZ>() {
734 self.gates
735 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
736 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<ISwap>() {
737 self.gates
738 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
739 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<ECR>() {
740 self.gates
741 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
742 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RXX>() {
743 self.gates
744 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
745 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RYY>() {
746 self.gates
747 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
748 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RZZ>() {
749 self.gates
750 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
751 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RZX>() {
752 self.gates
753 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
754 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<DCX>() {
755 self.gates
756 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
757 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RotationX>() {
758 self.gates
759 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
760 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RotationY>() {
761 self.gates
762 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
763 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<RotationZ>() {
764 self.gates
765 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
766 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Phase>() {
767 self.gates
768 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
769 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PhaseDagger>() {
770 self.gates
771 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
772 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<T>() {
773 self.gates
774 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
775 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<TDagger>() {
776 self.gates
777 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
778 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<SqrtX>() {
779 self.gates
780 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
781 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<SqrtXDagger>() {
782 self.gates
783 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
784 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<UGate>() {
785 self.gates
786 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
787 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PGate>() {
788 self.gates
789 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
790 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Identity>() {
791 self.gates
792 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
793 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Measure>() {
794 self.gates
795 .push(Arc::new(g.clone()) as Arc<dyn GateOp + Send + Sync>);
796 } else {
797 self.gates
804 .push(Arc::new(BoxGateWrapper(cloned_gate)) as Arc<dyn GateOp + Send + Sync>);
805 }
806
807 Ok(self)
808 }
809
810 pub fn create_composite(
815 &self,
816 start_idx: usize,
817 end_idx: usize,
818 name: &str,
819 ) -> QuantRS2Result<CompositeGate> {
820 if start_idx >= self.gates.len() || end_idx > self.gates.len() || start_idx >= end_idx {
821 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
822 "Invalid start/end indices ({}/{}) for circuit with {} gates",
823 start_idx,
824 end_idx,
825 self.gates.len()
826 )));
827 }
828
829 let mut gates: Vec<Box<dyn GateOp>> = Vec::new();
832 for gate in &self.gates[start_idx..end_idx] {
833 gates.push(decomp_utils::clone_gate(gate.as_ref())?);
834 }
835
836 let mut qubits = Vec::new();
838 for gate in &gates {
839 for qubit in gate.qubits() {
840 if !qubits.contains(&qubit) {
841 qubits.push(qubit);
842 }
843 }
844 }
845
846 Ok(CompositeGate {
847 gates,
848 qubits,
849 name: name.to_string(),
850 })
851 }
852
853 pub fn add_composite(&mut self, composite: &CompositeGate) -> QuantRS2Result<&mut Self> {
855 for gate in &composite.gates {
857 let gate_clone = decomp_utils::clone_gate(gate.as_ref())?;
862 self.add_gate_box(gate_clone)?;
863 }
864
865 Ok(self)
866 }
867
868 #[must_use]
870 pub fn with_classical_control(self) -> crate::classical::ClassicalCircuit<N> {
871 let mut classical_circuit = crate::classical::ClassicalCircuit::new();
872
873 let _ = classical_circuit.add_classical_register("c", N);
875
876 for gate in self.gates {
878 let boxed_gate = gate.clone_gate();
879 classical_circuit
880 .operations
881 .push(crate::classical::CircuitOp::Quantum(boxed_gate));
882 }
883
884 classical_circuit
885 }
886
887 pub fn bell_state(&mut self, qubit1: u32, qubit2: u32) -> QuantRS2Result<&mut Self> {
897 self.h(QubitId::new(qubit1))?;
898 self.cnot(QubitId::new(qubit1), QubitId::new(qubit2))?;
899 Ok(self)
900 }
901
902 pub fn ghz_state(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
910 if qubits.is_empty() {
911 return Ok(self);
912 }
913
914 self.h(QubitId::new(qubits[0]))?;
916
917 for i in 1..qubits.len() {
919 self.cnot(QubitId::new(qubits[0]), QubitId::new(qubits[i]))?;
920 }
921
922 Ok(self)
923 }
924
925 pub fn w_state(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
931 if qubits.is_empty() {
932 return Ok(self);
933 }
934
935 let n = qubits.len() as f64;
936
937 self.ry(QubitId::new(qubits[0]), 2.0 * (1.0 / n.sqrt()).acos())?;
940
941 for i in 1..qubits.len() {
942 let angle = 2.0 * (1.0 / (n - i as f64).sqrt()).acos();
943 self.cry(QubitId::new(qubits[i - 1]), QubitId::new(qubits[i]), angle)?;
944 }
945
946 for i in 0..qubits.len() - 1 {
948 self.cnot(QubitId::new(qubits[i + 1]), QubitId::new(qubits[i]))?;
949 }
950
951 Ok(self)
952 }
953
954 pub fn plus_state_all(&mut self) -> QuantRS2Result<&mut Self> {
962 for i in 0..N {
963 self.h(QubitId::new(i as u32))?;
964 }
965 Ok(self)
966 }
967
968 pub fn cnot_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
976 if qubits.len() < 2 {
977 return Ok(self);
978 }
979
980 for i in 0..qubits.len() - 1 {
981 self.cnot(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
982 }
983
984 Ok(self)
985 }
986
987 pub fn cnot_ring(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
991 if qubits.len() < 2 {
992 return Ok(self);
993 }
994
995 self.cnot_ladder(qubits)?;
997
998 let last_idx = qubits.len() - 1;
1000 self.cnot(QubitId::new(qubits[last_idx]), QubitId::new(qubits[0]))?;
1001
1002 Ok(self)
1003 }
1004
1005 pub fn swap_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
1013 if qubits.len() < 2 {
1014 return Ok(self);
1015 }
1016
1017 for i in 0..qubits.len() - 1 {
1018 self.swap(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
1019 }
1020
1021 Ok(self)
1022 }
1023
1024 pub fn cz_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
1032 if qubits.len() < 2 {
1033 return Ok(self);
1034 }
1035
1036 for i in 0..qubits.len() - 1 {
1037 self.cz(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
1038 }
1039
1040 Ok(self)
1041 }
1042}
1043
1044impl<const N: usize> Default for Circuit<N> {
1045 fn default() -> Self {
1046 Self::new()
1047 }
1048}
1049
1050pub trait Simulator<const N: usize> {
1052 fn run(&self, circuit: &Circuit<N>) -> QuantRS2Result<Register<N>>;
1054}
1055
1056#[cfg(test)]
1057mod tests;