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

Work on runtime support for NISQ IfStatement



Adding mechanism to link runtime mz and if statement in NISQ mode: using a pointer-based lookup map.

applyifelse in NISQ mode to construct IfStmt circuit and collect the body by executing the body callable.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent c8d1e6de
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -123,6 +123,15 @@ Result *__quantum__qis__mz(Qubit *q) {
  if (verbose)
    printf("[qir-qrt] Measuring qubit %lu\n", q->id);
  std::size_t qcopy = q->id;
  if (mode == QRT_MODE::NISQ && enable_extended_nisq) {
    Result *new_result = new Result();
    nisq_result_to_creg_idx[new_result] = nisq_result_to_creg_idx.size();
    std::pair<std::string, size_t> creg =
        std::make_pair("qir_creg", nisq_result_to_creg_idx[new_result]);
    // Create a NISQ measure storing to the specific creg.
    ::quantum::mz({"q", qcopy}, &creg);
    return new_result;
  } else {
    auto bit = ::quantum::mz({"q", qcopy});
    if (mode == QRT_MODE::FTQC)
      if (verbose)
@@ -130,3 +139,4 @@ Result *__quantum__qis__mz(Qubit *q) {
    return bit ? ResultOne : ResultZero;
  }
}
}
 No newline at end of file
+29 −4
Original line number Diff line number Diff line
#include "CommonGates.hpp"
#include "qir-qrt-ms-compat.hpp"
#include "qir-qrt.hpp"
#include "qrt.hpp"
#include <iostream>
#include <math.h>
#include <stdexcept>
#include "qrt.hpp"

namespace {
static std::vector<Pauli> extractPauliIds(Array *paulis) {
@@ -395,11 +396,35 @@ void __quantum__qis__applyifelseintrinsic__body(Result *r,
  if (verbose)
    std::cout << "CALL: " << __PRETTY_FUNCTION__ << "\n";

  // Get the runtime
  if (mode == QRT_MODE::NISQ) {
  if (mode == QRT_MODE::NISQ && enable_extended_nisq) {
    if (verbose)
      std::cout << "NISQ mode If statement generation\n";
    // TODO: need a way to cast infer the creg name.....
    // NOTE: We use a different pointer value (not the static ResultOne and
    // ResultZero) in NISQ mode to store the lookup key to look up classical
    // register id to construct IfStmt IR.
    if (clb_on_zero || clb_on_one) {
      assert(r != ResultOne && r != ResultZero);
      assert(nisq_result_to_creg_idx.find(r) != nisq_result_to_creg_idx.end());
      // nisq_result_to_creg_idx should have an entry for this Result *
      const auto bit_idx = nisq_result_to_creg_idx[r];
      auto current_prog = ::quantum::qrt_impl->get_current_program();
      auto ifStmt = std::make_shared<xacc::quantum::IfStmt>();
      ifStmt->setBits({bit_idx});
      xacc::InstructionParameter creg_name("qir_creg");
      ifStmt->setParameter(0, creg_name);
      // Set the NISQ program to the ifStmt
      ::quantum::qrt_impl->set_current_program(
          std::make_shared<qcor::CompositeInstruction>(ifStmt));
      // We don't support else block atm yet.
      assert(!clb_on_zero);
      // Execute the callable: this will append NISQ instructions to the IfStmt
      clb_on_one->invoke(nullptr, nullptr);

      // Add the whole IfStmt to the program
      current_prog->addInstruction(ifStmt);
      // Restore the main program.
      ::quantum::qrt_impl->set_current_program(current_prog);
    }
  } else {
    assert(r);
    if (*r) {
+3 −0
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ std::shared_ptr<xacc::Accelerator> qpu;
std::string qpu_name = "qpp";
std::string qpu_config = "";
QRT_MODE mode = QRT_MODE::FTQC;
// Thien debug: enable this permanently
bool enable_extended_nisq = true;
std::unordered_map<Result *, size_t> nisq_result_to_creg_idx = {};
std::vector<std::unique_ptr<Array>> allocated_arrays;
// Map of single-qubit allocations,
// i.e. arrays of size 1.
+10 −1
Original line number Diff line number Diff line
@@ -25,7 +25,16 @@ extern std::string qpu_name;
// Global register instance.
extern std::shared_ptr<xacc::AcceleratorBuffer> global_qreg;
extern QRT_MODE mode;

// Flag to enable extended NISQ mode runtime
// Convert conditional to QASM 'If' for submission.
// Manually enable for the time-being, will eventually make it the default.
extern bool enable_extended_nisq;
// In extened NISQ mode, we use dedicated Result* (not ResultZero or ResultOne)
// to lookup an id to a global classical register.
// This will link measure to subsequence conditional on the Result*.
// !!IMPORTANT!! We assume that we only do a Measure -> Store -> Conditional.
// i.e., manipulating the bit result after Measure is not supported.
extern std::unordered_map<Result *, size_t> nisq_result_to_creg_idx;
void initialize();

// Initialize/Finalize/Config API
+3 −1
Original line number Diff line number Diff line
@@ -176,7 +176,9 @@ void u3(const qubit &qidx, const double theta, const double phi,

void reset(const qubit &qidx) { qrt_impl->reset(qidx); }

bool mz(const qubit &qidx) { return qrt_impl->mz(qidx); }
bool mz(const qubit &qidx, std::pair<std::string, size_t> *optional_creg) {
  return qrt_impl->mz(qidx, optional_creg);
}

void cnot(const qubit &src_idx, const qubit &tgt_idx) {
  qrt_impl->cnot(src_idx, tgt_idx);
Loading