Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Conditional.h
Go to the documentation of this file.
1
16#pragma once
17
18#ifndef _CONDITIONAL_H_
19#define _CONDITIONAL_H_
20
21#include "Measurements.h"
22#include "QuantumGates.h"
23#include "RandomOp.h"
24
25namespace Circuits {
26
35class ICondition : public std::enable_shared_from_this<ICondition> {
36 public:
43 ICondition(const std::vector<size_t> &ind) : indices(ind) {}
44
52 virtual ~ICondition() = default;
53
62 virtual bool IsConditionMet(OperationState &state) const = 0;
63
70 const std::vector<size_t> &GetBitsIndices() const { return indices; }
71
78 void SetBitsIndices(const std::vector<size_t> &ind) { indices = ind; }
79
86 virtual std::shared_ptr<ICondition> Clone() const = 0;
87
97 virtual std::shared_ptr<ICondition> Remap(
98 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {})
99 const = 0;
100
108 std::shared_ptr<ICondition> getptr() {
109 return std::enable_shared_from_this<ICondition>::shared_from_this();
110 }
111
112 private:
113 std::vector<size_t>
114 indices;
115};
116
127 public:
136 EqualCondition(const std::vector<size_t> &ind, const std::vector<bool> &b)
137 : ICondition(ind), bits(b) {}
138
146 bool IsConditionMet(OperationState &state) const override {
147 return state.GetBits(GetBitsIndices()) == GetAllBits();
148 }
149
156 const std::vector<bool> &GetAllBits() const { return bits; }
157
164 void SetBits(const std::vector<bool> &b) { bits = b; }
165
172 std::shared_ptr<ICondition> Clone() const override {
173 return std::make_shared<EqualCondition>(GetBitsIndices(), GetAllBits());
174 }
175
185 std::shared_ptr<ICondition> Remap(
186 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {})
187 const override {
188 auto newCond = this->Clone();
189
190 auto newBits = newCond->GetBitsIndices();
191 for (size_t i = 0; i < newBits.size(); ++i) {
192 const auto bitit = bitsMap.find(newBits[i]);
193 if (bitit != bitsMap.end()) newBits[i] = bitit->second;
194 // else throw std::invalid_argument("Conditional operation: bit not found
195 // in the map, couldn't remap.");
196 }
197 newCond->SetBitsIndices(newBits);
198
199 return newCond;
200 }
201
202 private:
203 std::vector<bool> bits;
204};
205
216template <typename Time = Types::time_type>
217class IConditionalOperation : public IOperation<Time> {
218 public:
230 IConditionalOperation(const std::shared_ptr<IOperation<Time>> &operation,
231 const std::shared_ptr<ICondition> &condition,
232 Time delay = 0)
233 : IOperation<Time>(delay), operation(operation), condition(condition) {}
234
247 void Execute(const std::shared_ptr<Simulators::ISimulator> &sim,
248 OperationState &state) const override {
249 if (!condition || !operation) return;
250
251 if (condition->IsConditionMet(state)) operation->Execute(sim, state);
252 }
253
260 void SetOperation(const std::shared_ptr<IOperation<Time>> &op) {
261 if (!op) return;
262 // the reason why 'recursive' conditional gates are not allowed (as in
263 // conditional-conditional-...-gate) is because of the distribution for the
264 // network execution would work fine as long as it's 'local'
265 else if ((op->GetType() == OperationType::kGate &&
266 this->GetType() != OperationType::kConditionalGate) ||
267 (op->GetType() == OperationType::kMeasurement &&
268 this->GetType() != OperationType::kConditionalMeasurement) ||
269 (op->GetType() == OperationType::kRandomGen &&
270 this->GetType() != OperationType::kConditionalRandomGen))
271 return;
272
273 operation = op;
274 }
275
283 std::shared_ptr<IOperation<Time>> GetOperation() const { return operation; }
284
292 void SetCondition(const std::shared_ptr<ICondition> &cond) {
293 condition = cond;
294 }
295
303 std::shared_ptr<ICondition> GetCondition() const { return condition; }
304
311 std::vector<size_t> AffectedBits() const override {
312 if (!condition) return {};
313
314 return condition->GetBitsIndices();
315 }
316
323 Types::qubits_vector AffectedQubits() const override {
324 if (!operation) return {};
325
326 return operation->AffectedQubits();
327 }
328
339 std::shared_ptr<IOperation<Time>> Remap(
340 const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
341 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {})
342 const override {
343 const auto condOp =
344 std::static_pointer_cast<IConditionalOperation<Time>>(this->Clone());
345
346 condOp->SetCondition(condOp->GetCondition()->Remap(bitsMap));
347 condOp->SetOperation(condOp->GetOperation()->Remap(qubitsMap, bitsMap));
348
349 return condOp;
350 }
351
361 bool IsClifford() const override {
362 if (!operation) return true;
363
364 return operation->IsClifford();
365 }
366
367 private:
368 std::shared_ptr<IOperation<Time>>
369 operation;
370 std::shared_ptr<ICondition> condition;
371};
372
382template <typename Time = Types::time_type>
384 public:
397 ConditionalGate(const std::shared_ptr<IGateOperation<Time>> &operation,
398 const std::shared_ptr<ICondition> &condition, Time delay = 0)
399 : IConditionalOperation<Time>(operation, condition, delay) {}
400
408 OperationType GetType() const override {
410 }
411
418 std::shared_ptr<IOperation<Time>> Clone() const override {
419 const auto gate = std::static_pointer_cast<IGateOperation<Time>>(
421 const auto cond = std::static_pointer_cast<ICondition>(
423
424 return std::make_shared<ConditionalGate<Time>>(
425 gate, cond, IOperation<Time>::GetDelay());
426 }
427};
428
438template <typename Time = Types::time_type>
440 public:
454 const std::shared_ptr<MeasurementOperation<Time>> &operation,
455 const std::shared_ptr<ICondition> &condition, Time delay = 0)
456 : IConditionalOperation<Time>(operation, condition, delay) {}
457
468
475 std::shared_ptr<IOperation<Time>> Clone() const override {
476 return std::make_shared<ConditionalMeasurement<Time>>(
477 std::static_pointer_cast<MeasurementOperation<Time>>(
479 std::static_pointer_cast<ICondition>(
482 }
483};
484
494template <typename Time = Types::time_type>
496 public:
509 ConditionalRandomGen(const std::shared_ptr<Random<Time>> &operation,
510 const std::shared_ptr<ICondition> &condition,
511 Time delay = 0)
512 : IConditionalOperation<Time>(operation, condition, delay) {}
513
521 OperationType GetType() const override {
523 }
524
531 std::shared_ptr<IOperation<Time>> Clone() const override {
532 return std::make_shared<ConditionalRandomGen<Time>>(
533 std::static_pointer_cast<Random<Time>>(
535 std::static_pointer_cast<ICondition>(
538 }
539
548 Types::qubits_vector AffectedQubits() const override { return {}; }
549};
550
551} // namespace Circuits
552
553#endif // !_CONDITIONAL_H_
A conditional quantum gate.
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.
A conditional measurement.
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.
A conditional random generator.
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.
Condition that checks if the bits are equal to a given value.
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.
Interface for a condition.
Definition Conditional.h:35
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:70
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:78
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:43
An operation conditioned on classical values.
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.
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:603
The operation interface.
Definition Operations.h:357
Time GetDelay() const
Get the delay of the operation.
Definition Operations.h:496
virtual std::shared_ptr< IOperation< Time > > Clone() const =0
Get a shared pointer to a clone of this object.
Measurement operation class.
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:62
std::vector< bool > GetBits(const std::vector< size_t > &indices) const
Get the classical bits at the specified indices.
Definition Operations.h:198
Random operation.
Definition RandomOp.h:33
OperationType
The type of operations.
Definition Operations.h:26
@ kConditionalGate
conditional gate, similar with gate, but conditioned on something from 'OperationState'
@ kRandomGen
random classical bit generator, result in 'OperationState'
@ kConditionalRandomGen
conditional random generator, similar with random gen, but conditioned on something from 'OperationSt...
@ kConditionalMeasurement
conditional measurement, similar with measurement, but conditioned on something from 'OperationState'
@ kMeasurement
measurement, result in 'OperationState'
@ kGate
the usual quantum gate, result stays in simulator's state