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

Support Measure return for FTQC



We want the runtime mz to return a boolean in FTQC. For NISQ, the boolean return is just a dummy one.

Whenever we need to use the return value of the Measure (e.g. assignment or conditional), it's parsed as a classical instruction.

Hence, we just need to do token replacement in that code path.

Also, fixing the `else` path of the token collector to prevent it from combining the next line (could be a quantum instruction) into the `else` line.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 1758ac20
Loading
Loading
Loading
Loading
+5 −8
Original line number Diff line number Diff line
@@ -45,18 +45,16 @@ __qpu__ void correctLogicalQubit(qreg q, int logicalIdx, int ancIdx) {
  // Assume that we only has 1 ancilla qubit
  CX(q[physicalIdx], q[ancIdx]);
  CX(q[physicalIdx + 1], q[ancIdx]);
  Measure(q[ancIdx]);
  const bool parity01 = q.creg[ancIdx];
  if (q.creg[ancIdx]) {
  const bool parity01 = Measure(q[ancIdx]);
  if (parity01) {
    // Reset anc qubit for reuse
    X(q[ancIdx]);
  }

  CX(q[physicalIdx + 1], q[ancIdx]);
  CX(q[physicalIdx + 2], q[ancIdx]);
  Measure(q[ancIdx]);
  const bool parity12 = q.creg[ancIdx];
  if (q.creg[ancIdx]) {
  const bool parity12 = Measure(q[ancIdx]);
  if (parity12) {
    // Reset anc qubit
    X(q[ancIdx]);
  }
@@ -86,8 +84,7 @@ __qpu__ void runQecCycle(qreg q) {
__qpu__ void resetAll(qreg q) {
  for (int i = 0; i < q.size(); ++i) {
    // Reset qubits by measure + correct.
    Measure(q[i]);
    if (q.creg[i]) {
    if (Measure(q[i])) {
      X(q[i]);
    }
  }
+5 −7
Original line number Diff line number Diff line
@@ -20,16 +20,14 @@ __qpu__ void PrepareStateUsingRUS(qreg q, int maxIter) {

    // In order to measure in the PauliX basis, changes the basis.
    H(q[1]);
    Measure(q[1]);
    bool outcome = q.creg[1];
    if (!outcome) {
    if (!Measure(q[1])) {
      // Success (until (outcome == Zero))
      std::cout << "Success after " << i + 1 << " iterations.\n";
      break;
    } 
    // Fix up: Bring the auxiliary and target qubits back to |+> state.
    if (outcome) {
    else {
      // Measure 1: |1> state
      // Fix up: Bring the auxiliary and target qubits back to |+> state.
      X(q[1]);
      H(q[1]);
      X(q[0]);
+5 −5
Original line number Diff line number Diff line
@@ -10,18 +10,18 @@ __qpu__ void bell(qreg q, int nbRuns) {
  for (int i = 0; i < nbRuns; ++i) {
    H(q[0]);
    CX(q[0], q[1]);
    Measure(q[0]);
    Measure(q[1]);
    if (q.creg[0] == q.creg[1]) {
    const bool q0Result = Measure(q[0]);
    const bool q1Result = Measure(q[1]);
    if (q0Result == q1Result) {
      std::cout << "Iter " << i << ": Matched!\n";
    } else {
      std::cout << "Iter " << i << ": NOT Matched!\n";
    }
    // Reset qubits
    if (q.creg[0]) {
    if (q0Result) {
      X(q[0]);
    }
    if (q.creg[1]) {
    if (q1Result) {
      X(q[1]);
    }
  }
+22 −0
Original line number Diff line number Diff line
@@ -181,6 +181,28 @@ public:
          ss << c->getText() << " ";
        }
      }
    } else if (context->getText().find("Measure") != std::string::npos) {
      // Found measure in a classical instruction.
      // std::cout << "FOUND MEAS: " << context->getText() << "\n";
      // To be extra careful, we use search and replace to handle edge case
      // whereby `!Measure` is considered as 1 token.
      const auto replaceAll = [](std::string &s, const std::string &search,
                                 const std::string &replace) {
        for (size_t pos = 0;; pos += replace.length()) {
          pos = s.find(search, pos);
          if (pos == std::string::npos) {
            break;
          }

          s.erase(pos, search.length());
          s.insert(pos, replace);
        }
      };
      for (auto c : context->children) {
        auto origText = c->getText();
        replaceAll(origText, "Measure", " quantum::mz");
        ss << origText << " ";
      }
    } else {
      for (auto c : context->children) {
        ss << c->getText() << " ";
+8 −1
Original line number Diff line number Diff line
@@ -131,7 +131,14 @@ void XasmTokenCollector::collect(clang::Preprocessor &PP,

      lines.push_back("}\n");

    } else {
    } else if (current_token.is(clang::tok::kw_else)) { 
      auto tokenStr = PP.getSpelling(current_token);
      if (Toks[i + 1].is(clang::tok::l_brace)) {
        tokenStr += " { ";
      }
      lines.push_back(tokenStr);
    }
    else {

      // here we have some general statement, so
      // search til the semi colon
Loading