42 boost::system::error_code ec;
43 std::string strs(str);
44 std::stringstream ss(strs);
48 std::shared_ptr<Circuits::Circuit<Time>>
ParseCircuit(
const char *str)
const
50 const boost::json::value circuitJson =
ParseString(str);
52 std::shared_ptr<Circuits::Circuit<Time>> circuit;
54 if (circuitJson.is_array())
56 const auto circuitArray = circuitJson.as_array();
57 circuit = ParseCircuitArray(circuitArray);
59 else if (circuitJson.is_object())
61 std::string circuitStr;
62 const auto jsonObject = circuitJson.as_object();
63 if (jsonObject.contains(
"qasm"))
65 const auto qasmValue = jsonObject.at(
"qasm");
66 if (qasmValue.is_string())
67 circuitStr = qasmValue.as_string().c_str();
69 else if (jsonObject.contains(
"QASM"))
71 const auto qasmValue = jsonObject.at(
"QASM");
72 if (qasmValue.is_string())
73 circuitStr = qasmValue.as_string().c_str();
75 if (circuitStr.empty())
80 std::string qasmInput(circuitStr);
89 static std::string
GetConfigString(
const std::string &config,
const boost::json::value &jsonConfig)
91 if (jsonConfig.is_object())
93 const auto jsonObject = jsonConfig.as_object();
95 if (jsonObject.contains(config))
97 const auto configValue = jsonObject.at(config);
98 if (configValue.is_string())
99 return configValue.as_string().c_str();
100 else if (configValue.is_number())
102 if (configValue.is_int64())
103 return std::to_string(configValue.as_int64());
104 else if (configValue.is_uint64())
105 return std::to_string(configValue.as_uint64());
106 else if (configValue.is_double())
107 return boost::json::serialize(configValue);
109 else if (configValue.is_bool())
111 return configValue.as_bool() ?
"true" :
"false";
129 std::shared_ptr<Circuits::Circuit<Time>> ParseCircuitArray(
const boost::json::array &circuitArray)
const
131 const auto circuit = std::make_shared<Circuits::Circuit<Time>>();
133 for (
auto operationJson : circuitArray)
135 if (!operationJson.is_object())
136 throw std::runtime_error(
"Circuit operation must be an object.");
138 auto operationObject = operationJson.as_object();
139 if (!operationObject.contains(nameString))
140 throw std::runtime_error(
"Circuit operation does not have a type.");
141 else if (!operationObject.at(nameString).is_string())
142 throw std::runtime_error(
"Circuit operation type must be a string.");
144 const boost::json::string type = operationObject.at(nameString).as_string();
147 circuit->AddOperation(ParseOperation(type, operationObject));
163 std::shared_ptr<Circuits::IOperation<Time>> ParseOperation(
const boost::json::string &type, boost::json::object &obj)
const
165 std::shared_ptr<Circuits::IOperation<Time>> operation;
167 if (type == measurementString)
168 operation = ParseMeasurement(obj);
170 operation = ParseGate(type, obj);
184 std::shared_ptr<Circuits::MeasurementOperation<Time>> ParseMeasurement(boost::json::object &obj)
const
186 const auto qubits = ParseQubits(obj);
187 auto cbits = ParseCbits(obj);
189 cbits = std::vector<size_t>(qubits.begin(), qubits.end());
191 if (qubits.size() != cbits.size())
192 throw std::runtime_error(
"Number of qubits and cbits must be the same.");
194 std::vector<std::pair<Types::qubit_t, size_t>> qs;
196 for (
size_t i = 0; i < qubits.size(); i++)
197 qs.push_back(std::make_pair(qubits[i], cbits[i]));
213 std::shared_ptr<Circuits::IOperation<Time>> ParseGate(
const boost::json::string &type, boost::json::object &obj)
const
215 const std::string gateName = type.c_str();
217 const auto qubits = ParseQubits(obj);
219 throw std::runtime_error(
"No qubits specified.");
220 else if (qubits.size() > 3)
221 throw std::runtime_error(
"Number of qubits must be 1, 2, or 3.");
225 if (gatesMap.find(gateName) == gatesMap.end())
226 throw std::runtime_error(
"Gate type not supported.");
228 gateType = gatesMap.at(gateName);
231 const auto parameters = ParseParameters(obj);
234 gateType, qubits[0], qubits.size() > 1 ? qubits[1] : 0, qubits.size() > 2 ? qubits[2] : 0, parameters.size() > 0 ? parameters[0] : 0.,
235 parameters.size() > 1 ? parameters[1] : 0., parameters.size() > 2 ? parameters[2] : 0., parameters.size() > 3 ? parameters[3] : 0.);
239 if (operation->GetNumQubits() != qubits.size())
240 throw std::runtime_error(
"The specified number of qubits does not match the number of qubits "
241 "required by the gate type.");
246 if (obj.contains(
"conditional_reg"))
248 auto cond = obj.at(
"conditional_reg");
249 unsigned long long int cbit = 0;
250 if (cond.is_uint64())
251 cbit = cond.as_uint64();
252 else if (cond.is_int64())
253 cbit =
static_cast<unsigned long long int>(cond.as_int64());
254 else if (cond.is_array())
256 auto arr = cond.as_array();
257 if (arr.size() != 1 || !arr[0].is_number())
258 throw std::runtime_error(
"Conditional register must be a single integer.");
260 if (arr[0].is_uint64())
261 cbit = arr[0].as_uint64();
262 else if (arr[0].is_int64())
263 cbit =
static_cast<unsigned long long int>(arr[0].as_int64());
265 throw std::runtime_error(
"Conditional register must be an integer or "
266 "an array of one integer.");
269 throw std::runtime_error(
"Conditional register must be an integer or "
270 "an array of one integer.");
275 return std::static_pointer_cast<Circuits::IOperation<Time>>(operation);
286 std::vector<double> ParseParameters(boost::json::object &obj)
const
288 std::vector<double> parameters;
290 if (obj.contains(paramsString) && !obj.at(paramsString).is_array())
291 throw std::runtime_error(
"Parameters must be an array.");
293 auto paramsJson = (obj.contains(paramsString) ? obj.at(paramsString).as_array() : boost::json::array());
294 for (
auto param : paramsJson)
296 if (!param.is_number())
297 throw std::runtime_error(
"Parameter must be a number.");
298 else if (param.is_double())
299 parameters.push_back(param.as_double());
300 else if (param.is_int64())
301 parameters.push_back(
static_cast<double>(param.as_int64()));
303 parameters.push_back(
static_cast<double>(param.as_uint64()));
317 std::vector<Types::qubit_t> ParseQubits(
const boost::json::object &obj)
const
319 std::vector<Types::qubit_t> qubits;
321 if (!obj.contains(qubitsString))
322 throw std::runtime_error(
"No Qubits specified.");
323 else if (!obj.at(qubitsString).is_array())
324 throw std::runtime_error(
"Qubits must be an array.");
325 else if (obj.at(qubitsString).as_array().size() == 0)
326 throw std::runtime_error(
"Qubits array must not be empty.");
328 auto qubitsJson = obj.at(qubitsString).as_array();
329 for (
auto qubit : qubitsJson)
331 if (!qubit.is_int64() && !qubit.is_uint64())
332 throw std::runtime_error(
"Number of qubits must be an integer.");
333 else if (qubit.is_int64())
334 qubits.push_back(qubit.as_int64());
336 qubits.push_back(qubit.as_uint64());
352 std::vector<size_t> ParseCbits(
const boost::json::object &obj,
bool mustBeSpecified =
false)
const
354 std::vector<size_t> cbits;
358 if (!obj.contains(memoryString))
359 throw std::runtime_error(
"No Cbits specified.");
360 else if (!obj.at(memoryString).is_array())
361 throw std::runtime_error(
"Cbits must be an array.");
362 else if (obj.at(memoryString).as_array().size() == 0)
363 throw std::runtime_error(
"Cbits array must not be empty.");
365 else if (obj.contains(memoryString) && !obj.at(memoryString).is_array())
366 throw std::runtime_error(
"Cbits must be an array.");
368 auto cbitsJson = (obj.contains(memoryString) ? obj.at(memoryString).as_array() : boost::json::array());
369 for (
auto cbit : cbitsJson)
371 if (!cbit.is_int64() && !cbit.is_uint64())
372 throw std::runtime_error(
"Number of cbits must be an integer.");
373 else if (cbit.is_int64())
374 cbits.push_back(cbit.as_int64());
376 cbits.push_back(cbit.as_uint64());
391 static boost::json::value
ParseString(
const std::string &str, boost::system::error_code &ec)
393 std::stringstream ss(str);
406 static boost::json::value Parse(std::istream &is, boost::system::error_code &ec)
420 static boost::json::value Read(std::istream &is, boost::system::error_code &ec)
422 boost::json::stream_parser p;
424 while (std::getline(is, line))
437 const std::string circuitString =
"instructions";
438 const std::string nameString =
"name";
439 const std::string measurementString =
"measure";
441 const std::string qubitsString =
"qubits";
442 const std::string paramsString =
"params";
443 const std::string memoryString =
"clbits";
445 const std::unordered_map<std::string, Circuits::QuantumGateType> gatesMap = {