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

Refactor Measure rewrite to a helper



Also, apply Python constant rewrite and Measure result access to all classical context: If conditions and assigments.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent b6a4c079
Loading
Loading
Loading
Loading
+35 −26
Original line number Diff line number Diff line
@@ -220,7 +220,8 @@ class pyxasm_visitor : public pyxasmBaseVisitor {
      // Handle simple assignment: a = expr
      std::stringstream ss;
      const std::string lhs = ctx->testlist_star_expr(0)->getText();
      const std::string rhs = ctx->testlist_star_expr(1)->getText();
      const std::string rhs = replacePythonConstants(
          replaceMeasureAssignment(ctx->testlist_star_expr(1)->getText()));
      ss << "auto " << lhs << " = " << rhs << "; \n";
      result.first = ss.str();
      if (rhs.find("**") != std::string::npos) {
@@ -264,31 +265,10 @@ class pyxasm_visitor : public pyxasmBaseVisitor {
    // Only support single clause atm
    if (ctx->test().size() == 1) {
      std::stringstream ss;
      std::string ifConditionExpr = ctx->test(0)->getText();

      if (ifConditionExpr.find("Measure") != std::string::npos) {
        // Found measure in an if statement instruction.
        const auto replaceMeasureInst = [](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;
            }
            if (!isspace(s[pos + search.length()]) &&
                (s[pos + search.length()] != '(')) {
              continue;
            }
            s.erase(pos, search.length());
            s.insert(pos, replace);
          }
        };
        // Handle FTQC Measure in *if* conditional clause
        replaceMeasureInst(ifConditionExpr, "Measure", "quantum::mz");
      }

      ss << "if (" << ifConditionExpr << ") {\n";
      ss << "if ("
         << replacePythonConstants(
                replaceMeasureAssignment(ctx->test(0)->getText()))
         << ") {\n";
      result.first = ss.str();
      return 0;
    }
@@ -311,4 +291,33 @@ class pyxasm_visitor : public pyxasmBaseVisitor {
    }
    return newSrc;
  }

  // Assignment of Measure results -> variable or in if conditional statements
  std::string replaceMeasureAssignment(const std::string &in_expr) const {
    if (in_expr.find("Measure") != std::string::npos) {
      // Found measure in an if statement instruction.
      const auto replaceMeasureInst = [](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;
          }
          if (!isspace(s[pos + search.length()]) &&
              (s[pos + search.length()] != '(')) {
            continue;
          }
          s.erase(pos, search.length());
          s.insert(pos, replace);
        }
      };

      std::string result = in_expr;
      replaceMeasureInst(result, "Measure", "quantum::mz");
      return result;
    } else {
      return in_expr;
    }
  }
};
 No newline at end of file
+49 −0
Original line number Diff line number Diff line
# Using QCOR FTQC runtime, which supports 
# fast feedforward of measurement results.

from qcor import qjit, qalloc, qreg

# Encode qubits into logical qubits:
# Assume q[0], q[3], q[6] are initial physical qubits
# that will be mapped to logical qubits q[0-2], q[3-5], etc.
@qjit
def encodeLogicalQubit(q : qreg):
    nbLogicalQubits = q.size() / 3
    for i in range(nbLogicalQubits):
        physicalQubitIdx = 3 * i
        CX(q[physicalQubitIdx], q[physicalQubitIdx + 1])
        CX(q[physicalQubitIdx], q[physicalQubitIdx + 2])

# Measure syndromes of a logical qubit using the provided ancilla
# Assume that the ancilla is in |0> state and must be returned in that state.
@qjit
def measureSyndrome(q : qreg, logicalIdx: int, ancIdx: int):
    physicalIdx = logicalIdx * 3
    CX(q[physicalIdx], q[ancIdx])
    CX(q[physicalIdx + 1], q[ancIdx])
    parity01 = Measure(q[ancIdx])
    if parity01: 
        #Reset anc qubit
        X(q[ancIdx])
    
    CX(q[physicalIdx + 1], q[ancIdx])
    CX(q[physicalIdx + 2], q[ancIdx])
    parity12 = Measure(q[ancIdx])
    if parity12:
        #Reset anc qubit
        X(q[ancIdx])

@qjit
def testBitflipCode(q : qreg):
    H(q[0])
    encodeLogicalQubit(q)
    measureSyndrome(q, 0, 3)
    # Apply an X error
    X(q[0])
    measureSyndrome(q, 0, 3)


# Allocate 4 qubits: 3 qubits + 1 ancilla
q = qalloc(4)

testBitflipCode(q)
 No newline at end of file