1use std::sync::Arc;
9
10use quantrs2_core::{
11 error::QuantRS2Result,
12 gate::{
13 multi::{
14 Fredkin, ISwap, Toffoli, CH, CNOT, CRX, CRY, CRZ, CS, CY, CZ, DCX, ECR, RXX, RYY, RZX,
15 RZZ, SWAP,
16 },
17 single::{
18 Hadamard, Identity, PGate, PauliX, PauliY, PauliZ, Phase, PhaseDagger, RotationX,
19 RotationY, RotationZ, SqrtX, SqrtXDagger, TDagger, UGate, T,
20 },
21 GateOp,
22 },
23 qubit::QubitId,
24};
25
26use crate::builder::{BarrierInfo, Circuit, Measure};
27
28impl<const N: usize> Circuit<N> {
29 pub fn h(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
42 self.add_gate(Hadamard {
43 target: target.into(),
44 })
45 }
46
47 pub fn x(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
58 self.add_gate(PauliX {
59 target: target.into(),
60 })
61 }
62
63 pub fn y(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
65 self.add_gate(PauliY {
66 target: target.into(),
67 })
68 }
69
70 pub fn z(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
72 self.add_gate(PauliZ {
73 target: target.into(),
74 })
75 }
76
77 pub fn rx(&mut self, target: impl Into<QubitId>, theta: f64) -> QuantRS2Result<&mut Self> {
79 self.add_gate(RotationX {
80 target: target.into(),
81 theta,
82 })
83 }
84
85 pub fn ry(&mut self, target: impl Into<QubitId>, theta: f64) -> QuantRS2Result<&mut Self> {
87 self.add_gate(RotationY {
88 target: target.into(),
89 theta,
90 })
91 }
92
93 pub fn rz(&mut self, target: impl Into<QubitId>, theta: f64) -> QuantRS2Result<&mut Self> {
95 self.add_gate(RotationZ {
96 target: target.into(),
97 theta,
98 })
99 }
100
101 pub fn s(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
103 self.add_gate(Phase {
104 target: target.into(),
105 })
106 }
107
108 pub fn sdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
110 self.add_gate(PhaseDagger {
111 target: target.into(),
112 })
113 }
114
115 pub fn t(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
117 self.add_gate(T {
118 target: target.into(),
119 })
120 }
121
122 pub fn tdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
124 self.add_gate(TDagger {
125 target: target.into(),
126 })
127 }
128
129 pub fn sx(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
131 self.add_gate(SqrtX {
132 target: target.into(),
133 })
134 }
135
136 pub fn sxdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
138 self.add_gate(SqrtXDagger {
139 target: target.into(),
140 })
141 }
142
143 pub fn u(
150 &mut self,
151 target: impl Into<QubitId>,
152 theta: f64,
153 phi: f64,
154 lambda: f64,
155 ) -> QuantRS2Result<&mut Self> {
156 self.add_gate(UGate {
157 target: target.into(),
158 theta,
159 phi,
160 lambda,
161 })
162 }
163
164 pub fn p(&mut self, target: impl Into<QubitId>, lambda: f64) -> QuantRS2Result<&mut Self> {
168 self.add_gate(PGate {
169 target: target.into(),
170 lambda,
171 })
172 }
173
174 pub fn id(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
176 self.add_gate(Identity {
177 target: target.into(),
178 })
179 }
180
181 pub fn cnot(
196 &mut self,
197 control: impl Into<QubitId>,
198 target: impl Into<QubitId>,
199 ) -> QuantRS2Result<&mut Self> {
200 self.add_gate(CNOT {
201 control: control.into(),
202 target: target.into(),
203 })
204 }
205
206 pub fn cx(
208 &mut self,
209 control: impl Into<QubitId>,
210 target: impl Into<QubitId>,
211 ) -> QuantRS2Result<&mut Self> {
212 self.cnot(control, target)
213 }
214
215 pub fn cy(
217 &mut self,
218 control: impl Into<QubitId>,
219 target: impl Into<QubitId>,
220 ) -> QuantRS2Result<&mut Self> {
221 self.add_gate(CY {
222 control: control.into(),
223 target: target.into(),
224 })
225 }
226
227 pub fn cz(
229 &mut self,
230 control: impl Into<QubitId>,
231 target: impl Into<QubitId>,
232 ) -> QuantRS2Result<&mut Self> {
233 self.add_gate(CZ {
234 control: control.into(),
235 target: target.into(),
236 })
237 }
238
239 pub fn ch(
241 &mut self,
242 control: impl Into<QubitId>,
243 target: impl Into<QubitId>,
244 ) -> QuantRS2Result<&mut Self> {
245 self.add_gate(CH {
246 control: control.into(),
247 target: target.into(),
248 })
249 }
250
251 pub fn cs(
253 &mut self,
254 control: impl Into<QubitId>,
255 target: impl Into<QubitId>,
256 ) -> QuantRS2Result<&mut Self> {
257 self.add_gate(CS {
258 control: control.into(),
259 target: target.into(),
260 })
261 }
262
263 pub fn crx(
265 &mut self,
266 control: impl Into<QubitId>,
267 target: impl Into<QubitId>,
268 theta: f64,
269 ) -> QuantRS2Result<&mut Self> {
270 self.add_gate(CRX {
271 control: control.into(),
272 target: target.into(),
273 theta,
274 })
275 }
276
277 pub fn cry(
279 &mut self,
280 control: impl Into<QubitId>,
281 target: impl Into<QubitId>,
282 theta: f64,
283 ) -> QuantRS2Result<&mut Self> {
284 self.add_gate(CRY {
285 control: control.into(),
286 target: target.into(),
287 theta,
288 })
289 }
290
291 pub fn crz(
293 &mut self,
294 control: impl Into<QubitId>,
295 target: impl Into<QubitId>,
296 theta: f64,
297 ) -> QuantRS2Result<&mut Self> {
298 self.add_gate(CRZ {
299 control: control.into(),
300 target: target.into(),
301 theta,
302 })
303 }
304
305 pub fn cp(
307 &mut self,
308 control: impl Into<QubitId>,
309 target: impl Into<QubitId>,
310 lambda: f64,
311 ) -> QuantRS2Result<&mut Self> {
312 self.crz(control, target, lambda)
314 }
315
316 pub fn swap(
318 &mut self,
319 qubit1: impl Into<QubitId>,
320 qubit2: impl Into<QubitId>,
321 ) -> QuantRS2Result<&mut Self> {
322 self.add_gate(SWAP {
323 qubit1: qubit1.into(),
324 qubit2: qubit2.into(),
325 })
326 }
327
328 pub fn iswap(
332 &mut self,
333 qubit1: impl Into<QubitId>,
334 qubit2: impl Into<QubitId>,
335 ) -> QuantRS2Result<&mut Self> {
336 self.add_gate(ISwap {
337 qubit1: qubit1.into(),
338 qubit2: qubit2.into(),
339 })
340 }
341
342 pub fn ecr(
344 &mut self,
345 control: impl Into<QubitId>,
346 target: impl Into<QubitId>,
347 ) -> QuantRS2Result<&mut Self> {
348 self.add_gate(ECR {
349 control: control.into(),
350 target: target.into(),
351 })
352 }
353
354 pub fn rxx(
358 &mut self,
359 qubit1: impl Into<QubitId>,
360 qubit2: impl Into<QubitId>,
361 theta: f64,
362 ) -> QuantRS2Result<&mut Self> {
363 self.add_gate(RXX {
364 qubit1: qubit1.into(),
365 qubit2: qubit2.into(),
366 theta,
367 })
368 }
369
370 pub fn ryy(
374 &mut self,
375 qubit1: impl Into<QubitId>,
376 qubit2: impl Into<QubitId>,
377 theta: f64,
378 ) -> QuantRS2Result<&mut Self> {
379 self.add_gate(RYY {
380 qubit1: qubit1.into(),
381 qubit2: qubit2.into(),
382 theta,
383 })
384 }
385
386 pub fn rzz(
390 &mut self,
391 qubit1: impl Into<QubitId>,
392 qubit2: impl Into<QubitId>,
393 theta: f64,
394 ) -> QuantRS2Result<&mut Self> {
395 self.add_gate(RZZ {
396 qubit1: qubit1.into(),
397 qubit2: qubit2.into(),
398 theta,
399 })
400 }
401
402 pub fn rzx(
406 &mut self,
407 control: impl Into<QubitId>,
408 target: impl Into<QubitId>,
409 theta: f64,
410 ) -> QuantRS2Result<&mut Self> {
411 self.add_gate(RZX {
412 control: control.into(),
413 target: target.into(),
414 theta,
415 })
416 }
417
418 pub fn dcx(
422 &mut self,
423 qubit1: impl Into<QubitId>,
424 qubit2: impl Into<QubitId>,
425 ) -> QuantRS2Result<&mut Self> {
426 self.add_gate(DCX {
427 qubit1: qubit1.into(),
428 qubit2: qubit2.into(),
429 })
430 }
431
432 pub fn toffoli(
436 &mut self,
437 control1: impl Into<QubitId>,
438 control2: impl Into<QubitId>,
439 target: impl Into<QubitId>,
440 ) -> QuantRS2Result<&mut Self> {
441 self.add_gate(Toffoli {
442 control1: control1.into(),
443 control2: control2.into(),
444 target: target.into(),
445 })
446 }
447
448 pub fn cswap(
450 &mut self,
451 control: impl Into<QubitId>,
452 target1: impl Into<QubitId>,
453 target2: impl Into<QubitId>,
454 ) -> QuantRS2Result<&mut Self> {
455 self.add_gate(Fredkin {
456 control: control.into(),
457 target1: target1.into(),
458 target2: target2.into(),
459 })
460 }
461
462 pub fn ccx(
464 &mut self,
465 control1: impl Into<QubitId>,
466 control2: impl Into<QubitId>,
467 target: impl Into<QubitId>,
468 ) -> QuantRS2Result<&mut Self> {
469 self.toffoli(control1, control2, target)
470 }
471
472 pub fn fredkin(
474 &mut self,
475 control: impl Into<QubitId>,
476 target1: impl Into<QubitId>,
477 target2: impl Into<QubitId>,
478 ) -> QuantRS2Result<&mut Self> {
479 self.cswap(control, target1, target2)
480 }
481
482 pub fn measure(&mut self, qubit: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
489 let qubit_id = qubit.into();
490 self.add_gate(Measure { target: qubit_id })?;
491 Ok(self)
492 }
493
494 pub fn reset(&mut self, _qubit: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
499 Err(quantrs2_core::error::QuantRS2Error::UnsupportedOperation(
500 "Reset operation is not yet implemented. Reset requires special quantum state manipulation.".to_string()
501 ))
502 }
503
504 pub fn barrier(&mut self, qubits: &[QubitId]) -> QuantRS2Result<&mut Self> {
510 for &qubit in qubits {
512 if qubit.id() as usize >= N {
513 return Err(quantrs2_core::error::QuantRS2Error::InvalidQubitId(
514 qubit.id(),
515 ));
516 }
517 }
518
519 self.barriers.push(BarrierInfo {
527 after_gate_index: self.gates().len(),
528 qubits: qubits.to_vec(),
529 });
530 Ok(self)
531 }
532
533 pub fn measure_all(&mut self) -> QuantRS2Result<&mut Self> {
535 for i in 0..N {
536 self.measure(QubitId(i as u32))?;
537 }
538 Ok(self)
539 }
540
541 pub fn h_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
551 for &qubit in qubits {
552 self.h(QubitId::new(qubit))?;
553 }
554 Ok(self)
555 }
556
557 pub fn x_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
565 for &qubit in qubits {
566 self.x(QubitId::new(qubit))?;
567 }
568 Ok(self)
569 }
570
571 pub fn y_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
573 for &qubit in qubits {
574 self.y(QubitId::new(qubit))?;
575 }
576 Ok(self)
577 }
578
579 pub fn z_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
581 for &qubit in qubits {
582 self.z(QubitId::new(qubit))?;
583 }
584 Ok(self)
585 }
586
587 pub fn h_range(&mut self, range: std::ops::Range<u32>) -> QuantRS2Result<&mut Self> {
595 for qubit in range {
596 self.h(QubitId::new(qubit))?;
597 }
598 Ok(self)
599 }
600
601 pub fn x_range(&mut self, range: std::ops::Range<u32>) -> QuantRS2Result<&mut Self> {
603 for qubit in range {
604 self.x(QubitId::new(qubit))?;
605 }
606 Ok(self)
607 }
608
609 pub fn rx_all(&mut self, qubits: &[u32], theta: f64) -> QuantRS2Result<&mut Self> {
611 for &qubit in qubits {
612 self.rx(QubitId::new(qubit), theta)?;
613 }
614 Ok(self)
615 }
616
617 pub fn ry_all(&mut self, qubits: &[u32], theta: f64) -> QuantRS2Result<&mut Self> {
619 for &qubit in qubits {
620 self.ry(QubitId::new(qubit), theta)?;
621 }
622 Ok(self)
623 }
624
625 pub fn rz_all(&mut self, qubits: &[u32], theta: f64) -> QuantRS2Result<&mut Self> {
627 for &qubit in qubits {
628 self.rz(QubitId::new(qubit), theta)?;
629 }
630 Ok(self)
631 }
632
633 pub fn swap_all(&mut self, pairs: &[(u32, u32)]) -> QuantRS2Result<&mut Self> {
644 for &(q1, q2) in pairs {
645 self.swap(QubitId::new(q1), QubitId::new(q2))?;
646 }
647 Ok(self)
648 }
649
650 pub fn cz_all(&mut self, pairs: &[(u32, u32)]) -> QuantRS2Result<&mut Self> {
661 for &(q1, q2) in pairs {
662 self.cz(QubitId::new(q1), QubitId::new(q2))?;
663 }
664 Ok(self)
665 }
666
667 pub fn cnot_all(&mut self, pairs: &[(u32, u32)]) -> QuantRS2Result<&mut Self> {
678 for &(control, target) in pairs {
679 self.cnot(QubitId::new(control), QubitId::new(target))?;
680 }
681 Ok(self)
682 }
683
684 pub fn barrier_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
697 let qubit_ids: Vec<QubitId> = qubits.iter().map(|&q| QubitId::new(q)).collect();
698 self.barrier(&qubit_ids)?;
699 Ok(self)
700 }
701
702 #[cfg(feature = "python")]
706 pub fn get_single_qubit_for_gate(&self, gate_type: &str, index: usize) -> pyo3::PyResult<u32> {
707 self.find_gate_by_type_and_index(gate_type, index)
708 .and_then(|gate| {
709 if gate.qubits().len() == 1 {
710 Some(gate.qubits()[0].id())
711 } else {
712 None
713 }
714 })
715 .ok_or_else(|| {
716 pyo3::exceptions::PyValueError::new_err(format!(
717 "Gate {gate_type} at index {index} not found or is not a single-qubit gate"
718 ))
719 })
720 }
721
722 #[cfg(feature = "python")]
724 pub fn get_rotation_params_for_gate(
725 &self,
726 gate_type: &str,
727 index: usize,
728 ) -> pyo3::PyResult<(u32, f64)> {
729 self.find_gate_by_type_and_index(gate_type, index)
730 .and_then(|gate| {
731 if gate.qubits().len() == 1 {
732 Some((gate.qubits()[0].id(), 0.0))
733 } else {
734 None
735 }
736 })
737 .ok_or_else(|| {
738 pyo3::exceptions::PyValueError::new_err(format!(
739 "Gate {gate_type} at index {index} not found or is not a rotation gate"
740 ))
741 })
742 }
743
744 #[cfg(feature = "python")]
746 pub fn get_two_qubit_params_for_gate(
747 &self,
748 gate_type: &str,
749 index: usize,
750 ) -> pyo3::PyResult<(u32, u32)> {
751 self.find_gate_by_type_and_index(gate_type, index)
752 .and_then(|gate| {
753 if gate.qubits().len() == 2 {
754 Some((gate.qubits()[0].id(), gate.qubits()[1].id()))
755 } else {
756 None
757 }
758 })
759 .ok_or_else(|| {
760 pyo3::exceptions::PyValueError::new_err(format!(
761 "Gate {gate_type} at index {index} not found or is not a two-qubit gate"
762 ))
763 })
764 }
765
766 #[cfg(feature = "python")]
768 pub fn get_controlled_rotation_params_for_gate(
769 &self,
770 gate_type: &str,
771 index: usize,
772 ) -> pyo3::PyResult<(u32, u32, f64)> {
773 self.find_gate_by_type_and_index(gate_type, index)
774 .and_then(|gate| {
775 if gate.qubits().len() == 2 {
776 Some((gate.qubits()[0].id(), gate.qubits()[1].id(), 0.0))
777 } else {
778 None
779 }
780 })
781 .ok_or_else(|| {
782 pyo3::exceptions::PyValueError::new_err(format!(
783 "Gate {gate_type} at index {index} not found or is not a controlled rotation gate"
784 ))
785 })
786 }
787
788 #[cfg(feature = "python")]
790 pub fn get_three_qubit_params_for_gate(
791 &self,
792 gate_type: &str,
793 index: usize,
794 ) -> pyo3::PyResult<(u32, u32, u32)> {
795 self.find_gate_by_type_and_index(gate_type, index)
796 .and_then(|gate| {
797 if gate.qubits().len() == 3 {
798 Some((
799 gate.qubits()[0].id(),
800 gate.qubits()[1].id(),
801 gate.qubits()[2].id(),
802 ))
803 } else {
804 None
805 }
806 })
807 .ok_or_else(|| {
808 pyo3::exceptions::PyValueError::new_err(format!(
809 "Gate {gate_type} at index {index} not found or is not a three-qubit gate"
810 ))
811 })
812 }
813}