Commit 98c4469c authored by Nguyen, Thien Minh's avatar Nguyen, Thien Minh
Browse files

Fixed the QRT kernel calls



This turned out to be an easy fix: we just need to contribute the compiled kernels as circuits.

This will guarantee that the kernel invocation follows what provided at the call site.

Tested with various use cases and they worked as expected.

Signed-off-by: default avatarNguyen, Thien <nguyentm@ornl.gov>
parent 83af7f31
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -6,13 +6,15 @@
__qpu__ void f(qreg q) {
  const auto nQubits = q.size();
  // Add some gates
  for (int qIdx = 0; qIdx < nQubits; ++qIdx) {
    H(q[qIdx]);
  }  
  X(q[1]);

  // Call qft kernel (defined in a separate header file)
  qft(q);  
  quantumFourierTransform(q, nQubits);  
  
  // Inverse QFT:
  inverseQuantumFourierTransform(q, nQubits);
  
  // Measure all qubits
  for (int qIdx = 0; qIdx < nQubits; ++qIdx) {
    Measure(q[qIdx]);
  }  
@@ -20,6 +22,9 @@ __qpu__ void f(qreg q) {

// Compile:
// qcor -o multiple_kernels -qpu qpp -shots 1024 -qrt multiple_kernels.cpp
// Execute:
// ./multiple_kernels
// Expected: "010" state (all shots) since we do X(q[1]) the QFT->IQFT (identity)
int main(int argc, char **argv) {
  // Allocate 3 qubits
  auto q = qalloc(3);
+47 −0
Original line number Diff line number Diff line
#include "qcor.hpp"

// Demonstrating Bell Test using multiple kernels

__qpu__ void measureAllQubits(qreg q) {
  for (int qIdx = 0; qIdx < q.size(); ++qIdx) {
    Measure(q[qIdx]);
  }  
}

// Entangle all qubit in a qubit register with a master qubit
__qpu__ void entangleAll(qreg q, int masterBitIdx) {
  for (int qIdx = 0; qIdx < masterBitIdx; ++qIdx) {
    CNOT(q[masterBitIdx], q[qIdx]);
  }  
  
  for (int qIdx = masterBitIdx + 1; qIdx < q.size(); ++qIdx) {
    CNOT(q[masterBitIdx], q[qIdx]);
  }  
}

// Entry point kernel
__qpu__ void bellTest(qreg qBits) {
  // Add some gates
  // Entangle the *middle* qubit with all other qubits
  int masterBit = qBits.size() / 2;
  // Hadamard
  H(qBits[masterBit]);
  // Entangle
  entangleAll(qBits, masterBit);
  
  // Measure all qubits
  measureAllQubits(qBits);
}

// Compile:
// qcor -o multiple_kernels -qpu qpp -shots 1024 -qrt multiple_kernels.cpp
int main(int argc, char **argv) {
  // Allocate 7 qubits: 
  // i.e. Hadamard on q[3] and entangle q[3] with other qubits.
  auto q = qalloc(7);
  // Call entry-point kernel
  bellTest(q);
  // dump the results
  // Expect: ~50-50 for "0000000" and "1111111"
  q.print();
}
+25 −3
Original line number Diff line number Diff line
@@ -5,10 +5,12 @@

#include "qcor.hpp"

// QFT kernel
__qpu__ void qft(qreg q) {
// QFT kernel:
// Input: Qubit register and the max qubit index for the QFT,
// i.e. allow us to do QFT on a subset of the register [0, maxBitIdx)
__qpu__ void quantumFourierTransform(qreg q, int maxBitIdx) {
  // Local Declarations
  const auto nQubits = q.size();
  const auto nQubits = maxBitIdx;

  for (int qIdx = 0; qIdx < nQubits; ++qIdx) {
    auto bitIdx = nQubits - qIdx - 1;
@@ -24,3 +26,23 @@ __qpu__ void qft(qreg q) {
    Swap(q[qIdx], q[nQubits - qIdx - 1]);
  }
}

// Inverse QFT
__qpu__ void inverseQuantumFourierTransform(qreg q, int maxBitIdx) {
  // Local Declarations
  const auto nQubits = maxBitIdx;
  // Swap qubits
  for (int qIdx = 0; qIdx < nQubits / 2; ++qIdx) {
    Swap(q[qIdx], q[nQubits - qIdx - 1]);
  }

  for (int qIdx = 0; qIdx < nQubits - 1; ++qIdx) {
    H(q[qIdx]);
    for (int j = 0; j < qIdx + 1; ++j) {
      const double theta = -M_PI/std::pow(2.0, qIdx + 1 - j);
      CPhase(q[j], q[qIdx + 1], theta);
    }
  }

  H(q[nQubits - 1]);
}
 No newline at end of file
+6 −0
Original line number Diff line number Diff line
@@ -570,6 +570,12 @@ void run_token_collector_llvm_rt(clang::Preprocessor &PP,

  OS << ");\n";
  OS << "}";

  // In runtime mode, we contribute each annotated *kernel* as a circuit.
  // Hence, kernels can be used within other kernels similar to the way
  // XACC circuits are instantiated in XASM.
  auto circuit = std::shared_ptr<xacc::Instruction>(new xacc::quantum::Circuit(kernel_name));
  xacc::contributeService(kernel_name, circuit);
}

} // namespace qcor