Maestro 0.2.5
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Interface.cpp
Go to the documentation of this file.
1
9#include "Interface.h"
10
11#ifdef COMPOSER
12#include "../../composer/composer/Estimators/ExecutionEstimator.h"
13#endif
14
15#include "../Simulators/Factory.h"
16
17#include "Maestro.h"
18
19#include "Json.h"
20
21#include <atomic>
22#include <memory>
23
24#include "../Utils/LogFile.h"
25#include "../qasm/QasmCirc.h"
26
27static std::atomic_bool isInitialized{false};
28static std::unique_ptr<Maestro> maestroInstance;
29
30extern "C" {
31#ifdef _WIN32
32__declspec(dllexport)
33#endif
35 if (!isInitialized.exchange(true)) {
36#ifdef __linux__
38#endif
40
41#ifdef COMPOSER
42 Estimators::ExecutionEstimator<>::InitializeRegressors();
43#endif
44
45 maestroInstance = std::make_unique<Maestro>();
46 }
47
48 return (void *)maestroInstance.get();
49}
50
51#ifdef _WIN32
52__declspec(dllexport)
53#endif
55 if (!isInitialized.exchange(true)) {
56#ifdef __linux__
57 Simulators::SimulatorsFactory::InitGpuLibraryWithMute();
58#endif
59
60#ifdef COMPOSER
61 Estimators::ExecutionEstimator<>::InitializeRegressors();
62#endif
63
64 maestroInstance = std::make_unique<Maestro>();
65 }
66
67 return (void *)maestroInstance.get();
68}
69
70#ifdef _WIN32
71__declspec(dllexport)
72#endif
73 unsigned long int CreateSimpleSimulator(int nrQubits) {
74 if (!maestroInstance) return 0;
75
76 return maestroInstance->CreateSimpleSimulator(nrQubits);
77}
78
79#ifdef _WIN32
80__declspec(dllexport)
81#endif
82 void DestroySimpleSimulator(unsigned long int simHandle) {
83 if (!maestroInstance || simHandle == 0) return;
84
85 maestroInstance->DestroySimpleSimulator(simHandle);
86}
87
88#ifdef _WIN32
89__declspec(dllexport)
90#endif
91 int RemoveAllOptimizationSimulatorsAndAdd(unsigned long int simHandle,
92 int simType, int simExecType) {
93 if (!maestroInstance || simHandle == 0) return 0;
94
95 return maestroInstance->RemoveAllOptimizationSimulatorsAndAdd(
96 simHandle, static_cast<Simulators::SimulatorType>(simType),
97 static_cast<Simulators::SimulationType>(simExecType));
98}
99
100#ifdef _WIN32
101__declspec(dllexport)
102#endif
103 int AddOptimizationSimulator(unsigned long int simHandle, int simType,
104 int simExecType) {
105 if (!maestroInstance || simHandle == 0) return 0;
106
107 return maestroInstance->AddOptimizationSimulator(
108 simHandle, static_cast<Simulators::SimulatorType>(simType),
109 static_cast<Simulators::SimulationType>(simExecType));
110}
111
112#ifdef _WIN32
113__declspec(dllexport)
114#endif
115 char *SimpleExecute(unsigned long int simpleSim, const char *circuitStr,
116 const char *jsonConfig) {
117 if (simpleSim == 0 || !circuitStr || !jsonConfig || !maestroInstance)
118 return nullptr;
119
120 auto network = maestroInstance->GetSimpleSimulator(simpleSim);
121
122 // step 1: Parse the JSON circuit and configuration strings
123 // convert the JSON circuit into a Circuit object
124
125 // I'm unsure here on how it deals with the classical registers, more
126 // precisely with stuff like "other_measure_name" and "meas" (see below) since
127 // in the example it seems to just use the cbit number
128
129 // This is the json format:
130 // {"instructions":
131 // [{"name": "h", "qubits": [0], "params": []},
132 // {"name": "cx", "qubits": [0, 1], "params": []},
133 // {"name": "rx", "qubits": [0], "params": [0.39528385768119634]},
134 // {"name": "measure", "qubits": [0], "memory": [0]}],
135 //
136 // "num_qubits": 2, "num_clbits": 4,
137 // "quantum_registers": {"q": [0, 1]},
138 // "classical_registers": {"c": [0, 1], "other_measure_name": [2], "meas":
139 // [3]}}
140
141 std::shared_ptr<Circuits::Circuit<>> circuit;
142
143 if (circuitStr[0] == '{' || circuitStr[0] == '[') {
144 // assume JSON format only if either object or array
145 Json::JsonParserMaestro<> jsonParser;
146 circuit = jsonParser.ParseCircuit(circuitStr);
147 } else {
148 // QASM 2.0 format
149 qasm::QasmToCirc<> parser;
150 std::string qasmInput(circuitStr);
151 circuit = parser.ParseAndTranslate(qasmInput);
152 if (parser.Failed()) return nullptr;
153 }
154
155 // check if the circuit has measurements only at the end
156
157 // get the number of shots from the configuration
158 size_t nrShots = 1; // default value
159
160 const auto configJson = Json::JsonParserMaestro<>::ParseString(jsonConfig);
161
162 if (configJson.is_object()) {
163 const auto configObject = configJson.as_object();
164 // get whatever else is needed from the configuration
165 // maybe simulator type, allowed simulator types, bond dimension limit, etc.
166
167 // execute the circuit in the network object
168 if (configObject.contains("shots") &&
169 configObject.at("shots").is_number()) {
170 auto number = configObject.at("shots");
171 nrShots = number.is_int64() ? (size_t)number.as_int64()
172 : (size_t)number.as_uint64();
173 }
174 }
175
176 bool configured = false;
177
178 const std::string maxBondDim = Json::JsonParserMaestro<>::GetConfigString(
179 "matrix_product_state_max_bond_dimension", configJson);
180 if (!maxBondDim.empty()) {
181 configured = true;
182 if (network->GetSimulator()) network->GetSimulator()->Clear();
183 network->Configure("matrix_product_state_max_bond_dimension",
184 maxBondDim.c_str());
185 }
186
187 const std::string singularValueThreshold =
189 "matrix_product_state_truncation_threshold", configJson);
190 if (!singularValueThreshold.empty()) {
191 configured = true;
192 if (network->GetSimulator()) network->GetSimulator()->Clear();
193 network->Configure("matrix_product_state_truncation_threshold",
194 singularValueThreshold.c_str());
195 }
196
197 const std::string mpsSample = Json::JsonParserMaestro<>::GetConfigString(
198 "mps_sample_measure_algorithm", configJson);
199 if (!mpsSample.empty()) {
200 configured = true;
201 if (network->GetSimulator()) network->GetSimulator()->Clear();
202 network->Configure("mps_sample_measure_algorithm", mpsSample.c_str());
203 }
204
205 if (configured || !network->GetSimulator()) network->CreateSimulator();
206
207 // TODO: get from config the allowed simulators types and so on, if set
208 auto start = std::chrono::high_resolution_clock::now();
209 auto results = network->RepeatedExecuteOnHost(circuit, 0, nrShots);
210 auto end = std::chrono::high_resolution_clock::now();
211
212 std::chrono::duration<double> duration = end - start;
213 double time_taken = duration.count();
214 std::string timeStr = std::to_string(time_taken);
215
216 // convert the results into a JSON string
217 // allocate memory for the result string and copy the JSON result into it
218 // return the result string
219
220 boost::json::object jsonResult;
221 jsonResult.reserve(results.size());
222
223 for (auto &result : results) {
224 boost::json::string bits;
225 bits.reserve(result.first.size());
226 for (const auto bit : result.first) bits.append(bit ? "1" : "0");
227
228 jsonResult.emplace(std::move(bits), std::move(result.second));
229 }
230
231 boost::json::object response;
232 response.reserve(4);
233
234 response.emplace("counts", std::move(jsonResult));
235 response.emplace("time_taken", timeStr);
236
237 auto simulatorType = network->GetLastSimulatorType();
238
239 switch (simulatorType) {
240#ifndef NO_QISKIT_AER
242 response.emplace("simulator", "aer");
243 break;
244#endif
246 response.emplace("simulator", "qcsim");
247 break;
248#ifndef NO_QISKIT_AER
250 response.emplace("simulator", "composite_aer");
251 break;
252#endif
254 response.emplace("simulator", "composite_qcsim");
255 break;
257 response.emplace("simulator", "quest");
258 break;
259#ifdef __linux__
261 response.emplace("simulator", "gpu_simulator");
262 break;
263#endif
264 default:
265 response.emplace("simulator", "unknown");
266 break;
267 }
268
269 auto simulationType = network->GetLastSimulationType();
270 switch (simulationType) {
272 response.emplace("method", "statevector");
273 break;
275 response.emplace("method", "matrix_product_state");
276 break;
278 response.emplace("method", "stabilizer");
279 break;
281 response.emplace("method", "tensor_network");
282 break;
284 response.emplace("method", "pauli_propagation");
285 break;
286 default:
287 response.emplace("method", "unknown");
288 break;
289 }
290
291 const std::string responseStr = boost::json::serialize(response);
292 const size_t responseSize = responseStr.length();
293 char *result = new char[responseSize + 1];
294
295 const char *responseData = responseStr.c_str();
296 std::copy(responseData, responseData + responseSize, result);
297
298 result[responseSize] = 0; // ensure null-termination
299
300 return result;
301}
302
303#ifdef _WIN32
304__declspec(dllexport)
305#endif
306 char *SimpleEstimate(unsigned long int simpleSim, const char *circuitStr,
307 const char *observableStr, const char *jsonConfig) {
308 if (simpleSim == 0 || !circuitStr || !observableStr || !jsonConfig ||
310 return nullptr;
311
312 auto network = maestroInstance->GetSimpleSimulator(simpleSim);
313
314 std::shared_ptr<Circuits::Circuit<>> circuit;
315
316 if (circuitStr[0] == '{' || circuitStr[0] == '[') {
317 Json::JsonParserMaestro<> jsonParser;
318 circuit = jsonParser.ParseCircuit(circuitStr);
319 } else {
320 qasm::QasmToCirc<> parser;
321 std::string qasmInput(circuitStr);
322 circuit = parser.ParseAndTranslate(qasmInput);
323 if (parser.Failed()) return nullptr;
324 }
325
326 const auto configJson = Json::JsonParserMaestro<>::ParseString(jsonConfig);
327
328 bool configured = false;
329
330 const std::string maxBondDim = Json::JsonParserMaestro<>::GetConfigString(
331 "matrix_product_state_max_bond_dimension", configJson);
332 if (!maxBondDim.empty()) {
333 configured = true;
334 if (network->GetSimulator()) network->GetSimulator()->Clear();
335 network->Configure("matrix_product_state_max_bond_dimension",
336 maxBondDim.c_str());
337 }
338
339 const std::string singularValueThreshold =
341 "matrix_product_state_truncation_threshold", configJson);
342 if (!singularValueThreshold.empty()) {
343 configured = true;
344 if (network->GetSimulator()) network->GetSimulator()->Clear();
345 network->Configure("matrix_product_state_truncation_threshold",
346 singularValueThreshold.c_str());
347 }
348
349 const std::string mpsSample = Json::JsonParserMaestro<>::GetConfigString(
350 "mps_sample_measure_algorithm", configJson);
351 if (!mpsSample.empty()) {
352 configured = true;
353 if (network->GetSimulator()) network->GetSimulator()->Clear();
354 network->Configure("mps_sample_measure_algorithm", mpsSample.c_str());
355 }
356
357 if (configured || !network->GetSimulator()) network->CreateSimulator();
358
359 // Split observableStr by ';'
360 std::vector<std::string> paulis;
361 std::string obsStr(observableStr);
362 std::stringstream ss(obsStr);
363 std::string item;
364 while (std::getline(ss, item, ';')) {
365 if (!item.empty()) paulis.push_back(item);
366 }
367
368 auto start = std::chrono::high_resolution_clock::now();
369 auto expectations = network->ExecuteOnHostExpectations(circuit, 0, paulis);
370 auto end = std::chrono::high_resolution_clock::now();
371
372 std::chrono::duration<double> duration = end - start;
373 double time_taken = duration.count();
374 std::string timeStr = std::to_string(time_taken);
375
376 boost::json::object response;
377 response.reserve(4);
378
379 boost::json::array jsonExpectations;
380 jsonExpectations.reserve(expectations.size());
381 for (double val : expectations) {
382 jsonExpectations.push_back(val);
383 }
384
385 response.emplace("expectation_values", std::move(jsonExpectations));
386 response.emplace("time_taken", timeStr);
387
388 auto simulatorType = network->GetLastSimulatorType();
389
390 switch (simulatorType) {
391#ifndef NO_QISKIT_AER
393 response.emplace("simulator", "aer");
394 break;
395#endif
397 response.emplace("simulator", "qcsim");
398 break;
400 response.emplace("simulator", "quest");
401 break;
402#ifndef NO_QISKIT_AER
404 response.emplace("simulator", "composite_aer");
405 break;
406#endif
408 response.emplace("simulator", "composite_qcsim");
409 break;
410#ifdef __linux__
412 response.emplace("simulator", "gpu_simulator");
413 break;
414#endif
415 default:
416 response.emplace("simulator", "unknown");
417 break;
418 }
419
420 auto simulationType = network->GetLastSimulationType();
421 switch (simulationType) {
423 response.emplace("method", "statevector");
424 break;
426 response.emplace("method", "matrix_product_state");
427 break;
429 response.emplace("method", "stabilizer");
430 break;
432 response.emplace("method", "tensor_network");
433 break;
435 response.emplace("method", "pauli_propagation");
436 break;
437 default:
438 response.emplace("method", "unknown");
439 break;
440 }
441
442 const std::string responseStr = boost::json::serialize(response);
443 const size_t responseSize = responseStr.length();
444 char *result = new char[responseSize + 1];
445
446 const char *responseData = responseStr.c_str();
447 std::copy(responseData, responseData + responseSize, result);
448
449 result[responseSize] = 0; // ensure null-termination
450
451 return result;
452}
453
454#ifdef _WIN32
455__declspec(dllexport)
456#endif
457 void FreeResult(char *result) {
458 if (result) delete[] result;
459}
460
461#ifdef _WIN32
462__declspec(dllexport)
463#endif
464 unsigned long int CreateSimulator(int simType, int simExecType) {
465 if (!maestroInstance) return 0;
466
467 return maestroInstance->CreateSimulator(
468 static_cast<Simulators::SimulatorType>(simType),
469 static_cast<Simulators::SimulationType>(simExecType));
470}
471
472#ifdef _WIN32
473__declspec(dllexport)
474#endif
475 void *GetSimulator(unsigned long int simHandle) {
476 if (!maestroInstance || simHandle == 0) return nullptr;
477 return maestroInstance->GetSimulator(simHandle);
478}
479
480#ifdef _WIN32
481__declspec(dllexport)
482#endif
483 void DestroySimulator(unsigned long int simHandle) {
484 if (!maestroInstance || simHandle == 0) return;
485 maestroInstance->DestroySimulator(simHandle);
486}
487
488#ifdef _WIN32
489__declspec(dllexport)
490#endif
491 int ApplyX(void *sim, int qubit) {
492 if (!sim) return 0;
493
494 auto simulator = static_cast<Simulators::ISimulator *>(sim);
495 simulator->ApplyX(qubit);
496
497 return 1;
498}
499
500#ifdef _WIN32
501__declspec(dllexport)
502#endif
503 int ApplyY(void *sim, int qubit) {
504 if (!sim) return 0;
505 auto simulator = static_cast<Simulators::ISimulator *>(sim);
506 simulator->ApplyY(qubit);
507
508 return 1;
509}
510
511#ifdef _WIN32
512__declspec(dllexport)
513#endif
514 int ApplyZ(void *sim, int qubit) {
515 if (!sim) return 0;
516
517 auto simulator = static_cast<Simulators::ISimulator *>(sim);
518 simulator->ApplyZ(qubit);
519 return 1;
520}
521
522#ifdef _WIN32
523__declspec(dllexport)
524#endif
525 int ApplyH(void *sim, int qubit) {
526 if (!sim) return 0;
527 auto simulator = static_cast<Simulators::ISimulator *>(sim);
528 simulator->ApplyH(qubit);
529
530 return 1;
531}
532
533#ifdef _WIN32
534__declspec(dllexport)
535#endif
536 int ApplyS(void *sim, int qubit) {
537 if (!sim) return 0;
538 auto simulator = static_cast<Simulators::ISimulator *>(sim);
539 simulator->ApplyS(qubit);
540
541 return 1;
542}
543
544#ifdef _WIN32
545__declspec(dllexport)
546#endif
547 int ApplySDG(void *sim, int qubit) {
548 if (!sim) return 0;
549 auto simulator = static_cast<Simulators::ISimulator *>(sim);
550 simulator->ApplySDG(qubit);
551
552 return 1;
553}
554
555#ifdef _WIN32
556__declspec(dllexport)
557#endif
558 int ApplyT(void *sim, int qubit) {
559 if (!sim) return 0;
560 auto simulator = static_cast<Simulators::ISimulator *>(sim);
561 simulator->ApplyT(qubit);
562
563 return 1;
564}
565
566#ifdef _WIN32
567__declspec(dllexport)
568#endif
569 int ApplyTDG(void *sim, int qubit) {
570 if (!sim) return 0;
571 auto simulator = static_cast<Simulators::ISimulator *>(sim);
572 simulator->ApplyTDG(qubit);
573
574 return 1;
575}
576
577#ifdef _WIN32
578__declspec(dllexport)
579#endif
580 int ApplySX(void *sim, int qubit) {
581 if (!sim) return 0;
582 auto simulator = static_cast<Simulators::ISimulator *>(sim);
583 simulator->ApplySx(qubit);
584
585 return 1;
586}
587
588#ifdef _WIN32
589__declspec(dllexport)
590#endif
591 int ApplySXDG(void *sim, int qubit) {
592 if (!sim) return 0;
593 auto simulator = static_cast<Simulators::ISimulator *>(sim);
594 simulator->ApplySxDAG(qubit);
595
596 return 1;
597}
598
599#ifdef _WIN32
600__declspec(dllexport)
601#endif
602 int ApplyK(void *sim, int qubit) {
603 if (!sim) return 0;
604 auto simulator = static_cast<Simulators::ISimulator *>(sim);
605 simulator->ApplyK(qubit);
606
607 return 1;
608}
609
610#ifdef _WIN32
611__declspec(dllexport)
612#endif
613 int ApplyP(void *sim, int qubit, double theta) {
614 if (!sim) return 0;
615 auto simulator = static_cast<Simulators::ISimulator *>(sim);
616 simulator->ApplyP(qubit, theta);
617
618 return 1;
619}
620
621#ifdef _WIN32
622__declspec(dllexport)
623#endif
624 int ApplyRx(void *sim, int qubit, double theta) {
625 if (!sim) return 0;
626 auto simulator = static_cast<Simulators::ISimulator *>(sim);
627 simulator->ApplyRx(qubit, theta);
628
629 return 1;
630}
631
632#ifdef _WIN32
633__declspec(dllexport)
634#endif
635 int ApplyRy(void *sim, int qubit, double theta) {
636 if (!sim) return 0;
637 auto simulator = static_cast<Simulators::ISimulator *>(sim);
638 simulator->ApplyRy(qubit, theta);
639
640 return 1;
641}
642
643#ifdef _WIN32
644__declspec(dllexport)
645#endif
646 int ApplyRz(void *sim, int qubit, double theta) {
647 if (!sim) return 0;
648 auto simulator = static_cast<Simulators::ISimulator *>(sim);
649 simulator->ApplyRz(qubit, theta);
650
651 return 1;
652}
653
654#ifdef _WIN32
655__declspec(dllexport)
656#endif
657 int ApplyU(void *sim, int qubit, double theta, double phi, double lambda,
658 double gamma) {
659 if (!sim) return 0;
660 auto simulator = static_cast<Simulators::ISimulator *>(sim);
661 simulator->ApplyU(qubit, theta, phi, lambda, gamma);
662
663 return 1;
664}
665
666#ifdef _WIN32
667__declspec(dllexport)
668#endif
669 int ApplyCX(void *sim, int controlQubit, int targetQubit) {
670 if (!sim) return 0;
671 auto simulator = static_cast<Simulators::ISimulator *>(sim);
672 simulator->ApplyCX(controlQubit, targetQubit);
673
674 return 1;
675}
676
677#ifdef _WIN32
678__declspec(dllexport)
679#endif
680 int ApplyCY(void *sim, int controlQubit, int targetQubit) {
681 if (!sim) return 0;
682 auto simulator = static_cast<Simulators::ISimulator *>(sim);
683 simulator->ApplyCY(controlQubit, targetQubit);
684
685 return 1;
686}
687
688#ifdef _WIN32
689__declspec(dllexport)
690#endif
691 int ApplyCZ(void *sim, int controlQubit, int targetQubit) {
692 if (!sim) return 0;
693 auto simulator = static_cast<Simulators::ISimulator *>(sim);
694 simulator->ApplyCZ(controlQubit, targetQubit);
695
696 return 1;
697}
698
699#ifdef _WIN32
700__declspec(dllexport)
701#endif
702 int ApplyCH(void *sim, int controlQubit, int targetQubit) {
703 if (!sim) return 0;
704 auto simulator = static_cast<Simulators::ISimulator *>(sim);
705 simulator->ApplyCH(controlQubit, targetQubit);
706
707 return 1;
708}
709
710#ifdef _WIN32
711__declspec(dllexport)
712#endif
713 int ApplyCSX(void *sim, int controlQubit, int targetQubit) {
714 if (!sim) return 0;
715 auto simulator = static_cast<Simulators::ISimulator *>(sim);
716 simulator->ApplyCSx(controlQubit, targetQubit);
717
718 return 1;
719}
720
721#ifdef _WIN32
722__declspec(dllexport)
723#endif
724 int ApplyCSXDG(void *sim, int controlQubit, int targetQubit) {
725 if (!sim) return 0;
726 auto simulator = static_cast<Simulators::ISimulator *>(sim);
727 simulator->ApplyCSxDAG(controlQubit, targetQubit);
728
729 return 1;
730}
731
732#ifdef _WIN32
733__declspec(dllexport)
734#endif
735 int ApplyCP(void *sim, int controlQubit, int targetQubit, double theta) {
736 if (!sim) return 0;
737 auto simulator = static_cast<Simulators::ISimulator *>(sim);
738 simulator->ApplyCP(controlQubit, targetQubit, theta);
739
740 return 1;
741}
742
743#ifdef _WIN32
744__declspec(dllexport)
745#endif
746 int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta) {
747 if (!sim) return 0;
748 auto simulator = static_cast<Simulators::ISimulator *>(sim);
749 simulator->ApplyCRx(controlQubit, targetQubit, theta);
750
751 return 1;
752}
753
754#ifdef _WIN32
755__declspec(dllexport)
756#endif
757 int ApplyCRy(void *sim, int controlQubit, int targetQubit, double theta) {
758 if (!sim) return 0;
759 auto simulator = static_cast<Simulators::ISimulator *>(sim);
760 simulator->ApplyCRy(controlQubit, targetQubit, theta);
761
762 return 1;
763}
764
765#ifdef _WIN32
766__declspec(dllexport)
767#endif
768 int ApplyCRz(void *sim, int controlQubit, int targetQubit, double theta) {
769 if (!sim) return 0;
770 auto simulator = static_cast<Simulators::ISimulator *>(sim);
771 simulator->ApplyCRz(controlQubit, targetQubit, theta);
772
773 return 1;
774}
775
776#ifdef _WIN32
777__declspec(dllexport)
778#endif
779 int ApplyCCX(void *sim, int controlQubit1, int controlQubit2,
780 int targetQubit) {
781 if (!sim) return 0;
782 auto simulator = static_cast<Simulators::ISimulator *>(sim);
783 simulator->ApplyCCX(controlQubit1, controlQubit2, targetQubit);
784
785 return 1;
786}
787
788#ifdef _WIN32
789__declspec(dllexport)
790#endif
791 int ApplySwap(void *sim, int qubit1, int qubit2) {
792 if (!sim) return 0;
793 auto simulator = static_cast<Simulators::ISimulator *>(sim);
794 simulator->ApplySwap(qubit1, qubit2);
795
796 return 1;
797}
798
799#ifdef _WIN32
800__declspec(dllexport)
801#endif
802 int ApplyCSwap(void *sim, int controlQubit, int qubit1, int qubit2) {
803 if (!sim) return 0;
804 auto simulator = static_cast<Simulators::ISimulator *>(sim);
805 simulator->ApplyCSwap(controlQubit, qubit1, qubit2);
806
807 return 1;
808}
809
810#ifdef _WIN32
811__declspec(dllexport)
812#endif
813 int ApplyCU(void *sim, int controlQubit, int targetQubit, double theta,
814 double phi, double lambda, double gamma) {
815 if (!sim) return 0;
816 auto simulator = static_cast<Simulators::ISimulator *>(sim);
817 simulator->ApplyCU(controlQubit, targetQubit, theta, phi, lambda, gamma);
818
819 return 1;
820}
821
822#ifdef _WIN32
823__declspec(dllexport)
824#endif
825 int InitializeSimulator(void *sim) {
826 if (!sim) return 0;
827 auto simulator = static_cast<Simulators::ISimulator *>(sim);
828 simulator->Initialize();
829 return 1;
830}
831
832#ifdef _WIN32
833__declspec(dllexport)
834#endif
835 int ResetSimulator(void *sim) {
836 if (!sim) return 0;
837 auto simulator = static_cast<Simulators::ISimulator *>(sim);
838 simulator->Reset();
839 return 1;
840}
841
842#ifdef _WIN32
843__declspec(dllexport)
844#endif
845 int ConfigureSimulator(void *sim, const char *key, const char *value) {
846 if (!sim || !key || !value) return 0;
847 auto simulator = static_cast<Simulators::ISimulator *>(sim);
848 simulator->Configure(key, value);
849 return 1;
850}
851
852#ifdef _WIN32
853__declspec(dllexport)
854#endif
855 char *GetConfiguration(void *sim, const char *key) {
856 if (!sim || !key) return nullptr;
857 auto simulator = static_cast<Simulators::ISimulator *>(sim);
858 std::string value = simulator->GetConfiguration(key);
859 if (value.empty()) return nullptr;
860 // allocate memory for the result string and copy the configuration value into
861 // it
862 const size_t valueSize = value.length();
863 char *result = new char[valueSize + 1];
864 std::copy(value.c_str(), value.c_str() + valueSize, result);
865 result[valueSize] = 0; // ensure null-termination
866 return result;
867}
868
869#ifdef _WIN32
870__declspec(dllexport)
871#endif
872 unsigned long int AllocateQubits(void *sim, unsigned long int nrQubits) {
873 if (!sim || nrQubits == 0) return 0;
874 auto simulator = static_cast<Simulators::ISimulator *>(sim);
875 const size_t res = simulator->AllocateQubits(nrQubits);
876
877 return static_cast<unsigned long int>(res);
878}
879
880#ifdef _WIN32
881__declspec(dllexport)
882#endif
883 unsigned long int GetNumberOfQubits(void *sim) {
884 if (!sim) return 0;
885 auto simulator = static_cast<Simulators::ISimulator *>(sim);
886 const size_t res = simulator->GetNumberOfQubits();
887 return static_cast<unsigned long int>(res);
888}
889
890#ifdef _WIN32
891__declspec(dllexport)
892#endif
893 int ClearSimulator(void *sim) {
894 if (!sim) return 0;
895 auto simulator = static_cast<Simulators::ISimulator *>(sim);
896 simulator->Clear();
897 return 1;
898}
899
900#ifdef _WIN32
901__declspec(dllexport)
902#endif
903 unsigned long long int Measure(void *sim, const unsigned long int *qubits,
904 unsigned long int nrQubits) {
905 if (!sim || !qubits || nrQubits == 0) return 0;
906 auto simulator = static_cast<Simulators::ISimulator *>(sim);
907 Types::qubits_vector qubitVector(qubits, qubits + nrQubits);
908 const size_t res = simulator->Measure(qubitVector);
909 return static_cast<unsigned long long int>(res);
910}
911
912#ifdef _WIN32
913__declspec(dllexport)
914#endif
915 int ApplyReset(void *sim, const unsigned long int *qubits,
916 unsigned long int nrQubits) {
917 if (!sim || !qubits || nrQubits == 0) return 0;
918 auto simulator = static_cast<Simulators::ISimulator *>(sim);
919 Types::qubits_vector qubitVector(qubits, qubits + nrQubits);
920 simulator->ApplyReset(qubitVector);
921 return 1;
922}
923
924#ifdef _WIN32
925__declspec(dllexport)
926#endif
927 double Probability(void *sim, unsigned long long int outcome) {
928 if (!sim) return 0.0;
929 auto simulator = static_cast<Simulators::ISimulator *>(sim);
930 const double res = simulator->Probability(outcome);
931 return res;
932}
933
934#ifdef _WIN32
935__declspec(dllexport)
936#endif
937 void FreeDoubleVector(double *vec) {
938 if (vec) delete[] vec;
939}
940
941#ifdef _WIN32
942__declspec(dllexport)
943#endif
944 void FreeULLIVector(unsigned long long int *vec) {
945 if (vec) delete[] vec;
946}
947
948#ifdef _WIN32
949__declspec(dllexport)
950#endif
951 double *Amplitude(void *sim, unsigned long long int outcome) {
952 if (!sim) return nullptr;
953 auto simulator = static_cast<Simulators::ISimulator *>(sim);
954 const std::complex<double> amp = simulator->Amplitude(outcome);
955
956 double *result = new double[2];
957 result[0] = amp.real();
958 result[1] = amp.imag();
959 return result;
960}
961
962#ifdef _WIN32
963__declspec(dllexport)
964#endif
965 double *AllProbabilities(void *sim) {
966 if (!sim) return nullptr;
967 auto simulator = static_cast<Simulators::ISimulator *>(sim);
968 const auto probabilities = simulator->AllProbabilities();
969
970 double *result = new double[probabilities.size()];
971 std::copy(probabilities.begin(), probabilities.end(), result);
972 return result;
973}
974
975#ifdef _WIN32
976__declspec(dllexport)
977#endif
978 double *Probabilities(void *sim, const unsigned long long int *qubits,
979 unsigned long int nrQubits) {
980 if (!sim || !qubits || nrQubits == 0) return nullptr;
981 auto simulator = static_cast<Simulators::ISimulator *>(sim);
982 Types::qubits_vector qubitVector(qubits, qubits + nrQubits);
983 const auto probabilities = simulator->Probabilities(qubitVector);
984
985 double *result = new double[probabilities.size()];
986 std::copy(probabilities.begin(), probabilities.end(), result);
987 return result;
988}
989
990#ifdef _WIN32
991__declspec(dllexport)
992#endif
993 unsigned long long int *SampleCounts(void *sim,
994 const unsigned long long int *qubits,
995 unsigned long int nrQubits,
996 unsigned long int shots) {
997 if (!sim || !qubits || nrQubits == 0 || shots == 0) return nullptr;
998
999 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1000 Types::qubits_vector qubitVector(qubits, qubits + nrQubits);
1001 const auto counts = simulator->SampleCounts(qubitVector, shots);
1002
1003 unsigned long long int *result =
1004 new unsigned long long int[counts.size() * 2];
1005 size_t index = 0;
1006 for (const auto &count : counts) {
1007 result[index] = count.first; // outcome
1008 ++index;
1009 result[index] = count.second; // count
1010 ++index;
1011 }
1012 return result;
1013}
1014
1015#ifdef _WIN32
1016__declspec(dllexport)
1017#endif
1018 int GetSimulatorType(void *sim) {
1019 if (!sim) return -1;
1020 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1021 return static_cast<int>(simulator->GetType());
1022}
1023
1024#ifdef _WIN32
1025__declspec(dllexport)
1026#endif
1027 int GetSimulationType(void *sim) {
1028 if (!sim) return -1;
1029 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1030 return static_cast<int>(simulator->GetSimulationType());
1031}
1032
1033#ifdef _WIN32
1034__declspec(dllexport)
1035#endif
1036 int FlushSimulator(void *sim) {
1037 if (!sim) return 0;
1038 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1039 simulator->Flush();
1040 return 1;
1041}
1042
1043#ifdef _WIN32
1044__declspec(dllexport)
1045#endif
1047 if (!sim) return 0;
1048 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1049 simulator->SaveStateToInternalDestructive();
1050 return 1;
1051}
1052
1053#ifdef _WIN32
1054__declspec(dllexport)
1055#endif
1057 if (!sim) return 0;
1058 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1060 return 1;
1061}
1062
1063#ifdef _WIN32
1064__declspec(dllexport)
1065#endif
1066 int SaveState(void *sim) {
1067 if (!sim) return 0;
1068 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1069 simulator->SaveState();
1070 return 1;
1071}
1072
1073#ifdef _WIN32
1074__declspec(dllexport)
1075#endif
1076 int RestoreState(void *sim) {
1077 if (!sim) return 0;
1078 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1079 simulator->RestoreState();
1080 return 1;
1081}
1082
1083#ifdef _WIN32
1084__declspec(dllexport)
1085#endif
1086 int SetMultithreading(void *sim, int multithreading) {
1087 if (!sim) return 0;
1088 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1089 simulator->SetMultithreading(multithreading != 0);
1090 return 1;
1091}
1092
1093#ifdef _WIN32
1094__declspec(dllexport)
1095#endif
1096 int GetMultithreading(void *sim) {
1097 if (!sim) return 0;
1098 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1099 return simulator->GetMultithreading() ? 1 : 0;
1100}
1101
1102#ifdef _WIN32
1103__declspec(dllexport)
1104#endif
1105 int IsQcsim(void *sim) {
1106 if (!sim) return 0;
1107 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1108 return simulator->IsQcsim() ? 1 : 0;
1109}
1110
1111#ifdef _WIN32
1112__declspec(dllexport)
1113#endif
1114 unsigned long long int MeasureNoCollapse(void *sim) {
1115 if (!sim) return 0;
1116 auto simulator = static_cast<Simulators::ISimulator *>(sim);
1117 return static_cast<unsigned long long int>(simulator->MeasureNoCollapse());
1118}
1119}
int ApplyK(void *sim, int qubit)
double Probability(void *sim, unsigned long long int outcome)
char * GetConfiguration(void *sim, const char *key)
int InitializeSimulator(void *sim)
int RestoreState(void *sim)
void FreeDoubleVector(double *vec)
int ApplyRx(void *sim, int qubit, double theta)
int ApplyReset(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
int ApplyX(void *sim, int qubit)
int ApplyU(void *sim, int qubit, double theta, double phi, double lambda, double gamma)
int AddOptimizationSimulator(unsigned long int simHandle, int simType, int simExecType)
unsigned long int CreateSimulator(int simType, int simExecType)
int ApplyCRy(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyTDG(void *sim, int qubit)
int ApplyCSXDG(void *sim, int controlQubit, int targetQubit)
static std::atomic_bool isInitialized
Definition Interface.cpp:27
void FreeResult(char *result)
int ApplyS(void *sim, int qubit)
int ApplyCX(void *sim, int controlQubit, int targetQubit)
unsigned long int AllocateQubits(void *sim, unsigned long int nrQubits)
char * SimpleExecute(unsigned long int simpleSim, const char *circuitStr, const char *jsonConfig)
int ApplyCRz(void *sim, int controlQubit, int targetQubit, double theta)
unsigned long int GetNumberOfQubits(void *sim)
double * AllProbabilities(void *sim)
void * GetMaestroObjectWithMute()
Definition Interface.cpp:54
unsigned long long int MeasureNoCollapse(void *sim)
int ApplyCP(void *sim, int controlQubit, int targetQubit, double theta)
int ApplySXDG(void *sim, int qubit)
void * GetMaestroObject()
Definition Interface.cpp:34
int GetMultithreading(void *sim)
int ApplySDG(void *sim, int qubit)
unsigned long long int Measure(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
int ApplyCSwap(void *sim, int controlQubit, int qubit1, int qubit2)
void DestroySimpleSimulator(unsigned long int simHandle)
Definition Interface.cpp:82
int ApplyCCX(void *sim, int controlQubit1, int controlQubit2, int targetQubit)
int ApplyY(void *sim, int qubit)
double * Amplitude(void *sim, unsigned long long int outcome)
int ApplyZ(void *sim, int qubit)
int ApplyH(void *sim, int qubit)
int ApplyCY(void *sim, int controlQubit, int targetQubit)
char * SimpleEstimate(unsigned long int simpleSim, const char *circuitStr, const char *observableStr, const char *jsonConfig)
double * Probabilities(void *sim, const unsigned long long int *qubits, unsigned long int nrQubits)
int SetMultithreading(void *sim, int multithreading)
int ApplyCU(void *sim, int controlQubit, int targetQubit, double theta, double phi, double lambda, double gamma)
void DestroySimulator(unsigned long int simHandle)
int ApplySwap(void *sim, int qubit1, int qubit2)
void * GetSimulator(unsigned long int simHandle)
static std::unique_ptr< Maestro > maestroInstance
Definition Interface.cpp:28
int ApplyRy(void *sim, int qubit, double theta)
int ApplyP(void *sim, int qubit, double theta)
int SaveStateToInternalDestructive(void *sim)
int ApplyCH(void *sim, int controlQubit, int targetQubit)
int FlushSimulator(void *sim)
unsigned long int CreateSimpleSimulator(int nrQubits)
Definition Interface.cpp:73
int GetSimulationType(void *sim)
int ResetSimulator(void *sim)
unsigned long long int * SampleCounts(void *sim, const unsigned long long int *qubits, unsigned long int nrQubits, unsigned long int shots)
int ApplySX(void *sim, int qubit)
int ApplyCZ(void *sim, int controlQubit, int targetQubit)
int ApplyRz(void *sim, int qubit, double theta)
int GetSimulatorType(void *sim)
int RestoreInternalDestructiveSavedState(void *sim)
int ApplyT(void *sim, int qubit)
int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta)
int ConfigureSimulator(void *sim, const char *key, const char *value)
int ApplyCSX(void *sim, int controlQubit, int targetQubit)
int ClearSimulator(void *sim)
int IsQcsim(void *sim)
int RemoveAllOptimizationSimulatorsAndAdd(unsigned long int simHandle, int simType, int simExecType)
Definition Interface.cpp:91
void FreeULLIVector(unsigned long long int *vec)
int SaveState(void *sim)
static boost::json::value ParseString(const char *str)
Parses a string containing json.
Definition Json.h:39
std::shared_ptr< Circuits::Circuit< Time > > ParseCircuit(const char *str) const
Definition Json.h:46
static std::string GetConfigString(const std::string &config, const boost::json::value &jsonConfig)
Definition Json.h:76
Interface class for a quantum computing simulator.
Definition Simulator.h:33
virtual void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta)=0
Applies a CRz gate to the qubits.
virtual void ApplySDG(Types::qubit_t qubit)=0
Applies a S dagger gate to the qubit.
virtual void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1, Types::qubit_t qubit2)=0
Applies a controlled controlled not gate to the qubits.
virtual void ApplyX(Types::qubit_t qubit)=0
Applies a not gate to the qubit.
virtual void ApplyCSxDAG(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CSx dagger gate to the qubits.
virtual void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda, double gamma)=0
Applies a U gate to the qubit.
virtual void ApplyP(Types::qubit_t qubit, double lambda)=0
Applies a phase shift gate to the qubit.
virtual void ApplySx(Types::qubit_t qubit)=0
Applies a Sx gate to the qubit.
virtual void ApplyTDG(Types::qubit_t qubit)=0
Applies a T dagger gate to the qubit.
virtual void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta, double phi, double lambda, double gamma)=0
Applies a controlled U gate to the qubits.
virtual void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta)=0
Applies a CRy gate to the qubits.
virtual void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CX gate to the qubits.
virtual void ApplyRy(Types::qubit_t qubit, double theta)=0
Applies a Ry gate to the qubit.
virtual void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CH gate to the qubits.
virtual void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1)=0
Applies a swap gate to the qubits.
virtual void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CSx gate to the qubits.
virtual void ApplyK(Types::qubit_t qubit)=0
Applies a K gate to the qubit.
virtual void ApplyY(Types::qubit_t qubit)=0
Applies a Y gate to the qubit.
virtual void ApplyT(Types::qubit_t qubit)=0
Applies a T gate to the qubit.
virtual void ApplyS(Types::qubit_t qubit)=0
Applies a S gate to the qubit.
virtual void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0, Types::qubit_t qubit1)=0
Applies a controlled swap gate to the qubits.
virtual void ApplyZ(Types::qubit_t qubit)=0
Applies a Z gate to the qubit.
virtual void ApplyRz(Types::qubit_t qubit, double theta)=0
Applies a Rz gate to the qubit.
virtual void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta)=0
Applies a CRx gate to the qubits.
virtual void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CY gate to the qubits.
virtual void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CZ gate to the qubits.
virtual void ApplyH(Types::qubit_t qubit)=0
Applies a Hadamard gate to the qubit.
virtual void ApplyRx(Types::qubit_t qubit, double theta)=0
Applies a Rx gate to the qubit.
virtual void ApplySxDAG(Types::qubit_t qubit)=0
Applies a Sx dagger gate to the qubit.
virtual void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double lambda)=0
Applies a CP gate to the qubits.
virtual bool IsQcsim() const =0
Returns if the simulator is a qcsim simulator.
virtual void SaveStateToInternalDestructive()=0
Saves the state to internal storage.
virtual void RestoreState()=0
Restores the state from the internally saved state.
virtual void SaveState()=0
Saves the state to internal storage.
virtual double Probability(Types::qubit_t outcome)=0
Returns the probability of the specified outcome.
virtual void Initialize()=0
Initializes the state.
virtual size_t AllocateQubits(size_t num_qubits)=0
Allocates qubits.
virtual std::vector< double > AllProbabilities()=0
Returns the probabilities of all possible outcomes.
virtual void RestoreInternalDestructiveSavedState()=0
Restores the state from the internally saved state.
virtual void SetMultithreading(bool multithreading=true)=0
Enable/disable multithreading.
virtual std::complex< double > Amplitude(Types::qubit_t outcome)=0
Returns the amplitude of the specified state.
virtual size_t GetNumberOfQubits() const =0
Returns the number of qubits.
virtual void Flush()=0
Flushes the applied operations.
virtual void Configure(const char *key, const char *value)=0
Configures the state.
virtual void Clear()=0
Clears the state.
virtual bool GetMultithreading() const =0
Get the multithreading flag.
virtual void Reset()=0
Just resets the state to 0.
virtual std::string GetConfiguration(const char *key) const =0
Returns configuration value.
static bool InitQuestLibrary()
Definition Factory.cpp:81
bool Failed() const
Definition QasmCirc.h:61
std::shared_ptr< Circuits::Circuit< Time > > ParseAndTranslate(const std::string &qasmInputStr)
Definition QasmCirc.h:30
SimulationType
The type of simulation.
Definition State.h:85
@ kStatevector
statevector simulation type
@ kMatrixProductState
matrix product state simulation type
@ kStabilizer
Clifford gates simulation type.
@ kPauliPropagator
Pauli propagator simulation type.
@ kTensorNetwork
Tensor network simulation type.
SimulatorType
The type of simulator.
Definition State.h:68
@ kCompositeQCSim
composite qcsim simulator type
@ kQCSim
qcsim simulator type
@ kQiskitAer
qiskit aer simulator type
@ kQuestSim
quest simulator type
@ kCompositeQiskitAer
composite qiskit aer simulator type
@ kGpuSim
gpu simulator type
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:23