diff --git a/qiskit_dynamics/backend/backend_utils.py b/qiskit_dynamics/backend/backend_utils.py index 1c6f1a39b..95ccbab16 100644 --- a/qiskit_dynamics/backend/backend_utils.py +++ b/qiskit_dynamics/backend/backend_utils.py @@ -146,7 +146,10 @@ def _get_memory_slot_probabilities( def _sample_probability_dict( - probability_dict: Dict, shots: int, seed: Optional[int] = None + probability_dict: Dict, + shots: int, + normalize_probabilities: bool = True, + seed: Optional[int] = None, ) -> List[str]: """Sample outcomes based on probability dictionary. @@ -154,6 +157,8 @@ def _sample_probability_dict( probability_dict: Dictionary representing probability distribution, with keys being outcomes, values being probabilities. shots: Number of shots. + normalize_probabilities: Whether or not to normalize the probabilities to sum to 1 before + sampling. seed: Seed to use in rng construction. Return: @@ -161,6 +166,11 @@ def _sample_probability_dict( """ rng = np.random.default_rng(seed=seed) alphabet, probs = zip(*probability_dict.items()) + + if normalize_probabilities: + probs = np.array(probs) + probs = probs / probs.sum() + return rng.choice(alphabet, size=shots, replace=True, p=probs) diff --git a/qiskit_dynamics/backend/dynamics_backend.py b/qiskit_dynamics/backend/dynamics_backend.py index 02e4d1603..7fea3611c 100644 --- a/qiskit_dynamics/backend/dynamics_backend.py +++ b/qiskit_dynamics/backend/dynamics_backend.py @@ -118,9 +118,9 @@ class DynamicsBackend(BackendV2): indicating that the ground state for the system Hamiltonian should be used, or an arbitrary ``Statevector`` or ``DensityMatrix``. Defaults to ``"ground_state"``. * ``normalize_states``: Boolean indicating whether to normalize states before computing outcome - probabilities. Defaults to ``True``. Setting to ``False`` can result in errors if the solution - tolerance results in probabilities with significant numerical deviation from a proper - probability distribution. + probabilities, and normalize probablities before sampling. Defaults to ``True``. Setting to + ``False`` can result in errors if the solution tolerance results in probabilities with + significant numerical deviation from a proper probability distribution. * ``meas_level``: Form of measurement output. Supported values are ``1`` and ``2``. ``1`` returns IQ points and ``2`` returns counts. Defaults to ``meas_level == 2``. * ``meas_return``: Level of measurement data to return. For ``meas_level = 1`` ``"single"`` @@ -819,7 +819,10 @@ def default_experiment_result_function( # sample memory_samples = _sample_probability_dict( - memory_slot_probabilities, shots=backend.options.shots, seed=seed + memory_slot_probabilities, + shots=backend.options.shots, + normalize_probabilities=backend.options.normalize_states, + seed=seed, ) counts = _get_counts_from_samples(memory_samples) diff --git a/releasenotes/notes/normalize-probabilities-d729245bb3fe5f10.yaml b/releasenotes/notes/normalize-probabilities-d729245bb3fe5f10.yaml new file mode 100644 index 000000000..568d77eaf --- /dev/null +++ b/releasenotes/notes/normalize-probabilities-d729245bb3fe5f10.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + ``DynamicsBackend.options.normalize_states`` now also controls whether or not the probability + distribution over outcomes is normalized before sampling outcomes.