40 boost::system::error_code ec;
41 std::string strs(str);
42 std::stringstream ss(strs);
46 std::shared_ptr<Circuits::Circuit<Time>>
ParseCircuit(
const char *str)
const {
47 const boost::json::value circuitJson =
ParseString(str);
49 std::shared_ptr<Circuits::Circuit<Time>> circuit;
51 if (circuitJson.is_array()) {
52 const auto circuitArray = circuitJson.as_array();
53 circuit = ParseCircuitArray(circuitArray);
54 }
else if (circuitJson.is_object()) {
55 std::string circuitStr;
56 const auto jsonObject = circuitJson.as_object();
57 if (jsonObject.contains(
"qasm")) {
58 const auto qasmValue = jsonObject.at(
"qasm");
59 if (qasmValue.is_string()) circuitStr = qasmValue.as_string().c_str();
60 }
else if (jsonObject.contains(
"QASM")) {
61 const auto qasmValue = jsonObject.at(
"QASM");
62 if (qasmValue.is_string()) circuitStr = qasmValue.as_string().c_str();
64 if (circuitStr.empty())
return nullptr;
68 std::string qasmInput(circuitStr);
77 const boost::json::value &jsonConfig) {
78 if (jsonConfig.is_object()) {
79 const auto jsonObject = jsonConfig.as_object();
81 if (jsonObject.contains(config)) {
82 const auto configValue = jsonObject.at(config);
83 if (configValue.is_string())
84 return configValue.as_string().c_str();
85 else if (configValue.is_number()) {
86 if (configValue.is_int64())
87 return std::to_string(configValue.as_int64());
88 else if (configValue.is_uint64())
89 return std::to_string(configValue.as_uint64());
90 else if (configValue.is_double())
91 return std::to_string(configValue.as_double());
92 }
else if (configValue.is_bool()) {
93 return configValue.as_bool() ?
"true" :
"false";
111 std::shared_ptr<Circuits::Circuit<Time>> ParseCircuitArray(
112 const boost::json::array &circuitArray)
const {
113 const auto circuit = std::make_shared<Circuits::Circuit<Time>>();
115 for (
auto operationJson : circuitArray) {
116 if (!operationJson.is_object())
117 throw std::runtime_error(
"Circuit operation must be an object.");
119 auto operationObject = operationJson.as_object();
120 if (!operationObject.contains(nameString))
121 throw std::runtime_error(
"Circuit operation does not have a type.");
122 else if (!operationObject.at(nameString).is_string())
123 throw std::runtime_error(
"Circuit operation type must be a string.");
125 const boost::json::string type =
126 operationObject.at(nameString).as_string();
129 circuit->AddOperation(ParseOperation(type, operationObject));
145 std::shared_ptr<Circuits::IOperation<Time>> ParseOperation(
146 const boost::json::string &type, boost::json::object &obj)
const {
147 std::shared_ptr<Circuits::IOperation<Time>> operation;
149 if (type == measurementString)
150 operation = ParseMeasurement(obj);
152 operation = ParseGate(type, obj);
166 std::shared_ptr<Circuits::MeasurementOperation<Time>> ParseMeasurement(
167 boost::json::object &obj)
const {
168 const auto qubits = ParseQubits(obj);
169 auto cbits = ParseCbits(obj);
171 cbits = std::vector<size_t>(qubits.begin(), qubits.end());
173 if (qubits.size() != cbits.size())
174 throw std::runtime_error(
"Number of qubits and cbits must be the same.");
176 std::vector<std::pair<Types::qubit_t, size_t>> qs;
178 for (
size_t i = 0; i < qubits.size(); i++)
179 qs.push_back(std::make_pair(qubits[i], cbits[i]));
181 const auto operation =
182 std::static_pointer_cast<Circuits::MeasurementOperation<Time>>(
197 std::shared_ptr<Circuits::IOperation<Time>> ParseGate(
198 const boost::json::string &type, boost::json::object &obj)
const {
199 const std::string gateName = type.c_str();
201 const auto qubits = ParseQubits(obj);
203 throw std::runtime_error(
"No qubits specified.");
204 else if (qubits.size() > 3)
205 throw std::runtime_error(
"Number of qubits must be 1, 2, or 3.");
209 if (gatesMap.find(gateName) == gatesMap.end())
210 throw std::runtime_error(
"Gate type not supported.");
212 gateType = gatesMap.at(gateName);
215 const auto parameters = ParseParameters(obj);
218 gateType, qubits[0], qubits.size() > 1 ? qubits[1] : 0,
219 qubits.size() > 2 ? qubits[2] : 0,
220 parameters.size() > 0 ? parameters[0] : 0.,
221 parameters.size() > 1 ? parameters[1] : 0.,
222 parameters.size() > 2 ? parameters[2] : 0.,
223 parameters.size() > 3 ? parameters[3] : 0.);
227 if (operation->GetNumQubits() != qubits.size())
228 throw std::runtime_error(
229 "The specified number of qubits does not match the number of qubits "
230 "required by the gate type.");
235 if (obj.contains(
"conditional_reg")) {
236 auto cond = obj.at(
"conditional_reg");
237 unsigned long long int cbit = 0;
238 if (cond.is_uint64())
239 cbit = cond.as_uint64();
240 else if (cond.is_int64())
241 cbit =
static_cast<unsigned long long int>(cond.as_int64());
242 else if (cond.is_array()) {
243 auto arr = cond.as_array();
244 if (arr.size() != 1 || !arr[0].is_number())
245 throw std::runtime_error(
246 "Conditional register must be a single integer.");
248 if (arr[0].is_uint64())
249 cbit = arr[0].as_uint64();
250 else if (arr[0].is_int64())
251 cbit =
static_cast<unsigned long long int>(arr[0].as_int64());
253 throw std::runtime_error(
254 "Conditional register must be an integer or "
255 "an array of one integer.");
257 throw std::runtime_error(
258 "Conditional register must be an integer or "
259 "an array of one integer.");
265 return std::static_pointer_cast<Circuits::IOperation<Time>>(operation);
276 std::vector<double> ParseParameters(boost::json::object &obj)
const {
277 std::vector<double> parameters;
279 if (obj.contains(paramsString) && !obj.at(paramsString).is_array())
280 throw std::runtime_error(
"Parameters must be an array.");
283 (obj.contains(paramsString) ? obj.at(paramsString).as_array()
284 : boost::json::array());
285 for (
auto param : paramsJson) {
286 if (!param.is_number())
287 throw std::runtime_error(
"Parameter must be a number.");
288 else if (param.is_double())
289 parameters.push_back(param.as_double());
290 else if (param.is_int64())
291 parameters.push_back(
static_cast<double>(param.as_int64()));
293 parameters.push_back(
static_cast<double>(param.as_uint64()));
307 std::vector<Types::qubit_t> ParseQubits(
308 const boost::json::object &obj)
const {
309 std::vector<Types::qubit_t> qubits;
311 if (!obj.contains(qubitsString))
312 throw std::runtime_error(
"No Qubits specified.");
313 else if (!obj.at(qubitsString).is_array())
314 throw std::runtime_error(
"Qubits must be an array.");
315 else if (obj.at(qubitsString).as_array().size() == 0)
316 throw std::runtime_error(
"Qubits array must not be empty.");
318 auto qubitsJson = obj.at(qubitsString).as_array();
319 for (
auto qubit : qubitsJson) {
320 if (!qubit.is_int64() && !qubit.is_uint64())
321 throw std::runtime_error(
"Number of qubits must be an integer.");
322 else if (qubit.is_int64())
323 qubits.push_back(qubit.as_int64());
325 qubits.push_back(qubit.as_uint64());
341 std::vector<size_t> ParseCbits(
const boost::json::object &obj,
342 bool mustBeSpecified =
false)
const {
343 std::vector<size_t> cbits;
345 if (mustBeSpecified) {
346 if (!obj.contains(memoryString))
347 throw std::runtime_error(
"No Cbits specified.");
348 else if (!obj.at(memoryString).is_array())
349 throw std::runtime_error(
"Cbits must be an array.");
350 else if (obj.at(memoryString).as_array().size() == 0)
351 throw std::runtime_error(
"Cbits array must not be empty.");
352 }
else if (obj.contains(memoryString) && !obj.at(memoryString).is_array())
353 throw std::runtime_error(
"Cbits must be an array.");
356 (obj.contains(memoryString) ? obj.at(memoryString).as_array()
357 : boost::json::array());
358 for (
auto cbit : cbitsJson) {
359 if (!cbit.is_int64() && !cbit.is_uint64())
360 throw std::runtime_error(
"Number of cbits must be an integer.");
361 else if (cbit.is_int64())
362 cbits.push_back(cbit.as_int64());
364 cbits.push_back(cbit.as_uint64());
379 static boost::json::value
ParseString(
const std::string &str,
380 boost::system::error_code &ec) {
381 std::stringstream ss(str);
394 static boost::json::value Parse(std::istream &is,
395 boost::system::error_code &ec) {
408 static boost::json::value Read(std::istream &is,
409 boost::system::error_code &ec) {
410 boost::json::stream_parser p;
412 while (std::getline(is, line)) {
414 if (ec)
return nullptr;
417 if (ec)
return nullptr;
422 const std::string circuitString =
"instructions";
423 const std::string nameString =
"name";
424 const std::string measurementString =
"measure";
426 const std::string qubitsString =
"qubits";
427 const std::string paramsString =
"params";
428 const std::string memoryString =
"clbits";
430 const std::unordered_map<std::string, Circuits::QuantumGateType> gatesMap = {