MeasurementResult#
- class MeasurementResult[source]#
Raw bitstring counts returned by
Backend.run().run()always returns aMeasurementResult. For standard (non-batched) backends the object arrives pre-populated (data is immediately available without any further call). ForBatchedBackendthe object starts empty and is filled only whendispatch()is called. Any attempt to read the data before population raisesRuntimeError.MeasurementResultis aMapping, so all dict-style access works unchanged.Examples
The typical way to obtain a
MeasurementResultis throughrun():from qrisp import QuantumCircuit from qrisp.default_backend import QrispSimulatorBackend circuit = QuantumCircuit(1) circuit.h(0) circuit.measure(0) backend = QrispSimulatorBackend() result = backend.run(circuit, shots=1024)
The object supports all standard dict-style operations:
>>> print(result["0"]) # e.g. 512 >>> print(result["1"]) # e.g. 512 >>> print(len(result)) # 2 >>> print(set(result)) # {'1', '0'} >>> for bitstring, count in result.items(): ... print(bitstring, count)
Equality comparison works against a plain
dict:>>> result == {"0": 512, "1": 512} # True if counts match exactly
Membership check:
>>> isinstance(result, Mapping) # True >>> isinstance(result, dict) # False
For the batched (lazy) case, the object is returned before the circuits are executed. Accessing data before
dispatch()is called raisesRuntimeError:from qrisp import QuantumFloat from qrisp.default_backend import QrispSimulatorBackend batched_backend = QrispSimulatorBackend().batched() qf = QuantumFloat(3) qf[:] = 5 result = qf.get_measurement(backend=batched_backend) # returns immediately (empty) # result["0"] # RuntimeError: Call dispatch() first. batched_backend.dispatch() print(result) # {5: 1.0}
Methods#
- MeasurementResult._populate() None[source]#
Raise until the result is populated via
_inject().Re-raises
_errorif one was stored by_inject_error(), otherwise raisesRuntimeErrorto signal thatdispatch()has not been called yet.
- MeasurementResult._inject(counts: dict) None[source]#
Populate with raw backend results.
Called by
run()for standard backends and bydispatch()for batched backends.- Parameters:
- countsdict
Raw bitstring-to-count mapping produced by the backend.
- MeasurementResult._inject_error(exc: Exception) None[source]#
Store exc so it is raised on every subsequent data access.
After this call
_populatedremainsFalse, so every subsequent access calls_populate(), which immediately re-raises the stored exception. This ensures the error is visible no matter how many times the result is accessed.- Parameters:
- excException
The exception to store and re-raise on access.
DecodedMeasurementResult#
- class DecodedMeasurementResult(raw: LazyDict, decoder: Callable[[int], object])[source]#
Human-readable measurement result produced by
QuantumVariable.get_measurement().Wraps a raw or intermediate
LazyDicttogether with a decoder callable. On first access the raw data is read, decoder is applied to every key, duplicate labels are merged by summing their counts, and the result is cached sorted by probability (descending).Because decoding is deferred, this object can be returned before
dispatch()is called when using aBatchedBackend. The decoded data becomes available automatically once the underlying raw result is populated.- Parameters:
- rawLazyDict
The source of integer-keyed, normalised probability data (typically an
_IntKeyedResultreturned byget_measurement_from_qc).- decoderCallable[[int], object]
Maps an integer bitstring index to a user-facing label. This is
QuantumVariable.decoder.
Examples
DecodedMeasurementResultis returned directly byget_measurement():from qrisp import QuantumFloat from qrisp.default_backend import QrispSimulatorBackend backend = QrispSimulatorBackend() qf = QuantumFloat(4) qf[:] = 7 result = qf.get_measurement(backend=backend) >>> print(result) # {7: 1.0} >>> print(result[7]) # 1.0 >>> print(len(result)) # 1 >>> print(result == {7: 1.0}) # True
When multiple outcomes are possible, the result is sorted by probability, highest first:
from qrisp import QuantumFloat, h qf = QuantumFloat(2) h(qf[0]) result = qf.get_measurement(backend=backend, shots=1024) # e.g. {0: 0.51, 1: 0.49} or {1: 0.52, 0: 0.48} (highest first)
In the batched case the object is returned immediately and decoding happens lazily on first access after
dispatch():from qrisp import QuantumFloat from qrisp.default_backend import QrispSimulatorBackend batched_backend = QrispSimulatorBackend().batched() a = QuantumFloat(4); a[:] = 3 b = QuantumFloat(4); b[:] = 5 res_a = a.get_measurement(backend=batched_backend) res_b = b.get_measurement(backend=batched_backend) print(res_a) # <DecodedMeasurementResult pending> print(res_b) # <DecodedMeasurementResult pending> batched_backend.dispatch() # populates raw results print(res_a) # {3: 1.0} decoded on first access print(res_b) # {5: 1.0}
LazyDict#
- class LazyDict[source]#
Abstract lazy mapping whose data is computed exactly once on first access.
LazyDictis the common base class for all result types returned by Qrisp backends. Subclasses implement_populate()to fillself._datathe first time anyMappingoperation is called. Subsequent accesses reuse the cached data without re-running_populate().If
_populateraises an exception,_populatedstaysFalseand the next access will call_populateagain. Concrete subclasses such asMeasurementResultexploit this to implement persistent error propagation: they re-raise the stored exception on every call.All standard
Mappingoperations ([],len,iter,==) are supported and trigger population on first use.Implementing a custom LazyDict
Subclass
LazyDictand implement_populate()to fillself._datawith a plaindict:class MyResult(LazyDict): def _populate(self): self._data = {"answer": 42} r = MyResult() print(r._populated) # False print(r["answer"]) # 42 (population happens here) print(r._populated) # True
Methods#
- abstractmethod LazyDict._populate() None[source]#
Fill
self._data. Called at most once by_ensure_populated().
- LazyDict._ensure_populated() None[source]#
Trigger population if it has not happened yet.
Calls
_populate()exactly once on first access. If_populateraises,_populatedstaysFalseand the next access will call_populateagain.