Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Conditional.h
Go to the documentation of this file.
1
16
17#pragma once
18
19#ifndef _CONDITIONAL_H_
20#define _CONDITIONAL_H_
21
22#include "Measurements.h"
23#include "QuantumGates.h"
24#include "RandomOp.h"
25
26namespace Circuits
27{
28
37class ICondition : public std::enable_shared_from_this<ICondition>
38{
39 public:
46 ICondition(const std::vector<size_t> &ind) : indices(ind)
47 {
48 }
49
57 virtual ~ICondition() = default;
58
67 virtual bool IsConditionMet(OperationState &state) const = 0;
68
75 const std::vector<size_t> &GetBitsIndices() const
76 {
77 return indices;
78 }
79
86 void SetBitsIndices(const std::vector<size_t> &ind)
87 {
88 indices = ind;
89 }
90
97 virtual std::shared_ptr<ICondition> Clone() const = 0;
98
108 virtual std::shared_ptr<ICondition> Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {}) const = 0;
109
117 std::shared_ptr<ICondition> getptr()
118 {
119 return std::enable_shared_from_this<ICondition>::shared_from_this();
120 }
121
122 private:
123 std::vector<size_t> indices;
124};
125
136{
137 public:
146 EqualCondition(const std::vector<size_t> &ind, const std::vector<bool> &b) : ICondition(ind), bits(b)
147 {
148 }
149
157 bool IsConditionMet(OperationState &state) const override
158 {
159 return state.GetBits(GetBitsIndices()) == GetAllBits();
160 }
161
168 const std::vector<bool> &GetAllBits() const
169 {
170 return bits;
171 }
172
179 void SetBits(const std::vector<bool> &b)
180 {
181 bits = b;
182 }
183
190 std::shared_ptr<ICondition> Clone() const override
191 {
192 return std::make_shared<EqualCondition>(GetBitsIndices(), GetAllBits());
193 }
194
204 std::shared_ptr<ICondition> Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {}) const override
205 {
206 auto newCond = this->Clone();
207
208 auto newBits = newCond->GetBitsIndices();
209 for (size_t i = 0; i < newBits.size(); ++i)
210 {
211 const auto bitit = bitsMap.find(newBits[i]);
212 if (bitit != bitsMap.end())
213 newBits[i] = bitit->second;
214 // else throw std::invalid_argument("Conditional operation: bit not found
215 // in the map, couldn't remap.");
216 }
217 newCond->SetBitsIndices(newBits);
218
219 return newCond;
220 }
221
222 private:
223 std::vector<bool> bits;
224};
225
236template <typename Time = Types::time_type> class IConditionalOperation : public IOperation<Time>
237{
238 public:
250 IConditionalOperation(const std::shared_ptr<IOperation<Time>> &operation, const std::shared_ptr<ICondition> &condition, Time delay = 0)
251 : IOperation<Time>(delay), operation(operation), condition(condition)
252 {
253 }
254
267 void Execute(const std::shared_ptr<Simulators::ISimulator> &sim, OperationState &state) const override
268 {
269 if (!condition || !operation)
270 return;
271
272 if (condition->IsConditionMet(state))
273 operation->Execute(sim, state);
274 else if (sim)
275 sim->IncrementGatesCounter();
276 }
277
284 void SetOperation(const std::shared_ptr<IOperation<Time>> &op)
285 {
286 if (!op)
287 return;
288 // the reason why 'recursive' conditional gates are not allowed (as in
289 // conditional-conditional-...-gate) is because of the distribution for the
290 // network execution would work fine as long as it's 'local'
291 else if ((op->GetType() == OperationType::kGate && this->GetType() != OperationType::kConditionalGate) ||
292 (op->GetType() == OperationType::kMeasurement && this->GetType() != OperationType::kConditionalMeasurement) ||
293 (op->GetType() == OperationType::kRandomGen && this->GetType() != OperationType::kConditionalRandomGen))
294 return;
295
296 operation = op;
297 }
298
306 std::shared_ptr<IOperation<Time>> GetOperation() const
307 {
308 return operation;
309 }
310
318 void SetCondition(const std::shared_ptr<ICondition> &cond)
319 {
320 condition = cond;
321 }
322
330 std::shared_ptr<ICondition> GetCondition() const
331 {
332 return condition;
333 }
334
341 std::vector<size_t> AffectedBits() const override
342 {
343 if (!condition)
344 return {};
345
346 return condition->GetBitsIndices();
347 }
348
356 {
357 if (!operation)
358 return {};
359
360 return operation->AffectedQubits();
361 }
362
373 std::shared_ptr<IOperation<Time>> Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
374 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {}) const override
375 {
376 const auto condOp = std::static_pointer_cast<IConditionalOperation<Time>>(this->Clone());
377
378 condOp->SetCondition(condOp->GetCondition()->Remap(bitsMap));
379 condOp->SetOperation(condOp->GetOperation()->Remap(qubitsMap, bitsMap));
380
381 return condOp;
382 }
383
393 bool IsClifford() const override
394 {
395 if (!operation)
396 return true;
397
398 return operation->IsClifford();
399 }
400
409 bool IsBranching() const override
410 {
411 if (!operation)
412 return false;
413
414 return operation->IsBranching();
415 }
416
417 private:
418 std::shared_ptr<IOperation<Time>> operation;
419 std::shared_ptr<ICondition> condition;
420};
421
431template <typename Time = Types::time_type> class ConditionalGate : public IConditionalOperation<Time>
432{
433 public:
446 ConditionalGate(const std::shared_ptr<IGateOperation<Time>> &operation, const std::shared_ptr<ICondition> &condition, Time delay = 0)
447 : IConditionalOperation<Time>(operation, condition, delay)
448 {
449 }
450
458 OperationType GetType() const override
459 {
461 }
462
469 std::shared_ptr<IOperation<Time>> Clone() const override
470 {
471 const auto gate = std::static_pointer_cast<IGateOperation<Time>>(IConditionalOperation<Time>::GetOperation()->Clone());
472 const auto cond = std::static_pointer_cast<ICondition>(IConditionalOperation<Time>::GetCondition()->Clone());
473
474 return std::make_shared<ConditionalGate<Time>>(gate, cond, IOperation<Time>::GetDelay());
475 }
476};
477
487template <typename Time = Types::time_type> class ConditionalMeasurement : public IConditionalOperation<Time>
488{
489 public:
502 ConditionalMeasurement(const std::shared_ptr<MeasurementOperation<Time>> &operation, const std::shared_ptr<ICondition> &condition, Time delay = 0)
503 : IConditionalOperation<Time>(operation, condition, delay)
504 {
505 }
506
514 OperationType GetType() const override
515 {
517 }
518
525 std::shared_ptr<IOperation<Time>> Clone() const override
526 {
527 return std::make_shared<ConditionalMeasurement<Time>>(
528 std::static_pointer_cast<MeasurementOperation<Time>>(IConditionalOperation<Time>::GetOperation()->Clone()),
529 std::static_pointer_cast<ICondition>(IConditionalOperation<Time>::GetCondition()->Clone()), IOperation<Time>::GetDelay());
530 }
531};
532
542template <typename Time = Types::time_type> class ConditionalRandomGen : public IConditionalOperation<Time>
543{
544 public:
557 ConditionalRandomGen(const std::shared_ptr<Random<Time>> &operation, const std::shared_ptr<ICondition> &condition, Time delay = 0)
558 : IConditionalOperation<Time>(operation, condition, delay)
559 {
560 }
561
569 OperationType GetType() const override
570 {
572 }
573
580 std::shared_ptr<IOperation<Time>> Clone() const override
581 {
582 return std::make_shared<ConditionalRandomGen<Time>>(std::static_pointer_cast<Random<Time>>(IConditionalOperation<Time>::GetOperation()->Clone()),
583 std::static_pointer_cast<ICondition>(IConditionalOperation<Time>::GetCondition()->Clone()),
585 }
586
596 {
597 return {};
598 }
599};
600
601} // namespace Circuits
602
603#endif // !_CONDITIONAL_H_
ConditionalGate(const std::shared_ptr< IGateOperation< Time > > &operation, const std::shared_ptr< ICondition > &condition, Time delay=0)
Construct a new ConditionalGate object.
OperationType GetType() const override
Get the type of the operation.
std::shared_ptr< IOperation< Time > > Clone() const override
Get a shared pointer to a clone of this object.
ConditionalMeasurement(const std::shared_ptr< MeasurementOperation< Time > > &operation, const std::shared_ptr< ICondition > &condition, Time delay=0)
Construct a new ConditionalMeasurement object.
OperationType GetType() const override
Get the type of the operation.
std::shared_ptr< IOperation< Time > > Clone() const override
Get a shared pointer to a clone of this object.
OperationType GetType() const override
Get the type of the operation.
ConditionalRandomGen(const std::shared_ptr< Random< Time > > &operation, const std::shared_ptr< ICondition > &condition, Time delay=0)
Construct a new ConditionalRandomGen object.
Types::qubits_vector AffectedQubits() const override
Get the quantum bits affected by the operation.
std::shared_ptr< IOperation< Time > > Clone() const override
Get a shared pointer to a clone of this object.
std::shared_ptr< ICondition > Remap(const std::unordered_map< Types::qubit_t, Types::qubit_t > &bitsMap={}) const override
Get a shared pointer to a remapped condition.
bool IsConditionMet(OperationState &state) const override
Check if the condition is met.
const std::vector< bool > & GetAllBits() const
Get the values to compare the bits to.
std::shared_ptr< ICondition > Clone() const override
Get a shared pointer to a clone of this object.
void SetBits(const std::vector< bool > &b)
Set the values to compare the bits to.
EqualCondition(const std::vector< size_t > &ind, const std::vector< bool > &b)
Construct a new EqualCondition object.
virtual ~ICondition()=default
Virtual destructor.
virtual bool IsConditionMet(OperationState &state) const =0
Check if the condition is met.
const std::vector< size_t > & GetBitsIndices() const
Get the indices of the bits used in the condition.
Definition Conditional.h:75
std::shared_ptr< ICondition > getptr()
Get a shared pointer to this object.
void SetBitsIndices(const std::vector< size_t > &ind)
Set the indices of the bits used in the condition.
Definition Conditional.h:86
virtual std::shared_ptr< ICondition > Remap(const std::unordered_map< Types::qubit_t, Types::qubit_t > &bitsMap={}) const =0
Get a shared pointer to a remapped condition.
virtual std::shared_ptr< ICondition > Clone() const =0
Get a shared pointer to a clone of this object.
ICondition(const std::vector< size_t > &ind)
Construct a new ICondition object.
Definition Conditional.h:46
void SetCondition(const std::shared_ptr< ICondition > &cond)
Set the condition for the conditional operation.
bool IsClifford() const override
Checks if the operation is a Clifford one.
std::shared_ptr< IOperation< Time > > GetOperation() const
Get the operation for the conditional operation.
bool IsBranching() const override
Checks if the operation is a branching one.
IConditionalOperation(const std::shared_ptr< IOperation< Time > > &operation, const std::shared_ptr< ICondition > &condition, Time delay=0)
Construct a new IConditionalOperation object.
void SetOperation(const std::shared_ptr< IOperation< Time > > &op)
Set the operation for the conditional operation.
std::shared_ptr< IOperation< Time > > Remap(const std::unordered_map< Types::qubit_t, Types::qubit_t > &qubitsMap, const std::unordered_map< Types::qubit_t, Types::qubit_t > &bitsMap={}) const override
Get a shared pointer to a remapped operation.
std::vector< size_t > AffectedBits() const override
Get bits that are involved in the condition.
std::shared_ptr< ICondition > GetCondition() const
Get the condition for the conditional operation.
void Execute(const std::shared_ptr< Simulators::ISimulator > &sim, OperationState &state) const override
Execute the operation.
Types::qubits_vector AffectedQubits() const override
Get the qubits affected by the operation.
The gate operation interface.
Definition Operations.h:703
Time GetDelay() const
Get the delay of the operation.
Definition Operations.h:546
IOperation(Types::time_type delay=0)
Definition Operations.h:410
virtual std::shared_ptr< IOperation< Types::time_type > > Clone() const=0
Measurement operation class.
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:68
std::vector< bool > GetBits(const std::vector< size_t > &indices) const
Get the classical bits at the specified indices.
Definition Operations.h:227
Random operation.
Definition RandomOp.h:35
OperationType
The type of operations.
Definition Operations.h:29
@ kConditionalGate
conditional gate, similar with gate, but conditioned on something from 'OperationState'
Definition Operations.h:33
@ kRandomGen
random classical bit generator, result in 'OperationState'
Definition Operations.h:32
@ kConditionalRandomGen
conditional random generator, similar with random gen, but conditioned on something from 'OperationSt...
Definition Operations.h:38
@ kConditionalMeasurement
conditional measurement, similar with measurement, but conditioned on something from 'OperationState'
Definition Operations.h:35
@ kMeasurement
measurement, result in 'OperationState'
Definition Operations.h:31
@ kGate
the usual quantum gate, result stays in simulator's state
Definition Operations.h:30
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:24