Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
FusionGate.h
Go to the documentation of this file.
1#pragma once
4#include "GateFusion.h"
5#include <array>
6
7namespace Simulators
8{
9// Named gates retain their native entry point until another operation fuses
10// with them. Matrices are constructed lazily; routing preparation needs none.
12{
14 Kind kind = Kind::kNone;
16 std::array<double, 4> params{};
17 Eigen::MatrixXcd generic;
18
20 {
21 auto order = qubits;
22 if (kind != Kind::kNone && order.size() > 1 && kind != Kind::kSwapGateType)
23 std::reverse(order.begin(), order.end());
24 return order;
25 }
26
27 Eigen::MatrixXcd Matrix() const
28 {
29 using namespace Circuits;
30 const auto q1 = qubits[0], q2 = qubits.size() > 1 ? qubits[1] : 0, q3 = qubits.size() > 2 ? qubits[2] : 0;
31 const auto param1 = params[0], param2 = params[1], param3 = params[2], param4 = params[3];
32 // Construct named gates on the stack: merging needs only their matrix.
33 switch (kind)
34 {
35 case Kind::kNone:
36 return generic;
37 case Kind::kPhaseGateType:
38 return PhaseGate<>(q1, param1).GetMatrix();
39 case Kind::kXGateType:
40 return XGate<>(q1).GetMatrix();
41 case Kind::kYGateType:
42 return YGate<>(q1).GetMatrix();
43 case Kind::kZGateType:
44 return ZGate<>(q1).GetMatrix();
45 case Kind::kHadamardGateType:
46 return HadamardGate<>(q1).GetMatrix();
47 case Kind::kSGateType:
48 return SGate<>(q1).GetMatrix();
49 case Kind::kSdgGateType:
50 return SdgGate<>(q1).GetMatrix();
51 case Kind::kTGateType:
52 return TGate<>(q1).GetMatrix();
53 case Kind::kTdgGateType:
54 return TdgGate<>(q1).GetMatrix();
55 case Kind::kSxGateType:
56 return SxGate<>(q1).GetMatrix();
57 case Kind::kSxDagGateType:
58 return SxDagGate<>(q1).GetMatrix();
59 case Kind::kKGateType:
60 return KGate<>(q1).GetMatrix();
61 case Kind::kRxGateType:
62 return RxGate<>(q1, param1).GetMatrix();
63 case Kind::kRyGateType:
64 return RyGate<>(q1, param1).GetMatrix();
65 case Kind::kRzGateType:
66 return RzGate<>(q1, param1).GetMatrix();
67 case Kind::kUGateType:
68 return UGate<>(q1, param1, param2, param3, param4).GetMatrix();
69 case Kind::kSwapGateType:
70 return SwapGate<>(q1, q2).GetMatrix();
71 case Kind::kCXGateType:
72 return CXGate<>(q1, q2).GetMatrix();
73 case Kind::kCYGateType:
74 return CYGate<>(q1, q2).GetMatrix();
75 case Kind::kCZGateType:
76 return CZGate<>(q1, q2).GetMatrix();
77 case Kind::kCPGateType:
78 return CPGate<>(q1, q2, param1).GetMatrix();
79 case Kind::kCRxGateType:
80 return CRxGate<>(q1, q2, param1).GetMatrix();
81 case Kind::kCRyGateType:
82 return CRyGate<>(q1, q2, param1).GetMatrix();
83 case Kind::kCRzGateType:
84 return CRzGate<>(q1, q2, param1).GetMatrix();
85 case Kind::kCHGateType:
86 return CHGate<>(q1, q2).GetMatrix();
87 case Kind::kCSxGateType:
88 return CSxGate<>(q1, q2).GetMatrix();
89 case Kind::kCSxDagGateType:
90 return CSxDagGate<>(q1, q2).GetMatrix();
91 case Kind::kCUGateType:
92 return CUGate<>(q1, q2, param1, param2, param3, param4).GetMatrix();
93 case Kind::kCSwapGateType:
94 return CSwapGate<>(q1, q2, q3).GetMatrix();
95 case Kind::kCCXGateType:
96 return CCXGate<>(q1, q2, q3).GetMatrix();
97 }
98 throw std::logic_error("Unknown fusion gate");
99 }
100
101 // Effective Schmidt rank for routing (see EffectiveSchmidtRank); 1 for a
102 // one-qubit gate. Three-qubit gates are expanded before routing.
103 double SchmidtRank() const
104 {
105 if (qubits.size() < 2)
106 return 1.;
107 if (qubits.size() > 2)
108 return 4.;
109 return RoutingSchmidtRank(kind, params[0], [this] { return Matrix(); });
110 }
111
113 {
114 FusionGate result;
115 result.kind = gate.GetGateType();
116 if (result.kind == Kind::kNone)
117 result.generic = gate.GetMatrix();
118 for (size_t i = 0; i < gate.GetNumQubits(); ++i)
119 result.qubits.push_back(gate.GetQubit(i));
120 const auto p = gate.GetParams();
121 std::copy_n(p.begin(), std::min(p.size(), result.params.size()), result.params.begin());
122 return result;
123 }
124
125 bool Matches(const FusionGate &other) const
126 {
127 return kind == other.kind && qubits == other.qubits && params == other.params &&
128 (kind != Kind::kNone ||
129 (generic.rows() == other.generic.rows() && generic.cols() == other.generic.cols() && (generic.array() == other.generic.array()).all()));
130 }
131
132 bool IsStructured() const
133 {
134 switch (kind)
135 {
136 case Kind::kPhaseGateType:
137 case Kind::kXGateType:
138 case Kind::kYGateType:
139 case Kind::kZGateType:
140 case Kind::kSGateType:
141 case Kind::kSdgGateType:
142 case Kind::kTGateType:
143 case Kind::kTdgGateType:
144 case Kind::kRzGateType:
145 case Kind::kSwapGateType:
146 case Kind::kCXGateType:
147 case Kind::kCYGateType:
148 case Kind::kCZGateType:
149 case Kind::kCPGateType:
150 case Kind::kCRzGateType:
151 case Kind::kCSwapGateType:
152 case Kind::kCCXGateType:
153 return true;
154 default:
155 // Generic matrices already use the dense API; preserving their
156 // individual calls cannot recover a specialized native gate path.
157 return false;
158 }
159 }
160
161 void Apply(ISimulator &sim) const
162 {
163 switch (kind)
164 {
165 case Kind::kPhaseGateType:
166 sim.ApplyP(qubits[0], params[0]);
167 return;
168 case Kind::kXGateType:
169 sim.ApplyX(qubits[0]);
170 return;
171 case Kind::kYGateType:
172 sim.ApplyY(qubits[0]);
173 return;
174 case Kind::kZGateType:
175 sim.ApplyZ(qubits[0]);
176 return;
177 case Kind::kHadamardGateType:
178 sim.ApplyH(qubits[0]);
179 return;
180 case Kind::kSGateType:
181 sim.ApplyS(qubits[0]);
182 return;
183 case Kind::kSdgGateType:
184 sim.ApplySDG(qubits[0]);
185 return;
186 case Kind::kTGateType:
187 sim.ApplyT(qubits[0]);
188 return;
189 case Kind::kTdgGateType:
190 sim.ApplyTDG(qubits[0]);
191 return;
192 case Kind::kSxGateType:
193 sim.ApplySx(qubits[0]);
194 return;
195 case Kind::kSxDagGateType:
196 sim.ApplySxDAG(qubits[0]);
197 return;
198 case Kind::kKGateType:
199 sim.ApplyK(qubits[0]);
200 return;
201 case Kind::kRxGateType:
202 sim.ApplyRx(qubits[0], params[0]);
203 return;
204 case Kind::kRyGateType:
205 sim.ApplyRy(qubits[0], params[0]);
206 return;
207 case Kind::kRzGateType:
208 sim.ApplyRz(qubits[0], params[0]);
209 return;
210 case Kind::kUGateType:
211 sim.ApplyU(qubits[0], params[0], params[1], params[2], params[3]);
212 return;
213 case Kind::kSwapGateType:
214 sim.ApplySwap(qubits[0], qubits[1]);
215 return;
216 case Kind::kCXGateType:
217 sim.ApplyCX(qubits[0], qubits[1]);
218 return;
219 case Kind::kCYGateType:
220 sim.ApplyCY(qubits[0], qubits[1]);
221 return;
222 case Kind::kCZGateType:
223 sim.ApplyCZ(qubits[0], qubits[1]);
224 return;
225 case Kind::kCPGateType:
226 sim.ApplyCP(qubits[0], qubits[1], params[0]);
227 return;
228 case Kind::kCRxGateType:
229 sim.ApplyCRx(qubits[0], qubits[1], params[0]);
230 return;
231 case Kind::kCRyGateType:
232 sim.ApplyCRy(qubits[0], qubits[1], params[0]);
233 return;
234 case Kind::kCRzGateType:
235 sim.ApplyCRz(qubits[0], qubits[1], params[0]);
236 return;
237 case Kind::kCHGateType:
238 sim.ApplyCH(qubits[0], qubits[1]);
239 return;
240 case Kind::kCSxGateType:
241 sim.ApplyCSx(qubits[0], qubits[1]);
242 return;
243 case Kind::kCSxDagGateType:
244 sim.ApplyCSxDAG(qubits[0], qubits[1]);
245 return;
246 case Kind::kCUGateType:
247 sim.ApplyCU(qubits[0], qubits[1], params[0], params[1], params[2], params[3]);
248 return;
249 case Kind::kCSwapGateType:
250 sim.ApplyCSwap(qubits[0], qubits[1], qubits[2]);
251 return;
252 case Kind::kCCXGateType:
253 sim.ApplyCCX(qubits[0], qubits[1], qubits[2]);
254 return;
255 case Kind::kNone:
256 if (qubits.size() == 1)
258 else if (qubits.size() == 2)
260 else
262 return;
263 }
264 throw std::logic_error("Unknown fusion gate");
265 }
266
267 std::vector<FusionGate> Expand(unsigned width) const
268 {
269 if (qubits.size() <= width)
270 return {*this};
271 if (width != 2 || (kind != Kind::kCCXGateType && kind != Kind::kCSwapGateType))
272 throw std::invalid_argument("Unsupported generic gate width");
273 auto ccx = [](Types::qubit_t a, Types::qubit_t b, Types::qubit_t c) {
274 return std::vector<FusionGate>{{Kind::kCSxGateType, {b, c}, {}, {}},
275 {Kind::kCXGateType, {a, b}, {}, {}},
276 {Kind::kCSxDagGateType, {b, c}, {}, {}},
277 {Kind::kCXGateType, {a, b}, {}, {}},
278 {Kind::kCSxGateType, {a, c}, {}, {}}};
279 };
280 if (kind == Kind::kCCXGateType)
281 return ccx(qubits[0], qubits[1], qubits[2]);
282 auto result = ccx(qubits[0], qubits[1], qubits[2]);
283 FusionGate cx{Kind::kCXGateType, {qubits[2], qubits[1]}, {}, {}};
284 result.insert(result.begin(), cx);
285 result.push_back(cx);
286 return result;
287 }
288};
289
290// Routing-only operation. It cannot accidentally be executed as a quantum gate.
292{
293 public:
294 explicit FusionRoutingOperation(Types::qubits_vector targets, double rank = 4, bool swap = false) : Circuits::IOperation<>(0), targets_(std::move(targets))
295 {
296 schmidtRank = rank;
297 isSwap = swap;
298 }
299
301 {
302 return targets_;
303 }
304
306 {
308 }
309
310 void Execute(const std::shared_ptr<ISimulator> &, Circuits::OperationState &) const override
311 {
312 throw std::logic_error("A routing operation cannot be executed");
313 }
314
315 std::shared_ptr<Circuits::IOperation<>> Clone() const override
316 {
317 return std::make_shared<FusionRoutingOperation>(targets_, schmidtRank, isSwap);
318 }
319
320 std::shared_ptr<Circuits::IOperation<>> Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &map,
321 const std::unordered_map<Types::qubit_t, Types::qubit_t> & = {}) const override
322 {
323 auto targets = targets_;
324 for (auto &q : targets)
325 q = map.at(q);
326 return std::make_shared<FusionRoutingOperation>(std::move(targets), schmidtRank, isSwap);
327 }
328
329 private:
330 Types::qubits_vector targets_;
331};
332} // namespace Simulators
The controlled controlled x gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled H gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled P gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled x rotation gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled y rotation gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled z rotation gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled swap gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled Sx dagger gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled Sx gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled U gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled x gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled y gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The controlled z gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The Hadamard gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
virtual Types::qubit_t GetQubit(unsigned int index=0) const =0
Get the qubit involved.
virtual unsigned int GetNumQubits() const =0
Get the number of qubits.
The operation interface.
Definition Operations.h:402
IOperation(Time delay=0)
Construct a new IOperation object.
Definition Operations.h:410
The interface for quantum gates.
virtual QuantumGateType GetGateType() const =0
Get the type of the quantum gate.
virtual Eigen::MatrixXcd GetMatrix() const =0
Get the matrix representation of the quantum gate.
virtual std::vector< double > GetParams() const
Get the gate parameters.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:68
The phase gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The S gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The S dagger gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The swap gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The Sx dagger gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The T dagger gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The X gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The Y gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
The Z gate.
Eigen::MatrixXcd GetMatrix() const override
Get the matrix representation of the quantum gate.
FusionRoutingOperation(Types::qubits_vector targets, double rank=4, bool swap=false)
Definition FusionGate.h:294
std::shared_ptr< Circuits::IOperation<> > Clone() const override
Get a shared pointer to a clone of this object.
Definition FusionGate.h:315
std::shared_ptr< Circuits::IOperation<> > Remap(const std::unordered_map< Types::qubit_t, Types::qubit_t > &map, const std::unordered_map< Types::qubit_t, Types::qubit_t > &={}) const override
Get a shared pointer to a remapped operation.
Definition FusionGate.h:320
Types::qubits_vector AffectedQubits() const override
Returns the affected qubits.
Definition FusionGate.h:300
void Execute(const std::shared_ptr< ISimulator > &, Circuits::OperationState &) const override
Execute the operation.
Definition FusionGate.h:310
Circuits::OperationType GetType() const override
Get the type of the operation.
Definition FusionGate.h:305
Interface class for a quantum computing simulator.
Definition Simulator.h:41
virtual void ApplyCRz(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta)=0
Applies a CRz gate to the qubits.
virtual void ApplySDG(Types::qubit_t qubit)=0
Applies a S dagger gate to the qubit.
virtual void ApplyCCX(Types::qubit_t qubit0, Types::qubit_t qubit1, Types::qubit_t qubit2)=0
Applies a controlled controlled not gate to the qubits.
virtual void ApplyX(Types::qubit_t qubit)=0
Applies a not gate to the qubit.
virtual void ApplyCSxDAG(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CSx dagger gate to the qubits.
virtual void ApplyU(Types::qubit_t qubit, double theta, double phi, double lambda, double gamma)=0
Applies a U gate to the qubit.
virtual void ApplyP(Types::qubit_t qubit, double lambda)=0
Applies a phase shift gate to the qubit.
virtual void ApplySx(Types::qubit_t qubit)=0
Applies a Sx gate to the qubit.
virtual void ApplyTDG(Types::qubit_t qubit)=0
Applies a T dagger gate to the qubit.
virtual void ApplyCU(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta, double phi, double lambda, double gamma)=0
Applies a controlled U gate to the qubits.
virtual void ApplyGenericThreeQubitGate(Types::qubit_t, Types::qubit_t, Types::qubit_t, const Matrix8cd &)
Definition Simulator.h:67
virtual void ApplyCRy(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta)=0
Applies a CRy gate to the qubits.
virtual void ApplyCX(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CX gate to the qubits.
virtual void ApplyRy(Types::qubit_t qubit, double theta)=0
Applies a Ry gate to the qubit.
virtual void ApplyCH(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CH gate to the qubits.
virtual void ApplySwap(Types::qubit_t qubit0, Types::qubit_t qubit1)=0
Applies a swap gate to the qubits.
virtual void ApplyCSx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CSx gate to the qubits.
virtual void ApplyGenericTwoQubitGate(Types::qubit_t qubit0, Types::qubit_t qubit1, const Eigen::Matrix4cd &gate)=0
Apply a generic two-qubit gate to the specified qubits.
virtual void ApplyK(Types::qubit_t qubit)=0
Applies a K gate to the qubit.
virtual void ApplyY(Types::qubit_t qubit)=0
Applies a Y gate to the qubit.
virtual void ApplyT(Types::qubit_t qubit)=0
Applies a T gate to the qubit.
virtual void ApplyS(Types::qubit_t qubit)=0
Applies a S gate to the qubit.
virtual void ApplyCSwap(Types::qubit_t ctrl_qubit, Types::qubit_t qubit0, Types::qubit_t qubit1)=0
Applies a controlled swap gate to the qubits.
virtual void ApplyZ(Types::qubit_t qubit)=0
Applies a Z gate to the qubit.
virtual void ApplyRz(Types::qubit_t qubit, double theta)=0
Applies a Rz gate to the qubit.
virtual void ApplyCRx(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double theta)=0
Applies a CRx gate to the qubits.
virtual void ApplyCY(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CY gate to the qubits.
virtual void ApplyCZ(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit)=0
Applies a CZ gate to the qubits.
virtual void ApplyH(Types::qubit_t qubit)=0
Applies a Hadamard gate to the qubit.
virtual void ApplyRx(Types::qubit_t qubit, double theta)=0
Applies a Rx gate to the qubit.
virtual void ApplySxDAG(Types::qubit_t qubit)=0
Applies a Sx dagger gate to the qubit.
virtual void ApplyCP(Types::qubit_t ctrl_qubit, Types::qubit_t tgt_qubit, double lambda)=0
Applies a CP gate to the qubits.
virtual void ApplyGenericOneQubitGate(Types::qubit_t qubit, const Eigen::Matrix2cd &gate)=0
Apply a generic one-qubit gate to the specified qubit.
QuantumGateType
The type of quantum gates.
OperationType
The type of operations.
Definition Operations.h:29
@ kGate
the usual quantum gate, result stays in simulator's state
Definition Operations.h:30
Bounded online routing based on current physical bond dimensions.
double RoutingSchmidtRank(Circuits::QuantumGateType type, double angle, MatrixFn &&matrix)
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:24
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:23
Eigen::MatrixXcd generic
Definition FusionGate.h:17
double SchmidtRank() const
Definition FusionGate.h:103
Eigen::MatrixXcd Matrix() const
Definition FusionGate.h:27
bool Matches(const FusionGate &other) const
Definition FusionGate.h:125
void Apply(ISimulator &sim) const
Definition FusionGate.h:161
std::vector< FusionGate > Expand(unsigned width) const
Definition FusionGate.h:267
bool IsStructured() const
Definition FusionGate.h:132
Types::qubits_vector qubits
Definition FusionGate.h:15
static FusionGate FromCircuit(const Circuits::IQuantumGate<> &gate)
Definition FusionGate.h:112
std::array< double, 4 > params
Definition FusionGate.h:16
Circuits::QuantumGateType Kind
Definition FusionGate.h:13
Types::qubits_vector Targets() const
Definition FusionGate.h:19