Qit/gates.rs
1/*!
2 Basic gates that make up quantum circuits and traits related to gate applications
3
4 The following gates can act directly on qubits.
5
6* 1-Bit Gates
7 * X(X-Gate. Not Gate)
8 * Y(Y-Gate)
9 * Z(Z-Gate)
10 * H(Hadamard-Gate)
11 * R(R_z-Gate. Gate that rotates at any angle around the z-axis)
12* 2-Bit Gate
13 * CX(Controlled Not Gate)
14* 3-Bit Gate
15 * CCX(Controlled Controlled Not Gate)
16* N-Bit Gate
17 * CNX(Controlled Controlled ...(n) Not Gate)
18
19CNX is an X gate with an arbitrary number of control bits prepared for convenience in circuit creation.
20
21In addition to the above, there is a U structure that combines multiple gates into one circuit,
22and a CU structure that allows you to control multiple gates with one bit.
23
24# Example
25All gates can make changes to the qubit using the apply method.
26## 1-Bit Gates
27```
28use Qit::{gates::{X, Y, Z, H, R}, core::{Applicable, Qubits}};
29use std::f64::consts::PI;
30
31// create gate struct
32let x_0 = X::new(0);
33// make Qbit|000⟩ Qubits::from_num(size: 3, num: 0)
34let q_in = Qubits::from_num(2, 0);
35// apply X-gate to Qbit
36let q_out = x_0.apply(q_in);
37
38q_out.print_probs();
39// |00⟩ : +0.000 +0.000i
40// |01⟩ : +1.000 +0.000i
41// |10⟩ : +0.000 +0.000i
42// |11⟩ : +0.000 +0.000i
43
44// Y-Gate
45let y_0 = Y::new(0);
46let q_in = Qubits::zeros(2);
47let q_out = y_0.apply(q_in);
48q_out.print_cmps();
49// |00⟩ : +0.000 +0.000i
50// |01⟩ : +0.000 -1.000i
51// |10⟩ : +0.000 +0.000i
52// |11⟩ : +0.000 +0.000i
53
54// Z-Gate
55let z_0 = Z::new(0);
56let q_in = Qubits::from_num(2, 1);
57let q_out = z_0.apply(q_in);
58q_out.print_cmps();
59// |00⟩ : +0.000 +0.000i
60// |01⟩ : -1.000 -0.000i
61// |10⟩ : +0.000 +0.000i
62// |11⟩ : -0.000 -0.000i
63
64// Hadamard-Gate
65let h_0 = H::new(0);
66let q_in = Qubits::zeros(2);
67let q_out = h_0.apply(q_in);
68q_out.print_cmps();
69// |00⟩ : +0.707 +0.000i
70// |01⟩ : +0.707 +0.000i
71// |10⟩ : +0.000 +0.000i
72// |11⟩ : +0.000 +0.000i
73
74// R gate requires angle of f64.
75let angle = 0.5 * PI;
76let r_0 = R::new(0, angle);
77let q_in = q_out;
78let q_out = r_0.apply(q_in);
79q_out.print_cmps();
80// |00⟩ : +0.707 +0.000i
81// |01⟩ : +0.000 +0.707i
82// |10⟩ : +0.000 +0.000i
83// |11⟩ : +0.000 +0.000i
84
85```
86
87## 2-Bit Gate
88```
89use Qit::core::{Applicable, Qubits, Comp};
90use Qit::gates::CX;
91
92// create CX(0 → 1)
93let cx01 = CX::new(0, 1);
94let q_in = Qubits::from_num(2, 1);
95let q_out = cx01.apply(q_in);
96q_out.print_cmps();
97// |00⟩ : +0.000 +0.000i
98// |01⟩ : +0.000 +0.000i
99// |10⟩ : +0.000 +0.000i
100// |11⟩ : +1.000 +0.000i
101assert_eq!(q_out.bits[0b11], Comp::new(1.0, 0.0));
102```
103
104## 3-Bit Gate
105```
106use Qit::core::{Applicable, Comp, Qubits};
107use Qit::gates::CCX;
108
109let ccx = CCX::new(0, 1, 2);
110// q_in = |011⟩
111let q_in = Qubits::from_num(3, 3);
112let q_out = ccx.apply(q_in);
113q_out.print_cmps();
114// |000⟩ : +0.000 +0.000i
115// |001⟩ : +0.000 +0.000i
116// |010⟩ : +0.000 +0.000i
117// |011⟩ : +0.000 +0.000i
118// |100⟩ : +0.000 +0.000i
119// |101⟩ : +0.000 +0.000i
120// |110⟩ : +0.000 +0.000i
121// |111⟩ : +1.000 +0.000i
122assert_eq!(q_out.bits[0b111], Comp::new(1.0, 0.0));
123```
124
125## n-Bit Gate
126```
127use Qit::core::{Applicable, Comp, Qubits};
128use Qit::gates::CNX;
129
130let cnx = CNX::new(vec![0, 1, 2], 3);
131// q_in = |0111⟩
132let q_in = Qubits::from_num(4, 7);
133let q_out = cnx.apply(q_in);
134q_out.print_cmps();
135// |0000⟩ : +0.000 +0.000i
136// |0001⟩ : +0.000 +0.000i
137// .
138// .
139// .
140// |1110⟩ : +0.000 +0.000i
141// |1111⟩ : +1.000 +0.000i
142assert_eq!(q_out.bits[0b1111], Comp::new(1.0, 0.0));
143```
144*/
145
146use std::f64::consts::{PI, SQRT_2};
147
148use super::core::{Applicable, BitSlideIndex, Comp, Inversible, Operator, Qubits};
149
150const SQRT2_INV: f64 = 1.0 / SQRT_2;
151
152/**
153 * Hadamard Gate. 1√2(|0⟩⟨0| + |1⟩⟨0| + |0⟩⟨1| - |1⟩⟨1|)
154
155 # Usage
156 ```
157use Qit::{gates::H, core::{Applicable, Qubits}};
158
159// Hadamard-Gate
160let h_0 = H::new(0);
161let q_in = Qubits::zeros(2);
162let q_out = h_0.apply(q_in);
163q_out.print_cmps();
164// |00⟩ : +0.707 +0.000i
165// |01⟩ : +0.707 +0.000i
166// |10⟩ : +0.000 +0.000i
167// |11⟩ : +0.000 +0.000i
168 ```
169
170*/
171#[derive(Clone, Copy)]
172pub struct H {
173 target_bit: usize,
174}
175
176impl H {
177 pub fn new(target_bit: usize) -> Self {
178 return H {
179 target_bit: target_bit,
180 };
181 }
182}
183
184impl Applicable for H {
185 fn name(&self) -> String {
186 return format!("H({})", self.target_bit);
187 }
188
189 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
190 let step = 1 << self.target_bit;
191 let iter = iter.merge(step);
192
193 for idx1 in iter {
194 let idx0 = idx1 - step;
195 let temp = qubits.bits[idx0];
196 qubits.bits[idx0] = (qubits.bits[idx1] + temp) * SQRT2_INV;
197 qubits.bits[idx1] = (temp - qubits.bits[idx1]) * SQRT2_INV;
198 }
199
200 return qubits;
201 }
202}
203
204impl Inversible for H {}
205impl Operator for H {}
206
207/**
208Not Gate(pauli-X). (|1⟩⟨0| + |0⟩⟨1|)
209
210# Usage
211```
212use Qit::{gates::X, core::{Applicable, Qubits}};
213
214// X-Gate
215let x_0 = X::new(0);
216let q_in = Qubits::from_num(2, 0);
217let q_out = x_0.apply(q_in);
218q_out.print_probs();
219// |00⟩ : +0.000 +0.000i
220// |01⟩ : +1.000 +0.000i
221// |10⟩ : +0.000 +0.000i
222// |11⟩ : +0.000 +0.000i
223```
224*/
225#[derive(Clone, Copy)]
226pub struct X {
227 target_bit: usize,
228}
229impl X {
230 pub fn new(target_bit: usize) -> Self {
231 return X {
232 target_bit: target_bit,
233 };
234 }
235}
236
237impl Applicable for X {
238 fn name(&self) -> String {
239 return format!("X({})", self.target_bit);
240 }
241
242 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
243 let step = 1 << self.target_bit;
244 let iter = iter.merge(step);
245
246 for idx1 in iter {
247 let idx0 = idx1 - step;
248 let temp = qubits.bits[idx0];
249 qubits.bits[idx0] = qubits.bits[idx1];
250 qubits.bits[idx1] = temp;
251 }
252
253 return qubits;
254 }
255}
256
257impl Inversible for X {}
258impl Operator for X {}
259
260/**
261 pauli-Y Gate. i(|1⟩⟨0| - |0⟩⟨1|)
262
263# Usage
264```
265use Qit::{gates::Y, core::{Applicable, Qubits}};
266
267// Y-Gate
268let y_0 = Y::new(0);
269let q_in = Qubits::zeros(2);
270let q_out = y_0.apply(q_in);
271q_out.print_cmps();
272// |00⟩ : +0.000 +0.000i
273// |01⟩ : +0.000 -1.000i
274// |10⟩ : +0.000 +0.000i
275// |11⟩ : +0.000 +0.000i
276```
277*/
278#[derive(Clone, Copy)]
279pub struct Y {
280 target_bit: usize,
281}
282
283impl Y {
284 pub fn new(target_bit: usize) -> Self {
285 return Y {
286 target_bit: target_bit,
287 };
288 }
289}
290
291impl Applicable for Y {
292 fn name(&self) -> String {
293 return format!("Y({})", self.target_bit);
294 }
295
296 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
297 let step = 1 << self.target_bit;
298 let iter = iter.merge(step);
299
300 for idx1 in iter {
301 let idx0 = idx1 - step;
302 let temp = qubits.bits[idx0];
303 qubits.bits[idx0] = Comp::new(0.0, 1.0) * qubits.bits[idx1];
304 qubits.bits[idx1] = Comp::new(0.0, -1.0) * temp;
305 }
306
307 return qubits;
308 }
309}
310
311impl Inversible for Y {}
312impl Operator for Y {}
313
314/**
315 pauli-Z Gate. (|0⟩⟨0| - |1⟩⟨1|)
316
317 # Usage
318
319 ```
320use Qit::{gates::Z, core::{Applicable, Qubits}};
321
322// Z-Gate
323let z_0 = Z::new(0);
324let q_in = Qubits::from_num(2, 1);
325let q_out = z_0.apply(q_in);
326q_out.print_cmps();
327// |00⟩ : +0.000 +0.000i
328// |01⟩ : -1.000 -0.000i
329// |10⟩ : +0.000 +0.000i
330// |11⟩ : -0.000 -0.000i
331 ```
332*/
333#[derive(Clone, Copy)]
334pub struct Z {
335 target_bit: usize,
336}
337
338impl Z {
339 pub fn new(target_bit: usize) -> Self {
340 return Z {
341 target_bit: target_bit,
342 };
343 }
344}
345
346impl Applicable for Z {
347 fn name(&self) -> String {
348 return format!("Z({})", self.target_bit);
349 }
350
351 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
352 let step = 1 << self.target_bit;
353 let iter = iter.merge(step);
354
355 for idx1 in iter {
356 qubits.bits[idx1] = qubits.bits[idx1] * -1.0;
357 }
358
359 return qubits;
360 }
361}
362
363impl Inversible for Z {}
364impl Operator for Z {}
365
366/**
367Phase shift Gate. (|0⟩⟨0| + exp(ir)|1⟩⟨1|)
368
369(|0⟩ + |1⟩) →R(π)→ (|0⟩ - |1⟩)
370
371(|0⟩ + |1⟩) →R(π/2)→ (|0⟩ + i|1⟩)
372
373# Usage
374```
375use Qit::{gates::R, core::{Applicable, Qubits, Comp}};
376use std::f64::consts::PI;
377
378// R gate requires angle of f64.
379let angle = 0.5 * PI;
380let r_0 = R::new(0, angle);
381let q_in = Qubits::from_num(2, 1);
382let q_out = r_0.apply(q_in);
383q_out.print_cmps();
384// |00⟩ : +0.000 +0.000i
385// |01⟩ : +0.000 +1.000i
386// |10⟩ : +0.000 +0.000i
387// |11⟩ : +0.000 +0.000i
388```
389 */
390#[derive(Clone, Copy)]
391pub struct R {
392 target_bit: usize,
393 angle: f64,
394 phase: Comp,
395}
396
397impl R {
398 pub fn new(target_bit: usize, angle: f64) -> Self {
399 let phase = Comp(angle.cos(), angle.sin());
400 return R {
401 target_bit: target_bit,
402 angle: angle,
403 phase: phase,
404 };
405 }
406}
407
408impl Applicable for R {
409 fn name(&self) -> String {
410 return format!("R_{}({})", self.angle, self.target_bit);
411 }
412
413 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
414 let step = 1 << self.target_bit;
415 let iter = iter.merge(step);
416 for idx1 in iter {
417 qubits.bits[idx1] = qubits.bits[idx1] * self.phase;
418 }
419
420 return qubits;
421 }
422}
423
424impl Inversible for R {
425 fn inverse(&mut self) {
426 self.angle = 2.0 * PI - self.angle;
427 self.phase = Comp(self.angle.cos(), self.angle.sin());
428 }
429}
430impl Operator for R {}
431
432/**
433Controlled-Not Gate.
434
435# Usage
436
437```
438use Qit::core::{Applicable, Qubits, Comp};
439use Qit::gates::CX;
440
441// create CX(0 → 1)
442let cx01 = CX::new(0, 1);
443let q_in = Qubits::from_num(2, 1);
444let q_out = cx01.apply(q_in);
445q_out.print_cmps();
446// |00⟩ : +0.000 +0.000i
447// |01⟩ : +0.000 +0.000i
448// |10⟩ : +0.000 +0.000i
449// |11⟩ : +1.000 +0.000i
450assert_eq!(q_out.bits[0b11], Comp::new(1.0, 0.0));
451```
452 */
453#[derive(Clone, Copy)]
454pub struct CX {
455 controll_bit: usize,
456 target_bit: usize,
457}
458
459impl CX {
460 pub fn new(controll_bit: usize, target_bit: usize) -> Self {
461 return CX {
462 controll_bit: controll_bit,
463 target_bit: target_bit,
464 };
465 }
466}
467
468impl Applicable for CX {
469 fn name(&self) -> String {
470 return format!("CX({}->{})", self.controll_bit, self.target_bit);
471 }
472 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
473 let step = 1 << self.target_bit;
474 let iter = iter.merge((1 << self.controll_bit) | step);
475
476 for idx1 in iter {
477 let idx0 = idx1 - step;
478 let temp = qubits.bits[idx0];
479 qubits.bits[idx0] = qubits.bits[idx1];
480 qubits.bits[idx1] = temp;
481 }
482
483 return qubits;
484 }
485}
486
487impl Inversible for CX {}
488impl Operator for CX {}
489
490/**
491Controlled-Controlled-Not(CXX) Gate.
492
493# Usage
494
495```
496use Qit::core::{Applicable, Comp, Qubits};
497use Qit::gates::CCX;
498
499let ccx = CCX::new(0, 1, 2);
500// q_in = |011⟩
501let q_in = Qubits::from_num(3, 3);
502let q_out = ccx.apply(q_in);
503q_out.print_cmps();
504// |000⟩ : +0.000 +0.000i
505// |001⟩ : +0.000 +0.000i
506// |010⟩ : +0.000 +0.000i
507// |011⟩ : +0.000 +0.000i
508// |100⟩ : +0.000 +0.000i
509// |101⟩ : +0.000 +0.000i
510// |110⟩ : +0.000 +0.000i
511// |111⟩ : +1.000 +0.000i
512assert_eq!(q_out.bits[0b111], Comp::new(1.0, 0.0));
513```
514 */
515#[derive(Clone, Copy)]
516pub struct CCX {
517 controll_bit1: usize,
518 controll_bit2: usize,
519 target_bit: usize,
520}
521
522impl CCX {
523 pub fn new(controll_bit1: usize, controll_bit2: usize, target_bit: usize) -> Self {
524 return CCX {
525 controll_bit1: controll_bit1,
526 controll_bit2: controll_bit2,
527 target_bit: target_bit,
528 };
529 }
530}
531
532impl Applicable for CCX {
533 fn name(&self) -> String {
534 return format!(
535 "CCX([{},{}]->{})",
536 self.controll_bit1, self.controll_bit2, self.target_bit
537 );
538 }
539 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
540 let step = 1 << self.target_bit;
541 let iter = iter.merge((1 << self.controll_bit1) | (1 << self.controll_bit2) | step);
542
543 for idx1 in iter {
544 let idx0 = idx1 - step;
545 let temp = qubits.bits[idx0];
546 qubits.bits[idx0] = qubits.bits[idx1];
547 qubits.bits[idx1] = temp;
548 }
549
550 return qubits;
551 }
552}
553
554impl Inversible for CCX {}
555impl Operator for CCX {}
556
557/**
558Controlled-Controlled-Controlled-...(N)-Not Gate
559
560# Usage
561```
562use Qit::core::{Applicable, Comp, Qubits};
563use Qit::gates::CNX;
564
565let cnx = CNX::new(vec![0, 1, 2], 3);
566// q_in = |0111⟩
567let q_in = Qubits::from_num(4, 7);
568let q_out = cnx.apply(q_in);
569q_out.print_cmps();
570// |0000⟩ : +0.000 +0.000i
571// |0001⟩ : +0.000 +0.000i
572// .
573// .
574// .
575// |1110⟩ : +0.000 +0.000i
576// |1111⟩ : +1.000 +0.000i
577assert_eq!(q_out.bits[0b1111], Comp::new(1.0, 0.0));
578```
579*/
580#[derive(Clone)]
581pub struct CNX {
582 controll_bits: Vec<usize>,
583 target_bit: usize,
584}
585
586impl CNX {
587 pub fn new(controll_bits: Vec<usize>, target_bit: usize) -> Self {
588 return CNX {
589 controll_bits: controll_bits,
590 target_bit: target_bit,
591 };
592 }
593
594 fn cbit_mask(&self) -> usize {
595 let mut mask = 0;
596 for cbit in self.controll_bits.iter() {
597 mask |= 1 << (*cbit);
598 }
599 return mask;
600 }
601}
602
603impl Applicable for CNX {
604 fn name(&self) -> String {
605 let mut s = String::from("CNX[");
606 for i in self.controll_bits.iter() {
607 s += &format!("{},", i);
608 }
609 s += &format!("]->{}", self.target_bit);
610 return s;
611 }
612 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
613 let step = 1 << self.target_bit;
614 let iter = iter.merge(self.cbit_mask() | step);
615
616 for idx1 in iter {
617 let idx0 = idx1 - step;
618 let temp = qubits.bits[idx0];
619 qubits.bits[idx0] = qubits.bits[idx1];
620 qubits.bits[idx1] = temp;
621 }
622
623 return qubits;
624 }
625}
626
627impl Inversible for CNX {}
628impl Operator for CNX {}
629
630/**
631An alias for handling quantum gates together.
632
633# Example
634
635```
636use Qit::core::{Applicable, Qubits};
637use Qit::gates::{OperatorVec, PushOps, H, U};
638
639let mut v = OperatorVec::new();
640v.push_ops(H::new(0));
641v.push_ops(H::new(1));
642let u = U::new(v, String::from("hadamards"));
643let q_in = Qubits::from_num(2, 0);
644let q_out = u.apply(q_in);
645
646q_out.print_cmps();
647// |00⟩ : +0.500 +0.000i
648// |01⟩ : +0.500 +0.000i
649// |10⟩ : +0.500 +0.000i
650// |11⟩ : +0.500 +0.000i
651```
652*/
653pub type OperatorVec = Vec<Box<dyn Operator>>;
654
655/**
656A trait to make adding gates as easy as possible.
657 */
658pub trait PushOps {
659 fn push_ops(&mut self, op: impl Operator + 'static);
660}
661
662impl PushOps for OperatorVec {
663 fn push_ops(&mut self, op: impl Operator + 'static) {
664 self.push(Box::new(op));
665 }
666}
667
668// CU
669/**
670Controlled-Unitary Gate.
671Control a group of arbitrary gates using a specific qubit.
672
673```
674use Qit::circuits::wrapping_qadd_const;
675use Qit::core::{Applicable, Comp, Operator, Qubits};
676use Qit::gates::{CU, OperatorVec, PushOps};
677
678// make controlled-add_3
679let b_in = vec![0, 1, 2];
680let controll_bit = 3;
681
682let add_3 = wrapping_qadd_const(&b_in, 3);
683let controlled_add_3 = CU::from_u(controll_bit, add_3);
684
685// or
686let add_3 = wrapping_qadd_const(&b_in, 3);
687let add_3_gates: OperatorVec = add_3.gates;
688let controlled_add_3 = CU::new(
689 controll_bit,
690 add_3_gates,
691 String::from("something_name_you_like"),
692);
693
694// q_in = |1001⟩
695let q_in = Qubits::from_num(4, 0b1001);
696let q_out = controlled_add_3.apply(q_in);
697q_out.print_cmps();
698// |0000⟩ : +0.000 +0.000i
699// .
700// .
701// .
702// |1011⟩ : +0.000 +0.000i
703// |1100⟩ : +1.000 +0.000i
704// |1101⟩ : +0.000 +0.000i
705// |1110⟩ : +0.000 +0.000i
706// |1111⟩ : +0.000 +0.000i
707```
708*/
709pub struct CU {
710 controll_bit: usize,
711 gates: OperatorVec,
712 label: String,
713}
714
715impl CU {
716 pub fn new(controll_bit: usize, gates: OperatorVec, label: String) -> Self {
717 return CU {
718 controll_bit: controll_bit,
719 gates: gates,
720 label: label,
721 };
722 }
723
724 pub fn from_u(controll_bit: usize, u: U) -> Self {
725 return CU {
726 controll_bit: controll_bit,
727 gates: u.gates,
728 label: u.label,
729 };
730 }
731}
732
733impl Applicable for CU {
734 fn name(&self) -> String {
735 let mut s = format!("CU({}->", self.controll_bit);
736 for gate in &self.gates {
737 s.push_str(&format!("\n{}", gate.name()));
738 }
739 return format!("{})", s);
740 }
741
742 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
743 let iter = iter.merge(1 << self.controll_bit);
744 for gate in &self.gates {
745 qubits = gate.apply_iter(qubits, &iter);
746 }
747
748 return qubits;
749 }
750}
751
752impl Inversible for CU {
753 fn inverse(&mut self) {
754 for g in self.gates.iter_mut() {
755 g.inverse();
756 }
757 self.gates.reverse();
758 }
759}
760
761impl Operator for CU {}
762
763/**
764Unitary struct. struct for applying a vector of arbitrary gates together to a qubit
765
766# Example usage
767```
768use Qit::{gates::*};
769// full adder
770let a_in = 0;
771let b_in = 1;
772let c_in = 2;
773let c_out = 3;
774let ccx1 = CCX::new(a_in, b_in, c_out);
775let cx1 = CX::new(a_in, b_in);
776let ccx2 = CCX::new(b_in, c_in, c_out);
777let cx2 = CX::new(c_in, b_in);
778let adder = U::new(vec![Box::new(ccx1), Box::new(cx1), Box::new(ccx2), Box::new(cx2)],
779 String::from("full_adder_bit"));
780```
781 */
782pub struct U {
783 pub gates: OperatorVec,
784 label: String,
785}
786
787impl U {
788 pub fn new(gates: OperatorVec, name: String) -> Self {
789 return U {
790 gates: gates,
791 label: name,
792 };
793 }
794
795 pub fn rename(&mut self, name: String) {
796 self.label = name;
797 }
798}
799
800impl Applicable for U {
801 fn name(&self) -> String {
802 let mut s = format!("U[{}](", self.label);
803 for gate in &self.gates {
804 s.push_str(&format!("\n{}", gate.name()));
805 }
806 return format!("{})", s);
807 }
808
809 fn apply_iter(&self, mut qubits: Qubits, iter: &BitSlideIndex) -> Qubits {
810 for gate in &self.gates {
811 qubits = gate.apply_iter(qubits, &iter);
812 }
813
814 return qubits;
815 }
816}
817
818impl Inversible for U {
819 fn inverse(&mut self) {
820 for g in self.gates.iter_mut() {
821 g.inverse();
822 }
823 self.gates.reverse();
824 }
825}
826
827impl Operator for U {}