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> {
33 self.add_gate(Hadamard {
34 target: target.into(),
35 })
36 }
37
38 pub fn x(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
40 self.add_gate(PauliX {
41 target: target.into(),
42 })
43 }
44
45 pub fn y(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
47 self.add_gate(PauliY {
48 target: target.into(),
49 })
50 }
51
52 pub fn z(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
54 self.add_gate(PauliZ {
55 target: target.into(),
56 })
57 }
58
59 pub fn rx(&mut self, target: impl Into<QubitId>, theta: f64) -> QuantRS2Result<&mut Self> {
61 self.add_gate(RotationX {
62 target: target.into(),
63 theta,
64 })
65 }
66
67 pub fn ry(&mut self, target: impl Into<QubitId>, theta: f64) -> QuantRS2Result<&mut Self> {
69 self.add_gate(RotationY {
70 target: target.into(),
71 theta,
72 })
73 }
74
75 pub fn rz(&mut self, target: impl Into<QubitId>, theta: f64) -> QuantRS2Result<&mut Self> {
77 self.add_gate(RotationZ {
78 target: target.into(),
79 theta,
80 })
81 }
82
83 pub fn s(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
85 self.add_gate(Phase {
86 target: target.into(),
87 })
88 }
89
90 pub fn sdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
92 self.add_gate(PhaseDagger {
93 target: target.into(),
94 })
95 }
96
97 pub fn t(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
99 self.add_gate(T {
100 target: target.into(),
101 })
102 }
103
104 pub fn tdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
106 self.add_gate(TDagger {
107 target: target.into(),
108 })
109 }
110
111 pub fn sx(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
113 self.add_gate(SqrtX {
114 target: target.into(),
115 })
116 }
117
118 pub fn sxdg(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
120 self.add_gate(SqrtXDagger {
121 target: target.into(),
122 })
123 }
124
125 pub fn u(
132 &mut self,
133 target: impl Into<QubitId>,
134 theta: f64,
135 phi: f64,
136 lambda: f64,
137 ) -> QuantRS2Result<&mut Self> {
138 self.add_gate(UGate {
139 target: target.into(),
140 theta,
141 phi,
142 lambda,
143 })
144 }
145
146 pub fn p(&mut self, target: impl Into<QubitId>, lambda: f64) -> QuantRS2Result<&mut Self> {
150 self.add_gate(PGate {
151 target: target.into(),
152 lambda,
153 })
154 }
155
156 pub fn id(&mut self, target: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
158 self.add_gate(Identity {
159 target: target.into(),
160 })
161 }
162
163 pub fn cnot(
167 &mut self,
168 control: impl Into<QubitId>,
169 target: impl Into<QubitId>,
170 ) -> QuantRS2Result<&mut Self> {
171 self.add_gate(CNOT {
172 control: control.into(),
173 target: target.into(),
174 })
175 }
176
177 pub fn cx(
179 &mut self,
180 control: impl Into<QubitId>,
181 target: impl Into<QubitId>,
182 ) -> QuantRS2Result<&mut Self> {
183 self.cnot(control, target)
184 }
185
186 pub fn cy(
188 &mut self,
189 control: impl Into<QubitId>,
190 target: impl Into<QubitId>,
191 ) -> QuantRS2Result<&mut Self> {
192 self.add_gate(CY {
193 control: control.into(),
194 target: target.into(),
195 })
196 }
197
198 pub fn cz(
200 &mut self,
201 control: impl Into<QubitId>,
202 target: impl Into<QubitId>,
203 ) -> QuantRS2Result<&mut Self> {
204 self.add_gate(CZ {
205 control: control.into(),
206 target: target.into(),
207 })
208 }
209
210 pub fn ch(
212 &mut self,
213 control: impl Into<QubitId>,
214 target: impl Into<QubitId>,
215 ) -> QuantRS2Result<&mut Self> {
216 self.add_gate(CH {
217 control: control.into(),
218 target: target.into(),
219 })
220 }
221
222 pub fn cs(
224 &mut self,
225 control: impl Into<QubitId>,
226 target: impl Into<QubitId>,
227 ) -> QuantRS2Result<&mut Self> {
228 self.add_gate(CS {
229 control: control.into(),
230 target: target.into(),
231 })
232 }
233
234 pub fn crx(
236 &mut self,
237 control: impl Into<QubitId>,
238 target: impl Into<QubitId>,
239 theta: f64,
240 ) -> QuantRS2Result<&mut Self> {
241 self.add_gate(CRX {
242 control: control.into(),
243 target: target.into(),
244 theta,
245 })
246 }
247
248 pub fn cry(
250 &mut self,
251 control: impl Into<QubitId>,
252 target: impl Into<QubitId>,
253 theta: f64,
254 ) -> QuantRS2Result<&mut Self> {
255 self.add_gate(CRY {
256 control: control.into(),
257 target: target.into(),
258 theta,
259 })
260 }
261
262 pub fn crz(
264 &mut self,
265 control: impl Into<QubitId>,
266 target: impl Into<QubitId>,
267 theta: f64,
268 ) -> QuantRS2Result<&mut Self> {
269 self.add_gate(CRZ {
270 control: control.into(),
271 target: target.into(),
272 theta,
273 })
274 }
275
276 pub fn cp(
278 &mut self,
279 control: impl Into<QubitId>,
280 target: impl Into<QubitId>,
281 lambda: f64,
282 ) -> QuantRS2Result<&mut Self> {
283 self.crz(control, target, lambda)
285 }
286
287 pub fn swap(
289 &mut self,
290 qubit1: impl Into<QubitId>,
291 qubit2: impl Into<QubitId>,
292 ) -> QuantRS2Result<&mut Self> {
293 self.add_gate(SWAP {
294 qubit1: qubit1.into(),
295 qubit2: qubit2.into(),
296 })
297 }
298
299 pub fn iswap(
303 &mut self,
304 qubit1: impl Into<QubitId>,
305 qubit2: impl Into<QubitId>,
306 ) -> QuantRS2Result<&mut Self> {
307 self.add_gate(ISwap {
308 qubit1: qubit1.into(),
309 qubit2: qubit2.into(),
310 })
311 }
312
313 pub fn ecr(
315 &mut self,
316 control: impl Into<QubitId>,
317 target: impl Into<QubitId>,
318 ) -> QuantRS2Result<&mut Self> {
319 self.add_gate(ECR {
320 control: control.into(),
321 target: target.into(),
322 })
323 }
324
325 pub fn rxx(
329 &mut self,
330 qubit1: impl Into<QubitId>,
331 qubit2: impl Into<QubitId>,
332 theta: f64,
333 ) -> QuantRS2Result<&mut Self> {
334 self.add_gate(RXX {
335 qubit1: qubit1.into(),
336 qubit2: qubit2.into(),
337 theta,
338 })
339 }
340
341 pub fn ryy(
345 &mut self,
346 qubit1: impl Into<QubitId>,
347 qubit2: impl Into<QubitId>,
348 theta: f64,
349 ) -> QuantRS2Result<&mut Self> {
350 self.add_gate(RYY {
351 qubit1: qubit1.into(),
352 qubit2: qubit2.into(),
353 theta,
354 })
355 }
356
357 pub fn rzz(
361 &mut self,
362 qubit1: impl Into<QubitId>,
363 qubit2: impl Into<QubitId>,
364 theta: f64,
365 ) -> QuantRS2Result<&mut Self> {
366 self.add_gate(RZZ {
367 qubit1: qubit1.into(),
368 qubit2: qubit2.into(),
369 theta,
370 })
371 }
372
373 pub fn rzx(
377 &mut self,
378 control: impl Into<QubitId>,
379 target: impl Into<QubitId>,
380 theta: f64,
381 ) -> QuantRS2Result<&mut Self> {
382 self.add_gate(RZX {
383 control: control.into(),
384 target: target.into(),
385 theta,
386 })
387 }
388
389 pub fn dcx(
393 &mut self,
394 qubit1: impl Into<QubitId>,
395 qubit2: impl Into<QubitId>,
396 ) -> QuantRS2Result<&mut Self> {
397 self.add_gate(DCX {
398 qubit1: qubit1.into(),
399 qubit2: qubit2.into(),
400 })
401 }
402
403 pub fn toffoli(
407 &mut self,
408 control1: impl Into<QubitId>,
409 control2: impl Into<QubitId>,
410 target: impl Into<QubitId>,
411 ) -> QuantRS2Result<&mut Self> {
412 self.add_gate(Toffoli {
413 control1: control1.into(),
414 control2: control2.into(),
415 target: target.into(),
416 })
417 }
418
419 pub fn cswap(
421 &mut self,
422 control: impl Into<QubitId>,
423 target1: impl Into<QubitId>,
424 target2: impl Into<QubitId>,
425 ) -> QuantRS2Result<&mut Self> {
426 self.add_gate(Fredkin {
427 control: control.into(),
428 target1: target1.into(),
429 target2: target2.into(),
430 })
431 }
432
433 pub fn ccx(
435 &mut self,
436 control1: impl Into<QubitId>,
437 control2: impl Into<QubitId>,
438 target: impl Into<QubitId>,
439 ) -> QuantRS2Result<&mut Self> {
440 self.toffoli(control1, control2, target)
441 }
442
443 pub fn fredkin(
445 &mut self,
446 control: impl Into<QubitId>,
447 target1: impl Into<QubitId>,
448 target2: impl Into<QubitId>,
449 ) -> QuantRS2Result<&mut Self> {
450 self.cswap(control, target1, target2)
451 }
452
453 pub fn measure(&mut self, qubit: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
460 let qubit_id = qubit.into();
461 self.add_gate(Measure { target: qubit_id })?;
462 Ok(self)
463 }
464
465 pub fn reset(&mut self, _qubit: impl Into<QubitId>) -> QuantRS2Result<&mut Self> {
470 Err(quantrs2_core::error::QuantRS2Error::UnsupportedOperation(
471 "Reset operation is not yet implemented. Reset requires special quantum state manipulation.".to_string()
472 ))
473 }
474
475 pub fn barrier(&mut self, qubits: &[QubitId]) -> QuantRS2Result<&mut Self> {
481 for &qubit in qubits {
483 if qubit.id() as usize >= N {
484 return Err(quantrs2_core::error::QuantRS2Error::InvalidQubitId(
485 qubit.id(),
486 ));
487 }
488 }
489
490 self.barriers.push(BarrierInfo {
498 after_gate_index: self.gates().len(),
499 qubits: qubits.to_vec(),
500 });
501 Ok(self)
502 }
503
504 pub fn measure_all(&mut self) -> QuantRS2Result<&mut Self> {
506 for i in 0..N {
507 self.measure(QubitId(i as u32))?;
508 }
509 Ok(self)
510 }
511
512 pub fn h_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
522 for &qubit in qubits {
523 self.h(QubitId::new(qubit))?;
524 }
525 Ok(self)
526 }
527
528 pub fn x_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
536 for &qubit in qubits {
537 self.x(QubitId::new(qubit))?;
538 }
539 Ok(self)
540 }
541
542 pub fn y_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
544 for &qubit in qubits {
545 self.y(QubitId::new(qubit))?;
546 }
547 Ok(self)
548 }
549
550 pub fn z_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
552 for &qubit in qubits {
553 self.z(QubitId::new(qubit))?;
554 }
555 Ok(self)
556 }
557
558 pub fn h_range(&mut self, range: std::ops::Range<u32>) -> QuantRS2Result<&mut Self> {
566 for qubit in range {
567 self.h(QubitId::new(qubit))?;
568 }
569 Ok(self)
570 }
571
572 pub fn x_range(&mut self, range: std::ops::Range<u32>) -> QuantRS2Result<&mut Self> {
574 for qubit in range {
575 self.x(QubitId::new(qubit))?;
576 }
577 Ok(self)
578 }
579
580 pub fn rx_all(&mut self, qubits: &[u32], theta: f64) -> QuantRS2Result<&mut Self> {
582 for &qubit in qubits {
583 self.rx(QubitId::new(qubit), theta)?;
584 }
585 Ok(self)
586 }
587
588 pub fn ry_all(&mut self, qubits: &[u32], theta: f64) -> QuantRS2Result<&mut Self> {
590 for &qubit in qubits {
591 self.ry(QubitId::new(qubit), theta)?;
592 }
593 Ok(self)
594 }
595
596 pub fn rz_all(&mut self, qubits: &[u32], theta: f64) -> QuantRS2Result<&mut Self> {
598 for &qubit in qubits {
599 self.rz(QubitId::new(qubit), theta)?;
600 }
601 Ok(self)
602 }
603
604 pub fn swap_all(&mut self, pairs: &[(u32, u32)]) -> QuantRS2Result<&mut Self> {
615 for &(q1, q2) in pairs {
616 self.swap(QubitId::new(q1), QubitId::new(q2))?;
617 }
618 Ok(self)
619 }
620
621 pub fn cz_all(&mut self, pairs: &[(u32, u32)]) -> QuantRS2Result<&mut Self> {
632 for &(q1, q2) in pairs {
633 self.cz(QubitId::new(q1), QubitId::new(q2))?;
634 }
635 Ok(self)
636 }
637
638 pub fn cnot_all(&mut self, pairs: &[(u32, u32)]) -> QuantRS2Result<&mut Self> {
649 for &(control, target) in pairs {
650 self.cnot(QubitId::new(control), QubitId::new(target))?;
651 }
652 Ok(self)
653 }
654
655 pub fn barrier_all(&mut self, qubits: &[u32]) -> QuantRS2Result<&mut Self> {
668 let qubit_ids: Vec<QubitId> = qubits.iter().map(|&q| QubitId::new(q)).collect();
669 self.barrier(&qubit_ids)?;
670 Ok(self)
671 }
672
673 #[cfg(feature = "python")]
677 pub fn get_single_qubit_for_gate(&self, gate_type: &str, index: usize) -> pyo3::PyResult<u32> {
678 self.find_gate_by_type_and_index(gate_type, index)
679 .and_then(|gate| {
680 if gate.qubits().len() == 1 {
681 Some(gate.qubits()[0].id())
682 } else {
683 None
684 }
685 })
686 .ok_or_else(|| {
687 pyo3::exceptions::PyValueError::new_err(format!(
688 "Gate {gate_type} at index {index} not found or is not a single-qubit gate"
689 ))
690 })
691 }
692
693 #[cfg(feature = "python")]
695 pub fn get_rotation_params_for_gate(
696 &self,
697 gate_type: &str,
698 index: usize,
699 ) -> pyo3::PyResult<(u32, f64)> {
700 self.find_gate_by_type_and_index(gate_type, index)
701 .and_then(|gate| {
702 if gate.qubits().len() == 1 {
703 Some((gate.qubits()[0].id(), 0.0))
704 } else {
705 None
706 }
707 })
708 .ok_or_else(|| {
709 pyo3::exceptions::PyValueError::new_err(format!(
710 "Gate {gate_type} at index {index} not found or is not a rotation gate"
711 ))
712 })
713 }
714
715 #[cfg(feature = "python")]
717 pub fn get_two_qubit_params_for_gate(
718 &self,
719 gate_type: &str,
720 index: usize,
721 ) -> pyo3::PyResult<(u32, u32)> {
722 self.find_gate_by_type_and_index(gate_type, index)
723 .and_then(|gate| {
724 if gate.qubits().len() == 2 {
725 Some((gate.qubits()[0].id(), gate.qubits()[1].id()))
726 } else {
727 None
728 }
729 })
730 .ok_or_else(|| {
731 pyo3::exceptions::PyValueError::new_err(format!(
732 "Gate {gate_type} at index {index} not found or is not a two-qubit gate"
733 ))
734 })
735 }
736
737 #[cfg(feature = "python")]
739 pub fn get_controlled_rotation_params_for_gate(
740 &self,
741 gate_type: &str,
742 index: usize,
743 ) -> pyo3::PyResult<(u32, u32, f64)> {
744 self.find_gate_by_type_and_index(gate_type, index)
745 .and_then(|gate| {
746 if gate.qubits().len() == 2 {
747 Some((gate.qubits()[0].id(), gate.qubits()[1].id(), 0.0))
748 } else {
749 None
750 }
751 })
752 .ok_or_else(|| {
753 pyo3::exceptions::PyValueError::new_err(format!(
754 "Gate {gate_type} at index {index} not found or is not a controlled rotation gate"
755 ))
756 })
757 }
758
759 #[cfg(feature = "python")]
761 pub fn get_three_qubit_params_for_gate(
762 &self,
763 gate_type: &str,
764 index: usize,
765 ) -> pyo3::PyResult<(u32, u32, u32)> {
766 self.find_gate_by_type_and_index(gate_type, index)
767 .and_then(|gate| {
768 if gate.qubits().len() == 3 {
769 Some((
770 gate.qubits()[0].id(),
771 gate.qubits()[1].id(),
772 gate.qubits()[2].id(),
773 ))
774 } else {
775 None
776 }
777 })
778 .ok_or_else(|| {
779 pyo3::exceptions::PyValueError::new_err(format!(
780 "Gate {gate_type} at index {index} not found or is not a three-qubit gate"
781 ))
782 })
783 }
784}