Maestro 0.2.5
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Circuit/Factory.h
Go to the documentation of this file.
1
15#pragma once
16
17#ifndef _CIRCUIT_FACTORY_H_
18#define _CIRCUIT_FACTORY_H_
19
20#include "Circuit.h"
21#include "Conditional.h"
22#include "Measurements.h"
23#include "RandomOp.h"
24#include "Reset.h"
25
26namespace Circuits {
27
37template <typename Time = Types::time_type>
39 public:
48 static std::shared_ptr<Circuit<Time>> CreateCircuit(
49 const std::vector<std::shared_ptr<IOperation<Time>>> &ops = {}) {
50 return std::make_shared<Circuit<Time>>(ops);
51 }
52
65 static std::shared_ptr<IOperation<Time>> CreateReset(
66 const Types::qubits_vector &qubits = {},
67 const std::vector<bool> &resetTgts = {}) {
68 return std::make_shared<Reset<Time>>(qubits, 0, resetTgts);
69 }
70
81 static std::shared_ptr<IOperation<Time>> CreateRandom(
82 const std::vector<size_t> &bits = {}, size_t seed = 0) {
83 return std::make_shared<Random<Time>>(bits, seed);
84 }
85
96 static const std::shared_ptr<IOperation<Time>> CreateMeasurement(
97 const std::vector<std::pair<Types::qubit_t, size_t>> &qs = {}) {
98 return std::make_shared<MeasurementOperation<Time>>(qs);
99 }
100
123 static const std::shared_ptr<IQuantumGate<Time>> CreateGate(
124 QuantumGateType type, size_t q1, size_t q2 = 0, size_t q3 = 0,
125 double param1 = 0, double param2 = 0, double param3 = 0,
126 double param4 = 0) {
127 // parameters that do not make sense for a gate are ignored, eg if it's a
128 // single qubit gate, q2 and q3 are ignored if it doesn't have a parameter,
129 // the parameter is ignored if it has only one, the others are ignored
130 // TODO: maybe make specialized variants, as in CreateOneQubitGate,
131 // CreateTwoQubitGate, etc
132 std::shared_ptr<IQuantumGate<Time>> gate;
133
134 switch (type) {
135 // one qubit gates
137 gate = std::make_shared<PhaseGate<Time>>(q1, param1);
138 break;
140 gate = std::make_shared<XGate<Time>>(q1);
141 break;
143 gate = std::make_shared<YGate<Time>>(q1);
144 break;
146 gate = std::make_shared<ZGate<Time>>(q1);
147 break;
149 gate = std::make_shared<HadamardGate<Time>>(q1);
150 break;
152 gate = std::make_shared<SGate<Time>>(q1);
153 break;
155 gate = std::make_shared<SdgGate<Time>>(q1);
156 break;
158 gate = std::make_shared<TGate<Time>>(q1);
159 break;
161 gate = std::make_shared<TdgGate<Time>>(q1);
162 break;
164 gate = std::make_shared<SxGate<Time>>(q1);
165 break;
167 gate = std::make_shared<SxDagGate<Time>>(q1);
168 break;
170 gate = std::make_shared<KGate<Time>>(q1);
171 break;
173 gate = std::make_shared<RxGate<Time>>(q1, param1);
174 break;
176 gate = std::make_shared<RyGate<Time>>(q1, param1);
177 break;
179 gate = std::make_shared<RzGate<Time>>(q1, param1);
180 break;
182 gate =
183 std::make_shared<UGate<Time>>(q1, param1, param2, param3, param4);
184 break;
185 // two qubit gates
187 gate = std::make_shared<SwapGate<Time>>(q1, q2);
188 break;
190 gate = std::make_shared<CXGate<Time>>(q1, q2);
191 break;
193 gate = std::make_shared<CYGate<Time>>(q1, q2);
194 break;
196 gate = std::make_shared<CZGate<Time>>(q1, q2);
197 break;
199 gate = std::make_shared<CPGate<Time>>(q1, q2, param1);
200 break;
202 gate = std::make_shared<CRxGate<Time>>(q1, q2, param1);
203 break;
205 gate = std::make_shared<CRyGate<Time>>(q1, q2, param1);
206 break;
208 gate = std::make_shared<CRzGate<Time>>(q1, q2, param1);
209 break;
211 gate = std::make_shared<CHGate<Time>>(q1, q2);
212 break;
214 gate = std::make_shared<CSxGate<Time>>(q1, q2);
215 break;
217 gate = std::make_shared<CSxDagGate<Time>>(q1, q2);
218 break;
220 gate = std::make_shared<CUGate<Time>>(q1, q2, param1, param2, param3,
221 param4);
222 break;
223 // three qubit gates
225 gate = std::make_shared<CSwapGate<Time>>(q1, q2, q3);
226 break;
228 gate = std::make_shared<CCXGate<Time>>(q1, q2, q3);
229 break;
230 default:
231 break;
232 }
233
234 return gate;
235 }
236
249 static const std::shared_ptr<IOperation<Time>> CreateGateWithVectors(
250 QuantumGateType type, const Types::qubits_vector &qubits,
251 const std::vector<double> &params = {}) {
252 return CreateGate(type, qubits.empty() ? 0 : qubits[0],
253 (qubits.size() < 2) ? 0 : qubits[1],
254 (qubits.size() < 3) ? 0 : qubits[2],
255 params.empty() ? 0. : params[0],
256 (params.size() < 2) ? 0. : params[1],
257 (params.size() < 3) ? 0. : params[2],
258 (params.size() < 4) ? 0. : params[3]);
259 }
260
261 // maybe this could be refined, have a CreateCondition with the condition
262 // type, but for now we only have equality can be done later
263
275 static std::shared_ptr<ICondition> CreateEqualCondition(
276 const std::vector<size_t> &ind, const std::vector<bool> &b) {
277 return std::make_shared<EqualCondition>(ind, b);
278 }
279
280 // we have only three conditional things, I don't think we need a single
281 // factory method for them (with a 'type' parameter)
282
295 static std::shared_ptr<IOperation<Time>> CreateConditionalGate(
296 const std::shared_ptr<IGateOperation<Time>> &operation,
297 const std::shared_ptr<ICondition> &condition) {
298 return std::make_shared<ConditionalGate<Time>>(operation, condition);
299 }
300
314 static std::shared_ptr<IOperation<Time>> CreateSimpleConditionalGate(
315 const std::shared_ptr<IGateOperation<Time>> &operation,
316 const size_t cbit) {
317 const auto eqcond = CreateEqualCondition({cbit}, {true});
318 return std::make_shared<ConditionalGate<Time>>(operation, eqcond);
319 }
320
334 static std::shared_ptr<IOperation<Time>> CreateConditionalMeasurement(
335 const std::shared_ptr<MeasurementOperation<Time>> &measurement,
336 const std::shared_ptr<ICondition> &condition) {
337 return std::make_shared<ConditionalMeasurement<Time>>(measurement,
338 condition);
339 }
340
355 static std::shared_ptr<IOperation<Time>> CreateConditionalRandomGen(
356 const std::shared_ptr<Random<Time>> &randomGen,
357 const std::shared_ptr<ICondition> &condition) {
358 return std::make_shared<ConditionalRandomGen<Time>>(randomGen, condition);
359 }
360
369 static std::shared_ptr<IOperation<Time>> CreateNoOp() {
370 return std::make_shared<NoOperation<Time>>();
371 }
372
385 static std::vector<std::shared_ptr<IOperation<Time>>> CreateBellStateCircuit(
386 size_t qbit1, size_t qbit2, bool qbit1X = false, bool qbit2X = false) {
387 size_t s = 2;
388 if (qbit1X) ++s;
389 if (qbit2X) ++s;
390
391 std::vector<std::shared_ptr<IOperation<Time>>> ops(s);
392
393 s = 0;
394 if (qbit1X) ops[s++] = CreateGate(QuantumGateType::kXGateType, qbit1);
395 if (qbit2X) ops[s++] = CreateGate(QuantumGateType::kXGateType, qbit2);
397 ops[s] = CreateGate(QuantumGateType::kCXGateType, qbit1, qbit2);
398
399 return ops;
400 }
401
412 static std::vector<std::shared_ptr<IOperation<Time>>>
413 CreateBellStateDecoderCircuit(size_t qbit1, size_t qbit2) {
414 std::vector<std::shared_ptr<IOperation<Time>>> ops(2);
415
416 ops[0] = CreateGate(QuantumGateType::kCXGateType, qbit1, qbit2);
418
419 return ops;
420 }
421
433 static std::vector<std::shared_ptr<IOperation<Time>>> CreateGZHStateCircuit(
434 size_t qbit1, size_t qbit2, size_t qbit3) {
435 std::vector<std::shared_ptr<IOperation<Time>>> ops(3);
436
438 ops[1] = CreateGate(QuantumGateType::kCXGateType, qbit1, qbit2);
439 ops[2] = CreateGate(QuantumGateType::kCXGateType, qbit2, qbit3);
440
441 return ops;
442 }
443
460 static std::vector<std::shared_ptr<IOperation<Time>>>
461 CreateTeleportationCircuit(size_t entqbit1, size_t entqbit2, size_t srcqbit,
462 size_t cbit1, size_t cbit2) {
463 std::vector<std::shared_ptr<IOperation<Time>>> ops(8);
464
465 // EPR pair
467 ops[1] = CreateGate(QuantumGateType::kCXGateType, entqbit1, entqbit2);
468
469 // teleportation follows, using the entangled qubits
470 ops[2] = CreateGate(QuantumGateType::kCXGateType, srcqbit, entqbit1);
472
473 // measurements
474 ops[4] = CreateMeasurement({{srcqbit, cbit1}});
475 ops[5] = CreateMeasurement({{entqbit1, cbit2}});
476
477 // apply the conditional gates based on the measurements
478 const auto xgate = CreateGate(QuantumGateType::kXGateType, entqbit2);
479 const auto zgate = CreateGate(QuantumGateType::kZGateType, entqbit2);
480
481 ops[6] = CreateSimpleConditionalGate(xgate, cbit2);
482 ops[7] = CreateSimpleConditionalGate(zgate, cbit1);
483
484 return ops;
485 }
486
499 static std::vector<std::shared_ptr<IOperation<Time>>>
500 CreateStartDistributionCircuit(size_t ctrlQubit, size_t ctrlEntangledQubit,
501 size_t tgtEntangledQubit,
502 size_t ctrlEntangledMeasureBit) {
503 std::vector<std::shared_ptr<IOperation<Time>>> ops(5);
504 // 1. Entangle qubits for the two hosts
505 // auto ops = CreateBellStateCircuit(ctrlEntangledQubit, tgtEntangledQubit);
506 ops[0] = CreateGate(QuantumGateType::kHadamardGateType, ctrlEntangledQubit);
507 ops[1] = CreateGate(QuantumGateType::kCXGateType, ctrlEntangledQubit,
508 tgtEntangledQubit);
509
510 // 2. Now apply cnot from ctrl to entangled qubit on ctrl host
511 // ops.emplace_back(std::make_shared<Circuits::CXGate<Time>>(ctrlQubit,
512 // ctrlEntangledQubit));
513 ops[2] =
514 CreateGate(QuantumGateType::kCXGateType, ctrlQubit, ctrlEntangledQubit);
515 // 3. Measure the entangled qubit on ctrl host (then the measurement result
516 // is sent to the other host)
517 const std::vector<std::pair<Types::qubit_t, size_t>> measureOps{
518 {ctrlEntangledQubit, ctrlEntangledMeasureBit}};
519 // ops.emplace_back(std::make_shared<Circuits::MeasurementOperation<Time>>(measureOps));
520 ops[3] = CreateMeasurement(measureOps);
521
522 // 4. Send the measurement result to the target host, use the result to
523 // apply not on the target entangled qubit
524 // ops.emplace_back(std::make_shared<Circuits::ConditionalGate<Time>>(std::make_shared<Circuits::XGate<Time>>(tgtEntangledQubit),
525 // std::make_shared<Circuits::EqualCondition>(std::vector<size_t>{
526 // ctrlEntangledMeasureBit }, std::vector<bool>{true})));
527 ops[4] = std::make_shared<Circuits::ConditionalGate<Time>>(
528 std::make_shared<Circuits::XGate<Time>>(tgtEntangledQubit),
529 std::make_shared<Circuits::EqualCondition>(
530 std::vector<size_t>{ctrlEntangledMeasureBit},
531 std::vector<bool>{true}));
532
533 return ops;
534 }
535
547 static std::vector<std::shared_ptr<IOperation<Time>>>
548 CreateEndDistributionCircuit(size_t ctrlQubit, size_t tgtEntangledQubit,
549 size_t tgtEntangledMeasureBit) {
550 std::vector<std::shared_ptr<IOperation<Time>>> ops(3);
551
552 ops[0] = std::make_shared<Circuits::HadamardGate<Time>>(tgtEntangledQubit);
553 const std::vector<std::pair<Types::qubit_t, size_t>> measureOps{
554 {tgtEntangledQubit, tgtEntangledMeasureBit}};
555 ops[1] = std::make_shared<Circuits::MeasurementOperation<Time>>(measureOps);
556 ops[2] = std::make_shared<Circuits::ConditionalGate<Time>>(
557 std::make_shared<Circuits::ZGate<Time>>(ctrlQubit),
558 std::make_shared<Circuits::EqualCondition>(
559 std::vector<size_t>{tgtEntangledMeasureBit},
560 std::vector<bool>{true}));
561
562 return ops;
563 }
564
573 static std::vector<std::shared_ptr<IOperation<Time>>> CreateMeasureX(
574 size_t qubit, size_t cbit) {
575 std::vector<std::shared_ptr<IOperation<Time>>> ops(2);
577 ops[1] = CreateMeasurement({{qubit, cbit}});
578
579 return ops;
580 }
581
590 static std::vector<std::shared_ptr<IOperation<Time>>> CreateMeasureY(
591 size_t qubit, size_t cbit) {
592 std::vector<std::shared_ptr<IOperation<Time>>> ops(3);
595 ops[2] = CreateMeasurement({{qubit, cbit}});
596
597 return ops;
598 }
599
608 static std::vector<std::shared_ptr<IOperation<Time>>> CreateMeasureZ(
609 size_t qubit, size_t cbit) {
610 std::vector<std::shared_ptr<IOperation<Time>>> ops(1);
611 ops[0] = CreateMeasurement({{qubit, cbit}});
612
613 return ops;
614 }
615
623 static std::vector<std::shared_ptr<IOperation<Time>>> CreateInitZero(
624 size_t qubit) {
625 std::vector<std::shared_ptr<IOperation<Time>>> ops(1);
626 ops[0] = CreateReset({qubit});
627
628 return ops;
629 }
630
638 static std::vector<std::shared_ptr<IOperation<Time>>> CreateInitOne(
639 size_t qubit) {
640 std::vector<std::shared_ptr<IOperation<Time>>> ops(2);
641 ops[0] = CreateReset({qubit});
643
644 return ops;
645 }
646
654 static std::vector<std::shared_ptr<IOperation<Time>>> CreateInitPlus(
655 size_t qubit) {
656 std::vector<std::shared_ptr<IOperation<Time>>> ops(2);
657 ops[0] = CreateReset({qubit});
659
660 return ops;
661 }
662
670 static std::vector<std::shared_ptr<IOperation<Time>>> CreateInitMinus(
671 size_t qubit) {
672 std::vector<std::shared_ptr<IOperation<Time>>> ops(3);
673 ops[0] = CreateReset({qubit});
676
677 return ops;
678 }
679
687 static std::vector<std::shared_ptr<IOperation<Time>>> CreateInitPlusI(
688 size_t qubit) {
689 std::vector<std::shared_ptr<IOperation<Time>>> ops(3);
690 ops[0] = CreateReset({qubit});
693
694 return ops;
695 }
696
704 static std::vector<std::shared_ptr<IOperation<Time>>> CreateInitMinusI(
705 size_t qubit) {
706 std::vector<std::shared_ptr<IOperation<Time>>> ops(3);
707 ops[0] = CreateReset({qubit});
710
711 return ops;
712 }
713};
714} // namespace Circuits
715
716#endif // !_CIRCUIT_FACTORY_H_
Factory for quantum gates and other operations.
static std::shared_ptr< IOperation< Time > > CreateSimpleConditionalGate(const std::shared_ptr< IGateOperation< Time > > &operation, const size_t cbit)
Construct a simple conditional gate.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateGZHStateCircuit(size_t qbit1, size_t qbit2, size_t qbit3)
Creates a circuit that prepares three qubits in a GHZ state.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateInitMinusI(size_t qubit)
Creates the circuit for initializing a qubit in the |-i> state.
static std::shared_ptr< IOperation< Time > > CreateNoOp()
Creates a no op.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateInitMinus(size_t qubit)
Creates the circuit for initializing a qubit in the |-> state.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateInitOne(size_t qubit)
Creates the circuit for initializing a qubit in the |1> state.
static const std::shared_ptr< IQuantumGate< Time > > CreateGate(QuantumGateType type, size_t q1, size_t q2=0, size_t q3=0, double param1=0, double param2=0, double param3=0, double param4=0)
Construct a quantum gate.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateInitZero(size_t qubit)
Creates the circuit for initializing a qubit in the |0> state.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateMeasureY(size_t qubit, size_t cbit)
Creates the circuit for measuring a qubit in the Y basis.
static std::shared_ptr< IOperation< Time > > CreateConditionalGate(const std::shared_ptr< IGateOperation< Time > > &operation, const std::shared_ptr< ICondition > &condition)
Construct a conditional gate.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateInitPlusI(size_t qubit)
Creates the circuit for initializing a qubit in the |i> state.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateMeasureZ(size_t qubit, size_t cbit)
Creates the circuit for measuring a qubit in the Z basis.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateMeasureX(size_t qubit, size_t cbit)
Creates the circuit for measuring a qubit in the X basis.
static std::shared_ptr< IOperation< Time > > CreateReset(const Types::qubits_vector &qubits={}, const std::vector< bool > &resetTgts={})
Construct a reset operation.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateStartDistributionCircuit(size_t ctrlQubit, size_t ctrlEntangledQubit, size_t tgtEntangledQubit, size_t ctrlEntangledMeasureBit)
Creates the circuit for distribution start.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateEndDistributionCircuit(size_t ctrlQubit, size_t tgtEntangledQubit, size_t tgtEntangledMeasureBit)
Creates the circuit for distribution end.
static const std::shared_ptr< IOperation< Time > > CreateMeasurement(const std::vector< std::pair< Types::qubit_t, size_t > > &qs={})
Construct a measurement operation.
static std::shared_ptr< Circuit< Time > > CreateCircuit(const std::vector< std::shared_ptr< IOperation< Time > > > &ops={})
Construct a circuit.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateTeleportationCircuit(size_t entqbit1, size_t entqbit2, size_t srcqbit, size_t cbit1, size_t cbit2)
Creates a teleportation circuit.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateBellStateDecoderCircuit(size_t qbit1, size_t qbit2)
Creates a Bell state decoder circuit.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateBellStateCircuit(size_t qbit1, size_t qbit2, bool qbit1X=false, bool qbit2X=false)
Creates a circuit that prepares a qubit pair in a Bell state.
static std::shared_ptr< IOperation< Time > > CreateConditionalRandomGen(const std::shared_ptr< Random< Time > > &randomGen, const std::shared_ptr< ICondition > &condition)
Constructs a conditional random number generator.
static const std::shared_ptr< IOperation< Time > > CreateGateWithVectors(QuantumGateType type, const Types::qubits_vector &qubits, const std::vector< double > &params={})
Construct a quantum gate.
static std::shared_ptr< IOperation< Time > > CreateRandom(const std::vector< size_t > &bits={}, size_t seed=0)
Construct a random operation.
static std::vector< std::shared_ptr< IOperation< Time > > > CreateInitPlus(size_t qubit)
Creates the circuit for initializing a qubit in the |+> state.
static std::shared_ptr< IOperation< Time > > CreateConditionalMeasurement(const std::shared_ptr< MeasurementOperation< Time > > &measurement, const std::shared_ptr< ICondition > &condition)
Constructs a conditional measurement.
static std::shared_ptr< ICondition > CreateEqualCondition(const std::vector< size_t > &ind, const std::vector< bool > &b)
Construct an equality condition.
The gate operation interface.
Definition Operations.h:604
The operation interface.
Definition Operations.h:358
Measurement operation class.
Random operation.
Definition RandomOp.h:34
QuantumGateType
The type of quantum gates.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:23