diff --git a/src/qibo/measurements.py b/src/qibo/measurements.py index 978f0beae4..8573e88280 100644 --- a/src/qibo/measurements.py +++ b/src/qibo/measurements.py @@ -1,31 +1,10 @@ import collections -import numpy as np import sympy -from qibo import gates from qibo.config import raise_error -def frequencies_to_binary(frequencies, nqubits): - return collections.Counter( - {"{:b}".format(k).zfill(nqubits): v for k, v in frequencies.items()} - ) - - -def apply_bitflips(result, p0, p1=None): - gate = result.measurement_gate - if p1 is None: - probs = 2 * (gate._get_bitflip_tuple(gate.qubits, p0),) - else: - probs = ( - gate._get_bitflip_tuple(gate.qubits, p0), - gate._get_bitflip_tuple(gate.qubits, p1), - ) - noiseless_samples = result.samples() - return result.backend.apply_bitflips(noiseless_samples, probs) - - class MeasurementSymbol(sympy.Symbol): """``sympy.Symbol`` connected to measurement results. @@ -161,7 +140,7 @@ def samples(self, binary=True, registers=False): # individual register samples are registered here self.circuit.final_state.samples() if binary: - return np.array(self._samples, dtype="int32") + return self.backend.cast(self._samples, dtype="int32") else: qubits = self.measurement_gate.target_qubits return self.backend.samples_to_decimal(self._samples, len(qubits)) @@ -190,9 +169,29 @@ def frequencies(self, binary=True, registers=False): ) if binary: qubits = self.measurement_gate.target_qubits - return frequencies_to_binary(self._frequencies, len(qubits)) + return _frequencies_to_binary(self._frequencies, len(qubits)) else: return self._frequencies def apply_bitflips(self, p0, p1=None): # pragma: no cover - return apply_bitflips(self, p0, p1) + return _apply_bitflips(self, p0, p1) + + +def _frequencies_to_binary(frequencies, nqubits): + return collections.Counter( + {"{:b}".format(int(k)).zfill(nqubits): v for k, v in frequencies.items()} + ) + + +def _apply_bitflips(result, p0, p1=None): + gate = result.measurement_gate + if p1 is None: + probs = 2 * (gate._get_bitflip_tuple(gate.qubits, p0),) + else: + probs = ( + gate._get_bitflip_tuple(gate.qubits, p0), + gate._get_bitflip_tuple(gate.qubits, p1), + ) + noiseless_samples = result.samples() + + return result.backend.apply_bitflips(noiseless_samples, probs) diff --git a/src/qibo/result.py b/src/qibo/result.py index 007fb2ea36..5470df6e08 100644 --- a/src/qibo/result.py +++ b/src/qibo/result.py @@ -6,7 +6,7 @@ from qibo import __version__, backends, gates from qibo.config import raise_error -from qibo.measurements import apply_bitflips, frequencies_to_binary +from qibo.measurements import _apply_bitflips, _frequencies_to_binary def load_result(filename: str): @@ -236,7 +236,7 @@ def frequencies(self, binary: bool = True, registers: bool = False): # register frequencies to individual gate ``MeasurementResult`` qubit_map = {q: i for i, q in enumerate(qubits)} reg_frequencies = {} - binary_frequencies = frequencies_to_binary( + binary_frequencies = _frequencies_to_binary( self._frequencies, len(qubits) ) for gate in self.measurements: @@ -261,7 +261,7 @@ def frequencies(self, binary: bool = True, registers: bool = False): } if binary: - return frequencies_to_binary(self._frequencies, len(qubits)) + return _frequencies_to_binary(self._frequencies, len(qubits)) return self._frequencies @@ -288,7 +288,7 @@ def probabilities(self, qubits: Optional[Union[list, set]] = None): probs = [0 for _ in range(2**nqubits)] for state, freq in self.frequencies(binary=False).items(): - probs[state] = freq / self.nshots + probs[int(state)] = freq / self.nshots probs = self.backend.cast(probs) self._probs = probs return self.backend.calculate_probabilities(np.sqrt(probs), qubits, nqubits) @@ -395,7 +395,7 @@ def apply_bitflips(self, p0: float, p1: Optional[float] = None): p0 (float): Probability of the 0->1 flip. p1 (float): Probability of the 1->0 flip. """ - return apply_bitflips(self, p0, p1) + return _apply_bitflips(self, p0, p1) def expectation_from_samples(self, observable): """Computes the real expectation value of a diagonal observable from frequencies.