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>(
137 &mut self,
138 gate: G,
139 ) -> Arc<dyn GateOp + Send + Sync> {
140 let key = format!("{}_{:?}", gate.name(), gate.qubits());
141
142 if let Some(cached_gate) = self.gates.get(&key) {
143 cached_gate.clone()
144 } else {
145 let arc_gate = Arc::new(gate) as Arc<dyn GateOp + Send + Sync>;
146 self.gates.insert(key, arc_gate.clone());
147 arc_gate
148 }
149 }
150}
151
152impl Default for GatePool {
153 fn default() -> Self {
154 Self::new()
155 }
156}
157
158#[derive(Debug, Clone)]
160pub struct Measure {
161 pub target: QubitId,
162}
163
164impl GateOp for Measure {
165 fn name(&self) -> &'static str {
166 "measure"
167 }
168
169 fn qubits(&self) -> Vec<QubitId> {
170 vec![self.target]
171 }
172
173 fn is_parameterized(&self) -> bool {
174 false
175 }
176
177 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
178 Ok(vec![
180 Complex64::new(1.0, 0.0),
181 Complex64::new(0.0, 0.0),
182 Complex64::new(0.0, 0.0),
183 Complex64::new(1.0, 0.0),
184 ])
185 }
186
187 fn as_any(&self) -> &dyn Any {
188 self
189 }
190
191 fn clone_gate(&self) -> Box<dyn GateOp> {
192 Box::new(self.clone())
193 }
194}
195
196struct BoxGateWrapper(Box<dyn GateOp>);
200
201impl std::fmt::Debug for BoxGateWrapper {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 self.0.fmt(f)
204 }
205}
206
207unsafe impl Send for BoxGateWrapper {}
209unsafe impl Sync for BoxGateWrapper {}
210
211impl GateOp for BoxGateWrapper {
212 fn name(&self) -> &'static str {
213 self.0.name()
214 }
215 fn qubits(&self) -> Vec<QubitId> {
216 self.0.qubits()
217 }
218 fn num_qubits(&self) -> usize {
219 self.0.num_qubits()
220 }
221 fn is_parameterized(&self) -> bool {
222 self.0.is_parameterized()
223 }
224 fn matrix(&self) -> QuantRS2Result<Vec<Complex64>> {
225 self.0.matrix()
226 }
227 fn as_any(&self) -> &dyn std::any::Any {
228 self.0.as_any()
229 }
230 fn clone_gate(&self) -> Box<dyn GateOp> {
231 self.0.clone_gate()
232 }
233}
234
235#[derive(Debug, Clone)]
239pub struct BarrierInfo {
240 pub after_gate_index: usize,
243 pub qubits: Vec<QubitId>,
245}
246
247pub struct Circuit<const N: usize> {
249 gates: Vec<Arc<dyn GateOp + Send + Sync>>,
251 gate_pool: GatePool,
253 pub barriers: Vec<BarrierInfo>,
257}
258
259impl<const N: usize> Clone for Circuit<N> {
260 fn clone(&self) -> Self {
261 Self {
263 gates: self.gates.clone(),
264 gate_pool: self.gate_pool.clone(),
265 barriers: self.barriers.clone(),
266 }
267 }
268}
269
270impl<const N: usize> fmt::Debug for Circuit<N> {
271 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
272 f.debug_struct("Circuit")
273 .field("num_qubits", &N)
274 .field("num_gates", &self.gates.len())
275 .finish()
276 }
277}
278
279impl<const N: usize> Circuit<N> {
280 #[must_use]
282 pub fn new() -> Self {
283 Self {
284 gates: Vec::with_capacity(64), gate_pool: GatePool::new(),
286 barriers: Vec::new(),
287 }
288 }
289
290 #[must_use]
292 pub fn with_capacity(capacity: usize) -> Self {
293 Self {
294 gates: Vec::with_capacity(capacity),
295 gate_pool: GatePool::new(),
296 barriers: Vec::new(),
297 }
298 }
299
300 pub fn add_gate<G: GateOp + Clone + Send + Sync + 'static>(
302 &mut self,
303 gate: G,
304 ) -> QuantRS2Result<&mut Self> {
305 for qubit in gate.qubits() {
307 if qubit.id() as usize >= N {
308 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
309 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
310 gate.name(),
311 qubit.id(),
312 N,
313 N - 1
314 )));
315 }
316 }
317
318 let gate_arc = self.gate_pool.get_gate(gate);
320 self.gates.push(gate_arc);
321 Ok(self)
322 }
323
324 pub fn from_gates(gates: Vec<Box<dyn GateOp>>) -> QuantRS2Result<Self> {
330 let mut circuit = Self::with_capacity(gates.len());
331 for gate in gates {
332 let in_range = gate.qubits().iter().all(|q| (q.id() as usize) < N);
334 if in_range {
335 let arc: Arc<dyn GateOp + Send + Sync> = Arc::new(BoxGateWrapper(gate));
339 circuit.gates.push(arc);
340 }
341 }
342 Ok(circuit)
343 }
344
345 pub fn add_gate_arc(
347 &mut self,
348 gate: Arc<dyn GateOp + Send + Sync>,
349 ) -> QuantRS2Result<&mut Self> {
350 for qubit in gate.qubits() {
352 if qubit.id() as usize >= N {
353 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
354 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
355 gate.name(),
356 qubit.id(),
357 N,
358 N - 1
359 )));
360 }
361 }
362
363 self.gates.push(gate);
364 Ok(self)
365 }
366
367 #[must_use]
369 pub fn gates(&self) -> &[Arc<dyn GateOp + Send + Sync>] {
370 &self.gates
371 }
372
373 #[must_use]
375 pub fn gates_as_boxes(&self) -> Vec<Box<dyn GateOp>> {
376 self.gates
377 .iter()
378 .map(|arc_gate| arc_gate.clone_gate())
379 .collect()
380 }
381
382 #[must_use]
386 pub fn count_gates_by_type(&self) -> HashMap<String, usize> {
387 let mut counts = HashMap::new();
388 for gate in &self.gates {
389 *counts.entry(gate.name().to_string()).or_insert(0) += 1;
390 }
391 counts
392 }
393
394 #[must_use]
396 pub fn calculate_depth(&self) -> usize {
397 if self.gates.is_empty() {
398 return 0;
399 }
400
401 let mut qubit_last_used = vec![0; N];
403 let mut max_depth = 0;
404
405 for (gate_idx, gate) in self.gates.iter().enumerate() {
406 let gate_qubits = gate.qubits();
407
408 let gate_start_depth = gate_qubits
410 .iter()
411 .map(|q| qubit_last_used[q.id() as usize])
412 .max()
413 .unwrap_or(0);
414
415 let gate_end_depth = gate_start_depth + 1;
416
417 for qubit in gate_qubits {
419 qubit_last_used[qubit.id() as usize] = gate_end_depth;
420 }
421
422 max_depth = max_depth.max(gate_end_depth);
423 }
424
425 max_depth
426 }
427
428 #[must_use]
430 pub fn count_two_qubit_gates(&self) -> usize {
431 self.gates
432 .iter()
433 .filter(|gate| gate.qubits().len() == 2)
434 .count()
435 }
436
437 #[must_use]
439 pub fn count_multi_qubit_gates(&self) -> usize {
440 self.gates
441 .iter()
442 .filter(|gate| gate.qubits().len() >= 3)
443 .count()
444 }
445
446 #[must_use]
448 pub fn calculate_critical_path(&self) -> usize {
449 self.calculate_depth()
450 }
451
452 #[must_use]
454 pub fn calculate_gate_density(&self) -> f64 {
455 if N == 0 {
456 0.0
457 } else {
458 self.gates.len() as f64 / N as f64
459 }
460 }
461
462 #[must_use]
464 pub fn get_used_qubits(&self) -> HashSet<QubitId> {
465 let mut used_qubits = HashSet::new();
466 for gate in &self.gates {
467 for qubit in gate.qubits() {
468 used_qubits.insert(qubit);
469 }
470 }
471 used_qubits
472 }
473
474 #[must_use]
476 pub fn uses_all_qubits(&self) -> bool {
477 self.get_used_qubits().len() == N
478 }
479
480 #[must_use]
482 pub fn gates_on_qubit(&self, target_qubit: QubitId) -> Vec<&Arc<dyn GateOp + Send + Sync>> {
483 self.gates
484 .iter()
485 .filter(|gate| gate.qubits().contains(&target_qubit))
486 .collect()
487 }
488
489 #[must_use]
491 pub fn gates_in_range(&self, start: usize, end: usize) -> &[Arc<dyn GateOp + Send + Sync>] {
492 let end = end.min(self.gates.len().saturating_sub(1));
493 let start = start.min(end);
494 &self.gates[start..=end]
495 }
496
497 #[must_use]
499 pub fn is_empty(&self) -> bool {
500 self.gates.is_empty()
501 }
502
503 #[must_use]
505 pub fn get_stats(&self) -> CircuitStats {
506 let gate_counts = self.count_gates_by_type();
507 let depth = self.calculate_depth();
508 let two_qubit_gates = self.count_two_qubit_gates();
509 let multi_qubit_gates = self.count_multi_qubit_gates();
510 let gate_density = self.calculate_gate_density();
511 let used_qubits = self.get_used_qubits().len();
512
513 CircuitStats {
514 total_gates: self.gates.len(),
515 gate_counts,
516 depth,
517 two_qubit_gates,
518 multi_qubit_gates,
519 gate_density,
520 used_qubits,
521 total_qubits: N,
522 }
523 }
524
525 #[must_use]
527 pub const fn num_qubits(&self) -> usize {
528 N
529 }
530
531 #[must_use]
533 pub fn num_gates(&self) -> usize {
534 self.gates.len()
535 }
536
537 #[must_use]
539 pub fn get_gate_names(&self) -> Vec<String> {
540 self.gates
541 .iter()
542 .map(|gate| gate.name().to_string())
543 .collect()
544 }
545
546 pub(crate) fn find_gate_by_type_and_index(
548 &self,
549 gate_type: &str,
550 index: usize,
551 ) -> Option<&dyn GateOp> {
552 let mut count = 0;
553 for gate in &self.gates {
554 if gate.name() == gate_type {
555 if count == index {
556 return Some(gate.as_ref());
557 }
558 count += 1;
559 }
560 }
561 None
562 }
563
564 pub fn run<S: Simulator<N>>(&self, simulator: S) -> QuantRS2Result<Register<N>> {
566 simulator.run(self)
567 }
568
569 pub fn decompose(&self) -> QuantRS2Result<Self> {
574 let mut decomposed = Self::new();
575
576 let boxed_gates = self.gates_as_boxes();
578
579 let simple_gates = decomp_utils::decompose_circuit(&boxed_gates)?;
581
582 for gate in simple_gates {
584 decomposed.add_gate_box(gate)?;
585 }
586
587 Ok(decomposed)
588 }
589
590 #[must_use]
592 pub const fn build(self) -> Self {
593 self
594 }
595
596 pub fn optimize(&self) -> QuantRS2Result<Self> {
603 let mut optimized = Self::new();
604
605 let boxed_gates = self.gates_as_boxes();
607
608 let simplified_gates_result = decomp_utils::optimize_gate_sequence(&boxed_gates);
610
611 if let Ok(simplified_gates) = simplified_gates_result {
613 for g in simplified_gates {
614 optimized.add_gate_box(g)?;
615 }
616 }
617
618 let new_gate_count = optimized.gates.len();
621 optimized.barriers = self
622 .barriers
623 .iter()
624 .map(|b| BarrierInfo {
625 after_gate_index: b.after_gate_index.min(new_gate_count),
626 qubits: b.qubits.clone(),
627 })
628 .collect();
629
630 Ok(optimized)
631 }
632
633 pub(crate) fn add_gate_box(&mut self, gate: Box<dyn GateOp>) -> QuantRS2Result<&mut Self> {
636 for qubit in gate.qubits() {
638 if qubit.id() as usize >= N {
639 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
640 "Gate '{}' targets qubit {} which is out of range for {}-qubit circuit (valid range: 0-{})",
641 gate.name(),
642 qubit.id(),
643 N,
644 N - 1
645 )));
646 }
647 }
648
649 let cloned_gate = gate.clone_gate();
652
653 if let Some(g) = cloned_gate.as_any().downcast_ref::<Hadamard>() {
658 self.gates
659 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
660 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliX>() {
661 self.gates
662 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
663 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliY>() {
664 self.gates
665 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
666 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<PauliZ>() {
667 self.gates
668 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
669 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CNOT>() {
670 self.gates
671 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
672 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CZ>() {
673 self.gates
674 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
675 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<SWAP>() {
676 self.gates
677 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
678 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CY>() {
679 self.gates
680 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
681 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CH>() {
682 self.gates
683 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
684 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CS>() {
685 self.gates
686 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
687 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Toffoli>() {
688 self.gates
689 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
690 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<Fredkin>() {
691 self.gates
692 .push(Arc::new(*g) as Arc<dyn GateOp + Send + Sync>);
693 } else if let Some(g) = cloned_gate.as_any().downcast_ref::<CRX>() {
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::<CRY>() {
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::<CRZ>() {
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::<ISwap>() {
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::<ECR>() {
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::<RXX>() {
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::<RYY>() {
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::<RZZ>() {
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::<RZX>() {
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::<DCX>() {
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::<RotationX>() {
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::<RotationY>() {
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::<RotationZ>() {
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::<Phase>() {
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::<PhaseDagger>() {
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::<T>() {
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::<TDagger>() {
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::<SqrtX>() {
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::<SqrtXDagger>() {
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::<UGate>() {
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::<PGate>() {
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::<Identity>() {
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::<Measure>() {
760 self.gates
761 .push(Arc::new(g.clone()) as Arc<dyn GateOp + Send + Sync>);
762 } else {
763 self.gates
770 .push(Arc::new(BoxGateWrapper(cloned_gate)) as Arc<dyn GateOp + Send + Sync>);
771 }
772
773 Ok(self)
774 }
775
776 pub fn create_composite(
781 &self,
782 start_idx: usize,
783 end_idx: usize,
784 name: &str,
785 ) -> QuantRS2Result<CompositeGate> {
786 if start_idx >= self.gates.len() || end_idx > self.gates.len() || start_idx >= end_idx {
787 return Err(quantrs2_core::error::QuantRS2Error::InvalidInput(format!(
788 "Invalid start/end indices ({}/{}) for circuit with {} gates",
789 start_idx,
790 end_idx,
791 self.gates.len()
792 )));
793 }
794
795 let mut gates: Vec<Box<dyn GateOp>> = Vec::new();
798 for gate in &self.gates[start_idx..end_idx] {
799 gates.push(decomp_utils::clone_gate(gate.as_ref())?);
800 }
801
802 let mut qubits = Vec::new();
804 for gate in &gates {
805 for qubit in gate.qubits() {
806 if !qubits.contains(&qubit) {
807 qubits.push(qubit);
808 }
809 }
810 }
811
812 Ok(CompositeGate {
813 gates,
814 qubits,
815 name: name.to_string(),
816 })
817 }
818
819 pub fn add_composite(&mut self, composite: &CompositeGate) -> QuantRS2Result<&mut Self> {
821 for gate in &composite.gates {
823 let gate_clone = decomp_utils::clone_gate(gate.as_ref())?;
828 self.add_gate_box(gate_clone)?;
829 }
830
831 Ok(self)
832 }
833
834 #[must_use]
836 pub fn with_classical_control(self) -> crate::classical::ClassicalCircuit<N> {
837 let mut classical_circuit = crate::classical::ClassicalCircuit::new();
838
839 let _ = classical_circuit.add_classical_register("c", N);
841
842 for gate in self.gates {
844 let boxed_gate = gate.clone_gate();
845 classical_circuit
846 .operations
847 .push(crate::classical::CircuitOp::Quantum(boxed_gate));
848 }
849
850 classical_circuit
851 }
852
853 pub fn bell_state(&mut self, qubit1: u32, qubit2: u32) -> QuantRS2Result<&mut Self> {
863 self.h(QubitId::new(qubit1))?;
864 self.cnot(QubitId::new(qubit1), QubitId::new(qubit2))?;
865 Ok(self)
866 }
867
868 pub fn ghz_state(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
876 if qubits.is_empty() {
877 return Ok(self);
878 }
879
880 self.h(QubitId::new(qubits[0]))?;
882
883 for i in 1..qubits.len() {
885 self.cnot(QubitId::new(qubits[0]), QubitId::new(qubits[i]))?;
886 }
887
888 Ok(self)
889 }
890
891 pub fn w_state(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
897 if qubits.is_empty() {
898 return Ok(self);
899 }
900
901 let n = qubits.len() as f64;
902
903 self.ry(QubitId::new(qubits[0]), 2.0 * (1.0 / n.sqrt()).acos())?;
906
907 for i in 1..qubits.len() {
908 let angle = 2.0 * (1.0 / (n - i as f64).sqrt()).acos();
909 self.cry(QubitId::new(qubits[i - 1]), QubitId::new(qubits[i]), angle)?;
910 }
911
912 for i in 0..qubits.len() - 1 {
914 self.cnot(QubitId::new(qubits[i + 1]), QubitId::new(qubits[i]))?;
915 }
916
917 Ok(self)
918 }
919
920 pub fn plus_state_all(&mut self) -> QuantRS2Result<&mut Self> {
928 for i in 0..N {
929 self.h(QubitId::new(i as u32))?;
930 }
931 Ok(self)
932 }
933
934 pub fn cnot_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
942 if qubits.len() < 2 {
943 return Ok(self);
944 }
945
946 for i in 0..qubits.len() - 1 {
947 self.cnot(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
948 }
949
950 Ok(self)
951 }
952
953 pub fn cnot_ring(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
957 if qubits.len() < 2 {
958 return Ok(self);
959 }
960
961 self.cnot_ladder(qubits)?;
963
964 let last_idx = qubits.len() - 1;
966 self.cnot(QubitId::new(qubits[last_idx]), QubitId::new(qubits[0]))?;
967
968 Ok(self)
969 }
970
971 pub fn swap_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
979 if qubits.len() < 2 {
980 return Ok(self);
981 }
982
983 for i in 0..qubits.len() - 1 {
984 self.swap(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
985 }
986
987 Ok(self)
988 }
989
990 pub fn cz_ladder(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
998 if qubits.len() < 2 {
999 return Ok(self);
1000 }
1001
1002 for i in 0..qubits.len() - 1 {
1003 self.cz(QubitId::new(qubits[i]), QubitId::new(qubits[i + 1]))?;
1004 }
1005
1006 Ok(self)
1007 }
1008}
1009
1010impl<const N: usize> Default for Circuit<N> {
1011 fn default() -> Self {
1012 Self::new()
1013 }
1014}
1015
1016pub trait Simulator<const N: usize> {
1018 fn run(&self, circuit: &Circuit<N>) -> QuantRS2Result<Register<N>>;
1020}
1021
1022#[cfg(test)]
1023mod tests;