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

Work on FTQC QRT



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent ca101c2d
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -152,6 +152,12 @@ void QCORSyntaxHandler::GetReplacement(
        "qcor::__internal__::create_composite(kernel_name);\n";
  OS << "}\n";
  OS << "quantum::set_current_program(parent_kernel);\n";
  // Set the buffer in FTQC mode so that following QRT calls (in new_src) are
  // executed on that buffer.
  OS << "if (runtime_env == QrtType::FTQC) {\n";
  // We only support one buffer in FTQC mode atm.
  OS << "quantum::set_current_buffer(" << bufferNames[0] << ".results());\n";
  OS << "}\n";
  OS << new_src << "\n";
  OS << "}\n";

@@ -213,7 +219,7 @@ void QCORSyntaxHandler::GetReplacement(
  OS << "return;\n";
  OS << "}\n";

  OS << "if (is_callable) {\n";
  OS << "if (is_callable && (runtime_env == QrtType::NISQ)) {\n";
  if (bufferNames.size() > 1) {
    OS << "xacc::AcceleratorBuffer * buffers[" << bufferNames.size() << "] = {";
    OS << bufferNames[0] << ".results()";
+2 −1
Original line number Diff line number Diff line
@@ -50,7 +50,8 @@ public:
  // Flag to indicate we only want to
  // run the pass manager and not execute
  bool optimize_only = false;

  enum class QrtType { NISQ, FTQC };
  QrtType runtime_env = QrtType::NISQ;
  // Default constructor, takes quantum kernel function arguments
  QuantumKernel(Args... args) : args_tuple(std::forward_as_tuple(args...)) {}

+72 −40
Original line number Diff line number Diff line
@@ -15,41 +15,44 @@ using namespace cppmicroservices;
namespace qcor {
class FTQC : public quantum::QuantumRuntime {
public:
  virtual void initialize(const std::string kernel_name) override { /* TODO */
  virtual void initialize(const std::string kernel_name) override {
    provider = xacc::getIRProvider("quantum");
    qpu = xacc::internal_compiler::qpu;
  }

  const std::string name() const override { return "ftqc"; }
  const std::string description() const override { return ""; }

  virtual void h(const qubit &qidx) override { /* TODO */
  }
  virtual void x(const qubit &qidx) override { /* TODO */
  }
  virtual void y(const qubit &qidx) override { /* TODO */
  }
  virtual void z(const qubit &qidx) override { /* TODO */
  }
  virtual void t(const qubit &qidx) override { /* TODO */
  }
  virtual void tdg(const qubit &qidx) override { /* TODO */
  }
  virtual void s(const qubit &qidx) override { /* TODO */
  }
  virtual void sdg(const qubit &qidx) override { /* TODO */
  virtual void h(const qubit &qidx) override { applyGate("H", {qidx.second}); }
  virtual void x(const qubit &qidx) override { applyGate("X", {qidx.second}); }
  virtual void y(const qubit &qidx) override { applyGate("Y", {qidx.second}); }
  virtual void z(const qubit &qidx) override { applyGate("Z", {qidx.second}); }
  virtual void t(const qubit &qidx) override { applyGate("T", {qidx.second}); }
  virtual void tdg(const qubit &qidx) override {
    applyGate("Tdg", {qidx.second});
  }
  virtual void s(const qubit &qidx) override { applyGate("S", {qidx.second}); }
  virtual void sdg(const qubit &qidx) override {
    applyGate("Sdg", {qidx.second});
  }

  // Common single-qubit, parameterized instructions
  virtual void rx(const qubit &qidx, const double theta) override { /* TODO */
  virtual void rx(const qubit &qidx, const double theta) override {
    applyGate("Rx", {qidx.second}, {theta});
  }
  virtual void ry(const qubit &qidx, const double theta) override { /* TODO */
  virtual void ry(const qubit &qidx, const double theta) override {
    applyGate("Ry", {qidx.second}, {theta});
  }
  virtual void rz(const qubit &qidx, const double theta) override { /* TODO */
  virtual void rz(const qubit &qidx, const double theta) override {
    applyGate("Rz", {qidx.second}, {theta});
  }
  // U1(theta) gate
  virtual void u1(const qubit &qidx, const double theta) override { /* TODO */
  virtual void u1(const qubit &qidx, const double theta) override {
    applyGate("U1", {qidx.second}, {theta});
  }
  virtual void u3(const qubit &qidx, const double theta, const double phi,
                  const double lambda) override { /* TODO */
                  const double lambda) override {
    applyGate("U", {qidx.second}, {theta, phi, lambda});
  }

  // Measure-Z
@@ -57,28 +60,30 @@ public:
  }

  // Common two-qubit gates.
  virtual void cnot(const qubit &src_idx,
                    const qubit &tgt_idx) override { /* TODO */
  virtual void cnot(const qubit &src_idx, const qubit &tgt_idx) override {
    applyGate("CNOT", {src_idx.second, tgt_idx.second});
  }
  virtual void cy(const qubit &src_idx,
                  const qubit &tgt_idx) override { /* TODO */
  virtual void cy(const qubit &src_idx, const qubit &tgt_idx) override {
    applyGate("CY", {src_idx.second, tgt_idx.second});
  }
  virtual void cz(const qubit &src_idx,
                  const qubit &tgt_idx) override { /* TODO */
  virtual void cz(const qubit &src_idx, const qubit &tgt_idx) override {
    applyGate("CZ", {src_idx.second, tgt_idx.second});
  }
  virtual void ch(const qubit &src_idx,
                  const qubit &tgt_idx) override { /* TODO */
  virtual void ch(const qubit &src_idx, const qubit &tgt_idx) override {
    applyGate("CH", {src_idx.second, tgt_idx.second});
  }
  virtual void swap(const qubit &src_idx,
                    const qubit &tgt_idx) override { /* TODO */
  virtual void swap(const qubit &src_idx, const qubit &tgt_idx) override {
    applyGate("Swap", {src_idx.second, tgt_idx.second});
  }

  // Common parameterized 2 qubit gates.
  virtual void cphase(const qubit &src_idx, const qubit &tgt_idx,
                      const double theta) override { /* TODO */
                      const double theta) override {
    applyGate("CPhase", {src_idx.second, tgt_idx.second}, {theta});
  }
  virtual void crz(const qubit &src_idx, const qubit &tgt_idx,
                   const double theta) override { /* TODO */
                   const double theta) override {
    applyGate("CRZ", {src_idx.second, tgt_idx.second}, {theta});
  }

  // exponential of i * theta * H, where H is an Observable pointer
@@ -92,22 +97,49 @@ public:
                   std::shared_ptr<xacc::Observable> H) override { /* TODO */
  }

  // Submission API. Submit the constructed CompositeInstruction operating
  // on the provided AcceleratorBuffer(s) (note qreg wraps an AcceleratorBuffer)
  virtual void submit(xacc::AcceleratorBuffer *buffer) override { /* TODO */
  // Submission API: sanity check that we don't call these API's.
  // e.g. catch high-level code gen errors.
  virtual void submit(xacc::AcceleratorBuffer *buffer) override {
    throw std::runtime_error("FTQC runtime doesn't support submit API.");
  }
  virtual void submit(xacc::AcceleratorBuffer **buffers,
                      const int nBuffers) override { /* TODO */
                      const int nBuffers) override {
    throw std::runtime_error("FTQC runtime doesn't support submit API.");
  }

  // Some getters for the qcor runtime library.
  virtual void set_current_program(
      std::shared_ptr<xacc::CompositeInstruction> p) override { /* TODO */
  virtual void
  set_current_program(std::shared_ptr<xacc::CompositeInstruction> p) override {
    // Nothing to do
  }
  virtual std::shared_ptr<xacc::CompositeInstruction>
  get_current_program() override { /* TODO */
  get_current_program() override {
    return nullptr;
  }

  void set_current_buffer(xacc::AcceleratorBuffer *buffer) override {
    qReg = xacc::as_shared_ptr(buffer);
  }

private:
  // Notes: all gate parameters must be resolved (to double) for FT-QRT
  // execution.
  void applyGate(const std::string &gateName, const std::vector<size_t> &bits,
                 const std::vector<double> &params = {}) {
    std::vector<xacc::InstructionParameter> instParams;
    for (const auto &val : params) {
      instParams.emplace_back(val);
    }
    auto gateInst = provider->createInstruction(gateName, bits, instParams);
    qpu->apply(qReg, gateInst);
  }

private:
  std::shared_ptr<xacc::IRProvider> provider;
  std::shared_ptr<xacc::Accelerator> qpu;
  // TODO: eventually, we may want to support an arbitrary number of qubit
  // registers when the FTQC backend can support it.
  std::shared_ptr<xacc::AcceleratorBuffer> qReg;
};
} // namespace qcor

+5 −0
Original line number Diff line number Diff line
@@ -259,6 +259,11 @@ public:
    if (program && provider)
      program = provider->createComposite(program->name());
  }
  
  void set_current_buffer(xacc::AcceleratorBuffer* buffer) override {
    // Nothing to do: the NISQ runtime doesn't keep track of runtime buffer info.
  }

  const std::string name() const override { return "nisq"; }
  const std::string description() const override { return ""; }
};
+4 −0
Original line number Diff line number Diff line
@@ -179,4 +179,8 @@ void set_current_program(std::shared_ptr<xacc::CompositeInstruction> p) {
  qrt_impl->set_current_program(p);
}

void set_current_buffer(xacc::AcceleratorBuffer* buffer) {
  qrt_impl->set_current_buffer(buffer);
}

} // namespace quantum
 No newline at end of file
Loading