Maestro 0.2.5
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
maestroexe.cpp
Go to the documentation of this file.
1#include <iostream>
2#include <boost/program_options.hpp>
3#include <algorithm>
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <iostream>
8#include <fstream>
9
10#include "Simulator.hpp"
11
12static std::string _get_env_var(const char* envs) {
13 std::string val;
14
15#ifdef _WIN32
16 size_t sz;
17
18 getenv_s(&sz, NULL, 0, envs);
19 if (sz == 0 || sz > 49) return val;
20
21 char buf[50];
22
23 getenv_s(&sz, buf, sz, envs);
24
25 buf[49] = 0;
26 val = buf;
27#else
28 const char* env = getenv(envs);
29 if (env) val = env;
30#endif
31
32 return val;
33}
34
35static std::string GetConfigJson(int num_shots, int maxBondDim) {
36 std::string config = "{\"shots\": ";
37
38 config += std::to_string(num_shots);
39
40 if (maxBondDim != 0)
41 config += ", \"matrix_product_state_max_bond_dimension\": " +
42 std::to_string(maxBondDim);
43
44 config += "}";
45
46 return config;
47}
48
49int main(int argc, char** argv) {
50 try {
51 std::ios_base::sync_with_stdio(false);
52 std::cin.tie(nullptr);
53
54 boost::program_options::options_description desc("Allowed options");
55 desc.add_options()("help,h", "Print a help description")(
56 "version,v", "Print version information")(
57 "nrqubits,n", boost::program_options::value<int>(),
58 "Specify the number of qubits")(
59 "shots,s", boost::program_options::value<int>(),
60 "Specify the number of shots for execution")(
61 "mbd,m", boost::program_options::value<int>(),
62 "Specify the max bond dimension for the MPS simulator")(
63 "simulator,r", boost::program_options::value<std::string>(),
64 "Simulator type, either aer, qcsim, composite_aer, composite_qcsim, "
65 "gpu "
66 "or quest")("type,t", boost::program_options::value<std::string>(),
67 "Simulation type, either statevector, mps, stabilizer, "
68 "tensor or pauli_propagation")(
69 "file,f", boost::program_options::value<std::string>(),
70 "Provide a qasm file for execution")(
71 "output,o", boost::program_options::value<std::string>(),
72 "Specify the json output file")(
73 "expectations,e", "Compute expectation values of observables");
74
75 boost::program_options::positional_options_description pos_desc;
76 pos_desc.add("file", 1);
77 pos_desc.add("output", 1);
78
79 boost::program_options::variables_map vars;
80 try {
81 boost::program_options::basic_command_line_parser<char> parser(argc,
82 argv);
83 parser.positional(pos_desc);
84 parser.options(desc);
85
86 boost::program_options::store(parser.run(), vars);
87 boost::program_options::notify(vars);
88 } catch (boost::program_options::error& e) {
89 std::cerr << "ERROR: " << e.what() << "\n";
90 return 1;
91 }
92
93 if (vars.count("version")) std::cout << "Version 1.0\n";
94
95 if (vars.count("help")) std::cout << desc << "\n";
96
97 int nrQubits = 64;
98 int nrShots = 1;
99 int maxBondDim = 0;
100 int simulatorType = 0;
101 int simulationType = 0;
102
103 if (vars.count("nrqubits")) {
104 nrQubits = vars["nrqubits"].as<int>();
105
106 const std::string qstr = _get_env_var("maestro_nrqubits");
107 if (!qstr.empty()) {
108 const int nrQubitsMax = std::stoi(qstr);
109 if (nrQubits > nrQubitsMax) nrQubits = nrQubitsMax;
110 }
111 } else {
112 const std::string qstr = _get_env_var("maestro_nrqubits");
113 if (!qstr.empty()) nrQubits = std::stoi(qstr);
114 }
115
116 if (nrQubits <= 0) {
117 std::cerr << "Invalid number of qubits" << std::endl;
118 return 2;
119 }
120
121 if (vars.count("shots")) {
122 nrShots = vars["shots"].as<int>();
123
124 const std::string sstr = _get_env_var("maestro_shots");
125 if (!sstr.empty()) {
126 const int nrShotsMax = std::stoi(sstr);
127 if (nrShots > nrShotsMax) nrShots = nrShotsMax;
128 }
129 } else {
130 const std::string sstr = _get_env_var("maestro_shots");
131 if (!sstr.empty()) nrShots = std::stoi(sstr);
132 }
133
134 if (nrShots <= 0) nrShots = 1;
135
136 if (vars.count("mbd")) {
137 maxBondDim = vars["mbd"].as<int>();
138
139 const std::string mbds = _get_env_var("maestro_max_bond_dim");
140 if (!mbds.empty()) {
141 const int mbdMax = std::stoi(mbds);
142 if (maxBondDim > mbdMax || (maxBondDim <= 0 && mbdMax > 0))
143 maxBondDim = mbdMax;
144 }
145 } else {
146 const std::string mbds = _get_env_var("maestro_max_bond_dim");
147 if (!mbds.empty()) maxBondDim = std::stoi(mbds);
148 }
149
150 if (maxBondDim < 0) maxBondDim = 0;
151
152 std::string stype;
153 if (vars.count("simulator"))
154 stype = vars["simulator"].as<std::string>();
155 else
156 stype = _get_env_var("maestro_simulator_type");
157
158 if (!stype.empty()) {
159 std::transform(stype.begin(), stype.end(), stype.begin(),
160 [](unsigned char chr) { return std::tolower(chr); });
161
162 if (stype == "aer")
163 simulatorType = 0;
164 else if (stype == "qcsim")
165 simulatorType = 1;
166 else if (stype == "composite_aer" || stype == "pblocks_aer")
167 simulatorType = 2;
168 else if (stype == "composite_qcsim" || stype == "pblocks_qcsim")
169 simulatorType = 3;
170 else if (stype == "gpu")
171 simulatorType = 4;
172 else if (stype == "quest")
173 simulatorType = 5;
174 else
175 simulatorType = 1000; // something big, so it won't be set
176 }
177
178 if (simulatorType != 2 && simulatorType != 3) {
179 stype.clear();
180 if (vars.count("type"))
181 stype = vars["type"].as<std::string>();
182 else
183 stype = _get_env_var("maestro_simulation_type");
184
185 if (!stype.empty()) {
186 std::transform(stype.begin(), stype.end(), stype.begin(),
187 [](unsigned char chr) { return std::tolower(chr); });
188
189 if (stype == "statevector" || stype == "sv")
190 simulationType = 0;
191 else if (stype == "mps" || stype == "matrix_product_state")
192 simulationType = 1;
193 else if (stype == "stabilizer" || stype == "clifford")
194 simulationType = 2;
195 else if (stype == "tensor" || stype == "tensor_network" ||
196 stype == "tn")
197 simulationType = 3;
198 else if (stype == "pauli_propagation" || stype == "pauli" ||
199 stype == "pprop")
200 simulationType = 4;
201 else
202 simulationType = 1000;
203 }
204 } else
205 simulationType = 0; // statevector for composite
206
207 if (vars.count("file") == 0) {
208 std::cerr << "No qasm file provided" << std::endl;
209 return 3;
210 }
211
212 const std::string qasmFileName = vars["file"].as<std::string>();
213 if (qasmFileName.empty()) {
214 std::cerr << "Invalid qasm file" << std::endl;
215 return 4;
216 }
217
218 std::ifstream file(qasmFileName);
219 if (!file.is_open()) {
220 std::cerr << "Couldn't read the qasm file" << std::endl;
221 return 5;
222 }
223
224 std::string qasmStr((std::istreambuf_iterator<char>(file)),
225 std::istreambuf_iterator<char>());
226 if (qasmStr.empty()) {
227 std::cerr << "Empty qasm" << std::endl;
228 return 6;
229 }
230
231 bool computeExpectations = false;
232 if (vars.count("expectations"))
233 computeExpectations = true;
234 else {
235 const std::string estr = _get_env_var("maestro_expectations");
236 if (!estr.empty()) computeExpectations = (std::stoi(estr) != 0);
237 }
238
239 // after getting all params and so on, execute:
240
241 SimpleSimulator simulator;
242 if (!simulator.Init(
243#if defined(_WIN32)
244 "maestro.dll"
245#else
246 "libmaestro.so"
247
248#endif
249 )) {
250 std::cerr << "Couldn't load maestro library" << std::endl;
251 return 6;
252 }
253
254 simulator.CreateSimpleSimulator(nrQubits);
255
256 if (simulatorType < 2) // qcsim or aer
257 {
258 if (simulationType < 4 ||
259 (simulatorType == 1 &&
260 simulationType == 4)) // qcsim also supports pauli propagation
262 static_cast<int>(simulatorType), static_cast<int>(simulationType));
263 else {
265 static_cast<int>(simulatorType), 0);
266 simulator.AddOptimizationSimulator(static_cast<int>(simulatorType), 1);
267 simulator.AddOptimizationSimulator(static_cast<int>(simulatorType), 2);
268 }
269 } else if (simulatorType <
270 4) // composite, ignore exec type and set statevector
271 {
273 static_cast<int>(simulatorType), 0);
274 } else if (simulatorType == 4) // gpu
275 {
276 if (simulationType < 2 || simulationType == 3 ||
277 simulationType ==
278 4) // statevector or mps, or tensor or pauli propagation
280 static_cast<int>(simulatorType), static_cast<int>(simulationType));
281 else // other types are not supported yet on gpu, set statevector
283 static_cast<int>(simulatorType), 0);
284 } else if (simulatorType == 5) // quest, only supports statevector for now
285 {
287 static_cast<int>(simulatorType), 0);
288 }
289
290 static std::string configStr = GetConfigJson(nrShots, maxBondDim);
291
292 std::string result;
293 if (!qasmStr.empty()) {
294 if (computeExpectations) {
295 std::string obsFileName = qasmFileName;
296 size_t lastDot = obsFileName.find_last_of(".");
297 if (lastDot != std::string::npos) {
298 obsFileName = obsFileName.substr(0, lastDot);
299 }
300 obsFileName += ".obs";
301
302 std::ifstream obsFile(obsFileName);
303 if (obsFile.is_open()) {
304 std::string obsStr((std::istreambuf_iterator<char>(obsFile)),
305 std::istreambuf_iterator<char>());
306 obsStr.erase(std::remove(obsStr.begin(), obsStr.end(), '\n'),
307 obsStr.end());
308 obsStr.erase(std::remove(obsStr.begin(), obsStr.end(), '\r'),
309 obsStr.end());
310 if (!obsStr.empty()) {
311 char* res = simulator.SimpleEstimate(
312 qasmStr.c_str(), obsStr.c_str(), configStr.c_str());
313 if (res) {
314 result = res;
315 simulator.FreeResult(res);
316 }
317 } else {
318 std::cerr << "Empty .obs file" << std::endl;
319 }
320 } else {
321 std::cerr << "Couldn't read the .obs file: " << obsFileName
322 << std::endl;
323 }
324 } else {
325 char* res = simulator.SimpleExecute(qasmStr.c_str(), configStr.c_str());
326 if (res) {
327 result = res;
328 simulator.FreeResult(res);
329 }
330 }
331 }
332
333 // depending on params, write it on stdout or in a file
334
335 if (vars.count("output")) {
336 const std::string fileName = vars["output"].as<std::string>();
337 if (!fileName.empty()) {
338 std::ofstream outFile(fileName);
339 outFile << result;
340 }
341 } else
342 std::cout << result << std::endl;
343 } catch (std::exception& e) {
344 std::cerr << "ERROR: " << e.what() << std::endl;
345 return 7;
346 } catch (...) {
347 std::cerr << "Exception of unknown type!" << std::endl;
348 return 8;
349 }
350
351 return 0;
352}
bool AddOptimizationSimulator(int simType, int simExecType)
Definition Simulator.hpp:35
char * SimpleEstimate(const char *jsonCircuit, const char *observableStr, const char *jsonConfig)
Definition Simulator.hpp:47
unsigned long int CreateSimpleSimulator(int nrQubits) override
Definition Simulator.hpp:19
char * SimpleExecute(const char *jsonCircuit, const char *jsonConfig)
Definition Simulator.hpp:43
void FreeResult(char *result) override
Definition Simulator.hpp:53
bool Init(const char *libName) noexcept override
Definition Simulator.hpp:13
bool RemoveAllOptimizationSimulatorsAndAdd(int simType, int simExecType)
Definition Simulator.hpp:27
int main(int argc, char **argv)
static std::string _get_env_var(const char *envs)
static std::string GetConfigJson(int num_shots, int maxBondDim)