forked from Qiskit/qiskit-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquantumcircuit_def.hpp
More file actions
718 lines (584 loc) · 25.6 KB
/
Copy pathquantumcircuit_def.hpp
File metadata and controls
718 lines (584 loc) · 25.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
/*
# This code is part of Qiskit.
#
# (C) Copyright IBM 2024.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
*/
// Quantum circuit class definition
#ifndef __qiskitcpp_circuit_quantum_circuit_def_hpp__
#define __qiskitcpp_circuit_quantum_circuit_def_hpp__
#include <memory>
#include <functional>
#include <unordered_set>
#include "utils/types.hpp"
#include "circuit/parameter.hpp"
//#include "circuit/classical/expr.hpp"
#include "circuit/classicalregister.hpp"
#include "circuit/quantumregister.hpp"
#include "circuit/library/standard_gates/standard_gates.hpp"
#include "circuit/circuitinstruction.hpp"
#include <complex>
#include "qiskit.h"
// this macro replaces Complex64 used in rust FFI
#define Complex64 std::complex<double>
// qiskit C-API circuit data
using rust_circuit = ::QkCircuit;
namespace Qiskit
{
namespace circuit
{
class ControlFlowOp;
class IfElseOp;
static Parameter null_param;
/// @class QuantumCircuit
/// @brief Qiskit representation of a quantum circuit.
class QuantumCircuit
{
protected:
uint_t num_qubits_; // number of qubits
uint_t num_clbits_; // number of classical bits
double global_phase_ = 0.0; // initial global phase
std::vector<QuantumRegister> qregs_; // quantum registers
std::vector<ClassicalRegister> cregs_; // classical registers
std::shared_ptr<rust_circuit> rust_circuit_ = nullptr; // shared pointer to the circuit for Rust
std::shared_ptr<ControlFlowOp> pending_control_flow_op_ = nullptr; // shared pointer to control flow object
reg_t qubit_map_; // qubit map caused by transpiling
std::vector<std::pair<uint_t, uint_t>> measure_map_; // a list of pair of qubit and clbit for measure
public:
/// @brief Create a new QuantumCircuit
QuantumCircuit() {}
/// @brief Create a new QuantumCircuit
/// @param num_qubits The number of qubits in the circuit
/// @param num_clbits The number of clbits in the circuit
/// @param global_phase The global phase of the circuit, measured in radians
QuantumCircuit(const uint_t num_qubits, const uint_t num_clbits, const double global_phase = 0.0);
/// @brief Create a new QuantumCircuit
/// @param qreg A QuantumRegister
/// @param creg A ClassicalRegister
/// @param global_phase The global phase of the circuit, measured in radians
QuantumCircuit(QuantumRegister &qreg, ClassicalRegister &creg, const double global_phase = 0.0);
/// @brief Create a new QuantumCircuit
/// @param qregs A list of QuantumRegister
/// @param cregs A list of ClassicalRegister
/// @param global_phase The global phase of the circuit, measured in radians
QuantumCircuit(std::vector<QuantumRegister> qregs, std::vector<ClassicalRegister> cregs, const double global_phase = 0.0);
/// @brief Create a new reference to Quantum Circuit
/// @details Copy constructor of QuantumCircuit does not copy the circuit,
/// but copies shared pointer to Rust's circuit
/// If you want to make a copy of the circuit,
/// please call QuantumCircuit::copy explicitly.
/// @param circ a Quantum Circuit to be copied the refrence in the new object
QuantumCircuit(const QuantumCircuit &circ);
~QuantumCircuit();
/// @brief Return number of qubits
/// @return number of qubits
uint_t num_qubits(void) const
{
return num_qubits_;
}
/// @brief Return number of classical bits
/// @return number of classical bits
uint_t num_clbits(void) const
{
return num_clbits_;
}
/// @brief Return number of qregs
/// @return number of qregs
uint_t num_qregs(void) const
{
return qregs_.size();
}
/// @brief Return number of cregs
/// @return number of cregs
uint_t num_cregs(void) const
{
return cregs_.size();
}
/// @brief Return a list of qregs
/// @return reference to a list of qregs
const std::vector<QuantumRegister>& qregs(void) const
{
return qregs_;
}
/// @brief Return a list of cregs
/// @return reference to a list of cregs
const std::vector<ClassicalRegister>& cregs(void) const
{
return cregs_;
}
std::shared_ptr<rust_circuit> get_rust_circuit(const bool update = true)
{
if (update)
add_pending_control_flow_op();
return rust_circuit_;
}
/// @brief Copy Quantum Circuit
/// @return copied circuit
QuantumCircuit copy(void);
/// @brief set circuit reference of Qiskit circuit
/// @param circ smart pointer to RUst circuit
/// @param map layout mapping
void set_qiskit_circuit(std::shared_ptr<rust_circuit> circ, const std::vector<uint32_t> &map);
/// @brief get qubit mapping
/// @return qubit mapping
const reg_t &get_qubit_map(void)
{
return qubit_map_;
}
/// @brief get qubits to be measured
/// @return a set of qubits
std::vector<std::pair<uint_t, uint_t>> &get_measure_map(void)
{
return measure_map_;
}
/// @brief set global phase
/// @param phase global phase value
void global_phase(const double phase);
/// @brief Apply HGate
/// @param qubit The qubit to apply the gate to.
void h(const uint_t qubit);
/// @brief Apply IGate
/// @param qubit The qubit to apply the gate to.
void i(const uint_t qubit);
/// @brief Apply XGate
/// @param qubit The qubit to apply the gate to.
void x(const uint_t qubit);
/// @brief Apply YGate
/// @param qubit The qubit to apply the gate to.
void y(const uint_t qubit);
/// @brief Apply ZGate
/// @param qubit The qubit to apply the gate to.
void z(const uint_t qubit);
/// @brief Apply PhaseGate
/// @param phase Phase.
/// @param qubit The qubit to apply the gate to.
void p(const double phase, const uint_t qubit);
/// @brief Apply PhaseGate
/// @param phase Phase.
/// @param qubit The qubit to apply the gate to.
void p(const Parameter &phase, const uint_t qubit);
/// @brief Apply RGate
/// @param theta The angle of the rotation.
/// @param phi The angle of the axis of rotation in the x-y plane.
/// @param qubit The qubit to apply the gate to.
void r(const double theta, const double phi, const uint_t qubit);
/// @brief Apply RGate
/// @param theta The angle of the rotation
/// @param phi The angle of the axis of rotation in the x-y plane
/// @param qubit The qubit to apply the gate to
void r(const Parameter &theta, const Parameter &phi, const uint_t qubit);
/// @brief Apply RXGate
/// @param theta The angle of the rotation
/// @param qubit The qubit to apply the gate to
void rx(const double theta, const uint_t qubit);
/// @brief Apply RXGate
/// @param theta The angle of the rotation
/// @param qubit The qubit to apply the gate to
void rx(const Parameter &theta, const uint_t qubit);
/// @brief Apply RYGate
/// @param theta The angle of the rotation
/// @param qubit The qubit to apply the gate to
void ry(const double theta, const uint_t qubit);
/// @brief Apply RYGate
/// @param theta The angle of the rotation
/// @param qubit The qubit to apply the gate to
void ry(const Parameter &theta, const uint_t qubit);
/// @brief Apply RZGate
/// @param theta The angle of the rotation
/// @param qubit The qubit to apply the gate to
void rz(const double theta, const uint_t qubit);
/// @brief Apply RZGate
/// @param theta The angle of the rotation
/// @param qubit The qubit to apply the gate to
void rz(const Parameter &theta, const uint_t qubit);
/// @brief Apply SGate
/// @param qubit The qubit to apply the gate to.
void s(const uint_t qubit);
/// @brief Apply SdgGate
/// @param qubit The qubit to apply the gate to.
void sdg(const uint_t qubit);
/// @brief Apply SXGate
/// @param qubit The qubit to apply the gate to.
void sx(const uint_t qubit);
/// @brief Apply SXdgGate
/// @param qubit The qubit to apply the gate to.
void sxdg(const uint_t qubit);
/// @brief Apply TGate
/// @param qubit The qubit to apply the gate to.
void t(const uint_t qubit);
/// @brief Apply TdgGate
/// @param qubit The qubit to apply the gate to.
void tdg(const uint_t qubit);
/// @brief Apply UGate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param qubit The qubit to apply the gate to.
void u(const double theta, const double phi, const double lam, const uint_t qubit);
/// @brief Apply UGate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param qubit The qubit to apply the gate to.
void u(const Parameter &theta, const Parameter &phi, const Parameter &lam, const uint_t qubit);
/// @brief Apply U1Gate
/// @param theta The theta rotation angle of the gate.
void u1(const double theta, const uint_t qubit);
/// @brief Apply U1Gate
/// @param theta The theta rotation angle of the gate.
/// @param qubit The qubit to apply the gate to.
void u1(const Parameter &theta, const uint_t qubit);
/// @brief Apply U2Gate
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param qubit The qubit to apply the gate to.
void u2(const double phi, const double lam, const uint_t qubit);
/// @brief Apply U2Gate
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param qubit The qubit to apply the gate to.
void u2(const Parameter &phi, const Parameter &lam, const uint_t qubit);
/// @brief Apply U3Gate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param qubit The qubit to apply the gate to.
void u3(const double theta, const double phi, const double lam, const uint_t qubit);
/// @brief Apply U3Gate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param qubit The qubit to apply the gate to.
void u3(const Parameter &theta, const Parameter &phi, const Parameter &lam, const uint_t qubit);
/// @brief Apply unitary gate specified by unitary to qubits
/// @param unitary Unitary operator
/// @param qubits The circuit qubits to apply the transformation to
void unitary(const std::vector<complex_t> &unitary, const reg_t &qubits);
/// @brief Apply CHGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void ch(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CXGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cx(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CYGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cy(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CZGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cz(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply DCXGate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void dcx(const uint_t qubit1, const uint_t qubit2);
/// @brief Apply ECRGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void ecr(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply SwapGate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void swap(const uint_t qubit1, const uint_t qubit2);
/// @brief Apply iSwapGate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void iswap(const uint_t qubit1, const uint_t qubit2);
/// @brief Apply controlled PhaseGate
/// @param phase Phase.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cp(const double phase, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply controlled PhaseGate
/// @param phase Phase.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cp(const Parameter &phase, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply controlled RXGate
/// @param theta The angle of the rotation
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void crx(const double theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply controlled RXGate
/// @param theta The angle of the rotation
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void crx(const Parameter &theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply controlled RYGate
/// @param theta The angle of the rotation
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cry(const double theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply controlled RYGate
/// @param theta The angle of the rotation
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cry(const Parameter &theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply controlled RZGate
/// @param theta The angle of the rotation
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void crz(const double theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply controlled RZGate
/// @param theta The angle of the rotation
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void crz(const Parameter &theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CSGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cs(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CSdgGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void csdg(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CSXGate
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void csx(const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CUGate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cu(const double theta, const double phi, const double lam, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CUGate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cu(const Parameter &theta, const Parameter &phi, const Parameter &lam, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CU1Gate
/// @param theta The theta rotation angle of the gate.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cu1(const double theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CU1Gate
/// @param theta The theta rotation angle of the gate.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cu1(const Parameter &theta, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CU3Gate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cu3(const double theta, const double phi, const double lam, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply CU3Gate
/// @param theta The theta rotation angle of the gate.
/// @param phi The phi rotation angle of the gate.
/// @param lam The lam rotation angle of the gate.
/// @param cqubit The qubit used as the control
/// @param tqubit The qubit targeted by the gate
void cu3(const Parameter &theta, const Parameter &phi, const Parameter &lam, const uint_t cqubit, const uint_t tqubit);
/// @brief Apply RXXGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void rxx(const double theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RXXGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void rxx(const Parameter &theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RYYGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void ryy(const double theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RYYGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void ryy(const Parameter &theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RZZGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void rzz(const double theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RZZGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void rzz(const Parameter &theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RZXGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void rzx(const double theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RZXGate
/// @param theta The rotation angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void rzx(const Parameter &theta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply XXminusYY
/// @param theta The rotation angle of the gate
/// @param beta The phase angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void xx_minus_yy(const double theta, const double beta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply XXminusYY
/// @param theta The rotation angle of the gate
/// @param beta The phase angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void xx_minus_yy(const Parameter &theta, const Parameter &beta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply XXplusYY
/// @param theta The rotation angle of the gate
/// @param beta The phase angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void xx_plus_yy(const double theta, const double beta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply XXplusYY
/// @param theta The rotation angle of the gate
/// @param beta The phase angle of the gate
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void xx_plus_yy(const Parameter &theta, const Parameter &beta, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply CCXGate
/// @param cqubit1 The qubit used as the first control
/// @param cqubit2 The qubit used as the second control
/// @param tqubit The qubit targeted by the gate
void ccx(const uint_t cqubit1, const uint_t cqubit2, const uint_t tqubit);
/// @brief Apply CCZGate
/// @param cqubit1 The qubit used as the first control
/// @param cqubit2 The qubit used as the second control
/// @param tqubit The qubit targeted by the gate
void ccz(const uint_t cqubit1, const uint_t cqubit2, const uint_t tqubit);
/// @brief Apply CSwapGate
/// @param cqubit The qubit used as the control
/// @param qubit1 The qubit to apply the gate to
/// @param qubit2 The qubit to apply the gate to
void cswap(const uint_t cqubit, const uint_t qubit1, const uint_t qubit2);
/// @brief Apply RCCXGate
/// @param cqubit1 The qubit used as the first control
/// @param cqubit2 The qubit used as the second control
/// @param tqubit The qubit targeted by the gate
void rccx(const uint_t cqubit1, const uint_t cqubit2, const uint_t tqubit);
/// @brief Apply C3XGate
/// @param cqubit1 The qubit used as the first control
/// @param cqubit2 The qubit used as the second control
/// @param cqubit3 The qubit used as the third control
/// @param tqubit The qubit targeted by the gate
void cccx(const uint_t cqubit1, const uint_t cqubit2, const uint_t cqubit3, const uint_t tqubit);
/// @brief Apply C3SXGate
/// @param cqubit1 The qubit used as the first control
/// @param cqubit2 The qubit used as the second control
/// @param cqubit3 The qubit used as the third control
/// @param tqubit The qubit targeted by the gate
void cccsx(const uint_t cqubit1, const uint_t cqubit2, const uint_t cqubit3, const uint_t tqubit);
/// @brief Apply RC3XGate
/// @param cqubit1 The qubit used as the first control
/// @param cqubit2 The qubit used as the second control
/// @param cqubit3 The qubit used as the third control
/// @param tqubit The qubit targeted by the gate
void rcccx(const uint_t cqubit1, const uint_t cqubit2, const uint_t cqubit3, const uint_t tqubit);
// other operations
/// @brief Measure a quantum bit(qubit) in the Z basis into a classical bit(cbit)
/// @param qubit The qubit to measure
/// @param cbit The classical bit to place the measurement result in.
void measure(const uint_t qubit, const uint_t cbit);
/// @brief Measure a quantum bit(qreg) in the Z basis into a classical bit(creg)
/// @param qreg The qubit to measure
/// @param creg The classical bit to place the measurement result in.
void measure(QuantumRegister &qreg, ClassicalRegister &creg);
/// @brief Reset the quantum bit to their default state
/// @param qubit The qubit to reset
void reset(const uint_t qubit);
/// @brief Reset the quantum bit to their default state
/// @param qreg The qubit to reset
void reset(QuantumRegister &qreg);
/// @brief Insert barrier on specified qubit
/// @param qubit The qubit to put a barrier
void barrier(const uint_t qubit);
/// @brief Insert barrier on multiple qubits
/// @param qubits The qubits to put barrier
void barrier(const reg_t &qubits);
// control flow ops
/// @brief IfElseOp with only a True body
/// @param clbit
/// @param value
/// @param body The circuit body to be run if condition is true.
IfElseOp &if_test(const uint32_t clbit, const uint32_t value, const std::function<void(QuantumCircuit &)> body);
// IfElseOp& if_test(Expr expr, std::function<void(qiskitcpp::circuit::QuantumCircuit&)> body);
// parameter binding
/// @brief Return the number of parameter objects in the circuit
/// @return the number of parameter objects in the circuit
uint_t num_parameters(void) const;
/// @brief Assign parameters to new parameters or values.
/// @param keys a list of keys
/// @param values a list of values
void assign_parameters(const std::vector<std::string> keys, const std::vector<double> values);
/// @brief Assign parameter to new parameter or value.
/// @param key key
/// @param value value
void assign_parameter(const std::string key, const double val);
/// @brief Add other circuit at the end of this circuit
/// @param rhs circuit to be added
/// @param qubits a list of qubits to be mapped
/// @param clits a list of clbits to be mapped
QuantumCircuit &operator+=(QuantumCircuit &rhs);
QuantumCircuit operator+(QuantumCircuit &rhs);
void compose(QuantumCircuit &circ);
void compose(QuantumCircuit &circ, const reg_t &qubits, const reg_t &clbits);
/// @brief append a gate at the end of the circuit
/// @param op a gate to be added
/// @param qubits a list of qubits to be mapped
/// @param params a list of parameters
void append(const Instruction &op, const reg_t &qubits);
void append(const Instruction &op, const std::vector<std::uint32_t> &qubits);
/// @brief append a gate at the end of the circuit
/// @param inst an instruction to be added
void append(const CircuitInstruction &inst);
void append(const Instruction &op, const uint_t qubit)
{
reg_t qubits({qubit});
append(op, qubits);
}
/// @brief get number og instructions
/// @return number of instructions in the circuit
uint_t num_instructions(void);
/// @brief get instruction
/// @param i an index to the instruction
/// @return the instruction at index i
CircuitInstruction operator[](uint_t i);
// qasm3
/// @brief Serialize a QuantumCircuit object as an OpenQASM3 string.
/// @return An OpenQASM3 string.
std::string to_qasm3(void);
/// @brief print circuit (this is for debug)
void print(void) const;
/// @brief draw the circuit
void draw(void) const;
/// @brief compare two circuits
/// @param other a circuit to be compared with this circuit
/// @return true if two circuits are the same
bool operator==(const QuantumCircuit& other) const;
bool operator!=(const QuantumCircuit& other) const
{
return !(*this == other);
}
protected:
void add_pending_control_flow_op(void);
void pre_add_gate(void)
{
add_pending_control_flow_op();
}
void get_qubits(reg_t &bits);
void get_clbits(reg_t &bits);
};
} // namespace circuit
} // namespace Qiskit
#endif // __qiskitcpp_circuit_quantum_circuit_def_hpp__