Skip to content

Add probability normalization to DynamicsBackend sampling routine #239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion qiskit_dynamics/backend/backend_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,31 @@ 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.

Args:
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:
List: of entries of probability_dict, sampled according to the probabilities.
"""
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)


Expand Down
11 changes: 7 additions & 4 deletions qiskit_dynamics/backend/dynamics_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"``
Expand Down Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
@@ -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.