Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
Measurements.h
Go to the documentation of this file.
1
14
15#pragma once
16
17#ifndef _MEASUREMENTS_H_
18#define _MEASUREMENTS_H_
19
20#include "Operations.h"
21#include <vector>
22
23namespace Circuits {
24
35template <typename Time = Types::time_type>
36class MeasurementOperation : public IOperation<Time> {
37public:
49 const std::vector<std::pair<Types::qubit_t, size_t>> &qs = {},
50 Time delay = 0)
51 : IOperation<Time>(delay) {
52 SetQubits(qs);
53 }
54
63
70 virtual size_t GetNumQubits() const { return qubits.size(); }
71
77 void Clear() {
78 qubits.clear();
79 bits.clear();
80 }
81
90 void SetQubits(const std::vector<std::pair<Types::qubit_t, size_t>> &qs) {
91 qubits.resize(qs.size());
92 bits.resize(qs.size());
93 for (size_t i = 0; i < qs.size(); ++i) {
94 qubits[i] = qs[i].first;
95 bits[i] = qs[i].second;
96 }
97 }
98
105 const Types::qubits_vector &GetQubits() const { return qubits; }
106
113 const std::vector<size_t> &GetBitsIndices() const { return bits; }
114
124 void Execute(const std::shared_ptr<Simulators::ISimulator> &sim,
125 OperationState &state) const override {
126 if (qubits.empty())
127 return;
128
129 size_t res = sim->Measure(qubits);
130
131 for (size_t i = 0; i < qubits.size(); ++i) {
132 state.SetBit(bits[i], (res & 1) != 0);
133 res >>= 1;
134 }
135 }
136
148 void Sample(const std::shared_ptr<Simulators::ISimulator> &sim,
149 OperationState &state) const {
150 if (qubits.empty())
151 return;
152
153 size_t res = sim->SampleCounts(qubits, 1).begin()->first;
154
155 for (auto bit : bits) {
156 state.SetBit(bit, (res & 1) != 0);
157 res >>= 1;
158 }
159 }
160
161 void SetStateFromSample(size_t measurements, OperationState &state) const {
162 if (qubits.empty())
163 return;
164
165 for (size_t index = 0; index < qubits.size(); ++index) {
166 const auto cbit = bits[index];
167 const size_t qubitMask = 1ULL << index;
168 state.SetBit(cbit, (measurements & qubitMask) != 0);
169 }
170 }
171
172 void SetStateFromAllMeasurements(size_t allMeasurements,
173 OperationState &state) const {
174 if (qubits.empty())
175 return;
176
177 for (size_t index = 0; index < qubits.size(); ++index) {
178 const auto q = qubits[index];
179 const auto cbit = bits[index];
180
181 const size_t qubitMask = 1ULL << q;
182
183 state.SetBit(cbit, (allMeasurements & qubitMask) != 0);
184 }
185 }
186
193 std::shared_ptr<IOperation<Time>> Clone() const override {
194 std::vector<std::pair<Types::qubit_t, size_t>> qs(qubits.size());
195 for (size_t i = 0; i < qubits.size(); ++i)
196 qs[i] = std::make_pair(qubits[i], bits[i]);
197
198 return std::make_shared<MeasurementOperation<Time>>(
200 }
201
208 Types::qubits_vector AffectedQubits() const override { return qubits; }
209
216 std::vector<size_t> AffectedBits() const override { return GetBitsIndices(); }
217
228 std::shared_ptr<IOperation<Time>>
229 Remap(const std::unordered_map<Types::qubit_t, Types::qubit_t> &qubitsMap,
230 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap = {})
231 const override {
232 auto newOp = this->Clone();
233
234 for (size_t i = 0; i < qubits.size(); ++i) {
235 const auto qubitit = qubitsMap.find(qubits[i]);
236 if (qubitit != qubitsMap.end())
237 std::static_pointer_cast<MeasurementOperation<Time>>(newOp)->SetQubit(
238 i, qubitit->second);
239 // else throw std::runtime_error("MeasurementOperation::Remap: qubit not
240 // found in map.");
241 }
242
243 for (size_t i = 0; i < bits.size(); ++i) {
244 const auto bitit = bitsMap.find(bits[i]);
245 if (bitit != bitsMap.end())
246 std::static_pointer_cast<MeasurementOperation<Time>>(newOp)->SetBit(
247 i, bitit->second);
248 // else throw std::runtime_error("MeasurementOperation::Remap: bit not
249 // found in map.");
250 }
251
252 return newOp;
253 }
254
264 bool IsClifford() const override { return true; }
265
273 void SetQubit(size_t index, Types::qubit_t qubit) {
274 if (index < qubits.size())
275 qubits[index] = qubit;
276 }
277
285 void SetBit(size_t index, Types::qubit_t bit) {
286 if (index < bits.size())
287 bits[index] = bit;
288 }
289
290private:
291 Types::qubits_vector qubits;
292 std::vector<size_t>
293 bits;
294};
295
296} // namespace Circuits
297
298#endif // !_MEASUREMENTS_H_
The operation interface.
Definition Operations.h:361
Time GetDelay() const
Get the delay of the operation.
Definition Operations.h:500
IOperation(Types::time_type delay=0)
Definition Operations.h:369
std::shared_ptr< IOperation< Time > > Clone() const override
Get a shared pointer to a clone of this object.
void SetBit(size_t index, Types::qubit_t bit)
Set the classical bit to index.
void Clear()
Clears the qubits and classical bits involved in the measurement.
void SetQubits(const std::vector< std::pair< Types::qubit_t, size_t > > &qs)
Sets the qubits and classical bits involved in the measurement.
virtual size_t GetNumQubits() const
Get the number of qubits affected by the operation.
const std::vector< size_t > & GetBitsIndices() const
Returns the classical bits where the measurement results are stored.
void SetStateFromSample(size_t measurements, OperationState &state) const
const Types::qubits_vector & GetQubits() const
Returns the qubits that are to be measured.
MeasurementOperation(const std::vector< std::pair< Types::qubit_t, size_t > > &qs={}, Time delay=0)
Constructor.
void Sample(const std::shared_ptr< Simulators::ISimulator > &sim, OperationState &state) const
Samples the measurement on the given simulator.
OperationType GetType() const override
Get the type of the operation.
void SetStateFromAllMeasurements(size_t allMeasurements, OperationState &state) const
void SetQubit(size_t index, Types::qubit_t qubit)
Set the qubit to measure.
std::vector< size_t > AffectedBits() const override
Returns the classical bits affected by the measurement.
bool IsClifford() const override
Checks if the operation is a Clifford one.
void Execute(const std::shared_ptr< Simulators::ISimulator > &sim, OperationState &state) const override
Executes the measurement on the given simulator.
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.
Types::qubits_vector AffectedQubits() const override
Returns the qubits affected by the measurement.
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:62
void SetBit(size_t index, bool value=true)
Set the classical bit at the specified index.
Definition Operations.h:232
OperationType
The type of operations.
Definition Operations.h:26
@ kMeasurement
measurement, result in 'OperationState'
Definition Operations.h:28
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
Definition Types.h:21
uint_fast64_t qubit_t
The type of a qubit.
Definition Types.h:20