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

QuantumKernel to handle multiple controls



Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent 0a426ddb
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -26,3 +26,6 @@ add_test(NAME quasimo_qaoa COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOUR
add_test(NAME quasimo_qite COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/quasimo/QiteWorkflow.cpp)
add_test(NAME quasimo_heisenberg COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/quasimo/TdWorkflowHeisenbergModel.cpp)
add_test(NAME quasimo_verified_qpe COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/quasimo/VerifiedQuantumPhaseEstimation.cpp)
add_test(NAME hadamard_ctrl_test COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/ctrl-gates/simple_hadamard_test.cpp)
add_test(NAME multi_ctrl_test COMMAND ${CMAKE_BINARY_DIR}/qcor ${CMAKE_CURRENT_SOURCE_DIR}/ctrl-gates/multiple_controls.cpp)
+22 −0
Original line number Diff line number Diff line
// X kernel
__qpu__ void x_gate(qreg q) { X(q[0]); }

__qpu__ void ccxtest(qreg q) {
  for (int i = 0; i < q.size(); i++) {
    X(q[i]);
  } 

  // apply ctrl-U (CCX = Toffoli)
  x_gate::ctrl({q[1], q[2]}, q);

  // measure
  for (int i = 0; i < q.size(); i++) {
    Measure(q[i]);
  } 
}

int main() {
  auto q = qalloc(3);
  ccxtest(q);
  q.print();
}
 No newline at end of file
+24 −0
Original line number Diff line number Diff line
import faulthandler
faulthandler.enable()

import unittest
from qcor import *

class TestKernelJIT(unittest.TestCase):
    def test_multiple_control_kernel(self):
        @qjit
        def apply_X_at_idx(q : qreg, idx: int):
            X(q[idx])

        @qjit
        def test_ccx_gate(q : qreg):
           apply_X_at_idx.ctrl([1, 2], q, 0)
           for i in range(q.size()):
                Measure(q[i])
        
        q = qalloc(3)
        comp = test_ccx_gate.extract_composite(q)
        print(comp)
        
if __name__ == '__main__':
  unittest.main()
 No newline at end of file
+48 −1
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ class QuantumKernel {

  // Create the controlled version of this quantum kernel
  static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel,
                   int ctrlIdx, Args... args) {
                   const std::vector<int> &ctrlIdx, Args... args) {
    // instantiate and don't let it call the destructor
    Derived derived(args...);
    derived.disable_destructor = true;
@@ -177,6 +177,53 @@ class QuantumKernel {
    quantum::set_current_program(parent_kernel);
  }

  // Single-qubit overload
  static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel,
                   int ctrlIdx, Args... args) {
    ctrl(parent_kernel, {ctrlIdx}, 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;

    for (const auto &qb : ctrl_qbits) {
      if (qb.first != buffer_name) {
        // We can only handle control qubits on the same qReg.
        error("Unable to handle control qubits from different registers");
      }
    }

    std::vector<int> ctrl_bits;
    std::transform(ctrl_qbits.begin(), ctrl_qbits.end(),
                   std::back_inserter(ctrl_bits),
                   [](auto qb) { return qb.second; });

    // instantiate and don't let it call the destructor
    Derived derived(args...);
    derived.disable_destructor = true;

    // run the operator()(args...) call to get the the functor
    // as a CompositeInstruction (derived.parent_kernel)
    derived(args...);

    // Use the controlled gate module of XACC to transform
    auto tempKernel = qcor::__internal__::create_composite("temp_control");
    tempKernel->addInstruction(derived.parent_kernel);

    auto ctrlKernel = qcor::__internal__::create_ctrl_u();
    ctrlKernel->expand({{"U", tempKernel},
                        {"control-idx", ctrl_bits},
                        {"control-buffer", buffer_name}});

    for (int instId = 0; instId < ctrlKernel->nInstructions(); ++instId) {
      parent_kernel->addInstruction(
          ctrlKernel->getInstruction(instId)->clone());
    }
    // Need to reset and point current program to the parent
    quantum::set_current_program(parent_kernel);
  }

  // Create the controlled version of this quantum kernel
  static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel,
                   qubit ctrl_qbit, Args... args) {