Maestro 0.2.5
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Operations.h
Go to the documentation of this file.
1
14#pragma once
15
16#ifndef _CIRCUIT_OPERATIONS_H_
17#define _CIRCUIT_OPERATIONS_H_
18
19#include "../Simulators/Simulator.h"
20#include "../Types.h"
21
22namespace Circuits {
48
49// simulators keep track of the quantum state, but there are things that are not
50// part of it that need keeping around (for example, the result of a
51// measurement, or if it's a 'random generation' operation, the generated
52// number), so here it is the values in there are needed either for the end
53// result or for the next operation (conditional gate, conditional measurement)
54
64 public:
72 OperationState(size_t numBits = 0) { AllocateBits(numBits); }
73
81 OperationState(const OperationState &other) : bits(other.bits) {}
82
91 : bits(std::move(other.bits)) {}
92
99 OperationState(const std::vector<bool> &b) : bits(b) {}
100
107 OperationState(std::vector<bool> &&b) : bits(std::move(b)) {}
108
116 bits = other.bits;
117 return *this;
118 }
119
127 bits.swap(other.bits);
128 return *this;
129 }
130
137 OperationState &operator=(const std::vector<bool> &b) {
138 bits = b;
139 return *this;
140 }
141
148 OperationState &operator=(std::vector<bool> &&b) {
149 bits.swap(b);
150 return *this;
151 }
152
160 void AllocateBits(size_t numBits) {
161 bits.resize(bits.size() + numBits, false);
162 }
163
169 void Clear() { bits.clear(); }
170
177 size_t GetNumBits() const { return bits.size(); }
178
186 bool GetBit(size_t index) const {
187 if (index > bits.size()) return false;
188
189 return bits[index];
190 }
191
199 std::vector<bool> GetBits(const std::vector<size_t> &indices) const {
200 std::vector<bool> results(indices.size(), false);
201
202 for (size_t i = 0; i < indices.size(); ++i)
203 if (indices[i] < bits.size()) results[i] = bits[indices[i]];
204
205 return results;
206 }
207
214 const std::vector<bool> &GetAllBits() const { return bits; }
215
222 std::vector<bool> GetAllBitsCopy() const { return bits; }
223
231 void SetBit(size_t index, bool value = true) {
232 if (index > bits.size()) return;
233
234 bits[index] = value;
235 }
236
244 void Reset(bool value = false) { std::fill(bits.begin(), bits.end(), value); }
245
253 void SetResultsInOrder(const std::vector<bool> &results) {
254 const size_t theSize = std::max(bits.size(), results.size());
255
256 bits = results;
257 bits.resize(theSize, false);
258 }
259
268 void SetResults(const std::vector<size_t> &indices, size_t results) {
269 for (int i = 0; i < static_cast<int>(indices.size()); ++i) {
270 if (indices[i] < bits.size()) bits[indices[i]] = results & 1;
271 results >>= 1;
272 }
273 }
274
283 void Swap(OperationState &results) { bits.swap(results.bits); }
284
297 void Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &mapping,
298 bool ignoreNotMapped = false, size_t newSize = 0) {
299 std::vector<bool> newBits(
300 newSize > 0 ? newSize
301 : (ignoreNotMapped ? mapping.size() : bits.size()),
302 false);
303
304 for (size_t i = 0; i < bits.size(); ++i) {
305 const auto it = mapping.find(i);
306 if (it != mapping.end())
307 newBits[it->second] = bits[i];
308 else if (!ignoreNotMapped && i < newBits.size())
309 newBits[i] = bits[i];
310 }
311
312 bits.swap(newBits);
313 }
314
327 void RemapWithVector(const std::vector<Types::qubit_t> &mapping,
328 bool ignoreNotMapped = false, size_t newSize = 0) {
329 std::vector<bool> newBits(
330 newSize > 0 ? newSize
331 : (ignoreNotMapped ? mapping.size() : bits.size()),
332 false);
333
334 for (size_t i = 0; i < bits.size(); ++i) {
335 if (i < mapping.size())
336 newBits[mapping.at(i)] = bits[i];
337 else if (!ignoreNotMapped && i < newBits.size())
338 newBits[i] = bits[i];
339 }
340
341 bits.swap(newBits);
342 }
343
344 private:
345 std::vector<bool> bits;
346};
347
357template <typename Time = Types::time_type>
358class IOperation : public std::enable_shared_from_this<IOperation<Time>> {
359 public:
366 IOperation(Time delay = 0) : delay(delay){};
367
375 virtual ~IOperation() = default;
376
386 virtual void Execute(const std::shared_ptr<Simulators::ISimulator> &sim,
387 OperationState &state) const = 0;
388
396 virtual OperationType GetType() const { return OperationType::kNoOp; }
397
404 virtual std::shared_ptr<IOperation<Time>> Clone() const = 0;
405
416 virtual std::shared_ptr<IOperation<Time>> Remap(
417 const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
418 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {})
419 const = 0;
420
437
446 virtual bool NeedsEntanglementForDistribution() const {
447 return (GetType() == OperationType::kGate ||
449 AffectedQubits().size() > 1;
450 }
451
463
470 virtual Types::qubits_vector AffectedQubits() const { return {}; }
471
478 virtual std::vector<size_t> AffectedBits() const { return {}; }
479
487 std::shared_ptr<IOperation<Time>> getptr() {
488 return std::enable_shared_from_this<IOperation<Time>>::shared_from_this();
489 }
490
497 Time GetDelay() const { return delay; }
498
505 void SetDelay(Time d) { delay = d; }
506
516 virtual bool IsClifford() const { return false; }
517
518 private:
519 Time delay;
520};
521
530template <typename Time = Types::time_type>
531class NoOperation : public IOperation<Time> {
532 public:
539 NoOperation(Time delay = 0) : IOperation<Time>(delay){};
540
553 void Execute(const std::shared_ptr<Simulators::ISimulator> &sim,
554 OperationState &state) const override {}
555
562 std::shared_ptr<IOperation<Time>> Clone() const override {
563 return std::make_shared<NoOperation<Time>>(NoOperation<Time>::GetDelay());
564 }
565
576 std::shared_ptr<IOperation<Time>> Remap(
577 const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
578 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap)
579 const override {
580 return this->Clone();
581 }
582
592 bool IsClifford() const override { return true; }
593};
594
603template <typename Time = Types::time_type>
604class IGateOperation : public IOperation<Time> {
605 public:
612 IGateOperation(Time delay = 0) : IOperation<Time>(delay){};
613
621 OperationType GetType() const override { return OperationType::kGate; }
622
629 virtual unsigned int GetNumQubits() const = 0;
630
639 virtual void SetQubit(Types::qubit_t qubit, unsigned long index = 0) = 0;
640
649 virtual Types::qubit_t GetQubit(unsigned int index = 0) const = 0;
650};
651
652} // namespace Circuits
653
654#endif // !_CIRCUIT_OPERATIONS_H_
The gate operation interface.
Definition Operations.h:604
virtual Types::qubit_t GetQubit(unsigned int index=0) const =0
Get the qubit involved.
OperationType GetType() const override
Get the type of the operation.
Definition Operations.h:621
virtual void SetQubit(Types::qubit_t qubit, unsigned long index=0)=0
Set the qubits involved.
IGateOperation(Time delay=0)
Construct a new IGateOperation object.
Definition Operations.h:612
virtual unsigned int GetNumQubits() const =0
Get the number of qubits.
The operation interface.
Definition Operations.h:358
virtual bool IsClifford() const
Checks if the operation is a Clifford one.
Definition Operations.h:516
virtual std::vector< size_t > AffectedBits() const
Returns the affected bits.
Definition Operations.h:478
virtual bool CanAffectQuantumState() const
Find if the operation can affect the quantum state.
Definition Operations.h:429
void SetDelay(Time d)
Set the delay of the operation.
Definition Operations.h:505
virtual Types::qubits_vector AffectedQubits() const
Returns the affected qubits.
Definition Operations.h:470
Time GetDelay() const
Get the delay of the operation.
Definition Operations.h:497
virtual OperationType GetType() const
Get the type of the operation.
Definition Operations.h:396
IOperation(Time delay=0)
Construct a new IOperation object.
Definition Operations.h:366
virtual bool IsConditional() const
Find if the operation is a conditional operation.
Definition Operations.h:458
virtual ~IOperation()=default
Destroy the IOperation object.
virtual 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 =0
Get a shared pointer to a remapped operation.
virtual std::shared_ptr< IOperation< Time > > Clone() const =0
Get a shared pointer to a clone of this object.
virtual void Execute(const std::shared_ptr< Simulators::ISimulator > &sim, OperationState &state) const =0
Execute the operation.
std::shared_ptr< IOperation< Time > > getptr()
Get a shared pointer to this object.
Definition Operations.h:487
virtual bool NeedsEntanglementForDistribution() const
Find if the operation needs entanglement for distribution.
Definition Operations.h:446
The no operation.
Definition Operations.h:531
std::shared_ptr< IOperation< Time > > Clone() const override
Get a shared pointer to a clone of this object.
Definition Operations.h:562
bool IsClifford() const override
Checks if the operation is a Clifford one.
Definition Operations.h:592
NoOperation(Time delay=0)
Construct a new NoOperation object.
Definition Operations.h:539
void Execute(const std::shared_ptr< Simulators::ISimulator > &sim, OperationState &state) const override
Execute the operation.
Definition Operations.h:553
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.
Definition Operations.h:576
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:63
void Reset(bool value=false)
Set the classical bits with the specified value.
Definition Operations.h:244
OperationState(const OperationState &other)
Construct a new Operation State object.
Definition Operations.h:81
const std::vector< bool > & GetAllBits() const
Get the classical bits.
Definition Operations.h:214
OperationState(size_t numBits=0)
Construct a new Operation State object.
Definition Operations.h:72
void AllocateBits(size_t numBits)
Allocate more bits.
Definition Operations.h:160
OperationState(std::vector< bool > &&b)
Construct a new Operation State object.
Definition Operations.h:107
std::vector< bool > GetBits(const std::vector< size_t > &indices) const
Get the classical bits at the specified indices.
Definition Operations.h:199
void SetBit(size_t index, bool value=true)
Set the classical bit at the specified index.
Definition Operations.h:231
OperationState & operator=(const std::vector< bool > &b)
Assign the bits.
Definition Operations.h:137
void Clear()
Clear the classical state.
Definition Operations.h:169
OperationState(OperationState &&other) noexcept
Construct a new Operation State object.
Definition Operations.h:90
void SetResultsInOrder(const std::vector< bool > &results)
Set the classical bits.
Definition Operations.h:253
size_t GetNumBits() const
Get the number of classical bits.
Definition Operations.h:177
void Remap(const std::unordered_map< Types::qubit_t, Types::qubit_t > &mapping, bool ignoreNotMapped=false, size_t newSize=0)
Convert the state using the provided mapping.
Definition Operations.h:297
OperationState(const std::vector< bool > &b)
Construct a new Operation State object.
Definition Operations.h:99
std::vector< bool > GetAllBitsCopy() const
Get the classical bits.
Definition Operations.h:222
bool GetBit(size_t index) const
Get the classical bit at the specified index.
Definition Operations.h:186
void RemapWithVector(const std::vector< Types::qubit_t > &mapping, bool ignoreNotMapped=false, size_t newSize=0)
Convert the state using the provided mapping.
Definition Operations.h:327
OperationState & operator=(OperationState &&other) noexcept
Assign the bits.
Definition Operations.h:126
void Swap(OperationState &results)
Set results.
Definition Operations.h:283
OperationState & operator=(const OperationState &other)
Assign the bits.
Definition Operations.h:115
OperationState & operator=(std::vector< bool > &&b)
Assign the bits.
Definition Operations.h:148
void SetResults(const std::vector< size_t > &indices, size_t results)
Set the classical bits at the specified indices.
Definition Operations.h:268
OperationType
The type of operations.
Definition Operations.h:27
@ kConditionalGate
conditional gate, similar with gate, but conditioned on something from 'OperationState'
@ kNoOp
no operation, just a placeholder, could be used to erase some operation from a circuit
@ kComposite
a composite operation, contains other operations - should not be used in the beginning,...
@ 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
@ kReset
reset, no result in 'state', just apply measurement, then apply not on all qubits that were measured ...
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:21
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:23