Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
GpuStatevectorSimulator.h
Go to the documentation of this file.
1#pragma once
2#if defined(INCLUDED_BY_FACTORY) && defined(__linux__)
3#include "../Core/Factory.h"
5
7{
8// statevector backend. Owns exactly one native Gpu implementation.
9class GpuStatevectorSimulator : public ImmediateGpuSimulator
10{
11 public:
12 GpuStatevectorSimulator()
13 {
14 configuration.SetConfiguration("method", "statevector");
15 }
16
17 const char *MethodName() const override
18 {
19 return "statevector";
20 }
21
22 void Initialize() override
23 {
24 if (nrQubits)
25 {
26 auto initializationLock = GpuLibrary::GetInstance()->LockInitialization();
27 const int gpuDevice = configuration.IsSet("gpu_device") ? Configuration::ParseGpuDevice(configuration.GetConfiguration("gpu_device"))
28 : SimulatorsFactory::ResolveGpuDevice();
29 configuration.SetConfiguration("gpu_device", std::to_string(gpuDevice));
30 if (!SimulatorsFactory::GetGpuLibrary(gpuDevice))
31 throw std::runtime_error("GpuState::Initialize: Unable to initialize GPU device " + std::to_string(gpuDevice));
32 {
33 state = SimulatorsFactory::CreateGpuLibStateVectorSim(gpuDevice);
34 if (state)
35 {
36 for (const auto &[key, value] : configuration.GetConfigMap())
37 if (key != "method")
38 Configure(key.c_str(), value.c_str());
39 const bool res = state->Create(nrQubits);
40 if (!res)
41 throw std::runtime_error("GpuState::Initialize: Failed to create "
42 "and initialize the statevector state.");
43 }
44 else
45 throw std::runtime_error("GpuState::Initialize: Failed to create the statevector state.");
46 }
47 if (GetGpuDevice() != gpuDevice)
48 throw std::runtime_error("GpuState::Initialize: GPU plugin did not confirm the requested "
49 "device; update the GPU library");
50 }
51 }
52
53 void InitializeState(size_t num_qubits, std::vector<std::complex<double>> &amplitudes) override
54 {
55 if (num_qubits == 0)
56 return;
57 Clear();
58 nrQubits = num_qubits;
59 Initialize();
60 const bool created = state->CreateWithState(nrQubits, reinterpret_cast<const double *>(amplitudes.data()));
61 if (!created)
62 throw std::runtime_error("GpuState::InitializeState: Failed to initialize the state.");
63 }
64
65#ifndef NO_QISKIT_AER
66 void InitializeState(size_t num_qubits, AER::Vector<std::complex<double>> &amplitudes) override
67 {
68 if (num_qubits == 0)
69 return;
70 Clear();
71 nrQubits = num_qubits;
72 Initialize();
73 const bool created = state->CreateWithState(nrQubits, reinterpret_cast<const double *>(amplitudes.data()));
74 if (!created)
75 throw std::runtime_error("GpuState::InitializeState: Failed to initialize the state.");
76 }
77
78#endif
79
80 void InitializeState(size_t num_qubits, Eigen::VectorXcd &amplitudes) override
81 {
82 if (num_qubits == 0)
83 return;
84 Clear();
85 nrQubits = num_qubits;
86 Initialize();
87 const bool created = state->CreateWithState(nrQubits, reinterpret_cast<const double *>(amplitudes.data()));
88 if (!created)
89 throw std::runtime_error("GpuState::InitializeState: Failed to initialize the state.");
90 }
91
92 void Reset() override
93 {
94 if (state)
95 state->Reset();
96 upcomingGateIndex = 0;
97 }
98
99 void Configure(const char *key, const char *value) override
100 {
101 if (!key || !value)
102 return;
103 if (std::string("gpu_device") == key)
104 {
105 const int device = Configuration::ParseGpuDevice(value);
106 if ((state) && device != Configuration::ParseGpuDevice(configuration.GetConfiguration(key)))
107 throw std::invalid_argument("gpu_device cannot change after initialization; clear the "
108 "simulator first");
109 configuration.SetConfiguration(key, std::to_string(device));
110 return;
111 }
112 const auto svdGroup = Configuration::GpuSvdSettingGroup(key);
113 if (!svdGroup.empty())
114 {
115 Configuration::ParseGpuSvdFlag(value);
116 configuration.SetConfiguration(key, value);
117 return;
118 }
119 if (std::string("method") == key)
120 {
121 ValidateMethod(value);
122 configuration.SetConfiguration(key, value);
123 return;
124 }
125 if (std::string(key) == "precision" || std::string(key) == "use_double_precision")
126 {
127 // Precision is immutable after native storage is allocated.
128 // Replayed settings take effect after Clear and Initialize.
129 const bool useDouble = Configuration::ParsePrecision(key, value);
130 if ((state && state->GetNrQubits() > 0))
131 return;
132 if ((state && !state->SetDataType(useDouble)))
133 throw std::runtime_error("GPU precision configuration failed");
134 configuration.SetConfiguration(key, value);
135 return;
136 }
137 if (!configuration.WasApplied(key, value))
138 configuration.SetConfiguration(key, value);
139 if (std::string("seed") == key)
140 {
141 const uint64_t seed = std::stoull(value);
142 SeedAuxiliaryRng(seed);
143 nextSeedStream = 0;
144 if (state)
145 state->SetSeed(seed);
146 return;
147 }
148 // Configuration can be replayed from another method. Preserve the
149 // numeric validation, but tensor truncation has no native effect here.
150 if (std::string("matrix_product_state_truncation_threshold") == key || std::string("matrix_product_operator_truncation_threshold") == key)
151 std::stod(value);
152 else if (std::string("matrix_product_state_max_bond_dimension") == key || std::string("matrix_product_operator_max_bond_dimension") == key)
153 std::stoi(value);
154 }
155
156 std::string GetConfiguration(const char *key) const override
157 {
158 if (!key)
159 return {};
160 if (std::string(key) == "precision" || std::string(key) == "use_double_precision")
161 {
162 const bool useDouble = state ? state->IsDoublePrecision() : configuration.GetConfiguration("precision") == "double";
163 return std::string(key) == "precision" ? (useDouble ? "double" : "single") : (useDouble ? "1" : "0");
164 }
165 if (!key)
166 return {};
167 if (std::string("method") == key)
168 return MethodName();
169 return configuration.GetConfiguration(key);
170 }
171
172 size_t AllocateQubits(size_t num_qubits) override
173 {
174 if (state)
175 return 0;
176 const size_t oldNrQubits = nrQubits;
177 nrQubits += num_qubits;
178 return oldNrQubits;
179 }
180
181 void Clear() override
182 {
183 state = nullptr;
184 nrQubits = 0;
185 upcomingGateIndex = 0;
186 upcomingGates.clear();
187 }
188
189 size_t Measure(const Types::qubits_vector &qubits) override
190 {
191 if (qubits.size() > sizeof(size_t) * 8)
192 std::cerr << "Warning: The number of qubits to measure is larger than the "
193 "number of bits in the size_t type, the outcome will be undefined"
194 << std::endl;
195 size_t res = 0;
196 size_t mask = 1ULL;
197 DontNotify();
198 {
199 for (size_t qubit : qubits)
200 {
201 if (state->MeasureQubitCollapse(static_cast<int>(qubit)))
202 res |= mask;
203 mask <<= 1;
204 }
205 }
206 Notify();
207 NotifyObservers(qubits);
208 return res;
209 }
210
211 std::vector<bool> MeasureMany(const Types::qubits_vector &qubits) override
212 {
213 std::vector<bool> res(qubits.size(), false);
214 DontNotify();
215 {
216 for (size_t i = 0; i < qubits.size(); ++i)
217 res[i] = state->MeasureQubitCollapse(static_cast<int>(qubits[i]));
218 }
219 Notify();
220 NotifyObservers(qubits);
221 return res;
222 }
223
224 void ApplyReset(const Types::qubits_vector &qubits) override
225 {
226 DontNotify();
227 {
228 for (size_t qubit : qubits)
229 if (state->MeasureQubitCollapse(static_cast<int>(qubit)))
230 state->ApplyX(static_cast<int>(qubit));
231 }
232 Notify();
233 NotifyObservers(qubits);
234 }
235
236 double Probability(Types::qubit_t outcome) override
237 {
238 return state->BasisStateProbability(outcome);
239 }
240
241 std::complex<double> Amplitude(Types::qubit_t outcome) override
242 {
243 double real = 0.0;
244 double imag = 0.0;
245 state->Amplitude(outcome, &real, &imag);
246 return std::complex<double>(real, imag);
247 }
248
249 std::vector<double> AllProbabilities() override
250 {
251 if (nrQubits == 0)
252 return {};
253 if (nrQubits >= std::numeric_limits<size_t>::digits)
254 throw std::length_error("Full probability enumeration exceeds the basis-index API; query "
255 "selected bit vectors");
256 const size_t numStates = size_t{1} << nrQubits;
257 std::vector<double> result(numStates);
258 state->AllProbabilities(result.data());
259 return result;
260 }
261
262 std::vector<double> Probabilities(const Types::qubits_vector &qubits) override
263 {
264 std::vector<double> result(qubits.size());
265 {
266 for (size_t i = 0; i < qubits.size(); ++i)
267 result[i] = state->BasisStateProbability(qubits[i]);
268 }
269 return result;
270 }
271
272 std::unordered_map<Types::qubit_t, Types::qubit_t> SampleCounts(const Types::qubits_vector &qubits, size_t shots = 1000) override
273 {
274 if (qubits.empty() || shots == 0)
275 return {};
276 if (qubits.size() > sizeof(Types::qubit_t) * 8)
277 std::cerr << "Warning: The number of qubits to measure is larger than the "
278 "number of bits in the Types::qubit_t type, the outcome will be "
279 "undefined"
280 << std::endl;
281 std::unordered_map<Types::qubit_t, Types::qubit_t> result;
282 DontNotify();
283 {
284 std::vector<long int> samples(shots);
285 state->SampleAll(shots, samples.data());
286 for (auto outcome : samples)
287 {
288 Types::qubit_t translatedOutcome = 0;
289 Types::qubit_t mask = 1ULL;
290 for (size_t i = 0; i < qubits.size(); ++i)
291 {
292 if (outcome & (1ULL << qubits[i]))
293 translatedOutcome |= mask;
294 mask <<= 1;
295 }
296 ++result[translatedOutcome];
297 }
298 }
299 Notify();
300 NotifyObservers(qubits);
301 return result;
302 }
303
304 std::unordered_map<std::vector<bool>, Types::qubit_t> SampleCountsMany(const Types::qubits_vector &qubits, size_t shots = 1000) override
305 {
306 if (qubits.empty() || shots == 0)
307 return {};
308 std::unordered_map<std::vector<bool>, Types::qubit_t> result;
309 DontNotify();
310 {
311 std::vector<long int> samples(shots);
312 state->SampleAll(shots, samples.data());
313 std::vector<bool> outcomeVec(qubits.size());
314 for (auto outcome : samples)
315 {
316 for (size_t i = 0; i < qubits.size(); ++i)
317 outcomeVec[i] = ((outcome >> qubits[i]) & 1) == 1;
318 ++result[outcomeVec];
319 }
320 }
321 Notify();
322 NotifyObservers(qubits);
323 return result;
324 }
325
326 double ExpectationValue(const std::string &pauliString) override
327 {
328 double result = 0.0;
329 result = state->ExpectationValue(pauliString);
330 return result;
331 }
332
333 int GetGpuDevice() const override
334 {
335 if (state)
336 return state->GetGpuDevice();
337 return -1;
338 }
339
340 SimulationType GetSimulationType() const override
341 {
342 return SimulationType::kStatevector;
343 }
344
345 void Flush() override
346 {
347 const bool done = state ? state->Synchronize() : true;
348 if (!done)
349 throw std::runtime_error("GpuState::Flush: device synchronization failed");
350 }
351
352 void SaveStateToInternalDestructive() override
353 {
354 state->SaveStateDestructive();
355 }
356
358 {
359 state->RestoreStateFreeSaved();
360 }
361
362 void SaveState() override
363 {
364 state->SaveState();
365 }
366
367 void RestoreState() override
368 {
369 state->RestoreStateNoFreeSaved();
370 }
371
373 {
374 return state->MeasureAllQubitsNoCollapse();
375 }
376
377 std::vector<bool> MeasureNoCollapseMany() override
378 {
379 const auto meas = state->MeasureAllQubitsNoCollapse();
380 std::vector<bool> result(nrQubits, false);
381 for (size_t i = 0; i < nrQubits; ++i)
382 result[i] = ((meas >> i) & 1) == 1;
383 return result;
384 }
385
386 void ApplyGenericOneQubitGate(Types::qubit_t qubit, const Eigen::Matrix2cd &gate) override
387 {
388 ValidateStatevectorTarget(qubit);
389 if (!state->ApplyOneQubitMatrixWithLayout(static_cast<int>(qubit), reinterpret_cast<const double *>(gate.data()), GpuLibrary::MATRIX_COLUMN_MAJOR))
390 throw std::runtime_error("GPU statevector failed to apply one-qubit matrix");
391 NotifyObservers({qubit});
392 return;
393 }
394
395 void ApplyGenericTwoQubitGate(Types::qubit_t qubit0, Types::qubit_t qubit1, const Eigen::Matrix4cd &gate) override
396 {
397 ValidateStatevectorTarget(qubit0);
398 ValidateStatevectorTarget(qubit1);
399 if (!state->ApplyTwoQubitMatrixWithLayout(static_cast<int>(qubit0), static_cast<int>(qubit1), reinterpret_cast<const double *>(gate.data()),
400 GpuLibrary::MATRIX_COLUMN_MAJOR))
401 throw std::runtime_error("GPU statevector failed to apply two-qubit matrix");
402 NotifyObservers({qubit0, qubit1});
403 return;
404 }
405
407 const Eigen::Matrix<std::complex<double>, 8, 8> &gate) override
408 {
409 ValidateStatevectorTarget(qubit0);
410 ValidateStatevectorTarget(qubit1);
411 ValidateStatevectorTarget(qubit2);
412 if (!state->ApplyThreeQubitMatrixWithLayout(static_cast<int>(qubit0), static_cast<int>(qubit1), static_cast<int>(qubit2),
413 reinterpret_cast<const double *>(gate.data()), GpuLibrary::MATRIX_COLUMN_MAJOR))
414 throw std::runtime_error("GPU statevector failed to apply three-qubit matrix");
415 NotifyObservers({qubit0, qubit1, qubit2});
416 }
417
418 void ApplyP(Types::qubit_t qubit, double lambda) override
419 {
420 state->ApplyP(qubit, lambda);
421 NotifyObservers({qubit});
422 }
423
424 void ApplyX(Types::qubit_t qubit) override
425 {
426 state->ApplyX(qubit);
427 NotifyObservers({qubit});
428 }
429
430 void ApplyY(Types::qubit_t qubit) override
431 {
432 state->ApplyY(qubit);
433 NotifyObservers({qubit});
434 }
435
436 void ApplyZ(Types::qubit_t qubit) override
437 {
438 state->ApplyZ(qubit);
439 NotifyObservers({qubit});
440 }
441
442 void ApplyH(Types::qubit_t qubit) override
443 {
444 state->ApplyH(qubit);
445 NotifyObservers({qubit});
446 }
447
448 void ApplyS(Types::qubit_t qubit) override
449 {
450 state->ApplyS(qubit);
451 NotifyObservers({qubit});
452 }
453
454 void ApplySDG(Types::qubit_t qubit) override
455 {
456 state->ApplySDG(qubit);
457 NotifyObservers({qubit});
458 }
459
460 void ApplyT(Types::qubit_t qubit) override
461 {
462 state->ApplyT(qubit);
463 NotifyObservers({qubit});
464 }
465
466 void ApplyTDG(Types::qubit_t qubit) override
467 {
468 state->ApplyTDG(qubit);
469 NotifyObservers({qubit});
470 }
471
472 void ApplySx(Types::qubit_t qubit) override
473 {
474 state->ApplySX(qubit);
475 NotifyObservers({qubit});
476 }
477
478 void ApplySxDAG(Types::qubit_t qubit) override
479 {
480 state->ApplySXDG(qubit);
481 NotifyObservers({qubit});
482 }
483
484 void ApplyK(Types::qubit_t qubit) override
485 {
486 state->ApplyK(qubit);
487 NotifyObservers({qubit});
488 }
489
490 void ApplyRx(Types::qubit_t qubit, double theta) override
491 {
492 state->ApplyRx(qubit, theta);
493 NotifyObservers({qubit});
494 }
495
496 void ApplyRy(Types::qubit_t qubit, double theta) override
497 {
498 state->ApplyRy(qubit, theta);
499 NotifyObservers({qubit});
500 }
501
502 void ApplyRz(Types::qubit_t qubit, double theta) override
503 {
504 state->ApplyRz(qubit, theta);
505 NotifyObservers({qubit});
506 }
507
508 void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda, double gamma) override
509 {
510 state->ApplyU(qubit, theta, phi, lambda, gamma);
511 NotifyObservers({qubit});
512 }
513
514 void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override
515 {
516 state->ApplyCX(ctrl_qubit, tgt_qubit);
517 NotifyObservers({tgt_qubit, ctrl_qubit});
518 }
519
520 void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override
521 {
522 state->ApplyCY(ctrl_qubit, tgt_qubit);
523 NotifyObservers({tgt_qubit, ctrl_qubit});
524 }
525
526 void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override
527 {
528 state->ApplyCZ(ctrl_qubit, tgt_qubit);
529 NotifyObservers({tgt_qubit, ctrl_qubit});
530 }
531
532 void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double lambda) override
533 {
534 state->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
535 NotifyObservers({tgt_qubit, ctrl_qubit});
536 }
537
538 void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta) override
539 {
540 state->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
541 NotifyObservers({tgt_qubit, ctrl_qubit});
542 }
543
544 void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta) override
545 {
546 state->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
547 NotifyObservers({tgt_qubit, ctrl_qubit});
548 }
549
550 void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta) override
551 {
552 state->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
553 NotifyObservers({tgt_qubit, ctrl_qubit});
554 }
555
556 void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override
557 {
558 state->ApplyCH(ctrl_qubit, tgt_qubit);
559 NotifyObservers({tgt_qubit, ctrl_qubit});
560 }
561
562 void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override
563 {
564 state->ApplyCSX(ctrl_qubit, tgt_qubit);
565 NotifyObservers({tgt_qubit, ctrl_qubit});
566 }
567
568 void ApplyCSxDAG(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override
569 {
570 state->ApplyCSXDG(ctrl_qubit, tgt_qubit);
571 NotifyObservers({tgt_qubit, ctrl_qubit});
572 }
573
574 void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1) override
575 {
576 state->ApplySwap(qubit0, qubit1);
577 NotifyObservers({qubit1, qubit0});
578 }
579
580 void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1, Types::qubit_t qubit2) override
581 {
582 state->ApplyCCX(qubit0, qubit1, qubit2);
583 NotifyObservers({qubit0, qubit1, qubit2});
584 }
585
586 void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0, Types::qubit_t qubit1) override
587 {
588 state->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
589 NotifyObservers({qubit1, qubit0, ctrl_qubit});
590 }
591
592 void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta, double phi, double lambda, double gamma) override
593 {
594 state->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
595 NotifyObservers({tgt_qubit, ctrl_qubit});
596 }
597
598 std::unique_ptr<ISimulator> Clone() override
599 {
600 auto cloned = std::make_unique<GpuStatevectorSimulator>();
601 cloned->nrQubits = nrQubits;
602 cloned->upcomingGates = upcomingGates;
603 cloned->upcomingGateIndex = upcomingGateIndex;
604 cloned->configuration = configuration;
605 if (state)
606 cloned->state = state->Clone();
607 if (configuration.IsSet("seed"))
608 cloned->SetSeed(DeriveSeed(std::stoull(configuration.GetConfiguration("seed")), nextSeedStream++));
609 return cloned;
610 }
611
612 protected:
613 std::unique_ptr<GpuLibStateVectorSim> state;
614
615 private:
616 void ValidateStatevectorTarget(Types::qubit_t qubit) const
617 {
618 if (!state)
619 throw std::logic_error("GPU statevector is not initialized");
620 if (qubit >= GetNumberOfQubits())
621 throw std::out_of_range("GPU statevector qubit is out of range");
622 }
623};
624} // namespace Simulators::Private
625#endif
int ApplyK(void *sim, int qubit)
double Probability(void *sim, unsigned long long int outcome)
char * GetConfiguration(void *sim, const char *key)
int RestoreState(void *sim)
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 ApplyCRy(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyTDG(void *sim, int qubit)
int ApplyS(void *sim, int qubit)
int ApplyCX(void *sim, int controlQubit, int targetQubit)
unsigned long int AllocateQubits(void *sim, unsigned long int nrQubits)
int ApplyCRz(void *sim, int controlQubit, int targetQubit, double theta)
unsigned long int GetNumberOfQubits(void *sim)
double * AllProbabilities(void *sim)
unsigned long long int MeasureNoCollapse(void *sim)
int ApplyCP(void *sim, int controlQubit, int targetQubit, double theta)
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)
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 ApplyGenericThreeQubitGate(void *sim, unsigned long q0, unsigned long q1, unsigned long q2, const double *buffer)
int ApplyCY(void *sim, int controlQubit, int targetQubit)
double * Probabilities(void *sim, const unsigned long long int *qubits, unsigned long int nrQubits)
int ApplyCU(void *sim, int controlQubit, int targetQubit, double theta, double phi, double lambda, double gamma)
int ApplySwap(void *sim, int qubit1, int qubit2)
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 GetSimulationType(void *sim)
unsigned long long int * SampleCounts(void *sim, const unsigned long long int *qubits, unsigned long int nrQubits, unsigned long int shots)
int ApplyCZ(void *sim, int controlQubit, int targetQubit)
int ApplyRz(void *sim, int qubit, double theta)
int RestoreInternalDestructiveSavedState(void *sim)
int ApplyT(void *sim, int qubit)
int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyGenericOneQubitGate(void *sim, unsigned long q0, const double *buffer)
int ApplyGenericTwoQubitGate(void *sim, unsigned long q0, unsigned long q1, const double *buffer)
int SaveState(void *sim)
SimulationType
The type of simulation.
Definition State.h:109
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:24
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:23