Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Operations.h
Go to the documentation of this file.
1
13
14#pragma once
15
16#ifndef _CIRCUIT_OPERATIONS_H_
17#define _CIRCUIT_OPERATIONS_H_
18
20#include "../../Types.h"
21
22namespace Circuits
23{
52
53// simulators keep track of the quantum state, but there are things that are not
54// part of it that need keeping around (for example, the result of a
55// measurement, or if it's a 'random generation' operation, the generated
56// number), so here it is the values in there are needed either for the end
57// result or for the next operation (conditional gate, conditional measurement)
58
68{
69 public:
77 OperationState(size_t numBits = 0)
78 {
79 AllocateBits(numBits);
80 }
81
89 OperationState(const OperationState &other) : bits(other.bits)
90 {
91 }
92
100 OperationState(OperationState &&other) noexcept : bits(std::move(other.bits))
101 {
102 }
103
110 OperationState(const std::vector<bool> &b) : bits(b)
111 {
112 }
113
120 OperationState(std::vector<bool> &&b) : bits(std::move(b))
121 {
122 }
123
131 {
132 bits = other.bits;
133 return *this;
134 }
135
143 {
144 bits.swap(other.bits);
145 return *this;
146 }
147
154 OperationState &operator=(const std::vector<bool> &b)
155 {
156 bits = b;
157 return *this;
158 }
159
166 OperationState &operator=(std::vector<bool> &&b)
167 {
168 bits.swap(b);
169 return *this;
170 }
171
179 void AllocateBits(size_t numBits)
180 {
181 bits.resize(bits.size() + numBits, false);
182 }
183
189 void Clear()
190 {
191 bits.clear();
192 }
193
200 size_t GetNumBits() const
201 {
202 return bits.size();
203 }
204
212 bool GetBit(size_t index) const
213 {
214 if (index > bits.size())
215 return false;
216
217 return bits[index];
218 }
219
227 std::vector<bool> GetBits(const std::vector<size_t> &indices) const
228 {
229 std::vector<bool> results(indices.size(), false);
230
231 for (size_t i = 0; i < indices.size(); ++i)
232 if (indices[i] < bits.size())
233 results[i] = bits[indices[i]];
234
235 return results;
236 }
237
244 const std::vector<bool> &GetAllBits() const
245 {
246 return bits;
247 }
248
255 std::vector<bool> GetAllBitsCopy() const
256 {
257 return bits;
258 }
259
267 void SetBit(size_t index, bool value = true)
268 {
269 if (index > bits.size())
270 return;
271
272 bits[index] = value;
273 }
274
282 void Reset(bool value = false)
283 {
284 std::fill(bits.begin(), bits.end(), value);
285 }
286
294 void SetResultsInOrder(const std::vector<bool> &results)
295 {
296 const size_t theSize = std::max(bits.size(), results.size());
297
298 bits = results;
299 bits.resize(theSize, false);
300 }
301
310 void SetResults(const std::vector<size_t> &indices, size_t results)
311 {
312 for (int i = 0; i < static_cast<int>(indices.size()); ++i)
313 {
314 if (indices[i] < bits.size())
315 bits[indices[i]] = results & 1;
316 results >>= 1;
317 }
318 }
319
328 void Swap(OperationState &results)
329 {
330 bits.swap(results.bits);
331 }
332
345 void Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &mapping, bool ignoreNotMapped = false, size_t newSize = 0)
346 {
347 std::vector<bool> newBits(newSize > 0 ? newSize : (ignoreNotMapped ? mapping.size() : bits.size()), false);
348
349 for (size_t i = 0; i < bits.size(); ++i)
350 {
351 const auto it = mapping.find(i);
352 if (it != mapping.end())
353 newBits[it->second] = bits[i];
354 else if (!ignoreNotMapped && i < newBits.size())
355 newBits[i] = bits[i];
356 }
357
358 bits.swap(newBits);
359 }
360
373 void RemapWithVector(const std::vector<Types::qubit_t> &mapping, bool ignoreNotMapped = false, size_t newSize = 0)
374 {
375 std::vector<bool> newBits(newSize > 0 ? newSize : (ignoreNotMapped ? mapping.size() : bits.size()), false);
376
377 for (size_t i = 0; i < bits.size(); ++i)
378 {
379 if (i < mapping.size())
380 newBits[mapping.at(i)] = bits[i];
381 else if (!ignoreNotMapped && i < newBits.size())
382 newBits[i] = bits[i];
383 }
384
385 bits.swap(newBits);
386 }
387
388 private:
389 std::vector<bool> bits;
390};
391
401template <typename Time = Types::time_type> class IOperation : public std::enable_shared_from_this<IOperation<Time>>
402{
403 public:
410 IOperation(Time delay = 0) : delay(delay){};
411
419 virtual ~IOperation() = default;
420
430 virtual void Execute(const std::shared_ptr<Simulators::ISimulator> &sim, OperationState &state) const = 0;
431
439 virtual OperationType GetType() const
440 {
442 }
443
450 virtual std::shared_ptr<IOperation<Time>> Clone() const = 0;
451
462 virtual std::shared_ptr<IOperation<Time>> Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
463 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {}) const = 0;
464
479
493
505
513 {
514 return {};
515 }
516
523 virtual std::vector<size_t> AffectedBits() const
524 {
525 return {};
526 }
527
535 std::shared_ptr<IOperation<Time>> getptr()
536 {
537 return std::enable_shared_from_this<IOperation<Time>>::shared_from_this();
538 }
539
546 Time GetDelay() const
547 {
548 return delay;
549 }
550
557 virtual void SetDelay(Time d)
558 {
559 delay = d;
560 }
561
570 void SetNoiseless(bool value = true)
571 {
572 noiseless = value;
573 }
574
580 bool IsNoiseless() const
581 {
582 return noiseless;
583 }
584
594 virtual bool IsClifford() const
595 {
596 return false;
597 }
598
607 virtual bool IsBranching() const
608 {
609 return false;
610 }
611
612 private:
613 Time delay;
614 bool noiseless = false;
615};
616
625template <typename Time = Types::time_type> class NoOperation : public IOperation<Time>
626{
627 public:
634 NoOperation(Time delay = 0) : IOperation<Time>(delay){};
635
648 void Execute(const std::shared_ptr<Simulators::ISimulator> &sim, OperationState &state) const override
649 {
650 }
651
658 std::shared_ptr<IOperation<Time>> Clone() const override
659 {
660 return std::make_shared<NoOperation<Time>>(NoOperation<Time>::GetDelay());
661 }
662
673 std::shared_ptr<IOperation<Time>> Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
674 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap) const override
675 {
676 return this->Clone();
677 }
678
688 bool IsClifford() const override
689 {
690 return true;
691 }
692};
693
702template <typename Time = Types::time_type> class IGateOperation : public IOperation<Time>
703{
704 public:
711 IGateOperation(Time delay = 0) : IOperation<Time>(delay){};
712
720 OperationType GetType() const override
721 {
723 }
724
731 virtual unsigned int GetNumQubits() const = 0;
732
741 virtual void SetQubit(Types::qubit_t qubit, unsigned long index = 0) = 0;
742
751 virtual Types::qubit_t GetQubit(unsigned int index = 0) const = 0;
752};
753
754} // namespace Circuits
755
756#endif // !_CIRCUIT_OPERATIONS_H_
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:720
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:711
virtual unsigned int GetNumQubits() const =0
Get the number of qubits.
virtual bool IsClifford() const
Checks if the operation is a Clifford one.
Definition Operations.h:594
virtual std::vector< size_t > AffectedBits() const
Returns the affected bits.
Definition Operations.h:523
virtual bool CanAffectQuantumState() const
Find if the operation can affect the quantum state.
Definition Operations.h:473
virtual Types::qubits_vector AffectedQubits() const
Returns the affected qubits.
Definition Operations.h:512
Time GetDelay() const
Get the delay of the operation.
Definition Operations.h:546
virtual void SetDelay(Time d)
Set the delay of the operation.
Definition Operations.h:557
virtual OperationType GetType() const
Get the type of the operation.
Definition Operations.h:439
virtual bool IsBranching() const
Checks if the operation is a branching one.
Definition Operations.h:607
IOperation(Time delay=0)
Construct a new IOperation object.
Definition Operations.h:410
virtual bool IsConditional() const
Find if the operation is a conditional operation.
Definition Operations.h:500
virtual ~IOperation()=default
Destroy the IOperation object.
void SetNoiseless(bool value=true)
Mark the operation as exempt from injected gate noise.
Definition Operations.h:570
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.
bool IsNoiseless() const
Whether noise models skip this operation.
Definition Operations.h:580
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:535
virtual bool NeedsEntanglementForDistribution() const
Find if the operation needs entanglement for distribution.
Definition Operations.h:488
std::shared_ptr< IOperation< Time > > Clone() const override
Get a shared pointer to a clone of this object.
Definition Operations.h:658
bool IsClifford() const override
Checks if the operation is a Clifford one.
Definition Operations.h:688
NoOperation(Time delay=0)
Construct a new NoOperation object.
Definition Operations.h:634
void Execute(const std::shared_ptr< Simulators::ISimulator > &sim, OperationState &state) const override
Execute the operation.
Definition Operations.h:648
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:673
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:68
void Reset(bool value=false)
Set the classical bits with the specified value.
Definition Operations.h:282
OperationState(const OperationState &other)
Construct a new Operation State object.
Definition Operations.h:89
const std::vector< bool > & GetAllBits() const
Get the classical bits.
Definition Operations.h:244
OperationState(size_t numBits=0)
Construct a new Operation State object.
Definition Operations.h:77
void AllocateBits(size_t numBits)
Allocate more bits.
Definition Operations.h:179
OperationState(std::vector< bool > &&b)
Construct a new Operation State object.
Definition Operations.h:120
std::vector< bool > GetBits(const std::vector< size_t > &indices) const
Get the classical bits at the specified indices.
Definition Operations.h:227
void SetBit(size_t index, bool value=true)
Set the classical bit at the specified index.
Definition Operations.h:267
OperationState & operator=(const std::vector< bool > &b)
Assign the bits.
Definition Operations.h:154
void Clear()
Clear the classical state.
Definition Operations.h:189
OperationState(OperationState &&other) noexcept
Construct a new Operation State object.
Definition Operations.h:100
void SetResultsInOrder(const std::vector< bool > &results)
Set the classical bits.
Definition Operations.h:294
size_t GetNumBits() const
Get the number of classical bits.
Definition Operations.h:200
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:345
OperationState(const std::vector< bool > &b)
Construct a new Operation State object.
Definition Operations.h:110
std::vector< bool > GetAllBitsCopy() const
Get the classical bits.
Definition Operations.h:255
bool GetBit(size_t index) const
Get the classical bit at the specified index.
Definition Operations.h:212
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:373
OperationState & operator=(OperationState &&other) noexcept
Assign the bits.
Definition Operations.h:142
void Swap(OperationState &results)
Set results.
Definition Operations.h:328
OperationState & operator=(const OperationState &other)
Assign the bits.
Definition Operations.h:130
OperationState & operator=(std::vector< bool > &&b)
Assign the bits.
Definition Operations.h:166
void SetResults(const std::vector< size_t > &indices, size_t results)
Set the classical bits at the specified indices.
Definition Operations.h:310
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
@ kDelay
a delay or idle period on one or more qubits
Definition Operations.h:50
@ kNoOp
no operation, just a placeholder, could be used to erase some operation from a circuit
Definition Operations.h:44
@ kComposite
a composite operation, contains other operations - should not be used in the beginning,...
Definition Operations.h:46
@ 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
@ kReset
reset, no result in 'state', just apply measurement, then apply not on all qubits that were measured ...
Definition Operations.h:41
@ kQuantumChannel
a non-unitary CPTP operation on the simulator state
Definition Operations.h:49
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