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

Added functor generation test case



This also exposes missing API's for single-qubit allocation and deallocation (in the spec).
Leverage our qubit array alloc/dealloc to implement.

Signed-off-by: default avatarThien Nguyen <nguyentm@ornl.gov>
parent bb3d8232
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
#include <iostream>
#include <vector>

qcor_include_qsharp(QCOR__Testing__TestFunctors__Interop, void);

// Compile with:
// Include both the qsharp source and this driver file
// in the command line.
// $ qcor -qrt ftqc bell.qs bell_driver.cpp
// Run with:
// $ ./a.out
int main() {
  QCOR__Testing__TestFunctors__Interop();
  return 0;
}
 No newline at end of file
+86 −0
Original line number Diff line number Diff line
namespace QCOR.Testing {
    open Microsoft.Quantum.Intrinsic;
    operation Qop(q : Qubit, n : Int) : Unit
    is Adj+Ctl {
        body (...) {
            if n%2 == 1 { X(q); }
        }
        adjoint self;
        controlled (ctrls, ...) {
            if n%2 == 1 { Controlled X(ctrls, q); }
        }
    }

    @EntryPoint()
    operation TestFunctors() : Unit {
        let qop = Qop(_, 1);
        let adj_qop = Adjoint qop;
        let ctl_qop = Controlled qop;
        let adj_ctl_qop = Adjoint Controlled qop;
        let ctl_ctl_qop = Controlled ctl_qop;

        use (q1, q2, q3) = (Qubit(), Qubit(), Qubit()) {
            qop(q1);
            if (M(q1) != One) { Message("error code: 1"); }
 
            adj_qop(q2);
            if (M(q2) != One) { Message("error code: 2"); }

            ctl_qop([q1], q3);
            if (M(q3) != One) { Message("error code: 3"); }

            adj_ctl_qop([q2], q3);
            if (M(q3) != Zero) { Message("error code: 2"); }

            ctl_ctl_qop([q1], ([q2], q3));
            if (M(q3) != One) { Message("error code: 5"); }

            Controlled qop([q1, q2], q3);
            if (M(q3) != Zero) { Message("error code: 6"); }

            use q4 = Qubit() {
                Adjoint qop(q3);
                Adjoint Controlled ctl_ctl_qop([q1], ([q2], ([q3], q4)));
                if (M(q4) != One) { Message("error code: 7"); }
            }
        }
    }

    operation NoArgs() : Unit
    is Adj+Ctl {
        body (...) {
            use q = Qubit();
            X(q);
        }
        adjoint self;
        controlled (ctrls, ...) {
            use q = Qubit();
            Controlled X(ctrls, q);
        }
    }

    @EntryPoint()
    operation TestFunctorsNoArgs() : Unit {
        NoArgs();
        let qop = NoArgs;
        let adj_qop = Adjoint qop;
        let ctl_qop = Controlled qop;
        let adj_ctl_qop = Adjoint Controlled qop;
        let ctl_ctl_qop = Controlled ctl_qop;

        use (q1, q2, q3) = (Qubit(), Qubit(), Qubit()) {
            X(q1);
            X(q2);
            X(q3);

            qop();
            adj_qop();
            ctl_qop([q1], ());
            adj_ctl_qop([q1], ());
            ctl_ctl_qop([q1], ([q2], ()));

            Controlled qop([q1, q2], ());
            Adjoint Controlled ctl_ctl_qop([q1], ([q2], ([q3], ())));
        }
    }
}
 No newline at end of file
+25 −0
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ std::string qpu_name = "qpp";
std::string qpu_config = "";
QRT_MODE mode = QRT_MODE::FTQC;
std::vector<std::unique_ptr<Array>> allocated_arrays;
// Map of single-qubit allocations,
// i.e. arrays of size 1.
std::unordered_map<uint64_t, Array *> single_qubit_arrays;
std::stack<std::shared_ptr<xacc::CompositeInstruction>> internal_xacc_ir;
std::stack<std::shared_ptr<::quantum::QuantumRuntime>> internal_runtimes;

@@ -199,6 +202,28 @@ Array *__quantum__rt__qubit_allocate_array(uint64_t size) {
  return raw_ptr;
}

Qubit *__quantum__rt__qubit_allocate() {
  auto qArray = __quantum__rt__qubit_allocate_array(1);
  int8_t *arrayPtr = (*qArray)[0];
  Qubit *qubitPtr = *(reinterpret_cast<Qubit **>(arrayPtr));
  // We track the single-qubit array that holds this qubit.
  single_qubit_arrays[qubitPtr->id] = qArray;
  return qubitPtr;
}

void __quantum__rt__qubit_release(Qubit *q) {
  if (q == nullptr) {
    return;
  }
  if (single_qubit_arrays.find(q->id) != single_qubit_arrays.end()) {
    __quantum__rt__qubit_release_array(single_qubit_arrays[q->id]);
    single_qubit_arrays.erase(q->id);
  } else {
    throw "Illegal release of a qubit.";
  }
}


void __quantum__rt__start_pow_u_region() {
  // Create a new NISQ based runtime so that we can
  // queue up instructions and get them as a CompositeInstruction
+2 −0
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ Result *__quantum__rt__result_get_zero();
// Qubit Alloc/Dealloc API
Array *__quantum__rt__qubit_allocate_array(uint64_t idx);
void __quantum__rt__qubit_release_array(Array *q);
void __quantum__rt__qubit_release(Qubit *q);
Qubit *__quantum__rt__qubit_allocate();

void __quantum__rt__start_ctrl_u_region();
void __quantum__rt__end_ctrl_u_region(Qubit *ctrl_qubit);