38 boost::system::error_code ec;
39 std::string strs(str);
40 std::stringstream ss(strs);
44 std::shared_ptr<Circuits::Circuit<Time>>
ParseCircuit(
const char *str)
const {
45 const boost::json::value circuitJson =
ParseString(str);
47 std::shared_ptr<Circuits::Circuit<Time>> circuit;
49 if (circuitJson.is_array()) {
50 const auto circuitArray = circuitJson.as_array();
51 circuit = ParseCircuitArray(circuitArray);
52 }
else if (circuitJson.is_object()) {
53 std::string circuitStr;
54 const auto jsonObject = circuitJson.as_object();
55 if (jsonObject.contains(
"qasm")) {
56 const auto qasmValue = jsonObject.at(
"qasm");
57 if (qasmValue.is_string())
58 circuitStr = qasmValue.as_string().c_str();
59 }
else if (jsonObject.contains(
"QASM")) {
60 const auto qasmValue = jsonObject.at(
"QASM");
61 if (qasmValue.is_string())
62 circuitStr = qasmValue.as_string().c_str();
64 if (circuitStr.empty())
69 std::string qasmInput(circuitStr);
78 const boost::json::value &jsonConfig) {
79 if (jsonConfig.is_object()) {
80 const auto jsonObject = jsonConfig.as_object();
82 if (jsonObject.contains(config)) {
83 const auto configValue = jsonObject.at(config);
84 if (configValue.is_string())
85 return configValue.as_string().c_str();
86 else if (configValue.is_number()) {
87 if (configValue.is_int64())
88 return std::to_string(configValue.as_int64());
89 else if (configValue.is_uint64())
90 return std::to_string(configValue.as_uint64());
91 else if (configValue.is_double())
92 return std::to_string(configValue.as_double());
93 }
else if (configValue.is_bool()) {
94 return configValue.as_bool() ?
"true" :
"false";
112 std::shared_ptr<Circuits::Circuit<Time>>
113 ParseCircuitArray(
const boost::json::array &circuitArray)
const {
114 const auto circuit = std::make_shared<Circuits::Circuit<Time>>();
116 for (
auto operationJson : circuitArray) {
117 if (!operationJson.is_object())
118 throw std::runtime_error(
"Circuit operation must be an object.");
120 auto operationObject = operationJson.as_object();
121 if (!operationObject.contains(nameString))
122 throw std::runtime_error(
"Circuit operation does not have a type.");
123 else if (!operationObject.at(nameString).is_string())
124 throw std::runtime_error(
"Circuit operation type must be a string.");
126 const boost::json::string type =
127 operationObject.at(nameString).as_string();
130 circuit->AddOperation(ParseOperation(type, operationObject));
146 std::shared_ptr<Circuits::IOperation<Time>>
147 ParseOperation(
const boost::json::string &type,
148 boost::json::object &obj)
const {
149 std::shared_ptr<Circuits::IOperation<Time>> operation;
151 if (type == measurementString)
152 operation = ParseMeasurement(obj);
154 operation = ParseGate(type, obj);
168 std::shared_ptr<Circuits::MeasurementOperation<Time>>
169 ParseMeasurement(boost::json::object &obj)
const {
170 const auto qubits = ParseQubits(obj);
171 auto cbits = ParseCbits(obj);
173 cbits = std::vector<size_t>(qubits.begin(), qubits.end());
175 if (qubits.size() != cbits.size())
176 throw std::runtime_error(
"Number of qubits and cbits must be the same.");
178 std::vector<std::pair<Types::qubit_t, size_t>> qs;
180 for (
size_t i = 0; i < qubits.size(); i++)
181 qs.push_back(std::make_pair(qubits[i], cbits[i]));
183 const auto operation =
184 std::static_pointer_cast<Circuits::MeasurementOperation<Time>>(
199 std::shared_ptr<Circuits::IOperation<Time>>
200 ParseGate(
const boost::json::string &type, boost::json::object &obj)
const {
201 const std::string gateName = type.c_str();
203 const auto qubits = ParseQubits(obj);
205 throw std::runtime_error(
"No qubits specified.");
206 else if (qubits.size() > 3)
207 throw std::runtime_error(
"Number of qubits must be 1, 2, or 3.");
211 if (gatesMap.find(gateName) == gatesMap.end())
212 throw std::runtime_error(
"Gate type not supported.");
214 gateType = gatesMap.at(gateName);
217 const auto parameters = ParseParameters(obj);
220 gateType, qubits[0], qubits.size() > 1 ? qubits[1] : 0,
221 qubits.size() > 2 ? qubits[2] : 0,
222 parameters.size() > 0 ? parameters[0] : 0.,
223 parameters.size() > 1 ? parameters[1] : 0.,
224 parameters.size() > 2 ? parameters[2] : 0.,
225 parameters.size() > 3 ? parameters[3] : 0.);
229 if (operation->GetNumQubits() != qubits.size())
230 throw std::runtime_error(
231 "The specified number of qubits does not match the number of qubits "
232 "required by the gate type.");
237 if (obj.contains(
"conditional_reg")) {
238 auto cond = obj.at(
"conditional_reg");
239 unsigned long long int cbit = 0;
240 if (cond.is_uint64())
241 cbit = cond.as_uint64();
242 else if (cond.is_int64())
243 cbit =
static_cast<unsigned long long int>(cond.as_int64());
244 else if (cond.is_array()) {
245 auto arr = cond.as_array();
246 if (arr.size() != 1 || !arr[0].is_number())
247 throw std::runtime_error(
248 "Conditional register must be a single integer.");
250 if (arr[0].is_uint64())
251 cbit = arr[0].as_uint64();
252 else if (arr[0].is_int64())
253 cbit =
static_cast<unsigned long long int>(arr[0].as_int64());
255 throw std::runtime_error(
"Conditional register must be an integer or "
256 "an array of one integer.");
258 throw std::runtime_error(
"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>
308 ParseQubits(
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)) {
424 const std::string circuitString =
"instructions";
425 const std::string nameString =
"name";
426 const std::string measurementString =
"measure";
428 const std::string qubitsString =
"qubits";
429 const std::string paramsString =
"params";
430 const std::string memoryString =
"clbits";
432 const std::unordered_map<std::string, Circuits::QuantumGateType> gatesMap = {