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

Added Controlled-Op support



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent b115f887
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -2,6 +2,15 @@
// Use the pre-defined IQFT kernel
#include "qft.hpp"

using namespace qcor;

// The Oracle: T gate
__qpu__ void compositeOp(qreg q) {
  // T gate on the last qubit
  int bitIdx = q.size() - 1;
  T(q[bitIdx]);
}

// Example of Quantum Phase Estimation circuit using QCOR runtime.
// Compile with:
// qcor -o qpe -qpu qpp -shots 1024 -qrt qpe_example_qrt.cpp
@@ -28,9 +37,10 @@ __qpu__ void QuantumPhaseEstimation(qreg q) {
  const auto bitPrecision = nQubits - 1;
  for (int32_t i = 0; i < bitPrecision; ++i) {
    const int nbCalls = 1 << i;
    // Ctrl(T) = CPhase(pi/4)
    for (int j = 0; j < nbCalls; ++j) {
      CPhase(q[i], q[nQubits - 1], M_PI_4);
      int ctlBit = i;
      // Controlled-Oracle
      Controlled::Apply(ctlBit, compositeOp, q);
    }
  }

+21 −0
Original line number Diff line number Diff line
@@ -384,6 +384,27 @@ Handle taskInitiate(std::shared_ptr<ObjectiveFunction> objective,
      },
      nParameters);
}

#ifdef QCOR_USE_QRT
// Controlled-Op transform:
// Usage: Controlled::Apply(controlBit, QuantumKernel, Args...)
// where Args... are arguments that will be passed to the kernel.
// Note: we use a class with a static member function to enforce
// that the invocation is Controlled::Apply(...) (with the '::' separator), 
// hence the XASM compiler cannot mistakenly parse this as a XASM call.
class Controlled {
public:
  template <typename FunctorType, typename... ArgumentTypes>
  static void Apply(int ctrlIdx, FunctorType functor, ArgumentTypes... args) {
  __controlledIdx = { ctrlIdx };
  const auto __cached_execute_flag = __execute;
  __execute = false;
  functor(args...);
  __controlledIdx.clear();
  __execute = __cached_execute_flag;
}
};
#endif
} // namespace qcor

#endif
+35 −2
Original line number Diff line number Diff line
@@ -2,10 +2,13 @@
#include "Instruction.hpp"
#include "PauliOperator.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "xacc_internal_compiler.hpp"
#include <Eigen/Dense>
#include <Utils.hpp>

std::vector<int> xacc::internal_compiler::__controlledIdx = {};

namespace quantum {
std::shared_ptr<xacc::CompositeInstruction> program = nullptr;
std::shared_ptr<xacc::IRProvider> provider = nullptr;
@@ -31,6 +34,21 @@ void set_shots(int shots) {
      {std::make_pair("shots", shots)});
}

// Add a controlled instruction:
void add_controlled_inst(xacc::InstPtr &inst, int ctrlIdx) {
  auto tempKernel = provider->createComposite("temp_control");
  tempKernel->addInstruction(inst);
  auto ctrlKernel = std::dynamic_pointer_cast<xacc::CompositeInstruction>(xacc::getService<xacc::Instruction>("C-U"));
  ctrlKernel->expand({ 
    std::make_pair("U",  tempKernel),
    std::make_pair("control-idx",  ctrlIdx),
  });            
  
  for (int instId = 0; instId < ctrlKernel->nInstructions(); ++instId) {
    program->addInstruction(ctrlKernel->getInstruction(instId)->clone());
  }
}

void one_qubit_inst(const std::string &name, const qubit &qidx,
                    std::vector<double> parameters) {
  auto inst =
@@ -39,8 +57,16 @@ void one_qubit_inst(const std::string &name, const qubit &qidx,
  for (int i = 0; i < parameters.size(); i++) {
    inst->setParameter(i, parameters[i]);
  }
  // Not in a controlled-block
  if (xacc::internal_compiler::__controlledIdx.empty()){
    // Add the instruction
    program->addInstruction(inst);
  }
  else {
    // In a controlled block:
    add_controlled_inst(inst, __controlledIdx[0]);
  }
}

void two_qubit_inst(const std::string &name, const qubit &qidx1, const qubit &qidx2,
                    std::vector<double> parameters) {
@@ -50,8 +76,15 @@ void two_qubit_inst(const std::string &name, const qubit &qidx1, const qubit &qi
  for (int i = 0; i < parameters.size(); i++) {
    inst->setParameter(i, parameters[i]);
  }
  // Not in a controlled-block
  if (xacc::internal_compiler::__controlledIdx.empty()) {
    program->addInstruction(inst);     
  }
  else {
    // In a controlled block:
    add_controlled_inst(inst, __controlledIdx[0]);
  }                 
}

void h(const qubit &qidx) { one_qubit_inst("H", qidx); }
void x(const qubit &qidx) { one_qubit_inst("X", qidx); }
+6 −0
Original line number Diff line number Diff line
@@ -12,6 +12,12 @@ class AcceleratorBuffer;
class CompositeInstruction;
class IRProvider;
class Observable;

namespace internal_compiler {
// Current runtime controlled bit indices 
// (if the current kernel is wrapped in a Controlled block)
extern std::vector<int> __controlledIdx;
}
} // namespace xacc

namespace quantum {