Loading examples/qsharp/FTQC/VQE/vqe_driver.cpp +2 −3 Original line number Diff line number Diff line #include <iostream> #include <vector> #include "qir-types.hpp" #include "opt_stepper.hpp" #include "callable_util.hpp" #include "qir-types-utils.hpp" // Include the external QSharp function. qcor_include_qsharp(QCOR__DeuteronVqe__body, double, int64_t shots, Callable* opt_stepper); Loading Loading @@ -37,7 +36,7 @@ int main() { // Q# Callable type. const int64_t nb_shots = 2048; const double final_energy = QCOR__DeuteronVqe__body( nb_shots, qsharp::createCallable(stepper_callable)); nb_shots, qir::createCallable(stepper_callable)); std::cout << "Final energy = " << final_energy << "\n"; return 0; } No newline at end of file examples/qsharp/FTQC/VectorArg/vqe_ansatz.qs 0 → 100644 +28 −0 Original line number Diff line number Diff line namespace QCOR { open QCOR.Intrinsic; // Estimate energy value in a FTQC manner. // Passing Array type b/w C++ driver and Q# operation Ansatz(angles : Double[], shots: Int) : Double { mutable numParityOnes = 0; use qubits = Qubit[2] { for test in 1..shots { Rx(angles[0], qubits[0]); Rx(angles[1], qubits[1]); CNOT(qubits[1], qubits[0]); // Let's measure <X0X1> H(qubits[0]); H(qubits[1]); if M(qubits[0]) != M(qubits[1]) { set numParityOnes += 1; } Reset(qubits[0]); Reset(qubits[1]); } } let res = IntAsDouble(shots - numParityOnes)/IntAsDouble(shots) - IntAsDouble(numParityOnes)/IntAsDouble(shots); return res; } } No newline at end of file examples/qsharp/FTQC/VectorArg/vqe_driver.cpp 0 → 100644 +20 −0 Original line number Diff line number Diff line #include <iostream> #include <vector> #include "qir-types-utils.hpp" // Include the external QSharp function. qcor_include_qsharp(QCOR__Ansatz__body, double, ::Array *, int64_t); // Compile with: // Include both the qsharp source and this driver file // in the command line. // $ qcor -qrt ftqc vqe_ansatz.qs vqe_driver.cpp // Run with: // $ ./a.out int main() { const std::vector<double> angles{1.0, 2.0}; const double exp_val_xx = QCOR__Ansatz__body(qir::toArray(angles), 1024); std::cout << "<X0X1> = " << exp_val_xx << "\n"; return 0; } No newline at end of file mlir/qir_qrt/CMakeLists.txt +1 −1 Original line number Diff line number Diff line file(GLOB SRC *.cpp) file(GLOB HEADERS qir-types.hpp qir-qrt.hpp) file(GLOB HEADERS qir-types.hpp qir-qrt.hpp qir-types-utils.hpp) add_library(qir-qrt SHARED ${SRC}) Loading examples/qsharp/FTQC/VQE/callable_util.hpp→mlir/qir_qrt/qir-types-utils.hpp +48 −20 Original line number Diff line number Diff line #pragma once #include "qir-types.hpp" #include <typeinfo> #include <vector> // Utils for C++ -> QIR type conversion/marshaling namespace qcor { namespace qsharp { // Helper to marshal (pack and unpack) C++ data to Q# QIR data // e.g. vector is converted to Array type. template <typename T> TuplePtr pack(TuplePtr io_tuple, const std::vector<T> &in_vec) { static_assert(std::is_same<T, double>::value || std::is_same<T, int64_t>::value, "Only support vector of these types now."); namespace qir { /// Array type // std::vector -> QIR Array template <typename T> ::Array *toArray(const std::vector<T> &in_vec) { // Integral and Floating-point only static_assert(std::is_arithmetic_v<T>, "Only support vector of arithmetic types."); ::Array *qirArray = new ::Array(in_vec.size(), sizeof(T)); for (size_t i = 0; i < in_vec.size(); ++i) { auto dest = qirArray->getItemPointer(i); auto src = &in_vec[i]; memcpy(dest, src, sizeof(T)); } // TODO: QIR Array supports ref-counting, needs to handle lifetime properly. return qirArray; } template <typename T> std::vector<T> fromArray(::Array *in_array) { // Integral and Floating-point only static_assert(std::is_arithmetic_v<T>, "Only support vector of arithmetic types."); if (in_array->element_size() != sizeof(T)) { throw std::bad_cast(); } std::vector<T> resultArray; for (size_t i = 0; i < in_array->size(); ++i) { const T el = *(reinterpret_cast<T *>(in_array->getItemPointer(i))); resultArray.emplace_back(el); } return resultArray; } /// Tuple type // Helper to marshal (pack and unpack) C++ data to Q# QIR data // e.g. vector is converted to Array type. template <typename T> TuplePtr tuple_pack(TuplePtr io_tuple, const std::vector<T> &in_vec) { ::Array *qirArray = toArray(in_vec); TupleHeader *th = ::TupleHeader::getHeader(io_tuple); memcpy(io_tuple, &qirArray, sizeof(::Array *)); return io_tuple + sizeof(::Array *); } // Unpack a value from the tuple and move the pointer to the next element. template <typename T> TuplePtr unpack(TuplePtr in_tuple, T &out_val) { template <typename T> TuplePtr tuple_unpack(TuplePtr in_tuple, T &out_val) { static_assert(std::is_same<T, double>::value || std::is_same<T, int64_t>::value, "Only support these types now."); Loading @@ -32,29 +59,29 @@ template <typename T> TuplePtr unpack(TuplePtr in_tuple, T &out_val) { } template <typename T> TuplePtr unpack(TuplePtr in_tuple, std::vector<T> &out_val) { TuplePtr tuple_unpack(TuplePtr in_tuple, std::vector<T> &out_val) { static_assert(std::is_same<T, double>::value || std::is_same<T, int64_t>::value, "Only support vector of these types now."); out_val.clear(); ::Array *arrayPtr = *(reinterpret_cast<::Array **>(in_tuple)); for (size_t i = 0; i < arrayPtr->size(); ++i) { const double el = *(reinterpret_cast<T *>(arrayPtr->getItemPointer(i))); out_val.emplace_back(el); } out_val = fromArray<T>(arrayPtr); return in_tuple + sizeof(::Array *); } template <typename T> T marshal_one(TuplePtr &io_ptr) { T t; io_ptr = qsharp::unpack(io_ptr, t); io_ptr = tuple_unpack(io_ptr, t); return t; } // Marshal a QIR tuple to std::tuple template <typename... Args> std::tuple<Args...> marshal(TuplePtr &io_ptr) { return std::make_tuple(marshal_one<Args>(io_ptr)...); } /// Callable type // Wrap a std::function in an IFunctor // which can be used as a Callable. template <typename ReturnType, typename... Args> class qs_callback : public qsharp::IFunctor { public: Loading @@ -64,18 +91,19 @@ public: auto tuple_ptr = args; auto args_tuple = marshal<Args...>(tuple_ptr); // Pack the result to the return QIR Tuple qsharp::pack(result, std::apply(m_functor, args_tuple)); tuple_pack(result, std::apply(m_functor, args_tuple)); } private: std::function<ReturnType(Args...)> m_functor; }; // Create a QIR callable from a std::function. template <typename ReturnType, typename... Args> Callable *createCallable(std::function<ReturnType(Args...)> &in_func) { auto functor = new qs_callback<ReturnType, Args...>(in_func); // Create a QIR callable return new Callable(functor); } } // namespace qsharp } // namespace qir } // namespace qcor Loading
examples/qsharp/FTQC/VQE/vqe_driver.cpp +2 −3 Original line number Diff line number Diff line #include <iostream> #include <vector> #include "qir-types.hpp" #include "opt_stepper.hpp" #include "callable_util.hpp" #include "qir-types-utils.hpp" // Include the external QSharp function. qcor_include_qsharp(QCOR__DeuteronVqe__body, double, int64_t shots, Callable* opt_stepper); Loading Loading @@ -37,7 +36,7 @@ int main() { // Q# Callable type. const int64_t nb_shots = 2048; const double final_energy = QCOR__DeuteronVqe__body( nb_shots, qsharp::createCallable(stepper_callable)); nb_shots, qir::createCallable(stepper_callable)); std::cout << "Final energy = " << final_energy << "\n"; return 0; } No newline at end of file
examples/qsharp/FTQC/VectorArg/vqe_ansatz.qs 0 → 100644 +28 −0 Original line number Diff line number Diff line namespace QCOR { open QCOR.Intrinsic; // Estimate energy value in a FTQC manner. // Passing Array type b/w C++ driver and Q# operation Ansatz(angles : Double[], shots: Int) : Double { mutable numParityOnes = 0; use qubits = Qubit[2] { for test in 1..shots { Rx(angles[0], qubits[0]); Rx(angles[1], qubits[1]); CNOT(qubits[1], qubits[0]); // Let's measure <X0X1> H(qubits[0]); H(qubits[1]); if M(qubits[0]) != M(qubits[1]) { set numParityOnes += 1; } Reset(qubits[0]); Reset(qubits[1]); } } let res = IntAsDouble(shots - numParityOnes)/IntAsDouble(shots) - IntAsDouble(numParityOnes)/IntAsDouble(shots); return res; } } No newline at end of file
examples/qsharp/FTQC/VectorArg/vqe_driver.cpp 0 → 100644 +20 −0 Original line number Diff line number Diff line #include <iostream> #include <vector> #include "qir-types-utils.hpp" // Include the external QSharp function. qcor_include_qsharp(QCOR__Ansatz__body, double, ::Array *, int64_t); // Compile with: // Include both the qsharp source and this driver file // in the command line. // $ qcor -qrt ftqc vqe_ansatz.qs vqe_driver.cpp // Run with: // $ ./a.out int main() { const std::vector<double> angles{1.0, 2.0}; const double exp_val_xx = QCOR__Ansatz__body(qir::toArray(angles), 1024); std::cout << "<X0X1> = " << exp_val_xx << "\n"; return 0; } No newline at end of file
mlir/qir_qrt/CMakeLists.txt +1 −1 Original line number Diff line number Diff line file(GLOB SRC *.cpp) file(GLOB HEADERS qir-types.hpp qir-qrt.hpp) file(GLOB HEADERS qir-types.hpp qir-qrt.hpp qir-types-utils.hpp) add_library(qir-qrt SHARED ${SRC}) Loading
examples/qsharp/FTQC/VQE/callable_util.hpp→mlir/qir_qrt/qir-types-utils.hpp +48 −20 Original line number Diff line number Diff line #pragma once #include "qir-types.hpp" #include <typeinfo> #include <vector> // Utils for C++ -> QIR type conversion/marshaling namespace qcor { namespace qsharp { // Helper to marshal (pack and unpack) C++ data to Q# QIR data // e.g. vector is converted to Array type. template <typename T> TuplePtr pack(TuplePtr io_tuple, const std::vector<T> &in_vec) { static_assert(std::is_same<T, double>::value || std::is_same<T, int64_t>::value, "Only support vector of these types now."); namespace qir { /// Array type // std::vector -> QIR Array template <typename T> ::Array *toArray(const std::vector<T> &in_vec) { // Integral and Floating-point only static_assert(std::is_arithmetic_v<T>, "Only support vector of arithmetic types."); ::Array *qirArray = new ::Array(in_vec.size(), sizeof(T)); for (size_t i = 0; i < in_vec.size(); ++i) { auto dest = qirArray->getItemPointer(i); auto src = &in_vec[i]; memcpy(dest, src, sizeof(T)); } // TODO: QIR Array supports ref-counting, needs to handle lifetime properly. return qirArray; } template <typename T> std::vector<T> fromArray(::Array *in_array) { // Integral and Floating-point only static_assert(std::is_arithmetic_v<T>, "Only support vector of arithmetic types."); if (in_array->element_size() != sizeof(T)) { throw std::bad_cast(); } std::vector<T> resultArray; for (size_t i = 0; i < in_array->size(); ++i) { const T el = *(reinterpret_cast<T *>(in_array->getItemPointer(i))); resultArray.emplace_back(el); } return resultArray; } /// Tuple type // Helper to marshal (pack and unpack) C++ data to Q# QIR data // e.g. vector is converted to Array type. template <typename T> TuplePtr tuple_pack(TuplePtr io_tuple, const std::vector<T> &in_vec) { ::Array *qirArray = toArray(in_vec); TupleHeader *th = ::TupleHeader::getHeader(io_tuple); memcpy(io_tuple, &qirArray, sizeof(::Array *)); return io_tuple + sizeof(::Array *); } // Unpack a value from the tuple and move the pointer to the next element. template <typename T> TuplePtr unpack(TuplePtr in_tuple, T &out_val) { template <typename T> TuplePtr tuple_unpack(TuplePtr in_tuple, T &out_val) { static_assert(std::is_same<T, double>::value || std::is_same<T, int64_t>::value, "Only support these types now."); Loading @@ -32,29 +59,29 @@ template <typename T> TuplePtr unpack(TuplePtr in_tuple, T &out_val) { } template <typename T> TuplePtr unpack(TuplePtr in_tuple, std::vector<T> &out_val) { TuplePtr tuple_unpack(TuplePtr in_tuple, std::vector<T> &out_val) { static_assert(std::is_same<T, double>::value || std::is_same<T, int64_t>::value, "Only support vector of these types now."); out_val.clear(); ::Array *arrayPtr = *(reinterpret_cast<::Array **>(in_tuple)); for (size_t i = 0; i < arrayPtr->size(); ++i) { const double el = *(reinterpret_cast<T *>(arrayPtr->getItemPointer(i))); out_val.emplace_back(el); } out_val = fromArray<T>(arrayPtr); return in_tuple + sizeof(::Array *); } template <typename T> T marshal_one(TuplePtr &io_ptr) { T t; io_ptr = qsharp::unpack(io_ptr, t); io_ptr = tuple_unpack(io_ptr, t); return t; } // Marshal a QIR tuple to std::tuple template <typename... Args> std::tuple<Args...> marshal(TuplePtr &io_ptr) { return std::make_tuple(marshal_one<Args>(io_ptr)...); } /// Callable type // Wrap a std::function in an IFunctor // which can be used as a Callable. template <typename ReturnType, typename... Args> class qs_callback : public qsharp::IFunctor { public: Loading @@ -64,18 +91,19 @@ public: auto tuple_ptr = args; auto args_tuple = marshal<Args...>(tuple_ptr); // Pack the result to the return QIR Tuple qsharp::pack(result, std::apply(m_functor, args_tuple)); tuple_pack(result, std::apply(m_functor, args_tuple)); } private: std::function<ReturnType(Args...)> m_functor; }; // Create a QIR callable from a std::function. template <typename ReturnType, typename... Args> Callable *createCallable(std::function<ReturnType(Args...)> &in_func) { auto functor = new qs_callback<ReturnType, Args...>(in_func); // Create a QIR callable return new Callable(functor); } } // namespace qsharp } // namespace qir } // namespace qcor