def test_bin_no_prefix_quasi_bin_out(self): """Test binary input without a 0b prefix and binary output.""" qprobs = { "000": 3 / 5, "001": 1 / 2, "010": 7 / 20, "011": 1 / 10, "100": -11 / 20 } quasi = QuasiDistribution(qprobs) self.assertEqual(qprobs, quasi.binary_probabilities())
def test_known_quasi_conversion(self): """Reproduce conversion from Smolin PRL""" qprobs = {0: 3 / 5, 1: 1 / 2, 2: 7 / 20, 3: 1 / 10, 4: -11 / 20} closest, dist = QuasiDistribution( qprobs).nearest_probability_distribution(return_distance=True) ans = {0: 9 / 20, 1: 7 / 20, 2: 1 / 5} # Check probs are correct for key, val in closest.items(): assert abs(ans[key] - val) < 1e-14 # Check if distance calculation is correct assert abs(dist - sqrt(0.38)) < 1e-14
def test_hex_quasi_hex_out(self): """Test hexadecimal input and hexadecimal output.""" qprobs = { "0x0": 3 / 5, "0x1": 1 / 2, "0x2": 7 / 20, "0x3": 1 / 10, "0x4": -11 / 20 } quasi = QuasiDistribution(qprobs) self.assertEqual(qprobs, quasi.hex_probabilities())
def test_known_quasi_conversion(self): """Reproduce conversion from Smolin PRL""" qprobs = { "0": 3 / 5, "1": 1 / 2, "2": 7 / 20, "3": 1 / 10, "4": -11 / 20 } closest, dist = QuasiDistribution( qprobs).nearest_probability_distribution(return_distance=True) ans = {"0": 9 / 20, "1": 7 / 20, "2": 1 / 5} # Check probs are correct for key, val in closest.items(): self.assertLess(abs(ans[key] - val), 1e-14) # Check if distance calculation is correct self.assertLess(abs(dist - sqrt(0.38)), 1e-14)
def test_hex_quasi_bin_out_padded(self): """Test hexadecimal input and binary output, padded with zeros.""" qprobs = { "0x0": 3 / 5, "0x1": 1 / 2, "0x2": 7 / 20, "0x3": 1 / 10, "0x4": -11 / 20 } quasi = QuasiDistribution(qprobs) expected = { "0000": 3 / 5, "0001": 1 / 2, "0010": 7 / 20, "0011": 1 / 10, "0100": -11 / 20 } self.assertEqual(expected, quasi.binary_probabilities(num_bits=4))
def test_bin_quasi_bin_out(self): """Test binary input and binary output.""" qprobs = { "0b0": 3 / 5, "0b1": 1 / 2, "0b10": 7 / 20, "0b11": 1 / 10, "0b100": -11 / 20 } quasi = QuasiDistribution(qprobs) expected = { "000": 3 / 5, "001": 1 / 2, "010": 7 / 20, "011": 1 / 10, "100": -11 / 20 } self.assertEqual(expected, quasi.binary_probabilities())
def test_bin_no_prefix_quasi_hex_out(self): """Test binary input without a 0b prefix and hexadecimal output.""" qprobs = { "0": 3 / 5, "1": 1 / 2, "10": 7 / 20, "11": 1 / 10, "100": -11 / 20 } quasi = QuasiDistribution(qprobs) expected = { "0x0": 3 / 5, "0x1": 1 / 2, "0x2": 7 / 20, "0x3": 1 / 10, "0x4": -11 / 20 } self.assertEqual(expected, quasi.hex_probabilities())
def test_hex_quasi_bin_out(self): """Test hexadecimal input and binary output.""" qprobs = { "0x0": 3 / 5, "0x1": 1 / 2, "0x2": 7 / 20, "0x3": 1 / 10, "0x4": -11 / 20 } quasi = QuasiDistribution(qprobs) expected = { "0": 3 / 5, "1": 1 / 2, "10": 7 / 20, "11": 1 / 10, "100": -11 / 20 } self.assertEqual(expected, quasi.binary_probabilities())
def get_quasiprobabilities( self, experiment: Union[int, List] = None ) -> Union[QuasiDistribution, List[QuasiDistribution]]: """Get quasiprobabilites associated with one or more experiments. Parameters: experiment: Indices of experiments to grab quasiprobabilities from. Returns: A single distribution or a list of distributions. Raises: QiskitError: If experiment result doesn't contain quasiprobabilities. """ if experiment is None: exp_keys = range(len(self.results)) else: exp_keys = [experiment] # type: ignore[assignment] dict_list = [] for key in exp_keys: if 'quasiprobabilities' in self.data(key).keys(): shots = self.results[key].shots hex_quasi = self.results[key].data.quasiprobabilities bit_lenth = len( self.results[key].header.final_measurement_mapping) quasi = {} for hkey, val in hex_quasi.items(): quasi[_hex_to_bin(hkey).zfill(bit_lenth)] = val out = QuasiDistribution(quasi, shots) out.shots = shots dict_list.append(out) else: raise QiskitError( 'No quasiprobabilities for experiment "{}"'.format( repr(key))) # Return first item of dict_list if size is 1 if len(dict_list) == 1: return dict_list[0] else: return dict_list
def _call( self, circuits: Sequence[int], parameter_values: Sequence[Sequence[float]], **run_options, ) -> SamplerResult: if self._is_closed: raise QiskitError("The primitive has been closed.") shots = run_options.pop("shots", None) seed = run_options.pop("seed", None) if seed is None: rng = np.random.default_rng() elif isinstance(seed, np.random.Generator): rng = seed else: rng = np.random.default_rng(seed) # Initialize metadata metadata: list[dict[str, Any]] = [{}] * len(circuits) bound_circuits = [] qargs_list = [] for i, value in zip(circuits, parameter_values): if len(value) != len(self._parameters[i]): raise QiskitError( f"The number of values ({len(value)}) does not match " f"the number of parameters ({len(self._parameters[i])}).") bound_circuit = (self._circuits[i] if len(value) == 0 else self._circuits[i].bind_parameters( dict(zip(self._parameters[i], value)))) bound_circuits.append(bound_circuit) qargs_list.append(self._qargs_list[i]) probabilities = [ Statevector(circ).probabilities(qargs=qargs) for circ, qargs in zip(bound_circuits, qargs_list) ] if shots is not None: probabilities = [ rng.multinomial(shots, probability) / shots for probability in probabilities ] for metadatum in metadata: metadatum["shots"] = shots quasis = [QuasiDistribution(dict(enumerate(p))) for p in probabilities] return SamplerResult(quasis, metadata)
def test_bin_no_prefix_quasi(self): """Test binary input without 0b prefix.""" qprobs = { "0": 3 / 5, "1": 1 / 2, "10": 7 / 20, "11": 1 / 10, "100": -11 / 20 } quasi = QuasiDistribution(qprobs) self.assertEqual( { 0: 3 / 5, 1: 1 / 2, 2: 7 / 20, 3: 1 / 10, 4: -11 / 20 }, quasi)
def test_bin_quasi_no_0b(self): """Test binary input without 0b in front.""" qprobs = { "000": 3 / 5, "001": 1 / 2, "010": 7 / 20, "011": 1 / 10, "100": -11 / 20 } quasi = QuasiDistribution(qprobs) self.assertEqual( { 0: 3 / 5, 1: 1 / 2, 2: 7 / 20, 3: 1 / 10, 4: -11 / 20 }, quasi)
def test_bin_quasi(self): """Test binary input.""" qprobs = { "0b0": 3 / 5, "0b1": 1 / 2, "0b10": 7 / 20, "0b11": 1 / 10, "0b100": -11 / 20 } quasi = QuasiDistribution(qprobs) self.assertEqual( { 0: 3 / 5, 1: 1 / 2, 2: 7 / 20, 3: 1 / 10, 4: -11 / 20 }, quasi)
def test_hex_quasi(self): """Test hexadecimal input.""" qprobs = { "0x0": 3 / 5, "0x1": 1 / 2, "0x2": 7 / 20, "0x3": 1 / 10, "0x4": -11 / 20 } quasi = QuasiDistribution(qprobs) self.assertEqual( { 0: 3 / 5, 1: 1 / 2, 2: 7 / 20, 3: 1 / 10, 4: -11 / 20 }, quasi)
def __call__( self, circuit_indices: Sequence[int] | None = None, parameter_values: Sequence[Sequence[float]] | Sequence[float] | None = None, **run_options, ) -> SamplerResult: if self._is_closed: raise QiskitError("The primitive has been closed.") if isinstance(parameter_values, np.ndarray): parameter_values = parameter_values.tolist() if parameter_values and not isinstance(parameter_values[0], (np.ndarray, Sequence)): parameter_values = cast("Sequence[float]", parameter_values) parameter_values = [parameter_values] if circuit_indices is None: circuit_indices = list(range(len(self._circuits))) if parameter_values is None: parameter_values = [[]] * len(circuit_indices) if len(circuit_indices) != len(parameter_values): raise QiskitError( f"The number of circuit indices ({len(circuit_indices)}) does not match " f"the number of parameter value sets ({len(parameter_values)})." ) bound_circuits_qargs = [] for i, value in zip(circuit_indices, parameter_values): if len(value) != len(self._parameters[i]): raise QiskitError( f"The number of values ({len(value)}) does not match " f"the number of parameters ({len(self._parameters[i])}).") bound_circuits_qargs.append(( self._circuits[i].bind_parameters( dict(zip(self._parameters[i], value))), self._qargs_list[i], )) probabilities = [ Statevector(circ).probabilities(qargs=qargs) for circ, qargs in bound_circuits_qargs ] quasis = [QuasiDistribution(dict(enumerate(p))) for p in probabilities] return SamplerResult(quasis, [{}] * len(circuit_indices))
def test_empty(self): """Test empty input.""" quasi = QuasiDistribution({}) self.assertEqual(quasi, {})
def test_invalid_key_string(self): """Test invalid key string format raises.""" with self.assertRaises(ValueError): QuasiDistribution({"1a2b": 3 / 5})
def test_invalid_keys(self): """Test invalid key type raises.""" with self.assertRaises(TypeError): QuasiDistribution({1 + 2j: 3 / 5})
def test_empty_bin_out(self): """Test empty input with binary output.""" quasi = QuasiDistribution({}) self.assertEqual(quasi.binary_probabilities(), {})
def test_empty_hex_out(self): """Test empty input with hexadecimal output.""" quasi = QuasiDistribution({}) self.assertEqual(quasi.hex_probabilities(), {})