Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
QCSimSimulator.h
Go to the documentation of this file.
1
13#pragma once
14
15#ifndef _QCSIMSIMULATOR_H
16#define _QCSIMSIMULATOR_H
17
18#ifdef INCLUDED_BY_FACTORY
19
20#include "QCSimState.h"
21
22#define _USE_MATH_DEFINES
23#include <math.h>
24
25namespace Simulators {
26// TODO: Maybe use the pimpl idiom
27// https://en.cppreference.com/w/cpp/language/pimpl to hide the implementation
28// for good but during development this should be good enough
29namespace Private {
30
31class IndividualSimulator;
32
44class QCSimSimulator : public QCSimState {
45 friend class IndividualSimulator;
46
47 public:
48 QCSimSimulator() = default;
49 // allow no copy or assignment
50 QCSimSimulator(const QCSimSimulator &) = delete;
51 QCSimSimulator &operator=(const QCSimSimulator &) = delete;
52
53 // but allow moving
54 QCSimSimulator(QCSimSimulator &&other) = default;
55 QCSimSimulator &operator=(QCSimSimulator &&other) = default;
56
64 void ApplyP(Types::qubit_t qubit, double lambda) override {
65 pgate.SetPhaseShift(lambda);
66 if (GetSimulationType() == SimulationType::kMatrixProductState)
67 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(qubit));
68 else if (GetSimulationType() == SimulationType::kStabilizer) {
69 if (std::abs(lambda - M_PI_2) > 1e-10)
70 throw std::runtime_error(
71 "QCSimSimulator::ApplyP: Invalid phase shift "
72 "angle for a Clifford gate.");
73 cliffordSimulator->ApplyS(static_cast<unsigned int>(qubit));
74 } else if (GetSimulationType() == SimulationType::kTensorNetwork)
75 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(qubit));
76 else if (GetSimulationType() == SimulationType::kPauliPropagator)
77 pp->ApplyP(static_cast<unsigned int>(qubit), lambda);
78 else
79 state->ApplyGate(pgate, static_cast<unsigned int>(qubit));
80 NotifyObservers({qubit});
81 }
82
89 void ApplyX(Types::qubit_t qubit) override {
90 if (GetSimulationType() == SimulationType::kMatrixProductState)
91 mpsSimulator->ApplyGate(xgate, static_cast<unsigned int>(qubit));
92 else if (GetSimulationType() == SimulationType::kStabilizer)
93 cliffordSimulator->ApplyX(static_cast<unsigned int>(qubit));
94 else if (GetSimulationType() == SimulationType::kTensorNetwork)
95 tensorNetwork->AddGate(xgate, static_cast<unsigned int>(qubit));
96 else if (GetSimulationType() == SimulationType::kPauliPropagator)
97 pp->ApplyX(static_cast<unsigned int>(qubit));
98 else
99 state->ApplyGate(xgate, static_cast<unsigned int>(qubit));
100 NotifyObservers({qubit});
101 }
102
109 void ApplyY(Types::qubit_t qubit) override {
110 if (GetSimulationType() == SimulationType::kMatrixProductState)
111 mpsSimulator->ApplyGate(ygate, static_cast<unsigned int>(qubit));
112 else if (GetSimulationType() == SimulationType::kStabilizer)
113 cliffordSimulator->ApplyY(static_cast<unsigned int>(qubit));
114 else if (GetSimulationType() == SimulationType::kTensorNetwork)
115 tensorNetwork->AddGate(ygate, static_cast<unsigned int>(qubit));
116 else if (GetSimulationType() == SimulationType::kPauliPropagator)
117 pp->ApplyY(static_cast<unsigned int>(qubit));
118 else
119 state->ApplyGate(ygate, static_cast<unsigned int>(qubit));
120 NotifyObservers({qubit});
121 }
122
129 void ApplyZ(Types::qubit_t qubit) override {
130 if (GetSimulationType() == SimulationType::kMatrixProductState)
131 mpsSimulator->ApplyGate(zgate, static_cast<unsigned int>(qubit));
132 else if (GetSimulationType() == SimulationType::kStabilizer)
133 cliffordSimulator->ApplyZ(static_cast<unsigned int>(qubit));
134 else if (GetSimulationType() == SimulationType::kTensorNetwork)
135 tensorNetwork->AddGate(zgate, static_cast<unsigned int>(qubit));
136 else if (GetSimulationType() == SimulationType::kPauliPropagator)
137 pp->ApplyZ(static_cast<unsigned int>(qubit));
138 else
139 state->ApplyGate(zgate, static_cast<unsigned int>(qubit));
140 NotifyObservers({qubit});
141 }
142
149 void ApplyH(Types::qubit_t qubit) override {
150 if (GetSimulationType() == SimulationType::kMatrixProductState)
151 mpsSimulator->ApplyGate(h, static_cast<unsigned int>(qubit));
152 else if (GetSimulationType() == SimulationType::kStabilizer)
153 cliffordSimulator->ApplyH(static_cast<unsigned int>(qubit));
154 else if (GetSimulationType() == SimulationType::kTensorNetwork)
155 tensorNetwork->AddGate(h, static_cast<unsigned int>(qubit));
156 else if (GetSimulationType() == SimulationType::kPauliPropagator)
157 pp->ApplyH(static_cast<unsigned int>(qubit));
158 else
159 state->ApplyGate(h, static_cast<unsigned int>(qubit));
160 NotifyObservers({qubit});
161 }
162
169 void ApplyS(Types::qubit_t qubit) override {
170 if (GetSimulationType() == SimulationType::kMatrixProductState)
171 mpsSimulator->ApplyGate(sgate, static_cast<unsigned int>(qubit));
172 else if (GetSimulationType() == SimulationType::kStabilizer)
173 cliffordSimulator->ApplyS(static_cast<unsigned int>(qubit));
174 else if (GetSimulationType() == SimulationType::kTensorNetwork)
175 tensorNetwork->AddGate(sgate, static_cast<unsigned int>(qubit));
176 else if (GetSimulationType() == SimulationType::kPauliPropagator)
177 pp->ApplyS(static_cast<unsigned int>(qubit));
178 else
179 state->ApplyGate(sgate, static_cast<unsigned int>(qubit));
180 NotifyObservers({qubit});
181 }
182
189 void ApplySDG(Types::qubit_t qubit) override {
190 if (GetSimulationType() == SimulationType::kMatrixProductState)
191 mpsSimulator->ApplyGate(sdggate, static_cast<unsigned int>(qubit));
192 else if (GetSimulationType() == SimulationType::kStabilizer)
193 cliffordSimulator->ApplySdg(static_cast<unsigned int>(qubit));
194 else if (GetSimulationType() == SimulationType::kTensorNetwork)
195 tensorNetwork->AddGate(sdggate, static_cast<unsigned int>(qubit));
196 else if (GetSimulationType() == SimulationType::kPauliPropagator)
197 pp->ApplySDG(static_cast<unsigned int>(qubit));
198 else
199 state->ApplyGate(sdggate, static_cast<unsigned int>(qubit));
200 NotifyObservers({qubit});
201 }
202
209 void ApplyT(Types::qubit_t qubit) override {
210 if (GetSimulationType() == SimulationType::kMatrixProductState)
211 mpsSimulator->ApplyGate(tgate, static_cast<unsigned int>(qubit));
212 else if (GetSimulationType() == SimulationType::kStabilizer)
213 throw std::runtime_error(
214 "QCSimSimulator::ApplyT: The stabilizer simulator does not support "
215 "non-clifford gates.");
216 else if (GetSimulationType() == SimulationType::kTensorNetwork)
217 tensorNetwork->AddGate(tgate, static_cast<unsigned int>(qubit));
218 else if (GetSimulationType() == SimulationType::kPauliPropagator)
219 pp->ApplyT(static_cast<unsigned int>(qubit));
220 else
221 state->ApplyGate(tgate, static_cast<unsigned int>(qubit));
222 NotifyObservers({qubit});
223 }
224
231 void ApplyTDG(Types::qubit_t qubit) override {
232 if (GetSimulationType() == SimulationType::kMatrixProductState)
233 mpsSimulator->ApplyGate(tdggate, static_cast<unsigned int>(qubit));
234 else if (GetSimulationType() == SimulationType::kStabilizer)
235 throw std::runtime_error(
236 "QCSimSimulator::ApplyTDG: The stabilizer simulator does not support "
237 "non-clifford gates.");
238 else if (GetSimulationType() == SimulationType::kTensorNetwork)
239 tensorNetwork->AddGate(tdggate, static_cast<unsigned int>(qubit));
240 else if (GetSimulationType() == SimulationType::kPauliPropagator)
241 pp->ApplyTDG(static_cast<unsigned int>(qubit));
242 else
243 state->ApplyGate(tdggate, static_cast<unsigned int>(qubit));
244 NotifyObservers({qubit});
245 }
246
253 void ApplySx(Types::qubit_t qubit) override {
254 if (GetSimulationType() == SimulationType::kMatrixProductState)
255 mpsSimulator->ApplyGate(sxgate, static_cast<unsigned int>(qubit));
256 else if (GetSimulationType() == SimulationType::kStabilizer)
257 cliffordSimulator->ApplySx(static_cast<unsigned int>(qubit));
258 else if (GetSimulationType() == SimulationType::kTensorNetwork)
259 tensorNetwork->AddGate(sxgate, static_cast<unsigned int>(qubit));
260 else if (GetSimulationType() == SimulationType::kPauliPropagator)
261 pp->ApplySX(static_cast<unsigned int>(qubit));
262 else
263 state->ApplyGate(sxgate, static_cast<unsigned int>(qubit));
264 NotifyObservers({qubit});
265 }
266
273 void ApplySxDAG(Types::qubit_t qubit) override {
274 if (GetSimulationType() == SimulationType::kMatrixProductState)
275 mpsSimulator->ApplyGate(sxdaggate, static_cast<unsigned int>(qubit));
276 else if (GetSimulationType() == SimulationType::kStabilizer)
277 cliffordSimulator->ApplySxDag(static_cast<unsigned int>(qubit));
278 else if (GetSimulationType() == SimulationType::kTensorNetwork)
279 tensorNetwork->AddGate(sxdaggate, static_cast<unsigned int>(qubit));
280 else if (GetSimulationType() == SimulationType::kPauliPropagator)
281 pp->ApplySXDG(static_cast<unsigned int>(qubit));
282 else
283 state->ApplyGate(sxdaggate, static_cast<unsigned int>(qubit));
284 NotifyObservers({qubit});
285 }
286
293 void ApplyK(Types::qubit_t qubit) override {
294 if (GetSimulationType() == SimulationType::kMatrixProductState)
295 mpsSimulator->ApplyGate(k, static_cast<unsigned int>(qubit));
296 else if (GetSimulationType() == SimulationType::kStabilizer)
297 cliffordSimulator->ApplyK(static_cast<unsigned int>(qubit));
298 else if (GetSimulationType() == SimulationType::kTensorNetwork)
299 tensorNetwork->AddGate(k, static_cast<unsigned int>(qubit));
300 else if (GetSimulationType() == SimulationType::kPauliPropagator)
301 pp->ApplyK(static_cast<unsigned int>(qubit));
302 else
303 state->ApplyGate(k, static_cast<unsigned int>(qubit));
304 NotifyObservers({qubit});
305 }
306
314 void ApplyRx(Types::qubit_t qubit, double theta) override {
315 rxgate.SetTheta(theta);
316 if (GetSimulationType() == SimulationType::kMatrixProductState)
317 mpsSimulator->ApplyGate(rxgate, static_cast<unsigned int>(qubit));
318 else if (GetSimulationType() == SimulationType::kStabilizer)
319 throw std::runtime_error(
320 "QCSimSimulator::ApplyRx: The stabilizer "
321 "simulator does not support the Rx gate.");
322 else if (GetSimulationType() == SimulationType::kTensorNetwork)
323 tensorNetwork->AddGate(rxgate, static_cast<unsigned int>(qubit));
324 else if (GetSimulationType() == SimulationType::kPauliPropagator)
325 pp->ApplyRX(static_cast<unsigned int>(qubit), theta);
326 else
327 state->ApplyGate(rxgate, static_cast<unsigned int>(qubit));
328 NotifyObservers({qubit});
329 }
330
338 void ApplyRy(Types::qubit_t qubit, double theta) override {
339 rygate.SetTheta(theta);
340 if (GetSimulationType() == SimulationType::kMatrixProductState)
341 mpsSimulator->ApplyGate(rygate, static_cast<unsigned int>(qubit));
342 else if (GetSimulationType() == SimulationType::kStabilizer)
343 throw std::runtime_error(
344 "QCSimSimulator::ApplyRy: The stabilizer "
345 "simulator does not support the Ry gate.");
346 else if (GetSimulationType() == SimulationType::kTensorNetwork)
347 tensorNetwork->AddGate(rygate, static_cast<unsigned int>(qubit));
348 else if (GetSimulationType() == SimulationType::kPauliPropagator)
349 pp->ApplyRY(static_cast<unsigned int>(qubit), theta);
350 else
351 state->ApplyGate(rygate, static_cast<unsigned int>(qubit));
352 NotifyObservers({qubit});
353 }
354
362 void ApplyRz(Types::qubit_t qubit, double theta) override {
363 rzgate.SetTheta(theta);
364 if (GetSimulationType() == SimulationType::kMatrixProductState)
365 mpsSimulator->ApplyGate(rzgate, static_cast<unsigned int>(qubit));
366 else if (GetSimulationType() == SimulationType::kStabilizer)
367 throw std::runtime_error(
368 "QCSimSimulator::ApplyRz: The stabilizer "
369 "simulator does not support the Rz gate.");
370 else if (GetSimulationType() == SimulationType::kTensorNetwork)
371 tensorNetwork->AddGate(rzgate, static_cast<unsigned int>(qubit));
372 else if (GetSimulationType() == SimulationType::kPauliPropagator)
373 pp->ApplyRZ(static_cast<unsigned int>(qubit), theta);
374 else
375 state->ApplyGate(rzgate, static_cast<unsigned int>(qubit));
376 NotifyObservers({qubit});
377 }
378
389 void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda,
390 double gamma) override {
391 ugate.SetParams(theta, phi, lambda, gamma);
392 if (GetSimulationType() == SimulationType::kMatrixProductState)
393 mpsSimulator->ApplyGate(ugate, static_cast<unsigned int>(qubit));
394 else if (GetSimulationType() == SimulationType::kStabilizer)
395 throw std::runtime_error(
396 "QCSimSimulator::ApplyU: The stabilizer "
397 "simulator does not support the U gate.");
398 else if (GetSimulationType() == SimulationType::kTensorNetwork)
399 tensorNetwork->AddGate(ugate, static_cast<unsigned int>(qubit));
400 else if (GetSimulationType() == SimulationType::kPauliPropagator)
401 pp->ApplyU(static_cast<unsigned int>(qubit), theta, phi, lambda, gamma);
402 else
403 state->ApplyGate(ugate, static_cast<unsigned int>(qubit));
404 NotifyObservers({qubit});
405 }
406
414 void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
415 if (GetSimulationType() == SimulationType::kMatrixProductState)
416 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(tgt_qubit),
417 static_cast<unsigned int>(ctrl_qubit));
418 else if (GetSimulationType() == SimulationType::kStabilizer)
419 cliffordSimulator->ApplyCX(static_cast<unsigned int>(tgt_qubit),
420 static_cast<unsigned int>(ctrl_qubit));
421 else if (GetSimulationType() == SimulationType::kTensorNetwork)
422 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(ctrl_qubit),
423 static_cast<unsigned int>(tgt_qubit));
424 else if (GetSimulationType() == SimulationType::kPauliPropagator)
425 pp->ApplyCX(static_cast<unsigned int>(ctrl_qubit),
426 static_cast<unsigned int>(tgt_qubit));
427 else
428 state->ApplyGate(cxgate, static_cast<unsigned int>(tgt_qubit),
429 static_cast<unsigned int>(ctrl_qubit));
430 NotifyObservers({tgt_qubit, ctrl_qubit});
431 }
432
440 void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
441 if (GetSimulationType() == SimulationType::kMatrixProductState)
442 mpsSimulator->ApplyGate(cygate, static_cast<unsigned int>(tgt_qubit),
443 static_cast<unsigned int>(ctrl_qubit));
444 else if (GetSimulationType() == SimulationType::kStabilizer)
445 cliffordSimulator->ApplyCY(static_cast<unsigned int>(tgt_qubit),
446 static_cast<unsigned int>(ctrl_qubit));
447 else if (GetSimulationType() == SimulationType::kTensorNetwork)
448 tensorNetwork->AddGate(cygate, static_cast<unsigned int>(ctrl_qubit),
449 static_cast<unsigned int>(tgt_qubit));
450 else if (GetSimulationType() == SimulationType::kPauliPropagator)
451 pp->ApplyCY(static_cast<unsigned int>(ctrl_qubit),
452 static_cast<unsigned int>(tgt_qubit));
453 else
454 state->ApplyGate(cygate, static_cast<unsigned int>(tgt_qubit),
455 static_cast<unsigned int>(ctrl_qubit));
456 NotifyObservers({tgt_qubit, ctrl_qubit});
457 }
458
466 void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
467 if (GetSimulationType() == SimulationType::kMatrixProductState)
468 mpsSimulator->ApplyGate(czgate, static_cast<unsigned int>(tgt_qubit),
469 static_cast<unsigned int>(ctrl_qubit));
470 else if (GetSimulationType() == SimulationType::kStabilizer)
471 cliffordSimulator->ApplyCZ(static_cast<unsigned int>(tgt_qubit),
472 static_cast<unsigned int>(ctrl_qubit));
473 else if (GetSimulationType() == SimulationType::kTensorNetwork)
474 tensorNetwork->AddGate(czgate, static_cast<unsigned int>(ctrl_qubit),
475 static_cast<unsigned int>(tgt_qubit));
476 else if (GetSimulationType() == SimulationType::kPauliPropagator)
477 pp->ApplyCZ(static_cast<unsigned int>(ctrl_qubit),
478 static_cast<unsigned int>(tgt_qubit));
479 else
480 state->ApplyGate(czgate, static_cast<unsigned int>(tgt_qubit),
481 static_cast<unsigned int>(ctrl_qubit));
482 NotifyObservers({tgt_qubit, ctrl_qubit});
483 }
484
493 void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
494 double lambda) override {
495 cpgate.SetPhaseShift(lambda);
496 if (GetSimulationType() == SimulationType::kMatrixProductState)
497 mpsSimulator->ApplyGate(cpgate, static_cast<unsigned int>(tgt_qubit),
498 static_cast<unsigned int>(ctrl_qubit));
499 else if (GetSimulationType() == SimulationType::kStabilizer)
500 throw std::runtime_error(
501 "QCSimSimulator::ApplyCP: The stabilizer "
502 "simulator does not support the CP gate.");
503 else if (GetSimulationType() == SimulationType::kTensorNetwork)
504 tensorNetwork->AddGate(cpgate, static_cast<unsigned int>(ctrl_qubit),
505 static_cast<unsigned int>(tgt_qubit));
506 else if (GetSimulationType() == SimulationType::kPauliPropagator)
507 pp->ApplyCP(static_cast<unsigned int>(ctrl_qubit),
508 static_cast<unsigned int>(tgt_qubit), lambda);
509 else
510 state->ApplyGate(cpgate, static_cast<unsigned int>(tgt_qubit),
511 static_cast<unsigned int>(ctrl_qubit));
512 NotifyObservers({tgt_qubit, ctrl_qubit});
513 }
514
523 void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
524 double theta) override {
525 crxgate.SetTheta(theta);
526 if (GetSimulationType() == SimulationType::kMatrixProductState)
527 mpsSimulator->ApplyGate(crxgate, static_cast<unsigned int>(tgt_qubit),
528 static_cast<unsigned int>(ctrl_qubit));
529 else if (GetSimulationType() == SimulationType::kStabilizer)
530 throw std::runtime_error(
531 "QCSimSimulator::ApplyCRx: The stabilizer "
532 "simulator does not support the CRx gate.");
533 else if (GetSimulationType() == SimulationType::kTensorNetwork)
534 tensorNetwork->AddGate(crxgate, static_cast<unsigned int>(ctrl_qubit),
535 static_cast<unsigned int>(tgt_qubit));
536 else if (GetSimulationType() == SimulationType::kPauliPropagator)
537 pp->ApplyCRX(static_cast<unsigned int>(ctrl_qubit),
538 static_cast<unsigned int>(tgt_qubit), theta);
539 else
540 state->ApplyGate(crxgate, static_cast<unsigned int>(tgt_qubit),
541 static_cast<unsigned int>(ctrl_qubit));
542 NotifyObservers({tgt_qubit, ctrl_qubit});
543 }
544
553 void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
554 double theta) override {
555 crygate.SetTheta(theta);
556 if (GetSimulationType() == SimulationType::kMatrixProductState)
557 mpsSimulator->ApplyGate(crygate, static_cast<unsigned int>(tgt_qubit),
558 static_cast<unsigned int>(ctrl_qubit));
559 else if (GetSimulationType() == SimulationType::kStabilizer)
560 throw std::runtime_error(
561 "QCSimSimulator::ApplyCRy: The stabilizer "
562 "simulator does not support the CRy gate.");
563 else if (GetSimulationType() == SimulationType::kTensorNetwork)
564 tensorNetwork->AddGate(crygate, static_cast<unsigned int>(ctrl_qubit),
565 static_cast<unsigned int>(tgt_qubit));
566 else if (GetSimulationType() == SimulationType::kPauliPropagator)
567 pp->ApplyCRY(static_cast<unsigned int>(ctrl_qubit),
568 static_cast<unsigned int>(tgt_qubit), theta);
569 else
570 state->ApplyGate(crygate, static_cast<unsigned int>(tgt_qubit),
571 static_cast<unsigned int>(ctrl_qubit));
572 NotifyObservers({tgt_qubit, ctrl_qubit});
573 }
574
583 void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
584 double theta) override {
585 crzgate.SetTheta(theta);
586 if (GetSimulationType() == SimulationType::kMatrixProductState)
587 mpsSimulator->ApplyGate(crzgate, static_cast<unsigned int>(tgt_qubit),
588 static_cast<unsigned int>(ctrl_qubit));
589 else if (GetSimulationType() == SimulationType::kStabilizer)
590 throw std::runtime_error(
591 "QCSimSimulator::ApplyCRz: The stabilizer "
592 "simulator does not support the CRz gate.");
593 else if (GetSimulationType() == SimulationType::kTensorNetwork)
594 tensorNetwork->AddGate(crzgate, static_cast<unsigned int>(ctrl_qubit),
595 static_cast<unsigned int>(tgt_qubit));
596 else if (GetSimulationType() == SimulationType::kPauliPropagator)
597 pp->ApplyCRZ(static_cast<unsigned int>(ctrl_qubit),
598 static_cast<unsigned int>(tgt_qubit), theta);
599 else
600 state->ApplyGate(crzgate, static_cast<unsigned int>(tgt_qubit),
601 static_cast<unsigned int>(ctrl_qubit));
602 NotifyObservers({tgt_qubit, ctrl_qubit});
603 }
604
612 void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
613 if (GetSimulationType() == SimulationType::kMatrixProductState)
614 mpsSimulator->ApplyGate(ch, static_cast<unsigned int>(tgt_qubit),
615 static_cast<unsigned int>(ctrl_qubit));
616 else if (GetSimulationType() == SimulationType::kStabilizer)
617 throw std::runtime_error(
618 "QCSimSimulator::ApplyCH: The stabilizer "
619 "simulator does not support the CH gate.");
620 else if (GetSimulationType() == SimulationType::kTensorNetwork)
621 tensorNetwork->AddGate(ch, static_cast<unsigned int>(ctrl_qubit),
622 static_cast<unsigned int>(tgt_qubit));
623 else if (GetSimulationType() == SimulationType::kPauliPropagator)
624 pp->ApplyCH(static_cast<unsigned int>(ctrl_qubit),
625 static_cast<unsigned int>(tgt_qubit));
626 else
627 state->ApplyGate(ch, static_cast<unsigned int>(tgt_qubit),
628 static_cast<unsigned int>(ctrl_qubit));
629 NotifyObservers({tgt_qubit, ctrl_qubit});
630 }
631
639 void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
640 if (GetSimulationType() == SimulationType::kMatrixProductState)
641 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(tgt_qubit),
642 static_cast<unsigned int>(ctrl_qubit));
643 else if (GetSimulationType() == SimulationType::kStabilizer)
644 throw std::runtime_error(
645 "QCSimSimulator::ApplyCSx: The stabilizer "
646 "simulator does not support the CSx gate.");
647 else if (GetSimulationType() == SimulationType::kTensorNetwork)
648 tensorNetwork->AddGate(csx, static_cast<unsigned int>(ctrl_qubit),
649 static_cast<unsigned int>(tgt_qubit));
650 else if (GetSimulationType() == SimulationType::kPauliPropagator)
651 pp->ApplyCSX(static_cast<unsigned int>(ctrl_qubit),
652 static_cast<unsigned int>(tgt_qubit));
653 else
654 state->ApplyGate(csx, static_cast<unsigned int>(tgt_qubit),
655 static_cast<unsigned int>(ctrl_qubit));
656 NotifyObservers({tgt_qubit, ctrl_qubit});
657 }
658
666 void ApplyCSxDAG(Types::qubit_t ctrl_qubit,
667 Types::qubit_t tgt_qubit) override {
668 if (GetSimulationType() == SimulationType::kMatrixProductState)
669 mpsSimulator->ApplyGate(csxdag, static_cast<unsigned int>(tgt_qubit),
670 static_cast<unsigned int>(ctrl_qubit));
671 else if (GetSimulationType() == SimulationType::kStabilizer)
672 throw std::runtime_error(
673 "QCSimSimulator::ApplyCSxDAG: The stabilizer "
674 "simulator does not support the CSxDag gate.");
675 else if (GetSimulationType() == SimulationType::kTensorNetwork)
676 tensorNetwork->AddGate(csxdag, static_cast<unsigned int>(ctrl_qubit),
677 static_cast<unsigned int>(tgt_qubit));
678 else if (GetSimulationType() == SimulationType::kPauliPropagator)
679 pp->ApplyCSXDAG(static_cast<unsigned int>(ctrl_qubit),
680 static_cast<unsigned int>(tgt_qubit));
681 else
682 state->ApplyGate(csxdag, static_cast<unsigned int>(tgt_qubit),
683 static_cast<unsigned int>(ctrl_qubit));
684 NotifyObservers({tgt_qubit, ctrl_qubit});
685 }
686
694 void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1) override {
695 if (GetSimulationType() == SimulationType::kMatrixProductState)
696 mpsSimulator->ApplyGate(swapgate, static_cast<unsigned int>(qubit1),
697 static_cast<unsigned int>(qubit0));
698 else if (GetSimulationType() == SimulationType::kStabilizer)
699 cliffordSimulator->ApplySwap(static_cast<unsigned int>(qubit1),
700 static_cast<unsigned int>(qubit0));
701 else if (GetSimulationType() == SimulationType::kTensorNetwork)
702 tensorNetwork->AddGate(swapgate, static_cast<unsigned int>(qubit0),
703 static_cast<unsigned int>(qubit1));
704 else if (GetSimulationType() == SimulationType::kPauliPropagator)
705 pp->ApplySWAP(static_cast<unsigned int>(qubit0),
706 static_cast<unsigned int>(qubit1));
707 else
708 state->ApplyGate(swapgate, static_cast<unsigned int>(qubit1),
709 static_cast<unsigned int>(qubit0));
710 NotifyObservers({qubit1, qubit0});
711 }
712
721 void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1,
722 Types::qubit_t qubit2) override {
723 if (GetSimulationType() == SimulationType::kMatrixProductState) {
724 const size_t q1 = qubit0; // control 1
725 const size_t q2 = qubit1; // control 2
726 const size_t q3 = qubit2; // target
727
728 // Sleator-Weinfurter decomposition
729 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
730 static_cast<unsigned int>(q2));
731 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
732 static_cast<unsigned int>(q1));
733 mpsSimulator->ApplyGate(csxdag, static_cast<unsigned int>(q3),
734 static_cast<unsigned int>(q2));
735 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
736 static_cast<unsigned int>(q1));
737 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
738 static_cast<unsigned int>(q1));
739 } else if (GetSimulationType() == SimulationType::kStabilizer)
740 throw std::runtime_error(
741 "QCSimSimulator::ApplyCCX: The stabilizer "
742 "simulator does not support the CCX gate.");
743 else if (GetSimulationType() == SimulationType::kTensorNetwork) {
744 const size_t q1 = qubit0; // control 1
745 const size_t q2 = qubit1; // control 2
746 const size_t q3 = qubit2; // target
747
748 // Sleator-Weinfurter decomposition
749 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q2),
750 static_cast<unsigned int>(q3));
751 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
752 static_cast<unsigned int>(q2));
753 tensorNetwork->AddGate(csxdag, static_cast<unsigned int>(q2),
754 static_cast<unsigned int>(q3));
755 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
756 static_cast<unsigned int>(q2));
757 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q1),
758 static_cast<unsigned int>(q3));
759 } else if (GetSimulationType() == SimulationType::kPauliPropagator)
760 pp->ApplyCCX(static_cast<unsigned int>(qubit0),
761 static_cast<unsigned int>(qubit1),
762 static_cast<unsigned int>(qubit2));
763 else
764 state->ApplyGate(ccxgate, static_cast<unsigned int>(qubit2),
765 static_cast<unsigned int>(qubit1),
766 static_cast<unsigned int>(qubit0));
767 NotifyObservers({qubit2, qubit1, qubit0});
768 }
769
778 void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0,
779 Types::qubit_t qubit1) override {
780 if (GetSimulationType() == SimulationType::kMatrixProductState) {
781 const size_t q1 = ctrl_qubit; // control
782 const size_t q2 = qubit0;
783 const size_t q3 = qubit1;
784
785 // TODO: find a better decomposition
786 // this one I've got with the qiskit transpiler
787 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
788 static_cast<unsigned int>(q3));
789 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
790 static_cast<unsigned int>(q2));
791 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
792 static_cast<unsigned int>(q1));
793
794 pgate.SetPhaseShift(M_PI);
795 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(q3));
796 pgate.SetPhaseShift(-M_PI_2);
797 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(q2));
798
799 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
800 static_cast<unsigned int>(q2));
801 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
802 static_cast<unsigned int>(q1));
803
804 pgate.SetPhaseShift(M_PI);
805 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(q3));
806
807 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
808 static_cast<unsigned int>(q1));
809 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
810 static_cast<unsigned int>(q3));
811 } else if (GetSimulationType() == SimulationType::kStabilizer)
812 throw std::runtime_error(
813 "QCSimSimulator::ApplyCSwap: The stabilizer "
814 "simulator does not support the CSwap gate.");
815 else if (GetSimulationType() == SimulationType::kTensorNetwork) {
816 const size_t q1 = ctrl_qubit; // control
817 const size_t q2 = qubit0;
818 const size_t q3 = qubit1;
819
820 // TODO: find a better decomposition
821 // this one I've got with the qiskit transpiler
822 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q3),
823 static_cast<unsigned int>(q2));
824 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q2),
825 static_cast<unsigned int>(q3));
826 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
827 static_cast<unsigned int>(q2));
828
829 pgate.SetPhaseShift(M_PI);
830 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(q3));
831 pgate.SetPhaseShift(-M_PI_2);
832 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(q2));
833
834 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q2),
835 static_cast<unsigned int>(q3));
836 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
837 static_cast<unsigned int>(q2));
838
839 pgate.SetPhaseShift(M_PI);
840 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(q3));
841
842 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q1),
843 static_cast<unsigned int>(q3));
844 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q3),
845 static_cast<unsigned int>(q2));
846 } else if (GetSimulationType() == SimulationType::kPauliPropagator) {
847 pp->ApplyCSwap(static_cast<unsigned int>(ctrl_qubit),
848 static_cast<unsigned int>(qubit0),
849 static_cast<unsigned int>(qubit1));
850 } else
851 state->ApplyGate(cswapgate, static_cast<unsigned int>(qubit1),
852 static_cast<unsigned int>(qubit0),
853 static_cast<unsigned int>(ctrl_qubit));
854 NotifyObservers({qubit1, qubit0, ctrl_qubit});
855 }
856
868 void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
869 double theta, double phi, double lambda, double gamma) override {
870 cugate.SetParams(theta, phi, lambda, gamma);
871 if (GetSimulationType() == SimulationType::kMatrixProductState)
872 mpsSimulator->ApplyGate(cugate, static_cast<unsigned int>(tgt_qubit),
873 static_cast<unsigned int>(ctrl_qubit));
874 else if (GetSimulationType() == SimulationType::kStabilizer)
875 throw std::runtime_error(
876 "QCSimSimulator::ApplyCU: The stabilizer "
877 "simulator does not support the CU gate.");
878 else if (GetSimulationType() == SimulationType::kTensorNetwork)
879 tensorNetwork->AddGate(cugate, static_cast<unsigned int>(ctrl_qubit),
880 static_cast<unsigned int>(tgt_qubit));
881 else if (GetSimulationType() == SimulationType::kPauliPropagator)
882 pp->ApplyCU(static_cast<unsigned int>(ctrl_qubit),
883 static_cast<unsigned int>(tgt_qubit), theta, phi, lambda,
884 gamma);
885 else
886 state->ApplyGate(cugate, static_cast<unsigned int>(tgt_qubit),
887 static_cast<unsigned int>(ctrl_qubit));
888 NotifyObservers({tgt_qubit, ctrl_qubit});
889 }
890
898 void ApplyNop() override {
899 // do nothing
900 }
901
912 std::unique_ptr<ISimulator> Clone() override {
913 auto cloned = std::make_unique<QCSimSimulator>();
914
915 cloned->simulationType = simulationType;
916 cloned->nrQubits = nrQubits;
917
918 cloned->limitSize = limitSize;
919 cloned->limitEntanglement = limitEntanglement;
920 cloned->chi = chi;
921 cloned->singularValueThreshold = singularValueThreshold;
922
923 cloned->enableMultithreading = enableMultithreading;
924 cloned->useMPSMeasureNoCollapse = useMPSMeasureNoCollapse;
925
926 if (state) cloned->state = state->Clone();
927
928 if (mpsSimulator) {
929 cloned->mpsSimulator = mpsSimulator->Clone();
930
931 if (limitEntanglement && singularValueThreshold > 0.)
932 cloned->mpsSimulator->setLimitEntanglement(singularValueThreshold);
933 if (limitSize && chi > 0)
934 cloned->mpsSimulator->setLimitBondDimension(chi);
935 }
936
937 if (cliffordSimulator)
938 cloned->cliffordSimulator = cliffordSimulator->Clone();
939
940 if (tensorNetwork) cloned->tensorNetwork = tensorNetwork->Clone();
941
942 if (pp) cloned->pp = std::move(pp->Clone());
943
944 return cloned;
945 }
946
947 private:
948 QC::Gates::PhaseShiftGate<> pgate;
949 QC::Gates::PauliXGate<> xgate;
950 QC::Gates::PauliYGate<> ygate;
951 QC::Gates::PauliZGate<> zgate;
952 QC::Gates::HadamardGate<> h;
953 // QC::Gates::UGate<> ugate;
954 QC::Gates::SGate<> sgate;
955 QC::Gates::SDGGate<> sdggate;
956 QC::Gates::TGate<> tgate;
957 QC::Gates::TDGGate<> tdggate;
958 QC::Gates::SquareRootNOTGate<> sxgate;
959 QC::Gates::SquareRootNOTDagGate<> sxdaggate;
960 QC::Gates::HyGate<> k;
961 QC::Gates::RxGate<> rxgate;
962 QC::Gates::RyGate<> rygate;
963 QC::Gates::RzGate<> rzgate;
964 QC::Gates::UGate<> ugate;
965 QC::Gates::CNOTGate<> cxgate;
966 QC::Gates::ControlledYGate<> cygate;
967 QC::Gates::ControlledZGate<> czgate;
968 QC::Gates::ControlledPhaseShiftGate<> cpgate;
969 QC::Gates::ControlledRxGate<> crxgate;
970 QC::Gates::ControlledRyGate<> crygate;
971 QC::Gates::ControlledRzGate<> crzgate;
972 QC::Gates::ControlledHadamardGate<> ch;
973 QC::Gates::ControlledSquareRootNOTGate<> csx;
974 QC::Gates::ControlledSquareRootNOTDagGate<> csxdag;
975 QC::Gates::SwapGate<> swapgate;
976 QC::Gates::ToffoliGate<> ccxgate;
977 QC::Gates::FredkinGate<> cswapgate;
978 QC::Gates::ControlledUGate<> cugate;
979};
980
981} // namespace Private
982} // namespace Simulators
983
984#endif
985
986#endif // !_QCSIMSIMULATOR_H
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)