Commit ca08c86c authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

bug fix for adjoint, reset parent_kernel for backend qrt. add ctrl on ctrl-qreg to kernel

parent d1c68fb1
Loading
Loading
Loading
Loading
Loading
+14 −20
Original line number Diff line number Diff line
@@ -5,26 +5,27 @@ __qpu__ void reflect_about_uniform(qreg q) {
    H(q);
    X(q);
  } action {
    std::vector<qubit> ctrl_qubits;
    for (int i = 0; i < q.size() - 1; i++) {
      std::cout << "adding qubit " << q[i].second << "\n";
      ctrl_qubits.push_back(q[i]);
    }
    auto last_qubit = q[2];
    // we have N qubits, get the first N-1 as the 
    // ctrl qubits, and the last one for the 
    // ctrl-ctrl-...-ctrl-z operation qubit
    auto ctrl_qubits = q.head(q.size()-1);
    auto last_qubit = q.tail();
    Z::ctrl(ctrl_qubits, last_qubit);
  }

  return;
}

__qpu__ void run_grover(qreg q, GroverPhaseOracle oracle,
                        const int iterations) {
  // Put them all in a superposition
  H(q);

  // Iteratively apply the oracle then reflect
  for (int i = 0; i < iterations; i++) {
    oracle(q);
    reflect_about_uniform(q);
  }

  // Measure all qubits
  Measure(q);
}

@@ -33,17 +34,10 @@ __qpu__ void oracle(qreg q) {
    CZ(q[1], q[2]);
}

__qpu__ void ccz(qreg q) {
    Z::ctrl({q[0], q[1]}, q[2]);
}

int main() {
int main(int argc, char** argv) {
    auto q = qalloc(3);
    run_grover(q, oracle, 1);
    q.print();
    run_grover::print_kernel(q, oracle, 1);

    auto m = ccz::as_unitary_matrix(q);
    std::cout << m << "\n";
    std::cout << run_grover::openqasm(q, oracle, 1) << "\n";
    for (auto [bits, count] : q.counts()) {
      print(bits, ":", count);
    }
}
+36 −23
Original line number Diff line number Diff line
@@ -98,6 +98,8 @@ class QuantumKernel {
  // Create the Adjoint of this quantum kernel
  static void adjoint(std::shared_ptr<CompositeInstruction> parent_kernel,
                      Args... args) {
    auto provider = qcor::__internal__::get_provider();

    // instantiate and don't let it call the destructor
    Derived derived(args...);
    derived.disable_destructor = true;
@@ -117,7 +119,6 @@ class QuantumKernel {
          "Unable to create Adjoint for kernels that have Measure operations.");
    }

    auto provider = qcor::__internal__::get_provider();
    for (int i = 0; i < instructions.size(); i++) {
      auto inst = derived.parent_kernel->getInstruction(i);
      // Parametric gates:
@@ -144,6 +145,8 @@ class QuantumKernel {
    // add the instructions to the current parent kernel
    parent_kernel->addInstructions(new_instructions);

    quantum::set_current_program(parent_kernel);

    // no measures, so no execute
  }

@@ -183,6 +186,15 @@ class QuantumKernel {
    ctrl(parent_kernel, {ctrlIdx}, args...);
  }

  static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel,
                   qreg ctrl_qbits, Args... args) {
    std::vector<qubit> ctrl_qubit_vec;
    for (int i = 0; i < ctrl_qbits.size(); i++)
      ctrl_qubit_vec.push_back(ctrl_qbits[i]);

    ctrl(parent_kernel, ctrl_qubit_vec, args...);
  }
  
  static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel,
                   const std::vector<qubit> &ctrl_qbits, Args... args) {
    const auto buffer_name = ctrl_qbits[0].first;
@@ -412,21 +424,23 @@ class KernelSignature {
  }
};

// We use the following to enable ctrl operations on our single
// qubit gates, X::ctrl(), Z::ctrl(), H::ctrl(), etc....
template <typename Derived>
using OneQubitKernel = QuantumKernel<Derived, qubit>;

template <typename Derived>
using TwoQubitKernel = QuantumKernel<Derived, qubit, qubit>;

#define ONE_QUBIT_KERNEL_CTRL_ENABLER(CLASSNAME, QRTNAME)                 \
  class CLASSNAME : public OneQubitKernel<class CLASSNAME> {              \
   public:                                                                \
    CLASSNAME(qubit q) : OneQubitKernel<CLASSNAME>(q) {}                  \
  CLASSNAME(std::shared_ptr<qcor::CompositeInstruction> _parent_kernel, qubit q) \
      : OneQubitKernel<CLASSNAME>(_parent_kernel, q) { throw std::runtime_error("you cannot call this.");} \
    CLASSNAME(std::shared_ptr<qcor::CompositeInstruction> _parent_kernel, \
              qubit q)                                                    \
        : OneQubitKernel<CLASSNAME>(_parent_kernel, q) {                  \
      throw std::runtime_error("you cannot call this.");                  \
    }                                                                     \
    void operator()(qubit q) {                                            \
    parent_kernel = \
        qcor::__internal__::create_composite("__tmp_one_qubit_ctrl_enabler"); \
      parent_kernel = qcor::__internal__::create_composite(               \
          "__tmp_one_qubit_ctrl_enabler");                                \
      quantum::set_current_program(parent_kernel);                        \
      if (runtime_env == QrtType::FTQC) {                                 \
        quantum::set_current_buffer(q.results());                         \
@@ -446,5 +460,4 @@ ONE_QUBIT_KERNEL_CTRL_ENABLER(Tdg, tdg)
ONE_QUBIT_KERNEL_CTRL_ENABLER(S, s)
ONE_QUBIT_KERNEL_CTRL_ENABLER(Sdg, sdg)


}  // namespace qcor