QCOR
common.hpp
1 #pragma once
2 #include <qalloc>
3 #include <vector>
4 #include "qcor_observable.hpp"
5 
6 #ifdef _QCOR_FTQC_RUNTIME
7 namespace ftqc {
8 __qpu__ void reset_all(qreg q) {
9  for (int i = 0; i < q.size(); ++i) {
10  if (Measure(q[i])) {
11  X(q[i]);
12  }
13  }
14 }
15 
16 // FTQC "sync" Pauli measurement: returns the parity output
17 __qpu__ void measure_basis(qreg q, std::vector<qcor::Operator> bases,
18  int &out_parity) {
19  int oneCount = 0;
20  for (int i = 0; i < bases.size(); ++i) {
21  auto pauliOp = bases[i];
22  const std::string pauliStr = pauliOp.toString().substr(6);
23  const auto bitIdx = std::stoi(pauliStr.substr(1));
24  // TODO: fix XASM compiler to handle char literal
25  if (pauliStr.rfind("X", 0) == 0) {
26  H(q[bitIdx]);
27  }
28 
29  if (pauliStr.rfind("Y", 0) == 0) {
30  Rx(q[bitIdx], M_PI_2);
31  }
32  if (Measure(q[bitIdx])) {
33  oneCount++;
34  }
35  }
36  out_parity = oneCount - 2 * (oneCount / 2);
37 }
38 
39 // Measure the given Pauli operator using an explicit scratch qubit to perform the measurement.
40 __qpu__ void measure_basis_with_scratch(qreg q, int scratchQubit,
41  std::vector<qcor::Operator> bases,
42  int &out_result) {
43  H(q[scratchQubit]);
44  for (int i = 0; i < bases.size(); ++i) {
45  auto pauliOp = bases[i];
46  const std::string pauliStr = pauliOp.toString().substr(6);
47  const auto bitIdx = std::stoi(pauliStr.substr(1));
48  // Pauli-X
49  if (pauliStr.rfind("X", 0) == 0) {
50  CX(q[scratchQubit], q[bitIdx]);
51  }
52  // Pauli-Y
53  if (pauliStr.rfind("Y", 0) == 0) {
54  CY(q[scratchQubit], q[bitIdx]);
55  }
56  // Pauli-Z
57  if (pauliStr.rfind("Z", 0) == 0) {
58  CZ(q[scratchQubit], q[bitIdx]);
59  }
60  }
61  H(q[scratchQubit]);
62  if (Measure(q[scratchQubit])) {
63  out_result = 1;
64  // Reset scratchQubit as well
65  X(q[scratchQubit]);
66  } else {
67  out_result = 0;
68  }
69 }
70 } // namespace ftqc
71 #endif