1717#ifndef __qiskitcpp_providers_SQC_backend_def_hpp__
1818#define __qiskitcpp_providers_SQC_backend_def_hpp__
1919
20+ #include < memory>
21+
2022#include " utils/types.hpp"
2123#include " transpiler/target.hpp"
2224#include " primitives/containers/sampler_pub.hpp"
23- #include " providers/job .hpp"
25+ #include " providers/sqc_job .hpp"
2426
27+ #include " sqc_ecode.h"
2528#include " sqc_api.h"
2629
2730namespace Qiskit {
2831namespace providers {
2932
33+ // / @brief Convert a qiskit quantum circuit to a SQC circuit.
34+ // / @param A SQC circuit where a result is stored
35+ // / @param An original qiskit circuit
36+ // / @note This function destroys the original SQC circuit data.
37+ // / @note Currently parameterized circuits are not supported.
38+ bool qk_circ_to_sqc_circ (sqcQC* qc_handle, circuit::QuantumCircuit& qk_circ);
39+
3040// / @class SQCBackend
3141// / @brief Backend class using SQC.
3242class SQCBackend : public BackendV2 {
3343private:
34- // / @note A circuit data will be built via qiskit-cpp, not SQC.
35- // / A `qc_handle_` field is just used for an interface between qiskit-cpp and SQC.
36- sqcQC* qc_handle_;
3744 const sqcBackend backend_type_;
45+ std::shared_ptr<transpiler::Target> target_;
3846
3947public:
4048 // / @brief Create a new SQCBackend. Internally this initializes SQC.
4149 SQCBackend ()
42- : SQCBackend(" unspecified" ) // @TODO
50+ : SQCBackend(" unspecified" )
4351 {}
4452
4553 // / @brief Create a new SQCBackend object
4654 // / @param backend_name a resource name for backend.
4755 SQCBackend (const std::string name)
48- : name_(name),
49- qc_handle_ (NULL ),
56+ : BackendV2(name),
5057 backend_type_ (SQC_RPC_SCHED_QC_TYPE_IBM_DACC),
51- {
52-
53- qc_handle_ = sqcQuantumCircuit (0 );
54- }
58+ target_(nullptr )
59+ {}
5560
56- ~SQCBackend ()
57- {
58- sqcDestroyQuantumCircuit (qc_handle_);
59- }
61+ SQCBackend (const SQCBackend& other)
62+ : BackendV2(other.name_),
63+ backend_type_(other.backend_type_),
64+ target_(other.target_)
65+ {}
66+
67+ ~SQCBackend () {}
6068
6169 // / @brief Return a target properties for this backend.
6270 // / @return a target class (nullptr)
@@ -65,14 +73,14 @@ class SQCBackend : public BackendV2 {
6573 if (target_) return target_;
6674
6775 // Create a dummy circuit to get target json files
68- std::unique_ptr<sqcQC> qc_handle (sqcQuantumCircuit (0 ), sqcDestroyQuantumCircuit);
76+ std::unique_ptr<sqcQC, decltype (&sqcDestroyQuantumCircuit) > qc_handle (sqcQuantumCircuit (0 ), & sqcDestroyQuantumCircuit);
6977 if (sqcIbmdTranspileInfo (qc_handle.get (), backend_type_) != SQC_RESULT_OK) {
7078 std::cerr << " Failed to get the target information" << std::endl;
7179 return nullptr ;
7280 }
7381
7482 nlohmann::ordered_json target_json;
75- target_json[" configuration" ] = nlohmann::ordered_json::parse (qc_handle->backend_config_json )
83+ target_json[" configuration" ] = nlohmann::ordered_json::parse (qc_handle->backend_config_json );
7684 target_json[" properties" ] = nlohmann::ordered_json::parse (qc_handle->backend_props_json );
7785 auto target = std::shared_ptr<transpiler::Target>();
7886 if (!target->from_json (target_json)) {
@@ -89,25 +97,28 @@ class SQCBackend : public BackendV2 {
8997 std::shared_ptr<providers::Job> run (std::vector<primitives::SamplerPub>& input_pubs, uint_t shots) override
9098 {
9199 auto circuit = input_pubs[0 ].circuit ();
92- std::cout << " run qasm3: \n " << circuit.to_qasm3 () << std::endl;
93-
94- if (!qk_circ_to_sqc_circ (qc_handle_, circuit))
100+ const auto qasm3_str = circuit.to_qasm3 ();
101+ std::cout << " run qasm3: \n " << qasm3_str << std::endl;
102+
103+ // Create a sqcQC from a qiskit circuit
104+ const uint_t qasm_len = qasm3_str.size () + 500 ;
105+ std::unique_ptr<sqcQC, decltype (&sqcDestroyQuantumCircuit)> sqc_circ (sqcQuantumCircuit (0 ), &sqcDestroyQuantumCircuit);
106+ sqc_circ->qasm = (char *)malloc (qasm_len);
107+ if (!qk_circ_to_sqc_circ (sqc_circ.get (), circuit))
95108 {
96109 std::cerr << " Error: Failed to convert a given qiskit circuit to a SQC circuit." << std::endl;
97110 return nullptr ;
98111 }
99-
100- // @TODO: gateInfo2qasm3 is implemented in sqc_api.c, but not declared in the header file.
101- qc_handle_->qasm = gateInfo2qasm3 (qc_handle_);
112+ sqcConvQASMtoMemory (sqc_circ.get (), backend_type_, sqc_circ->qasm , qasm_len);
102113
103114 std::unique_ptr<sqcRunOptions> run_options (new sqcRunOption);
104115 sqcInitializeRunOpt (run_options.get ());
105116 run_options->nshots = shots;
106- run_options->qubits = qc_handle_ ->qubits ;
117+ run_options->qubits = sqc_circ ->qubits ;
107118 run_options->outFormat = SQC_OUT_RAW; // @TODO
108119
109- std::unique_ptr <sqcOut> result (new sqcOut, [](sqcOut* out) { sqcFreeOut (out, SQC_OUT_RAW); });
110- int error_code = sqcQCRun (qc_handle_ , backend_type_, *run_options, result);
120+ std::shared_ptr <sqcOut> result (new sqcOut, [](sqcOut* out) { sqcFreeOut (out, SQC_OUT_RAW); });
121+ int error_code = sqcQCRun (sqc_circ. get () , backend_type_, *run_options, result. get () );
111122
112123 if (error_code != SQC_RESULT_OK)
113124 {
@@ -122,12 +133,7 @@ class SQCBackend : public BackendV2 {
122133};
123134
124135
125- // / @brief Convert a qiskit quantum circuit to a SQC circuit.
126- // / @param A SQC circuit where a result is stored
127- // / @param An original qiskit circuit
128- // / @note This function destroys the original SQC circuit data.
129- // / @note Currently parameterized circuits are not supported.
130- bool qk_circ_to_sqc_circ (sqcQC* qc_handle, const circuit::QuantumCircuit& qk_circ)
136+ bool qk_circ_to_sqc_circ (sqcQC* qc_handle, circuit::QuantumCircuit& qk_circ)
131137{
132138 if (qc_handle == NULL )
133139 {
@@ -199,7 +205,8 @@ bool qk_circ_to_sqc_circ(sqcQC* qc_handle, const circuit::QuantumCircuit& qk_cir
199205 }
200206 else if (instr_name == " p" )
201207 {
202- sqcU1Gate (qc_handle, qubits[0 ]);
208+ const auto & instr = circ_instr.instruction ();
209+ sqcU1Gate (qc_handle, instr.params ()[0 ], qubits[0 ]);
203210 }
204211 else if (instr_name == " reset" )
205212 {
0 commit comments