Maestro 0.3.1
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
QCSimSimulator.h
Go to the documentation of this file.
1
12
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
57
63 void ApplyGenericOneQubitGate(Types::qubit_t qubit,
64 const Eigen::Matrix2cd& gate) override {
65 if (GetSimulationType() != SimulationType::kMatrixProductState &&
66 GetSimulationType() != SimulationType::kMatrixProductOperator &&
67 GetSimulationType() != SimulationType::kTensorNetwork&&
68 GetSimulationType() != SimulationType::kStatevector &&
69 GetSimulationType() != SimulationType::kDensityMatrix)
70 throw std::runtime_error("QCSimSimulator::ApplyGenericOneQubitGate: Unsupported simulation type.");
71
72 const QC::Gates::AppliedGate<> agate(gate, qubit);
73
74 if (GetSimulationType() == SimulationType::kMatrixProductState)
75 mpsSimulator->ApplyGate(agate);
76 else if (GetSimulationType() == SimulationType::kTensorNetwork)
77 tensorNetwork->AddGate(agate, qubit);
78 else if (GetSimulationType() == SimulationType::kStatevector ||
79 GetSimulationType() == SimulationType::kDensityMatrix ||
80 GetSimulationType() == SimulationType::kMatrixProductOperator)
81 ApplyStatevectorOrDensityMatrix(agate);
82
83 NotifyObservers({qubit});
84 }
85
92 void ApplyGenericTwoQubitGate(Types::qubit_t qubit0, Types::qubit_t qubit1,
93 const Eigen::Matrix4cd& gate) override {
94 if (GetSimulationType() != SimulationType::kMatrixProductState &&
95 GetSimulationType() != SimulationType::kMatrixProductOperator &&
96 GetSimulationType() != SimulationType::kTensorNetwork &&
97 GetSimulationType() != SimulationType::kStatevector &&
98 GetSimulationType() != SimulationType::kDensityMatrix)
99 throw std::runtime_error(
100 "QCSimSimulator::ApplyGenericTwoQubitGate: Unsupported simulation "
101 "type.");
102
103 const QC::Gates::AppliedGate<> agate(gate, qubit0, qubit1);
104
105 if (GetSimulationType() == SimulationType::kMatrixProductState)
106 mpsSimulator->ApplyGate(agate);
107 else if (GetSimulationType() == SimulationType::kTensorNetwork)
108 tensorNetwork->AddGate(agate, qubit0, qubit1);
109 else if (GetSimulationType() == SimulationType::kStatevector ||
110 GetSimulationType() == SimulationType::kDensityMatrix ||
111 GetSimulationType() == SimulationType::kMatrixProductOperator)
112 ApplyStatevectorOrDensityMatrix(agate);
113
114 NotifyObservers({qubit0, qubit1});
115 }
116
124 void ApplyP(Types::qubit_t qubit, double lambda) override {
125 pgate.SetPhaseShift(lambda);
126 if (GetSimulationType() == SimulationType::kMatrixProductState)
127 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(qubit));
128 else if (GetSimulationType() == SimulationType::kStabilizer) {
129 if (std::abs(lambda - M_PI_2) > 1e-10)
130 throw std::runtime_error(
131 "QCSimSimulator::ApplyP: Invalid phase shift "
132 "angle for a Clifford gate.");
133 cliffordSimulator->ApplyS(static_cast<unsigned int>(qubit));
134 } else if (GetSimulationType() == SimulationType::kTensorNetwork)
135 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(qubit));
136 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
137 extendedStabilizer->ApplyP(qubit, lambda);
138 else if (GetSimulationType() == SimulationType::kPauliPropagator)
139 pp->ApplyP(static_cast<unsigned int>(qubit), lambda);
140 else if (GetSimulationType() == SimulationType::kPathIntegral) {
141 QC::Gates::AppliedGate<> agate(pgate.getRawOperatorMatrix(), qubit);
142 pathIntegralSimulator->ApplyGate(agate);
143 }
144 else
145 ApplyStatevectorOrDensityMatrix(pgate,
146 static_cast<unsigned int>(qubit));
147 NotifyObservers({qubit});
148 }
149
156 void ApplyX(Types::qubit_t qubit) override {
157 if (GetSimulationType() == SimulationType::kMatrixProductState)
158 mpsSimulator->ApplyGate(xgate, static_cast<unsigned int>(qubit));
159 else if (GetSimulationType() == SimulationType::kStabilizer)
160 cliffordSimulator->ApplyX(static_cast<unsigned int>(qubit));
161 else if (GetSimulationType() == SimulationType::kTensorNetwork)
162 tensorNetwork->AddGate(xgate, static_cast<unsigned int>(qubit));
163 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
164 extendedStabilizer->ApplyX(qubit);
165 else if (GetSimulationType() == SimulationType::kPauliPropagator)
166 pp->ApplyX(static_cast<unsigned int>(qubit));
167 else if (GetSimulationType() == SimulationType::kPathIntegral) {
168 QC::Gates::AppliedGate<> agate(xgate.getRawOperatorMatrix(), qubit);
169 pathIntegralSimulator->ApplyGate(agate);
170 }
171 else
172 ApplyStatevectorOrDensityMatrix(xgate,
173 static_cast<unsigned int>(qubit));
174 NotifyObservers({qubit});
175 }
176
183 void ApplyY(Types::qubit_t qubit) override {
184 if (GetSimulationType() == SimulationType::kMatrixProductState)
185 mpsSimulator->ApplyGate(ygate, static_cast<unsigned int>(qubit));
186 else if (GetSimulationType() == SimulationType::kStabilizer)
187 cliffordSimulator->ApplyY(static_cast<unsigned int>(qubit));
188 else if (GetSimulationType() == SimulationType::kTensorNetwork)
189 tensorNetwork->AddGate(ygate, static_cast<unsigned int>(qubit));
190 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
191 extendedStabilizer->ApplyY(qubit);
192 else if (GetSimulationType() == SimulationType::kPauliPropagator)
193 pp->ApplyY(static_cast<unsigned int>(qubit));
194 else if (GetSimulationType() == SimulationType::kPathIntegral) {
195 QC::Gates::AppliedGate<> agate(ygate.getRawOperatorMatrix(), qubit);
196 pathIntegralSimulator->ApplyGate(agate);
197 }
198 else
199 ApplyStatevectorOrDensityMatrix(ygate,
200 static_cast<unsigned int>(qubit));
201 NotifyObservers({qubit});
202 }
203
210 void ApplyZ(Types::qubit_t qubit) override {
211 if (GetSimulationType() == SimulationType::kMatrixProductState)
212 mpsSimulator->ApplyGate(zgate, static_cast<unsigned int>(qubit));
213 else if (GetSimulationType() == SimulationType::kStabilizer)
214 cliffordSimulator->ApplyZ(static_cast<unsigned int>(qubit));
215 else if (GetSimulationType() == SimulationType::kTensorNetwork)
216 tensorNetwork->AddGate(zgate, static_cast<unsigned int>(qubit));
217 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
218 extendedStabilizer->ApplyZ(qubit);
219 else if (GetSimulationType() == SimulationType::kPauliPropagator)
220 pp->ApplyZ(static_cast<unsigned int>(qubit));
221 else if (GetSimulationType() == SimulationType::kPathIntegral) {
222 QC::Gates::AppliedGate<> agate(zgate.getRawOperatorMatrix(), qubit);
223 pathIntegralSimulator->ApplyGate(agate);
224 }
225 else
226 ApplyStatevectorOrDensityMatrix(zgate,
227 static_cast<unsigned int>(qubit));
228 NotifyObservers({qubit});
229 }
230
237 void ApplyH(Types::qubit_t qubit) override {
238 if (GetSimulationType() == SimulationType::kMatrixProductState)
239 mpsSimulator->ApplyGate(h, static_cast<unsigned int>(qubit));
240 else if (GetSimulationType() == SimulationType::kStabilizer)
241 cliffordSimulator->ApplyH(static_cast<unsigned int>(qubit));
242 else if (GetSimulationType() == SimulationType::kTensorNetwork)
243 tensorNetwork->AddGate(h, static_cast<unsigned int>(qubit));
244 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
245 extendedStabilizer->ApplyH(qubit);
246 else if (GetSimulationType() == SimulationType::kPauliPropagator)
247 pp->ApplyH(static_cast<unsigned int>(qubit));
248 else if (GetSimulationType() == SimulationType::kPathIntegral) {
249 QC::Gates::AppliedGate<> agate(h.getRawOperatorMatrix(), qubit);
250 pathIntegralSimulator->ApplyGate(agate);
251 }
252 else
253 ApplyStatevectorOrDensityMatrix(h, static_cast<unsigned int>(qubit));
254 NotifyObservers({qubit});
255 }
256
263 void ApplyS(Types::qubit_t qubit) override {
264 if (GetSimulationType() == SimulationType::kMatrixProductState)
265 mpsSimulator->ApplyGate(sgate, static_cast<unsigned int>(qubit));
266 else if (GetSimulationType() == SimulationType::kStabilizer)
267 cliffordSimulator->ApplyS(static_cast<unsigned int>(qubit));
268 else if (GetSimulationType() == SimulationType::kTensorNetwork)
269 tensorNetwork->AddGate(sgate, static_cast<unsigned int>(qubit));
270 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
271 extendedStabilizer->ApplyS(qubit);
272 else if (GetSimulationType() == SimulationType::kPauliPropagator)
273 pp->ApplyS(static_cast<unsigned int>(qubit));
274 else if (GetSimulationType() == SimulationType::kPathIntegral) {
275 QC::Gates::AppliedGate<> agate(sgate.getRawOperatorMatrix(), qubit);
276 pathIntegralSimulator->ApplyGate(agate);
277 }
278 else
279 ApplyStatevectorOrDensityMatrix(sgate,
280 static_cast<unsigned int>(qubit));
281 NotifyObservers({qubit});
282 }
283
290 void ApplySDG(Types::qubit_t qubit) override {
291 if (GetSimulationType() == SimulationType::kMatrixProductState)
292 mpsSimulator->ApplyGate(sdggate, static_cast<unsigned int>(qubit));
293 else if (GetSimulationType() == SimulationType::kStabilizer)
294 cliffordSimulator->ApplySdg(static_cast<unsigned int>(qubit));
295 else if (GetSimulationType() == SimulationType::kTensorNetwork)
296 tensorNetwork->AddGate(sdggate, static_cast<unsigned int>(qubit));
297 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
298 extendedStabilizer->ApplySDG(qubit);
299 else if (GetSimulationType() == SimulationType::kPauliPropagator)
300 pp->ApplySDG(static_cast<unsigned int>(qubit));
301 else if (GetSimulationType() == SimulationType::kPathIntegral) {
302 QC::Gates::AppliedGate<> agate(sdggate.getRawOperatorMatrix(), qubit);
303 pathIntegralSimulator->ApplyGate(agate);
304 }
305 else
306 ApplyStatevectorOrDensityMatrix(sdggate,
307 static_cast<unsigned int>(qubit));
308 NotifyObservers({qubit});
309 }
310
317 void ApplyT(Types::qubit_t qubit) override {
318 if (GetSimulationType() == SimulationType::kMatrixProductState)
319 mpsSimulator->ApplyGate(tgate, static_cast<unsigned int>(qubit));
320 else if (GetSimulationType() == SimulationType::kStabilizer)
321 throw std::runtime_error(
322 "QCSimSimulator::ApplyT: The stabilizer simulator does not support "
323 "non-clifford gates.");
324 else if (GetSimulationType() == SimulationType::kTensorNetwork)
325 tensorNetwork->AddGate(tgate, static_cast<unsigned int>(qubit));
326 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
327 extendedStabilizer->ApplyT(qubit);
328 else if (GetSimulationType() == SimulationType::kPauliPropagator)
329 pp->ApplyT(static_cast<unsigned int>(qubit));
330 else if (GetSimulationType() == SimulationType::kPathIntegral) {
331 QC::Gates::AppliedGate<> agate(tgate.getRawOperatorMatrix(), qubit);
332 pathIntegralSimulator->ApplyGate(agate);
333 }
334 else
335 ApplyStatevectorOrDensityMatrix(tgate,
336 static_cast<unsigned int>(qubit));
337 NotifyObservers({qubit});
338 }
339
346 void ApplyTDG(Types::qubit_t qubit) override {
347 if (GetSimulationType() == SimulationType::kMatrixProductState)
348 mpsSimulator->ApplyGate(tdggate, static_cast<unsigned int>(qubit));
349 else if (GetSimulationType() == SimulationType::kStabilizer)
350 throw std::runtime_error(
351 "QCSimSimulator::ApplyTDG: The stabilizer simulator does not support "
352 "non-clifford gates.");
353 else if (GetSimulationType() == SimulationType::kTensorNetwork)
354 tensorNetwork->AddGate(tdggate, static_cast<unsigned int>(qubit));
355 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
356 extendedStabilizer->ApplyTDG(qubit);
357 else if (GetSimulationType() == SimulationType::kPauliPropagator)
358 pp->ApplyTDG(static_cast<unsigned int>(qubit));
359 else if (GetSimulationType() == SimulationType::kPathIntegral) {
360 QC::Gates::AppliedGate<> agate(tdggate.getRawOperatorMatrix(), qubit);
361 pathIntegralSimulator->ApplyGate(agate);
362 }
363 else
364 ApplyStatevectorOrDensityMatrix(tdggate,
365 static_cast<unsigned int>(qubit));
366 NotifyObservers({qubit});
367 }
368
375 void ApplySx(Types::qubit_t qubit) override {
376 if (GetSimulationType() == SimulationType::kMatrixProductState)
377 mpsSimulator->ApplyGate(sxgate, static_cast<unsigned int>(qubit));
378 else if (GetSimulationType() == SimulationType::kStabilizer)
379 cliffordSimulator->ApplySx(static_cast<unsigned int>(qubit));
380 else if (GetSimulationType() == SimulationType::kTensorNetwork)
381 tensorNetwork->AddGate(sxgate, static_cast<unsigned int>(qubit));
382 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
383 extendedStabilizer->ApplySX(qubit);
384 else if (GetSimulationType() == SimulationType::kPauliPropagator)
385 pp->ApplySX(static_cast<unsigned int>(qubit));
386 else if (GetSimulationType() == SimulationType::kPathIntegral) {
387 QC::Gates::AppliedGate<> agate(sxgate.getRawOperatorMatrix(), qubit);
388 pathIntegralSimulator->ApplyGate(agate);
389 }
390 else
391 ApplyStatevectorOrDensityMatrix(sxgate,
392 static_cast<unsigned int>(qubit));
393 NotifyObservers({qubit});
394 }
395
402 void ApplySxDAG(Types::qubit_t qubit) override {
403 if (GetSimulationType() == SimulationType::kMatrixProductState)
404 mpsSimulator->ApplyGate(sxdaggate, static_cast<unsigned int>(qubit));
405 else if (GetSimulationType() == SimulationType::kStabilizer)
406 cliffordSimulator->ApplySxDag(static_cast<unsigned int>(qubit));
407 else if (GetSimulationType() == SimulationType::kTensorNetwork)
408 tensorNetwork->AddGate(sxdaggate, static_cast<unsigned int>(qubit));
409 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
410 extendedStabilizer->ApplySXDG(qubit);
411 else if (GetSimulationType() == SimulationType::kPauliPropagator)
412 pp->ApplySXDG(static_cast<unsigned int>(qubit));
413 else if (GetSimulationType() == SimulationType::kPathIntegral) {
414 QC::Gates::AppliedGate<> agate(sxdaggate.getRawOperatorMatrix(), qubit);
415 pathIntegralSimulator->ApplyGate(agate);
416 }
417 else
418 ApplyStatevectorOrDensityMatrix(sxdaggate,
419 static_cast<unsigned int>(qubit));
420 NotifyObservers({qubit});
421 }
422
429 void ApplyK(Types::qubit_t qubit) override {
430 if (GetSimulationType() == SimulationType::kMatrixProductState)
431 mpsSimulator->ApplyGate(k, static_cast<unsigned int>(qubit));
432 else if (GetSimulationType() == SimulationType::kStabilizer)
433 cliffordSimulator->ApplyK(static_cast<unsigned int>(qubit));
434 else if (GetSimulationType() == SimulationType::kTensorNetwork)
435 tensorNetwork->AddGate(k, static_cast<unsigned int>(qubit));
436 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
437 extendedStabilizer->ApplyK(qubit);
438 else if (GetSimulationType() == SimulationType::kPauliPropagator)
439 pp->ApplyK(static_cast<unsigned int>(qubit));
440 else if (GetSimulationType() == SimulationType::kPathIntegral) {
441 QC::Gates::AppliedGate<> agate(k.getRawOperatorMatrix(), qubit);
442 pathIntegralSimulator->ApplyGate(agate);
443 }
444 else
445 ApplyStatevectorOrDensityMatrix(k, static_cast<unsigned int>(qubit));
446 NotifyObservers({qubit});
447 }
448
456 void ApplyRx(Types::qubit_t qubit, double theta) override {
457 rxgate.SetTheta(theta);
458 if (GetSimulationType() == SimulationType::kMatrixProductState)
459 mpsSimulator->ApplyGate(rxgate, static_cast<unsigned int>(qubit));
460 else if (GetSimulationType() == SimulationType::kStabilizer)
461 throw std::runtime_error(
462 "QCSimSimulator::ApplyRx: The stabilizer "
463 "simulator does not support the Rx gate.");
464 else if (GetSimulationType() == SimulationType::kTensorNetwork)
465 tensorNetwork->AddGate(rxgate, static_cast<unsigned int>(qubit));
466 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
467 extendedStabilizer->ApplyRX(qubit, theta);
468 else if (GetSimulationType() == SimulationType::kPauliPropagator)
469 pp->ApplyRX(static_cast<unsigned int>(qubit), theta);
470 else if (GetSimulationType() == SimulationType::kPathIntegral) {
471 QC::Gates::AppliedGate<> agate(rxgate.getRawOperatorMatrix(), qubit);
472 pathIntegralSimulator->ApplyGate(agate);
473 }
474 else
475 ApplyStatevectorOrDensityMatrix(rxgate,
476 static_cast<unsigned int>(qubit));
477 NotifyObservers({qubit});
478 }
479
487 void ApplyRy(Types::qubit_t qubit, double theta) override {
488 rygate.SetTheta(theta);
489 if (GetSimulationType() == SimulationType::kMatrixProductState)
490 mpsSimulator->ApplyGate(rygate, static_cast<unsigned int>(qubit));
491 else if (GetSimulationType() == SimulationType::kStabilizer)
492 throw std::runtime_error(
493 "QCSimSimulator::ApplyRy: The stabilizer "
494 "simulator does not support the Ry gate.");
495 else if (GetSimulationType() == SimulationType::kTensorNetwork)
496 tensorNetwork->AddGate(rygate, static_cast<unsigned int>(qubit));
497 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
498 extendedStabilizer->ApplyRY(qubit, theta);
499 else if (GetSimulationType() == SimulationType::kPauliPropagator)
500 pp->ApplyRY(static_cast<unsigned int>(qubit), theta);
501 else if (GetSimulationType() == SimulationType::kPathIntegral) {
502 QC::Gates::AppliedGate<> agate(rygate.getRawOperatorMatrix(), qubit);
503 pathIntegralSimulator->ApplyGate(agate);
504 }
505 else
506 ApplyStatevectorOrDensityMatrix(rygate,
507 static_cast<unsigned int>(qubit));
508 NotifyObservers({qubit});
509 }
510
518 void ApplyRz(Types::qubit_t qubit, double theta) override {
519 rzgate.SetTheta(theta);
520 if (GetSimulationType() == SimulationType::kMatrixProductState)
521 mpsSimulator->ApplyGate(rzgate, static_cast<unsigned int>(qubit));
522 else if (GetSimulationType() == SimulationType::kStabilizer)
523 throw std::runtime_error(
524 "QCSimSimulator::ApplyRz: The stabilizer "
525 "simulator does not support the Rz gate.");
526 else if (GetSimulationType() == SimulationType::kTensorNetwork)
527 tensorNetwork->AddGate(rzgate, static_cast<unsigned int>(qubit));
528 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
529 extendedStabilizer->ApplyRZ(qubit, theta);
530 else if (GetSimulationType() == SimulationType::kPauliPropagator)
531 pp->ApplyRZ(static_cast<unsigned int>(qubit), theta);
532 else if (GetSimulationType() == SimulationType::kPathIntegral) {
533 QC::Gates::AppliedGate<> agate(rzgate.getRawOperatorMatrix(), qubit);
534 pathIntegralSimulator->ApplyGate(agate);
535 }
536 else
537 ApplyStatevectorOrDensityMatrix(rzgate,
538 static_cast<unsigned int>(qubit));
539 NotifyObservers({qubit});
540 }
541
552 void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda,
553 double gamma) override {
554 ugate.SetParams(theta, phi, lambda, gamma);
555 if (GetSimulationType() == SimulationType::kMatrixProductState)
556 mpsSimulator->ApplyGate(ugate, static_cast<unsigned int>(qubit));
557 else if (GetSimulationType() == SimulationType::kStabilizer)
558 throw std::runtime_error(
559 "QCSimSimulator::ApplyU: The stabilizer "
560 "simulator does not support the U gate.");
561 else if (GetSimulationType() == SimulationType::kTensorNetwork)
562 tensorNetwork->AddGate(ugate, static_cast<unsigned int>(qubit));
563 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
564 extendedStabilizer->ApplyU(qubit, theta, phi, lambda, gamma);
565 else if (GetSimulationType() == SimulationType::kPauliPropagator)
566 pp->ApplyU(static_cast<unsigned int>(qubit), theta, phi, lambda, gamma);
567 else if (GetSimulationType() == SimulationType::kPathIntegral) {
568 QC::Gates::AppliedGate<> agate(ugate.getRawOperatorMatrix(), qubit);
569 pathIntegralSimulator->ApplyGate(agate);
570 }
571 else
572 ApplyStatevectorOrDensityMatrix(ugate,
573 static_cast<unsigned int>(qubit));
574 NotifyObservers({qubit});
575 }
576
584 void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
585 if (GetSimulationType() == SimulationType::kMatrixProductState)
586 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(tgt_qubit),
587 static_cast<unsigned int>(ctrl_qubit));
588 else if (GetSimulationType() == SimulationType::kStabilizer)
589 cliffordSimulator->ApplyCX(static_cast<unsigned int>(tgt_qubit),
590 static_cast<unsigned int>(ctrl_qubit));
591 else if (GetSimulationType() == SimulationType::kTensorNetwork)
592 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(ctrl_qubit),
593 static_cast<unsigned int>(tgt_qubit));
594 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
595 extendedStabilizer->ApplyCX(ctrl_qubit, tgt_qubit);
596 else if (GetSimulationType() == SimulationType::kPauliPropagator)
597 pp->ApplyCX(static_cast<unsigned int>(ctrl_qubit),
598 static_cast<unsigned int>(tgt_qubit));
599 else if (GetSimulationType() == SimulationType::kPathIntegral) {
600 QC::Gates::AppliedGate<> agate(cxgate.getRawOperatorMatrix(),
601 tgt_qubit, ctrl_qubit);
602 pathIntegralSimulator->ApplyGate(agate);
603 }
604 else
605 ApplyStatevectorOrDensityMatrix(
606 cxgate, static_cast<unsigned int>(tgt_qubit),
607 static_cast<unsigned int>(ctrl_qubit));
608 NotifyObservers({tgt_qubit, ctrl_qubit});
609 }
610
618 void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
619 if (GetSimulationType() == SimulationType::kMatrixProductState)
620 mpsSimulator->ApplyGate(cygate, static_cast<unsigned int>(tgt_qubit),
621 static_cast<unsigned int>(ctrl_qubit));
622 else if (GetSimulationType() == SimulationType::kStabilizer)
623 cliffordSimulator->ApplyCY(static_cast<unsigned int>(tgt_qubit),
624 static_cast<unsigned int>(ctrl_qubit));
625 else if (GetSimulationType() == SimulationType::kTensorNetwork)
626 tensorNetwork->AddGate(cygate, static_cast<unsigned int>(ctrl_qubit),
627 static_cast<unsigned int>(tgt_qubit));
628 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
629 extendedStabilizer->ApplyCY(ctrl_qubit, tgt_qubit);
630 else if (GetSimulationType() == SimulationType::kPauliPropagator)
631 pp->ApplyCY(static_cast<unsigned int>(ctrl_qubit),
632 static_cast<unsigned int>(tgt_qubit));
633 else if (GetSimulationType() == SimulationType::kPathIntegral) {
634 QC::Gates::AppliedGate<> agate(cygate.getRawOperatorMatrix(),
635 tgt_qubit, ctrl_qubit);
636 pathIntegralSimulator->ApplyGate(agate);
637 }
638 else
639 ApplyStatevectorOrDensityMatrix(
640 cygate, static_cast<unsigned int>(tgt_qubit),
641 static_cast<unsigned int>(ctrl_qubit));
642 NotifyObservers({tgt_qubit, ctrl_qubit});
643 }
644
652 void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
653 if (GetSimulationType() == SimulationType::kMatrixProductState)
654 mpsSimulator->ApplyGate(czgate, static_cast<unsigned int>(tgt_qubit),
655 static_cast<unsigned int>(ctrl_qubit));
656 else if (GetSimulationType() == SimulationType::kStabilizer)
657 cliffordSimulator->ApplyCZ(static_cast<unsigned int>(tgt_qubit),
658 static_cast<unsigned int>(ctrl_qubit));
659 else if (GetSimulationType() == SimulationType::kTensorNetwork)
660 tensorNetwork->AddGate(czgate, static_cast<unsigned int>(ctrl_qubit),
661 static_cast<unsigned int>(tgt_qubit));
662 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
663 extendedStabilizer->ApplyCZ(ctrl_qubit, tgt_qubit);
664 else if (GetSimulationType() == SimulationType::kPauliPropagator)
665 pp->ApplyCZ(static_cast<unsigned int>(ctrl_qubit),
666 static_cast<unsigned int>(tgt_qubit));
667 else if (GetSimulationType() == SimulationType::kPathIntegral) {
668 QC::Gates::AppliedGate<> agate(czgate.getRawOperatorMatrix(),
669 tgt_qubit, ctrl_qubit);
670 pathIntegralSimulator->ApplyGate(agate);
671 }
672 else
673 ApplyStatevectorOrDensityMatrix(
674 czgate, static_cast<unsigned int>(tgt_qubit),
675 static_cast<unsigned int>(ctrl_qubit));
676 NotifyObservers({tgt_qubit, ctrl_qubit});
677 }
678
687 void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
688 double lambda) override {
689 cpgate.SetPhaseShift(lambda);
690 if (GetSimulationType() == SimulationType::kMatrixProductState)
691 mpsSimulator->ApplyGate(cpgate, static_cast<unsigned int>(tgt_qubit),
692 static_cast<unsigned int>(ctrl_qubit));
693 else if (GetSimulationType() == SimulationType::kStabilizer)
694 throw std::runtime_error(
695 "QCSimSimulator::ApplyCP: The stabilizer "
696 "simulator does not support the CP gate.");
697 else if (GetSimulationType() == SimulationType::kTensorNetwork)
698 tensorNetwork->AddGate(cpgate, static_cast<unsigned int>(ctrl_qubit),
699 static_cast<unsigned int>(tgt_qubit));
700 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
701 extendedStabilizer->ApplyCP(ctrl_qubit, tgt_qubit, lambda);
702 else if (GetSimulationType() == SimulationType::kPauliPropagator)
703 pp->ApplyCP(static_cast<unsigned int>(ctrl_qubit),
704 static_cast<unsigned int>(tgt_qubit), lambda);
705 else if (GetSimulationType() == SimulationType::kPathIntegral) {
706 QC::Gates::AppliedGate<> agate(cpgate.getRawOperatorMatrix(),
707 tgt_qubit, ctrl_qubit);
708 pathIntegralSimulator->ApplyGate(agate);
709 }
710 else
711 ApplyStatevectorOrDensityMatrix(
712 cpgate, static_cast<unsigned int>(tgt_qubit),
713 static_cast<unsigned int>(ctrl_qubit));
714 NotifyObservers({tgt_qubit, ctrl_qubit});
715 }
716
725 void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
726 double theta) override {
727 crxgate.SetTheta(theta);
728 if (GetSimulationType() == SimulationType::kMatrixProductState)
729 mpsSimulator->ApplyGate(crxgate, static_cast<unsigned int>(tgt_qubit),
730 static_cast<unsigned int>(ctrl_qubit));
731 else if (GetSimulationType() == SimulationType::kStabilizer)
732 throw std::runtime_error(
733 "QCSimSimulator::ApplyCRx: The stabilizer "
734 "simulator does not support the CRx gate.");
735 else if (GetSimulationType() == SimulationType::kTensorNetwork)
736 tensorNetwork->AddGate(crxgate, static_cast<unsigned int>(ctrl_qubit),
737 static_cast<unsigned int>(tgt_qubit));
738 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
739 extendedStabilizer->ApplyCRX(ctrl_qubit, tgt_qubit, theta);
740 else if (GetSimulationType() == SimulationType::kPauliPropagator)
741 pp->ApplyCRX(static_cast<unsigned int>(ctrl_qubit),
742 static_cast<unsigned int>(tgt_qubit), theta);
743 else if (GetSimulationType() == SimulationType::kPathIntegral) {
744 QC::Gates::AppliedGate<> agate(crxgate.getRawOperatorMatrix(),
745 tgt_qubit, ctrl_qubit);
746 pathIntegralSimulator->ApplyGate(agate);
747 }
748 else
749 ApplyStatevectorOrDensityMatrix(
750 crxgate, static_cast<unsigned int>(tgt_qubit),
751 static_cast<unsigned int>(ctrl_qubit));
752 NotifyObservers({tgt_qubit, ctrl_qubit});
753 }
754
763 void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
764 double theta) override {
765 crygate.SetTheta(theta);
766 if (GetSimulationType() == SimulationType::kMatrixProductState)
767 mpsSimulator->ApplyGate(crygate, static_cast<unsigned int>(tgt_qubit),
768 static_cast<unsigned int>(ctrl_qubit));
769 else if (GetSimulationType() == SimulationType::kStabilizer)
770 throw std::runtime_error(
771 "QCSimSimulator::ApplyCRy: The stabilizer "
772 "simulator does not support the CRy gate.");
773 else if (GetSimulationType() == SimulationType::kTensorNetwork)
774 tensorNetwork->AddGate(crygate, static_cast<unsigned int>(ctrl_qubit),
775 static_cast<unsigned int>(tgt_qubit));
776 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
777 extendedStabilizer->ApplyCRY(ctrl_qubit, tgt_qubit, theta);
778 else if (GetSimulationType() == SimulationType::kPauliPropagator)
779 pp->ApplyCRY(static_cast<unsigned int>(ctrl_qubit),
780 static_cast<unsigned int>(tgt_qubit), theta);
781 else if (GetSimulationType() == SimulationType::kPathIntegral) {
782 QC::Gates::AppliedGate<> agate(crygate.getRawOperatorMatrix(),
783 tgt_qubit, ctrl_qubit);
784 pathIntegralSimulator->ApplyGate(agate);
785 }
786 else
787 ApplyStatevectorOrDensityMatrix(
788 crygate, static_cast<unsigned int>(tgt_qubit),
789 static_cast<unsigned int>(ctrl_qubit));
790 NotifyObservers({tgt_qubit, ctrl_qubit});
791 }
792
801 void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
802 double theta) override {
803 crzgate.SetTheta(theta);
804 if (GetSimulationType() == SimulationType::kMatrixProductState)
805 mpsSimulator->ApplyGate(crzgate, static_cast<unsigned int>(tgt_qubit),
806 static_cast<unsigned int>(ctrl_qubit));
807 else if (GetSimulationType() == SimulationType::kStabilizer)
808 throw std::runtime_error(
809 "QCSimSimulator::ApplyCRz: The stabilizer "
810 "simulator does not support the CRz gate.");
811 else if (GetSimulationType() == SimulationType::kTensorNetwork)
812 tensorNetwork->AddGate(crzgate, static_cast<unsigned int>(ctrl_qubit),
813 static_cast<unsigned int>(tgt_qubit));
814 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
815 extendedStabilizer->ApplyCRZ(ctrl_qubit, tgt_qubit, theta);
816 else if (GetSimulationType() == SimulationType::kPauliPropagator)
817 pp->ApplyCRZ(static_cast<unsigned int>(ctrl_qubit),
818 static_cast<unsigned int>(tgt_qubit), theta);
819 else if (GetSimulationType() == SimulationType::kPathIntegral) {
820 QC::Gates::AppliedGate<> agate(crzgate.getRawOperatorMatrix(), tgt_qubit,
821 ctrl_qubit);
822 pathIntegralSimulator->ApplyGate(agate);
823 }
824 else
825 ApplyStatevectorOrDensityMatrix(
826 crzgate, static_cast<unsigned int>(tgt_qubit),
827 static_cast<unsigned int>(ctrl_qubit));
828 NotifyObservers({tgt_qubit, ctrl_qubit});
829 }
830
838 void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
839 if (GetSimulationType() == SimulationType::kMatrixProductState)
840 mpsSimulator->ApplyGate(ch, static_cast<unsigned int>(tgt_qubit),
841 static_cast<unsigned int>(ctrl_qubit));
842 else if (GetSimulationType() == SimulationType::kStabilizer)
843 throw std::runtime_error(
844 "QCSimSimulator::ApplyCH: The stabilizer "
845 "simulator does not support the CH gate.");
846 else if (GetSimulationType() == SimulationType::kTensorNetwork)
847 tensorNetwork->AddGate(ch, static_cast<unsigned int>(ctrl_qubit),
848 static_cast<unsigned int>(tgt_qubit));
849 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
850 extendedStabilizer->ApplyCH(ctrl_qubit, tgt_qubit);
851 else if (GetSimulationType() == SimulationType::kPauliPropagator)
852 pp->ApplyCH(static_cast<unsigned int>(ctrl_qubit),
853 static_cast<unsigned int>(tgt_qubit));
854 else if (GetSimulationType() == SimulationType::kPathIntegral) {
855 QC::Gates::AppliedGate<> agate(ch.getRawOperatorMatrix(), tgt_qubit,
856 ctrl_qubit);
857 pathIntegralSimulator->ApplyGate(agate);
858 }
859 else
860 ApplyStatevectorOrDensityMatrix(
861 ch, static_cast<unsigned int>(tgt_qubit),
862 static_cast<unsigned int>(ctrl_qubit));
863 NotifyObservers({tgt_qubit, ctrl_qubit});
864 }
865
873 void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit) override {
874 if (GetSimulationType() == SimulationType::kMatrixProductState)
875 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(tgt_qubit),
876 static_cast<unsigned int>(ctrl_qubit));
877 else if (GetSimulationType() == SimulationType::kStabilizer)
878 throw std::runtime_error(
879 "QCSimSimulator::ApplyCSx: The stabilizer "
880 "simulator does not support the CSx gate.");
881 else if (GetSimulationType() == SimulationType::kTensorNetwork)
882 tensorNetwork->AddGate(csx, static_cast<unsigned int>(ctrl_qubit),
883 static_cast<unsigned int>(tgt_qubit));
884 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
885 extendedStabilizer->ApplyCSX(ctrl_qubit, tgt_qubit);
886 else if (GetSimulationType() == SimulationType::kPauliPropagator)
887 pp->ApplyCSX(static_cast<unsigned int>(ctrl_qubit),
888 static_cast<unsigned int>(tgt_qubit));
889 else if (GetSimulationType() == SimulationType::kPathIntegral) {
890 QC::Gates::AppliedGate<> agate(csx.getRawOperatorMatrix(), tgt_qubit,
891 ctrl_qubit);
892 pathIntegralSimulator->ApplyGate(agate);
893 }
894 else
895 ApplyStatevectorOrDensityMatrix(
896 csx, static_cast<unsigned int>(tgt_qubit),
897 static_cast<unsigned int>(ctrl_qubit));
898 NotifyObservers({tgt_qubit, ctrl_qubit});
899 }
900
908 void ApplyCSxDAG(Types::qubit_t ctrl_qubit,
909 Types::qubit_t tgt_qubit) override {
910 if (GetSimulationType() == SimulationType::kMatrixProductState)
911 mpsSimulator->ApplyGate(csxdag, static_cast<unsigned int>(tgt_qubit),
912 static_cast<unsigned int>(ctrl_qubit));
913 else if (GetSimulationType() == SimulationType::kStabilizer)
914 throw std::runtime_error(
915 "QCSimSimulator::ApplyCSxDAG: The stabilizer "
916 "simulator does not support the CSxDag gate.");
917 else if (GetSimulationType() == SimulationType::kTensorNetwork)
918 tensorNetwork->AddGate(csxdag, static_cast<unsigned int>(ctrl_qubit),
919 static_cast<unsigned int>(tgt_qubit));
920 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
921 extendedStabilizer->ApplyCSXDAG(ctrl_qubit, tgt_qubit);
922 else if (GetSimulationType() == SimulationType::kPauliPropagator)
923 pp->ApplyCSXDAG(static_cast<unsigned int>(ctrl_qubit),
924 static_cast<unsigned int>(tgt_qubit));
925 else if (GetSimulationType() == SimulationType::kPathIntegral) {
926 QC::Gates::AppliedGate<> agate(csxdag.getRawOperatorMatrix(), tgt_qubit,
927 ctrl_qubit);
928 pathIntegralSimulator->ApplyGate(agate);
929 }
930 else
931 ApplyStatevectorOrDensityMatrix(
932 csxdag, static_cast<unsigned int>(tgt_qubit),
933 static_cast<unsigned int>(ctrl_qubit));
934 NotifyObservers({tgt_qubit, ctrl_qubit});
935 }
936
944 void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1) override {
945 if (GetSimulationType() == SimulationType::kMatrixProductState)
946 mpsSimulator->ApplyGate(swapgate, static_cast<unsigned int>(qubit1),
947 static_cast<unsigned int>(qubit0));
948 else if (GetSimulationType() == SimulationType::kStabilizer)
949 cliffordSimulator->ApplySwap(static_cast<unsigned int>(qubit1),
950 static_cast<unsigned int>(qubit0));
951 else if (GetSimulationType() == SimulationType::kTensorNetwork)
952 tensorNetwork->AddGate(swapgate, static_cast<unsigned int>(qubit0),
953 static_cast<unsigned int>(qubit1));
954 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
955 extendedStabilizer->ApplySWAP(qubit0, qubit1);
956 else if (GetSimulationType() == SimulationType::kPauliPropagator)
957 pp->ApplySWAP(static_cast<unsigned int>(qubit0),
958 static_cast<unsigned int>(qubit1));
959 else if (GetSimulationType() == SimulationType::kPathIntegral) {
960 QC::Gates::AppliedGate<> agate(swapgate.getRawOperatorMatrix(), qubit1,
961 qubit0);
962 pathIntegralSimulator->ApplyGate(agate);
963 }
964 else
965 ApplyStatevectorOrDensityMatrix(
966 swapgate, static_cast<unsigned int>(qubit1),
967 static_cast<unsigned int>(qubit0));
968 NotifyObservers({qubit1, qubit0});
969 }
970
979 void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1,
980 Types::qubit_t qubit2) override {
981 if (GetSimulationType() == SimulationType::kMatrixProductState) {
982 const size_t q1 = qubit0; // control 1
983 const size_t q2 = qubit1; // control 2
984 const size_t q3 = qubit2; // target
985
986 // Sleator-Weinfurter decomposition
987 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
988 static_cast<unsigned int>(q2));
989 NotifyObservers({qubit1, qubit2});
990
991 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
992 static_cast<unsigned int>(q1));
993 NotifyObservers({qubit0, qubit1});
994
995 mpsSimulator->ApplyGate(csxdag, static_cast<unsigned int>(q3),
996 static_cast<unsigned int>(q2));
997 NotifyObservers({qubit1, qubit2});
998
999 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
1000 static_cast<unsigned int>(q1));
1001 NotifyObservers({qubit0, qubit1});
1002
1003 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
1004 static_cast<unsigned int>(q1));
1005 NotifyObservers({qubit0, qubit2});
1006 } else if (GetSimulationType() ==
1007 SimulationType::kMatrixProductOperator) {
1008 ApplyDecomposedGate(
1009 [&]() {
1010 ApplyCSx(qubit1, qubit2);
1011 ApplyCX(qubit0, qubit1);
1012 ApplyCSxDAG(qubit1, qubit2);
1013 ApplyCX(qubit0, qubit1);
1014 ApplyCSx(qubit0, qubit2);
1015 },
1016 {qubit2, qubit1, qubit0});
1017 } else if (GetSimulationType() == SimulationType::kStabilizer)
1018 throw std::runtime_error(
1019 "QCSimSimulator::ApplyCCX: The stabilizer "
1020 "simulator does not support the CCX gate.");
1021 else if (GetSimulationType() == SimulationType::kTensorNetwork) {
1022 const size_t q1 = qubit0; // control 1
1023 const size_t q2 = qubit1; // control 2
1024 const size_t q3 = qubit2; // target
1025
1026 // Sleator-Weinfurter decomposition
1027 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q2),
1028 static_cast<unsigned int>(q3));
1029 NotifyObservers({qubit1, qubit2});
1030
1031 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
1032 static_cast<unsigned int>(q2));
1033 NotifyObservers({qubit0, qubit1});
1034
1035 tensorNetwork->AddGate(csxdag, static_cast<unsigned int>(q2),
1036 static_cast<unsigned int>(q3));
1037 NotifyObservers({qubit1, qubit2});
1038
1039 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
1040 static_cast<unsigned int>(q2));
1041 NotifyObservers({qubit0, qubit1});
1042
1043 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q1),
1044 static_cast<unsigned int>(q3));
1045 NotifyObservers({qubit0, qubit2});
1046 } else if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
1047 extendedStabilizer->ApplyCCX(qubit0, qubit1, qubit2);
1048 NotifyObservers({qubit2, qubit1, qubit0});
1049 } else if (GetSimulationType() == SimulationType::kPauliPropagator) {
1050 pp->ApplyCCX(static_cast<unsigned int>(qubit0),
1051 static_cast<unsigned int>(qubit1),
1052 static_cast<unsigned int>(qubit2));
1053 NotifyObservers({qubit2, qubit1, qubit0});
1054 } else if (GetSimulationType() == SimulationType::kPathIntegral) {
1055 QC::Gates::AppliedGate<> agate(ccxgate.getRawOperatorMatrix(), qubit2,
1056 qubit1, qubit0);
1057 pathIntegralSimulator->ApplyGate(agate);
1058 NotifyObservers({qubit2, qubit1, qubit0});
1059 } else {
1060 ApplyStatevectorOrDensityMatrix(
1061 ccxgate, static_cast<unsigned int>(qubit2),
1062 static_cast<unsigned int>(qubit1),
1063 static_cast<unsigned int>(qubit0));
1064 NotifyObservers({qubit2, qubit1, qubit0});
1065 }
1066 }
1067
1076 void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0,
1077 Types::qubit_t qubit1) override {
1078 if (GetSimulationType() == SimulationType::kMatrixProductState) {
1079 const size_t q1 = ctrl_qubit; // control
1080 const size_t q2 = qubit0;
1081 const size_t q3 = qubit1;
1082
1083 // TODO: find a better decomposition
1084 // this one I've got with the qiskit transpiler
1085 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
1086 static_cast<unsigned int>(q3));
1087 NotifyObservers({qubit1, qubit0});
1088
1089 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
1090 static_cast<unsigned int>(q2));
1091 NotifyObservers({qubit0, qubit1});
1092
1093 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
1094 static_cast<unsigned int>(q1));
1095 NotifyObservers({ctrl_qubit, qubit0});
1096
1097 pgate.SetPhaseShift(M_PI);
1098 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(q3));
1099 NotifyObservers({qubit1});
1100 pgate.SetPhaseShift(-M_PI_2);
1101 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(q2));
1102 NotifyObservers({qubit0});
1103
1104 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
1105 static_cast<unsigned int>(q2));
1106 NotifyObservers({qubit0, qubit1});
1107
1108 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
1109 static_cast<unsigned int>(q1));
1110 NotifyObservers({ctrl_qubit, qubit0});
1111
1112 pgate.SetPhaseShift(M_PI);
1113 mpsSimulator->ApplyGate(pgate, static_cast<unsigned int>(q3));
1114 NotifyObservers({qubit1});
1115
1116 mpsSimulator->ApplyGate(csx, static_cast<unsigned int>(q3),
1117 static_cast<unsigned int>(q1));
1118 NotifyObservers({ctrl_qubit, qubit1});
1119
1120 mpsSimulator->ApplyGate(cxgate, static_cast<unsigned int>(q2),
1121 static_cast<unsigned int>(q3));
1122 NotifyObservers({qubit1, qubit0});
1123 } else if (GetSimulationType() ==
1124 SimulationType::kMatrixProductOperator) {
1125 ApplyDecomposedGate(
1126 [&]() {
1127 ApplyCX(qubit1, qubit0);
1128 ApplyCSx(qubit0, qubit1);
1129 ApplyCX(ctrl_qubit, qubit0);
1130 ApplyP(qubit1, M_PI);
1131 ApplyP(qubit0, -M_PI_2);
1132 ApplyCSx(qubit0, qubit1);
1133 ApplyCX(ctrl_qubit, qubit0);
1134 ApplyP(qubit1, M_PI);
1135 ApplyCSx(ctrl_qubit, qubit1);
1136 ApplyCX(qubit1, qubit0);
1137 },
1138 {qubit1, qubit0, ctrl_qubit});
1139 } else if (GetSimulationType() == SimulationType::kStabilizer)
1140 throw std::runtime_error(
1141 "QCSimSimulator::ApplyCSwap: The stabilizer "
1142 "simulator does not support the CSwap gate.");
1143 else if (GetSimulationType() == SimulationType::kTensorNetwork) {
1144 const size_t q1 = ctrl_qubit; // control
1145 const size_t q2 = qubit0;
1146 const size_t q3 = qubit1;
1147
1148 // TODO: find a better decomposition
1149 // this one I've got with the qiskit transpiler
1150 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q3),
1151 static_cast<unsigned int>(q2));
1152 NotifyObservers({qubit1, qubit0});
1153
1154 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q2),
1155 static_cast<unsigned int>(q3));
1156 NotifyObservers({qubit0, qubit1});
1157
1158 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
1159 static_cast<unsigned int>(q2));
1160 NotifyObservers({ctrl_qubit, qubit0});
1161
1162 pgate.SetPhaseShift(M_PI);
1163 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(q3));
1164 NotifyObservers({qubit1});
1165 pgate.SetPhaseShift(-M_PI_2);
1166 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(q2));
1167 NotifyObservers({qubit0});
1168
1169 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q2),
1170 static_cast<unsigned int>(q3));
1171 NotifyObservers({qubit0, qubit1});
1172
1173 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q1),
1174 static_cast<unsigned int>(q2));
1175 NotifyObservers({ctrl_qubit, qubit0});
1176
1177 pgate.SetPhaseShift(M_PI);
1178 tensorNetwork->AddGate(pgate, static_cast<unsigned int>(q3));
1179 NotifyObservers({qubit1});
1180
1181 tensorNetwork->AddGate(csx, static_cast<unsigned int>(q1),
1182 static_cast<unsigned int>(q3));
1183 NotifyObservers({ctrl_qubit, qubit1});
1184
1185 tensorNetwork->AddGate(cxgate, static_cast<unsigned int>(q3),
1186 static_cast<unsigned int>(q2));
1187 NotifyObservers({qubit1, qubit0});
1188 } else if (GetSimulationType() == SimulationType::kExtendedStabilizer) {
1189 extendedStabilizer->ApplyCSwap(ctrl_qubit, qubit0, qubit1);
1190 NotifyObservers({qubit1, qubit0, ctrl_qubit});
1191 } else if (GetSimulationType() == SimulationType::kPauliPropagator) {
1192 pp->ApplyCSwap(static_cast<unsigned int>(ctrl_qubit),
1193 static_cast<unsigned int>(qubit0),
1194 static_cast<unsigned int>(qubit1));
1195 NotifyObservers({qubit1, qubit0, ctrl_qubit});
1196 } else if (GetSimulationType() == SimulationType::kPathIntegral) {
1197 QC::Gates::AppliedGate<> agate(cswapgate.getRawOperatorMatrix(),
1198 qubit1, qubit0, ctrl_qubit);
1199 pathIntegralSimulator->ApplyGate(agate);
1200 NotifyObservers({qubit1, qubit0, ctrl_qubit});
1201 } else {
1202 ApplyStatevectorOrDensityMatrix(
1203 cswapgate, static_cast<unsigned int>(qubit1),
1204 static_cast<unsigned int>(qubit0),
1205 static_cast<unsigned int>(ctrl_qubit));
1206 NotifyObservers({qubit1, qubit0, ctrl_qubit});
1207 }
1208 }
1209
1221 void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit,
1222 double theta, double phi, double lambda, double gamma) override {
1223 cugate.SetParams(theta, phi, lambda, gamma);
1224 if (GetSimulationType() == SimulationType::kMatrixProductState)
1225 mpsSimulator->ApplyGate(cugate, static_cast<unsigned int>(tgt_qubit),
1226 static_cast<unsigned int>(ctrl_qubit));
1227 else if (GetSimulationType() == SimulationType::kStabilizer)
1228 throw std::runtime_error(
1229 "QCSimSimulator::ApplyCU: The stabilizer "
1230 "simulator does not support the CU gate.");
1231 else if (GetSimulationType() == SimulationType::kTensorNetwork)
1232 tensorNetwork->AddGate(cugate, static_cast<unsigned int>(ctrl_qubit),
1233 static_cast<unsigned int>(tgt_qubit));
1234 else if (GetSimulationType() == SimulationType::kExtendedStabilizer)
1235 extendedStabilizer->ApplyCU(ctrl_qubit, tgt_qubit, theta, phi, lambda,
1236 gamma);
1237 else if (GetSimulationType() == SimulationType::kPauliPropagator)
1238 pp->ApplyCU(static_cast<unsigned int>(ctrl_qubit),
1239 static_cast<unsigned int>(tgt_qubit), theta, phi, lambda,
1240 gamma);
1241 else if (GetSimulationType() == SimulationType::kPathIntegral) {
1242 QC::Gates::AppliedGate<> agate(cugate.getRawOperatorMatrix(), tgt_qubit,
1243 ctrl_qubit);
1244 pathIntegralSimulator->ApplyGate(agate);
1245 }
1246 else
1247 ApplyStatevectorOrDensityMatrix(
1248 cugate, static_cast<unsigned int>(tgt_qubit),
1249 static_cast<unsigned int>(ctrl_qubit));
1250 NotifyObservers({tgt_qubit, ctrl_qubit});
1251 }
1252
1260 void ApplyNop() override {
1261 // do nothing
1262 }
1263
1274 std::unique_ptr<ISimulator> Clone() override {
1275 auto cloned = std::make_unique<QCSimSimulator>();
1276
1277 cloned->simulationType = simulationType;
1278 cloned->nrQubits = nrQubits;
1279
1280 cloned->enableMultithreading = enableMultithreading;
1281
1282 cloned->lookaheadDepth = lookaheadDepth;
1283 cloned->lookaheadDepthWithHeuristic = lookaheadDepthWithHeuristic;
1284 cloned->useOptimalMeetingPosition = useOptimalMeetingPosition;
1285 cloned->upcomingGates = upcomingGates;
1286 cloned->upcomingGateIndex = upcomingGateIndex;
1287 cloned->growthFactorGate = growthFactorGate;
1288 cloned->growthFactorSwap = growthFactorSwap;
1289
1290 if (state) cloned->state = state->Clone();
1291
1292 if (mpsSimulator) {
1293 cloned->mpsSimulator = mpsSimulator->Clone();
1294
1295 cloned->dummySim = dummySim ? dummySim->Clone() : nullptr;
1296
1297 cloned->gateCounterObserver =
1298 std::make_shared<GateCounterObserver>(cloned->upcomingGateIndex);
1299 cloned->RegisterObserver(cloned->gateCounterObserver);
1300
1301 cloned->curMaxBondDim = curMaxBondDim;
1302
1303 cloned->mpsSimulator->SetMeetingPositionCallback(
1304 cloned->meetingPositionCallback);
1305 cloned->mpsSimulator->SetBondDimensionCallback(
1306 cloned->bondDimensionCallback);
1307 }
1308
1309 if (mpoSimulator) {
1310 cloned->mpoSimulator = mpoSimulator->Clone();
1311 cloned->dummySim = dummySim ? dummySim->Clone() : nullptr;
1312 cloned->curMaxBondDim = curMaxBondDim;
1313 cloned->gateCounterObserver =
1314 std::make_shared<GateCounterObserver>(cloned->upcomingGateIndex);
1315 cloned->RegisterObserver(cloned->gateCounterObserver);
1316 cloned->mpoSimulator->SetMeetingPositionCallback(
1317 cloned->meetingPositionCallback);
1318 cloned->mpoSimulator->SetBondDimensionCallback(
1319 cloned->bondDimensionCallback);
1320 }
1321
1322 if (cliffordSimulator)
1323 cloned->cliffordSimulator = cliffordSimulator->Clone();
1324
1325 if (tensorNetwork) cloned->tensorNetwork = tensorNetwork->Clone();
1326
1327 if (pp) cloned->pp = pp->Clone();
1328
1329 if (pathIntegralSimulator)
1330 cloned->pathIntegralSimulator = pathIntegralSimulator->Clone();
1331
1332 if (densityMatrix) cloned->densityMatrix = densityMatrix->Clone();
1333
1334 if (extendedStabilizer)
1335 cloned->extendedStabilizer = extendedStabilizer->Clone();
1336
1337 for (const auto& [key, value] : configuration.GetConfigMap())
1338 cloned->Configure(key.c_str(), value.c_str());
1339
1340 if (configuration.IsSet("seed"))
1341 cloned->SetSeed(DeriveSeed(
1342 std::stoull(configuration.GetConfiguration("seed")),
1343 nextSeedStream++));
1344
1345 return cloned;
1346 }
1347
1348 private:
1349 template <class Function>
1350 void ApplyDecomposedGate(Function&& apply,
1351 const Types::qubits_vector& affectedQubits) {
1352 DontNotify();
1353 try {
1354 std::forward<Function>(apply)();
1355 } catch (...) {
1356 Notify();
1357 throw;
1358 }
1359 Notify();
1360 NotifyObservers(affectedQubits);
1361 }
1362
1363 template <class Gate, class... Qubits>
1364 void ApplyStatevectorOrDensityMatrix(const Gate& gate, Qubits... qubits) {
1365 if (GetSimulationType() == SimulationType::kMatrixProductOperator) {
1366 if constexpr (sizeof...(Qubits) <= 2) {
1367 mpoSimulator->ApplyGate(gate, static_cast<Eigen::Index>(qubits)...);
1368 } else {
1369 throw std::runtime_error(
1370 "QCSimSimulator: The matrix product operator simulator supports "
1371 "only one- and two-qubit gate operators.");
1372 }
1373 } else if (GetSimulationType() == SimulationType::kDensityMatrix)
1374 densityMatrix->ApplyGate(gate, static_cast<size_t>(qubits)...);
1375 else
1376 state->ApplyGate(gate, qubits...);
1377 }
1378
1379 QC::Gates::PhaseShiftGate<> pgate;
1380 QC::Gates::PauliXGate<> xgate;
1381 QC::Gates::PauliYGate<> ygate;
1382 QC::Gates::PauliZGate<> zgate;
1383 QC::Gates::HadamardGate<> h;
1384 // QC::Gates::UGate<> ugate;
1385 QC::Gates::SGate<> sgate;
1386 QC::Gates::SDGGate<> sdggate;
1387 QC::Gates::TGate<> tgate;
1388 QC::Gates::TDGGate<> tdggate;
1389 QC::Gates::SquareRootNOTGate<> sxgate;
1390 QC::Gates::SquareRootNOTDagGate<> sxdaggate;
1391 QC::Gates::HyGate<> k;
1392 QC::Gates::RxGate<> rxgate;
1393 QC::Gates::RyGate<> rygate;
1394 QC::Gates::RzGate<> rzgate;
1395 QC::Gates::UGate<> ugate;
1396 QC::Gates::CNOTGate<> cxgate;
1397 QC::Gates::ControlledYGate<> cygate;
1398 QC::Gates::ControlledZGate<> czgate;
1399 QC::Gates::ControlledPhaseShiftGate<> cpgate;
1400 QC::Gates::ControlledRxGate<> crxgate;
1401 QC::Gates::ControlledRyGate<> crygate;
1402 QC::Gates::ControlledRzGate<> crzgate;
1403 QC::Gates::ControlledHadamardGate<> ch;
1404 QC::Gates::ControlledSquareRootNOTGate<> csx;
1405 QC::Gates::ControlledSquareRootNOTDagGate<> csxdag;
1406 QC::Gates::SwapGate<> swapgate;
1407 QC::Gates::ToffoliGate<> ccxgate;
1408 QC::Gates::FredkinGate<> cswapgate;
1409 QC::Gates::ControlledUGate<> cugate;
1410};
1411
1412} // namespace Private
1413} // namespace Simulators
1414
1415#endif
1416
1417#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)
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:22
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:21