QCOR
hadamard_test.hpp
1 #pragma once
2 
3 #include "qalloc.hpp"
4 
5 using Unitary = KernelSignature<qreg>;
6 using StatePrep = KernelSignature<qreg>;
7 
8 // <U> = <state_prep| U |state_prep>
9 __qpu__ void __quantum_hadamard_test(qreg q, StatePrep state_prep,
10  Unitary unitary) {
11  auto test_qubit = q.head();
12  auto psi = q.extract_range({1, static_cast<std::size_t>(q.size())});
13 
14  // Prepare state |psi> on qreg of size n_qubits
15  state_prep(psi);
16 
17  // Create the superposition on the first qubit
18  H(test_qubit);
19 
20  // perform ctrl-U
21  unitary.ctrl(test_qubit, psi);
22 
23  // add the last hadamard
24  H(test_qubit);
25 
26  // measure
27  Measure(test_qubit);
28 }
29 
30 namespace qcor {
31 // Compute <U> = <state_prep | unitary | state_prep>
32 double hadamard_test(StatePrep state_prep, Unitary unitary,
33  int n_state_qubits) {
34  auto q = qalloc(n_state_qubits + 1);
35  __quantum_hadamard_test(q, state_prep, unitary);
36  // Compute <psi|U|psi>
37  // First make sure we have counts,
38  // if not, grab exp-val-z key in buffer
39  auto counts = q.counts();
40  if (counts.empty()) {
41  return q.exp_val_z();
42  }
43 
44  // We have counts, so use that
45  double count1 = (double)q.counts().find("1")->second;
46  double count2 = (double)q.counts().find("0")->second;
47  return std::fabs((count1 - count2) / (count1 + count2));
48 }
49 } // namespace qcor
qcor
Definition: qcor_syntax_handler.cpp:15