Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
GpuSimulator.h
Go to the documentation of this file.
1
12
13#pragma once
14
15#ifndef _GPUSIMULATOR_H
16#define _GPUSIMULATOR_H
17
18#ifdef INCLUDED_BY_FACTORY
19
20#ifdef __linux__
21
22#include "GpuState.h"
23
24namespace Simulators {
25// TODO: Maybe use the pimpl idiom
26// https://en.cppreference.com/w/cpp/language/pimpl to hide the implementation
27// for good but during development this should be good enough
28namespace Private {
29
41class GpuSimulator : public GpuState {
42public:
43 GpuSimulator() = default;
44 // allow no copy or assignment
45 GpuSimulator(const GpuSimulator &) = delete;
46 GpuSimulator &operator=(const GpuSimulator &) = delete;
47
48 // but allow moving
49 GpuSimulator(GpuSimulator &&other) = default;
50 GpuSimulator &operator=(GpuSimulator &&other) = default;
51
59 void ApplyP(Types::qubit_t qubit, double lambda) override {
60 if (GetSimulationType() == SimulationType::kStatevector)
61 state->ApplyP(qubit, lambda);
62 else if (GetSimulationType() == SimulationType::kMatrixProductState)
63 mps->ApplyP(qubit, lambda);
64
65 NotifyObservers({qubit});
66 }
67
74 void ApplyX(Types::qubit_t qubit) override {
75 if (GetSimulationType() == SimulationType::kStatevector)
76 state->ApplyX(qubit);
77 else if (GetSimulationType() == SimulationType::kMatrixProductState)
78 mps->ApplyX(qubit);
79
80 NotifyObservers({qubit});
81 }
82
89 void ApplyY(Types::qubit_t qubit) override {
90 if (GetSimulationType() == SimulationType::kStatevector)
91 state->ApplyY(qubit);
92 else if (GetSimulationType() == SimulationType::kMatrixProductState)
93 mps->ApplyY(qubit);
94
95 NotifyObservers({qubit});
96 }
97
104 void ApplyZ(Types::qubit_t qubit) override {
105 if (GetSimulationType() == SimulationType::kStatevector)
106 state->ApplyZ(qubit);
107 else if (GetSimulationType() == SimulationType::kMatrixProductState)
108 mps->ApplyZ(qubit);
109
110 NotifyObservers({qubit});
111 }
112
119 void ApplyH(Types::qubit_t qubit) override {
120 if (GetSimulationType() == SimulationType::kStatevector)
121 state->ApplyH(qubit);
122 else if (GetSimulationType() == SimulationType::kMatrixProductState)
123 mps->ApplyH(qubit);
124
125 NotifyObservers({qubit});
126 }
127
134 void ApplyS(Types::qubit_t qubit) override {
135 if (GetSimulationType() == SimulationType::kStatevector)
136 state->ApplyS(qubit);
137 else if (GetSimulationType() == SimulationType::kMatrixProductState)
138 mps->ApplyS(qubit);
139
140 NotifyObservers({qubit});
141 }
142
149 void ApplySDG(Types::qubit_t qubit) override {
150 if (GetSimulationType() == SimulationType::kStatevector)
151 state->ApplySDG(qubit);
152 else if (GetSimulationType() == SimulationType::kMatrixProductState)
153 mps->ApplySDG(qubit);
154
155 NotifyObservers({qubit});
156 }
157
164 void ApplyT(Types::qubit_t qubit) override {
165 if (GetSimulationType() == SimulationType::kStatevector)
166 state->ApplyT(qubit);
167 else if (GetSimulationType() == SimulationType::kMatrixProductState)
168 mps->ApplyT(qubit);
169
170 NotifyObservers({qubit});
171 }
172
179 void ApplyTDG(Types::qubit_t qubit) override {
180 if (GetSimulationType() == SimulationType::kStatevector)
181 state->ApplyTDG(qubit);
182 else if (GetSimulationType() == SimulationType::kMatrixProductState)
183 mps->ApplyTDG(qubit);
184
185 NotifyObservers({qubit});
186 }
187
194 void ApplySx(Types::qubit_t qubit) override {
195 if (GetSimulationType() == SimulationType::kStatevector)
196 state->ApplySX(qubit);
197 else if (GetSimulationType() == SimulationType::kMatrixProductState)
198 mps->ApplySX(qubit);
199
200 NotifyObservers({qubit});
201 }
202
209 void ApplySxDAG(Types::qubit_t qubit) override {
210 if (GetSimulationType() == SimulationType::kStatevector)
211 state->ApplySXDG(qubit);
212 else if (GetSimulationType() == SimulationType::kMatrixProductState)
213 mps->ApplySXDG(qubit);
214
215 NotifyObservers({qubit});
216 }
217
224 void ApplyK(Types::qubit_t qubit) override {
225 if (GetSimulationType() == SimulationType::kStatevector)
226 state->ApplyK(qubit);
227 else if (GetSimulationType() == SimulationType::kMatrixProductState)
228 mps->ApplyK(qubit);
229
230 NotifyObservers({qubit});
231 }
232
240 void ApplyRx(Types::qubit_t qubit, double theta) override {
241 if (GetSimulationType() == SimulationType::kStatevector)
242 state->ApplyRx(qubit, theta);
243 else if (GetSimulationType() == SimulationType::kMatrixProductState)
244 mps->ApplyRx(qubit, theta);
245
246 NotifyObservers({qubit});
247 }
248
256 void ApplyRy(Types::qubit_t qubit, double theta) override {
257 if (GetSimulationType() == SimulationType::kStatevector)
258 state->ApplyRy(qubit, theta);
259 else if (GetSimulationType() == SimulationType::kMatrixProductState)
260 mps->ApplyRy(qubit, theta);
261
262 NotifyObservers({qubit});
263 }
264
272 void ApplyRz(Types::qubit_t qubit, double theta) override {
273 if (GetSimulationType() == SimulationType::kStatevector)
274 state->ApplyRz(qubit, theta);
275 else if (GetSimulationType() == SimulationType::kMatrixProductState)
276 mps->ApplyRz(qubit, theta);
277
278 NotifyObservers({qubit});
279 }
280
288 void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda,
289 double gamma) override {
290 if (GetSimulationType() == SimulationType::kStatevector)
291 state->ApplyU(qubit, theta, phi, lambda, gamma);
292 else if (GetSimulationType() == SimulationType::kMatrixProductState)
293 mps->ApplyU(qubit, theta, phi, lambda, gamma);
294
295 NotifyObservers({qubit});
296 }
297
305 void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
306 if (GetSimulationType() == SimulationType::kStatevector)
307 state->ApplyCX(ctrl_qubit, tgt_qubit);
308 else if (GetSimulationType() == SimulationType::kMatrixProductState)
309 mps->ApplyCX(ctrl_qubit, tgt_qubit);
310
311 NotifyObservers({tgt_qubit, ctrl_qubit});
312 }
313
321 void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
322 if (GetSimulationType() == SimulationType::kStatevector)
323 state->ApplyCY(ctrl_qubit, tgt_qubit);
324 else if (GetSimulationType() == SimulationType::kMatrixProductState)
325 mps->ApplyCY(ctrl_qubit, tgt_qubit);
326
327 NotifyObservers({tgt_qubit, ctrl_qubit});
328 }
329
337 void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
338 if (GetSimulationType() == SimulationType::kStatevector)
339 state->ApplyCZ(ctrl_qubit, tgt_qubit);
340 else if (GetSimulationType() == SimulationType::kMatrixProductState)
341 mps->ApplyCZ(ctrl_qubit, tgt_qubit);
342
343 NotifyObservers({tgt_qubit, ctrl_qubit});
344 }
345
354 void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
355 double lambda) override {
356 if (GetSimulationType() == SimulationType::kStatevector)
357 state->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
358 else if (GetSimulationType() == SimulationType::kMatrixProductState)
359 mps->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
360
361 NotifyObservers({tgt_qubit, ctrl_qubit});
362 }
363
372 void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
373 double theta) override {
374 if (GetSimulationType() == SimulationType::kStatevector)
375 state->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
376 else if (GetSimulationType() == SimulationType::kMatrixProductState)
377 mps->ApplyCRx(ctrl_qubit, tgt_qubit, theta);
378
379 NotifyObservers({tgt_qubit, ctrl_qubit});
380 }
381
390 void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
391 double theta) override {
392 if (GetSimulationType() == SimulationType::kStatevector)
393 state->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
394 else if (GetSimulationType() == SimulationType::kMatrixProductState)
395 mps->ApplyCRy(ctrl_qubit, tgt_qubit, theta);
396
397 NotifyObservers({tgt_qubit, ctrl_qubit});
398 }
399
408 void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
409 double theta) override {
410 if (GetSimulationType() == SimulationType::kStatevector)
411 state->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
412 else if (GetSimulationType() == SimulationType::kMatrixProductState)
413 mps->ApplyCRz(ctrl_qubit, tgt_qubit, theta);
414
415 NotifyObservers({tgt_qubit, ctrl_qubit});
416 }
417
425 void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
426 if (GetSimulationType() == SimulationType::kStatevector)
427 state->ApplyCH(ctrl_qubit, tgt_qubit);
428 else if (GetSimulationType() == SimulationType::kMatrixProductState)
429 mps->ApplyCH(ctrl_qubit, tgt_qubit);
430
431 NotifyObservers({tgt_qubit, ctrl_qubit});
432 }
433
441 void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
442 if (GetSimulationType() == SimulationType::kStatevector)
443 state->ApplyCSX(ctrl_qubit, tgt_qubit);
444 else if (GetSimulationType() == SimulationType::kMatrixProductState)
445 mps->ApplyCSX(ctrl_qubit, tgt_qubit);
446
447 NotifyObservers({tgt_qubit, ctrl_qubit});
448 }
449
457 void ApplyCSxDAG(Types::qubit_t ctrl_qubit,
458 Types::qubit_t tgt_qubit) override {
459 if (GetSimulationType() == SimulationType::kStatevector)
460 state->ApplyCSXDG(ctrl_qubit, tgt_qubit);
461 else if (GetSimulationType() == SimulationType::kMatrixProductState)
462 mps->ApplyCSXDG(ctrl_qubit, tgt_qubit);
463
464 NotifyObservers({tgt_qubit, ctrl_qubit});
465 }
466
474 void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1) override {
475 if (GetSimulationType() == SimulationType::kStatevector)
476 state->ApplySwap(qubit0, qubit1);
477 else if (GetSimulationType() == SimulationType::kMatrixProductState)
478 mps->ApplySwap(qubit0, qubit1);
479
480 NotifyObservers({qubit1, qubit0});
481 }
482
491 void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1,
492 Types::qubit_t qubit2) override {
493 if (GetSimulationType() == SimulationType::kStatevector)
494 state->ApplyCCX(qubit0, qubit1, qubit2);
495 else if (GetSimulationType() == SimulationType::kMatrixProductState) {
496 const size_t q1 = qubit0; // control 1
497 const size_t q2 = qubit1; // control 2
498 const size_t q3 = qubit2; // target
499
500 // Sleator-Weinfurter decomposition
501 mps->ApplyCSX(static_cast<unsigned int>(q2),
502 static_cast<unsigned int>(q3));
503 mps->ApplyCX(static_cast<unsigned int>(q1),
504 static_cast<unsigned int>(q2));
505 mps->ApplyCSXDG(static_cast<unsigned int>(q2),
506 static_cast<unsigned int>(q3));
507 mps->ApplyCX(static_cast<unsigned int>(q1),
508 static_cast<unsigned int>(q2));
509 mps->ApplyCSX(static_cast<unsigned int>(q1),
510 static_cast<unsigned int>(q3));
511 }
512
513 NotifyObservers({qubit2, qubit1, qubit0});
514 }
515
524 void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0,
525 Types::qubit_t qubit1) override {
526 if (GetSimulationType() == SimulationType::kStatevector)
527 state->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
528 else if (GetSimulationType() == SimulationType::kMatrixProductState) {
529 const size_t q1 = ctrl_qubit; // control
530 const size_t q2 = qubit0;
531 const size_t q3 = qubit1;
532
533 // TODO: find a better decomposition
534 // this one I've got with the qiskit transpiler
535 mps->ApplyCX(static_cast<unsigned int>(q3),
536 static_cast<unsigned int>(q2));
537 mps->ApplyCSX(static_cast<unsigned int>(q2),
538 static_cast<unsigned int>(q3));
539 mps->ApplyCX(static_cast<unsigned int>(q1),
540 static_cast<unsigned int>(q2));
541
542 mps->ApplyP(static_cast<unsigned int>(q3), M_PI);
543 mps->ApplyP(static_cast<unsigned int>(q2), -M_PI_2);
544
545 mps->ApplyCSX(static_cast<unsigned int>(q2),
546 static_cast<unsigned int>(q3));
547 mps->ApplyCX(static_cast<unsigned int>(q1),
548 static_cast<unsigned int>(q2));
549
550 mps->ApplyP(static_cast<unsigned int>(q3), M_PI);
551
552 mps->ApplyCSX(static_cast<unsigned int>(q1),
553 static_cast<unsigned int>(q3));
554 mps->ApplyCX(static_cast<unsigned int>(q3),
555 static_cast<unsigned int>(q2));
556 }
557
558 NotifyObservers({qubit1, qubit0, ctrl_qubit});
559 }
560
572 void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
573 double theta, double phi, double lambda, double gamma) override {
574 if (GetSimulationType() == SimulationType::kStatevector)
575 state->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
576 else if (GetSimulationType() == SimulationType::kMatrixProductState)
577 mps->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda, gamma);
578
579 NotifyObservers({tgt_qubit, ctrl_qubit});
580 }
581
589 void ApplyNop() override {
590 // do nothing
591 }
592
603 std::unique_ptr<ISimulator> Clone() override {
604 auto cloned = std::make_unique<GpuSimulator>();
605
606 cloned->simulationType = simulationType;
607 cloned->nrQubits = nrQubits;
608
609 cloned->limitSize = limitSize;
610 cloned->limitEntanglement = limitEntanglement;
611 cloned->chi = chi;
612 cloned->singularValueThreshold = singularValueThreshold;
613
614 if (state)
615 cloned->state = state->Clone();
616 else if (mps)
617 cloned->mps = mps->Clone();
618
619 return cloned;
620 }
621};
622
623} // namespace Private
624} // namespace Simulators
625
626#endif
627#endif
628#endif
int ApplyK(void *sim, int qubit)
int ApplyRx(void *sim, int qubit, double theta)
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)
int ApplyCRz(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyCP(void *sim, int controlQubit, int targetQubit, double theta)
int ApplySDG(void *sim, int qubit)
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)
int ApplyZ(void *sim, int qubit)
int ApplyH(void *sim, int qubit)
int ApplyCY(void *sim, int controlQubit, int targetQubit)
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 ApplyCH(void *sim, int controlQubit, int targetQubit)
int GetSimulationType(void *sim)
int ApplyCZ(void *sim, int controlQubit, int targetQubit)
int ApplyRz(void *sim, int qubit, double theta)
int ApplyT(void *sim, int qubit)
int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta)
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:20