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

Syntactic sugar for loop



Rewrite Python for loops into C++ range-based for loops.

Hence, we can loop directly on python arrays, e.g. list of Pauli terms.

Add C++ range() and len() impl in QCOR utils.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent e34245b1
Loading
Loading
Loading
Loading
+10 −22
Original line number Diff line number Diff line
@@ -152,28 +152,16 @@ public:

  antlrcpp::Any visitFor_stmt(pyxasmParser::For_stmtContext *context) override {
    auto counter_expr = context->exprlist()->expr()[0];

    if (context->testlist()->test()[0]->getText().find("range") !=
        std::string::npos) {
      auto range_str = context->testlist()->test()[0]->getText();
      auto found_paren = range_str.find_first_of("(");
      auto range_contents = range_str.substr(
          found_paren + 1, range_str.length() - found_paren - 2);

    auto iter_container = context->testlist()->test()[0]->getText();
    // Rewrite:
    // Python: "for <var> in <expr>:"
    // C++: for (auto& var: <expr>) {}
    // Note: we add range(int) as a C++ function to support this common pattern.
    std::stringstream ss;
      ss << "for (int " << counter_expr->getText() << " = 0; "
         << counter_expr->getText() << " < " << range_contents << "; ++"
         << counter_expr->getText() << " ) {\n";

    ss << "for (auto &" << counter_expr->getText() << " : " << iter_container
       << ") {\n";
    result.first = ss.str();
    in_for_loop = true;

    } else {
      xacc::error(
          "QCOR PyXasm can only handle 'for VAR in range(QREG.size())' at the "
          "moment.");
    }

    return 0;
  }

+3 −5
Original line number Diff line number Diff line
@@ -15,13 +15,11 @@ def qaoa_circ(q: qreg, cost_ham: PauliOperator, nbSteps: int, theta: List[float]
    
    terms = cost_ham.getNonIdentitySubTerms()
    for step in range(nbSteps):
        # TODO: this looks weird (terms is a vector)
        # we need to support Pythonic len() method
        for i in range(terms.size()):
            exp_i_theta(q, theta[step], terms[i])
        for term in terms:
            exp_i_theta(q, theta[step], term)

        # Reference Hamiltonian: 
        for i in range(q.size()):
        for i in range(len(q)):
            ref_ham_term = X(i)
            exp_i_theta(q, beta[step], ref_ham_term)
   
+10 −0
Original line number Diff line number Diff line
@@ -57,6 +57,16 @@ template <typename T> std::vector<T> linspace(T a, T b, size_t N) {
  return xs;
}

inline std::vector<int> range(int N) {
  std::vector<int> vec(N);
  std::iota(vec.begin(), vec.end(), 0);
  return vec;
}

// Get size() of any types that have size() implemented.
template <typename T> int len(const T &countable) { return countable.size(); }
template <typename T> int len(T &countable) { return countable.size(); }

// The TranslationFunctor maps vector<double> to a tuple of Args...
template <typename... Args>
using TranslationFunctor =