Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Operations.h
Go to the documentation of this file.
1
13#pragma once
14
15#ifndef _CIRCUIT_OPERATIONS_H_
16#define _CIRCUIT_OPERATIONS_H_
17
18#include "../Simulators/Simulator.h"
19#include "../Types.h"
20
21namespace Circuits {
47
48// simulators keep track of the quantum state, but there are things that are not
49// part of it that need keeping around (for example, the result of a
50// measurement, or if it's a 'random generation' operation, the generated
51// number), so here it is the values in there are needed either for the end
52// result or for the next operation (conditional gate, conditional measurement)
53
63 public:
71 OperationState(size_t numBits = 0) { AllocateBits(numBits); }
72
80 OperationState(const OperationState &other) : bits(other.bits) {}
81
90 : bits(std::move(other.bits)) {}
91
98 OperationState(const std::vector<bool> &b) : bits(b) {}
99
106 OperationState(std::vector<bool> &&b) : bits(std::move(b)) {}
107
115 bits = other.bits;
116 return *this;
117 }
118
126 bits.swap(other.bits);
127 return *this;
128 }
129
136 OperationState &operator=(const std::vector<bool> &b) {
137 bits = b;
138 return *this;
139 }
140
147 OperationState &operator=(std::vector<bool> &&b) {
148 bits.swap(b);
149 return *this;
150 }
151
159 void AllocateBits(size_t numBits) {
160 bits.resize(bits.size() + numBits, false);
161 }
162
168 void Clear() { bits.clear(); }
169
176 size_t GetNumBits() const { return bits.size(); }
177
185 bool GetBit(size_t index) const {
186 if (index > bits.size()) return false;
187
188 return bits[index];
189 }
190
198 std::vector<bool> GetBits(const std::vector<size_t> &indices) const {
199 std::vector<bool> results(indices.size(), false);
200
201 for (size_t i = 0; i < indices.size(); ++i)
202 if (indices[i] < bits.size()) results[i] = bits[indices[i]];
203
204 return results;
205 }
206
213 const std::vector<bool> &GetAllBits() const { return bits; }
214
221 std::vector<bool> GetAllBitsCopy() const { return bits; }
222
230 void SetBit(size_t index, bool value = true) {
231 if (index > bits.size()) return;
232
233 bits[index] = value;
234 }
235
243 void Reset(bool value = false) { std::fill(bits.begin(), bits.end(), value); }
244
252 void SetResultsInOrder(const std::vector<bool> &results) {
253 const size_t theSize = std::max(bits.size(), results.size());
254
255 bits = results;
256 bits.resize(theSize, false);
257 }
258
267 void SetResults(const std::vector<size_t> &indices, size_t results) {
268 for (int i = 0; i < static_cast<int>(indices.size()); ++i) {
269 if (indices[i] < bits.size()) bits[indices[i]] = results & 1;
270 results >>= 1;
271 }
272 }
273
282 void Swap(OperationState &results) { bits.swap(results.bits); }
283
296 void Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &mapping,
297 bool ignoreNotMapped = false, size_t newSize = 0) {
298 std::vector<bool> newBits(
299 newSize > 0 ? newSize
300 : (ignoreNotMapped ? mapping.size() : bits.size()),
301 false);
302
303 for (size_t i = 0; i < bits.size(); ++i) {
304 const auto it = mapping.find(i);
305 if (it != mapping.end())
306 newBits[it->second] = bits[i];
307 else if (!ignoreNotMapped && i < newBits.size())
308 newBits[i] = bits[i];
309 }
310
311 bits.swap(newBits);
312 }
313
326 void RemapWithVector(const std::vector<Types::qubit_t> &mapping,
327 bool ignoreNotMapped = false, size_t newSize = 0) {
328 std::vector<bool> newBits(
329 newSize > 0 ? newSize
330 : (ignoreNotMapped ? mapping.size() : bits.size()),
331 false);
332
333 for (size_t i = 0; i < bits.size(); ++i) {
334 if (i < mapping.size())
335 newBits[mapping.at(i)] = bits[i];
336 else if (!ignoreNotMapped && i < newBits.size())
337 newBits[i] = bits[i];
338 }
339
340 bits.swap(newBits);
341 }
342
343 private:
344 std::vector<bool> bits;
345};
346
356template <typename Time = Types::time_type>
357class IOperation : public std::enable_shared_from_this<IOperation<Time>> {
358 public:
365 IOperation(Time delay = 0) : delay(delay){};
366
374 virtual ~IOperation() = default;
375
385 virtual void Execute(const std::shared_ptr<Simulators::ISimulator> &sim,
386 OperationState &state) const = 0;
387
395 virtual OperationType GetType() const { return OperationType::kNoOp; }
396
403 virtual std::shared_ptr<IOperation<Time>> Clone() const = 0;
404
415 virtual std::shared_ptr<IOperation<Time>> Remap(
416 const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
417 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {})
418 const = 0;
419
436
445 virtual bool NeedsEntanglementForDistribution() const {
446 return (GetType() == OperationType::kGate ||
448 AffectedQubits().size() > 1;
449 }
450
462
469 virtual Types::qubits_vector AffectedQubits() const { return {}; }
470
477 virtual std::vector<size_t> AffectedBits() const { return {}; }
478
486 std::shared_ptr<IOperation<Time>> getptr() {
487 return std::enable_shared_from_this<IOperation<Time>>::shared_from_this();
488 }
489
496 Time GetDelay() const { return delay; }
497
504 void SetDelay(Time d) { delay = d; }
505
515 virtual bool IsClifford() const { return false; }
516
517 private:
518 Time delay;
519};
520
529template <typename Time = Types::time_type>
530class NoOperation : public IOperation<Time> {
531 public:
538 NoOperation(Time delay = 0) : IOperation<Time>(delay){};
539
552 void Execute(const std::shared_ptr<Simulators::ISimulator> &sim,
553 OperationState &state) const override {}
554
561 std::shared_ptr<IOperation<Time>> Clone() const override {
562 return std::make_shared<NoOperation<Time>>(NoOperation<Time>::GetDelay());
563 }
564
575 std::shared_ptr<IOperation<Time>> Remap(
576 const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
577 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap)
578 const override {
579 return this->Clone();
580 }
581
591 bool IsClifford() const override { return true; }
592};
593
602template <typename Time = Types::time_type>
603class IGateOperation : public IOperation<Time> {
604 public:
611 IGateOperation(Time delay = 0) : IOperation<Time>(delay){};
612
620 OperationType GetType() const override { return OperationType::kGate; }
621
628 virtual unsigned int GetNumQubits() const = 0;
629
638 virtual void SetQubit(Types::qubit_t qubit, unsigned long index = 0) = 0;
639
648 virtual Types::qubit_t GetQubit(unsigned int index = 0) const = 0;
649};
650
651} // namespace Circuits
652
653#endif // !_CIRCUIT_OPERATIONS_H_
The gate operation interface.
Definition Operations.h:603
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:620
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:611
virtual unsigned int GetNumQubits() const =0
Get the number of qubits.
The operation interface.
Definition Operations.h:357
virtual bool IsClifford() const
Checks if the operation is a Clifford one.
Definition Operations.h:515
virtual std::vector< size_t > AffectedBits() const
Returns the affected bits.
Definition Operations.h:477
virtual bool CanAffectQuantumState() const
Find if the operation can affect the quantum state.
Definition Operations.h:428
void SetDelay(Time d)
Set the delay of the operation.
Definition Operations.h:504
virtual Types::qubits_vector AffectedQubits() const
Returns the affected qubits.
Definition Operations.h:469
Time GetDelay() const
Get the delay of the operation.
Definition Operations.h:496
virtual OperationType GetType() const
Get the type of the operation.
Definition Operations.h:395
IOperation(Time delay=0)
Construct a new IOperation object.
Definition Operations.h:365
virtual bool IsConditional() const
Find if the operation is a conditional operation.
Definition Operations.h:457
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:486
virtual bool NeedsEntanglementForDistribution() const
Find if the operation needs entanglement for distribution.
Definition Operations.h:445
The no operation.
Definition Operations.h:530
std::shared_ptr< IOperation< Time > > Clone() const override
Get a shared pointer to a clone of this object.
Definition Operations.h:561
bool IsClifford() const override
Checks if the operation is a Clifford one.
Definition Operations.h:591
NoOperation(Time delay=0)
Construct a new NoOperation object.
Definition Operations.h:538
void Execute(const std::shared_ptr< Simulators::ISimulator > &sim, OperationState &state) const override
Execute the operation.
Definition Operations.h:552
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:575
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:62
void Reset(bool value=false)
Set the classical bits with the specified value.
Definition Operations.h:243
OperationState(const OperationState &other)
Construct a new Operation State object.
Definition Operations.h:80
const std::vector< bool > & GetAllBits() const
Get the classical bits.
Definition Operations.h:213
OperationState(size_t numBits=0)
Construct a new Operation State object.
Definition Operations.h:71
void AllocateBits(size_t numBits)
Allocate more bits.
Definition Operations.h:159
OperationState(std::vector< bool > &&b)
Construct a new Operation State object.
Definition Operations.h:106
std::vector< bool > GetBits(const std::vector< size_t > &indices) const
Get the classical bits at the specified indices.
Definition Operations.h:198
void SetBit(size_t index, bool value=true)
Set the classical bit at the specified index.
Definition Operations.h:230
OperationState & operator=(const std::vector< bool > &b)
Assign the bits.
Definition Operations.h:136
void Clear()
Clear the classical state.
Definition Operations.h:168
OperationState(OperationState &&other) noexcept
Construct a new Operation State object.
Definition Operations.h:89
void SetResultsInOrder(const std::vector< bool > &results)
Set the classical bits.
Definition Operations.h:252
size_t GetNumBits() const
Get the number of classical bits.
Definition Operations.h:176
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:296
OperationState(const std::vector< bool > &b)
Construct a new Operation State object.
Definition Operations.h:98
std::vector< bool > GetAllBitsCopy() const
Get the classical bits.
Definition Operations.h:221
bool GetBit(size_t index) const
Get the classical bit at the specified index.
Definition Operations.h:185
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:326
OperationState & operator=(OperationState &&other) noexcept
Assign the bits.
Definition Operations.h:125
void Swap(OperationState &results)
Set results.
Definition Operations.h:282
OperationState & operator=(const OperationState &other)
Assign the bits.
Definition Operations.h:114
OperationState & operator=(std::vector< bool > &&b)
Assign the bits.
Definition Operations.h:147
void SetResults(const std::vector< size_t > &indices, size_t results)
Set the classical bits at the specified indices.
Definition Operations.h:267
OperationType
The type of operations.
Definition Operations.h:26
@ 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 ...