Skip to content
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

Add new method for single bitstring target when measuring stabilizerstate probabilities_dict #12147

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
82716cd
added new method, deterministic helper unction
DerekMiner Feb 23, 2024
560a640
Adding test timing, fixed algorithm for determining if should get pro…
DerekMiner Feb 23, 2024
0407cf9
Adding more tests, fixing deterministic issues with bad target
DerekMiner Feb 23, 2024
d68f819
Prob of targets with 0.0 probability
DerekMiner Feb 26, 2024
4f2e508
target calc changes
DerekMiner Feb 26, 2024
81a8b88
Simpler way to get all targets
DerekMiner Feb 26, 2024
2bcdff0
Need to improve performance with multiple targets
DerekMiner Feb 26, 2024
24ae34b
Simplified the probabilities_dict_from_bitstrings method
DerekMiner Feb 27, 2024
57cd066
Adding tests for targets
DerekMiner Feb 27, 2024
6811775
Added tests to test_probablities_dict_qubits
DerekMiner Feb 27, 2024
09835fb
Add performance boost check when using targets for test_probablities_…
DerekMiner Feb 27, 2024
d4817f0
Added Caching to prevent duplicate branch calculations
DerekMiner Feb 27, 2024
6ba22ef
improve performance by performing expensive operations only when needed
DerekMiner Feb 27, 2024
7781b67
Optimization for caching, deterministic calcs for branches, enabling/…
DerekMiner Mar 1, 2024
4d0a2b5
improved tests, checking of caching vs not caching
DerekMiner Mar 1, 2024
6cee48e
added more tests and variations for stabilizerstate
DerekMiner Mar 1, 2024
37316cf
Corrected deterministic probability calculations
DerekMiner Mar 1, 2024
8734b60
Fixed bug with cache in wrong place for some calculations
DerekMiner Mar 1, 2024
baf39ff
added more test cases
DerekMiner Mar 1, 2024
3b5c068
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 1, 2024
5589458
Probabilities update for moved method call
DerekMiner Mar 1, 2024
213391a
Added test for random test_probs_random_subsystem
DerekMiner Mar 1, 2024
c429bcc
fixed single probabilities tests lost in previous merge
DerekMiner Mar 1, 2024
7970128
Removed caching of deterministic values
DerekMiner Mar 1, 2024
edfd7f0
Fixed failing test with test_probs_random_subsystem
DerekMiner Mar 4, 2024
79a4731
Adding tests back that were not test_probs_random_subsystem, removed …
DerekMiner Mar 4, 2024
acc9569
Created ProbabilityCache object for dealing with caching
DerekMiner Mar 4, 2024
e738982
Finished adding ProbabilityCache object and commenting
DerekMiner Mar 4, 2024
b40142b
Added more documentation for stabilizer state
DerekMiner Mar 4, 2024
a28f332
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 4, 2024
214244c
Fixing style with tox -eblack
DerekMiner Mar 4, 2024
278ee6b
commenting fixes in stabilizerstate
DerekMiner Mar 4, 2024
a0ede2d
Added release note
DerekMiner Mar 4, 2024
76918db
Updated release notes
DerekMiner Mar 4, 2024
219cb24
added __future__ to probabilitiescache, removed unused import stabili…
DerekMiner Mar 4, 2024
e90fd91
run tox -eblack to correct probabilitiescache
DerekMiner Mar 4, 2024
b093966
Corrected lint issues in multiple classes
DerekMiner Mar 5, 2024
463c011
fixed more pylint lint issues
DerekMiner Mar 5, 2024
56203aa
fixed more lint issues
DerekMiner Mar 5, 2024
4f2e321
added a bit more variance allowance for performance tests
DerekMiner Mar 5, 2024
92c9d44
Corrected Lint issues, added test for probabilitycache
DerekMiner Mar 5, 2024
010342a
Fixed remaining import ordering issue
DerekMiner Mar 5, 2024
91f04f0
readded ddt decorator for test_probabilitycache
DerekMiner Mar 5, 2024
ab477a6
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 6, 2024
4b08290
Changed to using process_time_ns from monotonic for performance measu…
DerekMiner Mar 6, 2024
5b8c4b3
Merge branch 'add_target_stablizerstate_probabilities_simple' of http…
DerekMiner Mar 6, 2024
5813c06
Added output when performance times fail to aid in debugging in test_…
DerekMiner Mar 6, 2024
f0edd20
moved performance end time out of same method to calculate times
DerekMiner Mar 6, 2024
0c7b146
changed method name in test_stabilizerstate
DerekMiner Mar 6, 2024
2b16125
Added GC disabling between timed tests
DerekMiner Mar 6, 2024
0e2fba5
Attempting using perf_counter_ns instead of process_time_ns
DerekMiner Mar 6, 2024
82589d2
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 6, 2024
ad51cec
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 7, 2024
49adeee
Updated commenting, moved 'X' outcome check
DerekMiner Mar 7, 2024
c3e37d3
more comment updating
DerekMiner Mar 7, 2024
dd8ebb8
Merge branch 'add_target_stablizerstate_probabilities_simple' of http…
DerekMiner Mar 7, 2024
5a6b38c
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 7, 2024
a40ef26
Changed performance timer based on OS type
DerekMiner Mar 7, 2024
f3c5c17
Changing to time.thread_time_ns(), and raising performance varabiliti…
DerekMiner Mar 7, 2024
b7dd15c
changing time.thread_time() vs time.thread_time_ns() to see if compat…
DerekMiner Mar 7, 2024
012c086
Changing performance timer based on OS for test_stablizerstate
DerekMiner Mar 7, 2024
31b67b1
fixed small issue in probabilitycache, improved probabilitycache test
DerekMiner Mar 8, 2024
34ac6bf
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 11, 2024
ea63fe2
Added correct type hinting to probabilitycache
DerekMiner Mar 11, 2024
ad553eb
Merge branch 'add_target_stablizerstate_probabilities_simple' of http…
DerekMiner Mar 11, 2024
79e5fbc
removed typing hint module
DerekMiner Mar 11, 2024
5642431
Fix test pylint failure of Value 'list' is unsubscriptable (unsubscri…
DerekMiner Mar 11, 2024
634c71f
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 13, 2024
68a8e1a
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 14, 2024
f8b84be
Fix small comment error in test, Added use_caching to tests, simplifi…
DerekMiner Mar 14, 2024
8993a19
Merge branch 'add_target_stablizerstate_probabilities_simple' of http…
DerekMiner Mar 14, 2024
8e0b31f
Merge branch 'main' into add_target_stablizerstate_probabilities_simple
DerekMiner Mar 15, 2024
6250c70
Significant code refactoring in StabiizerState
DerekMiner Mar 15, 2024
5277437
Fixed stabilizerstate cache key outcome not found
DerekMiner Mar 15, 2024
e304359
Moved all caching retrieval outside of _get_probabilities for perform…
DerekMiner Mar 15, 2024
52dba85
Simplified Bitstring method for probability cache, removed unnecessar…
DerekMiner Apr 5, 2024
6e30cc4
Commenting update for _probabilities_bitstring_verify
DerekMiner Apr 5, 2024
55285f5
black lint formatter ran
DerekMiner Apr 5, 2024
4c92f3e
Uncomment out line causing circular import
DerekMiner Apr 5, 2024
875109f
Remove type hints from test_stabilizerstate
DerekMiner Apr 5, 2024
4e7a7b5
Updated test_stabilizerstate, removed helper test method, new release…
DerekMiner Apr 9, 2024
a7b79ba
Added large qubit test with h gates, reorder imports for test_stabili…
DerekMiner Apr 9, 2024
448fb8e
moved methods out of loop that are unnecessary in test_stabilizerstate
DerekMiner Apr 9, 2024
c89eb35
Merge branch 'main' into add_target_stabilizerstate_probabilities_sin…
DerekMiner Apr 9, 2024
0f9ff56
broke out medium hgate test to own test method, issue with assertTrue…
DerekMiner Apr 9, 2024
34d799e
Merge branch 'add_target_stabilizerstate_probabilities_single_bitstri…
DerekMiner Apr 9, 2024
eb42523
fixed commenting in stabilizerstate, removed unnecessary outcome_bits…
DerekMiner Apr 9, 2024
85c1dbf
Condensed tests in test_stabilizerstate, added helper test class, mor…
DerekMiner Apr 10, 2024
3361ae4
Merge branch 'main' into add_target_stabilizerstate_probabilities_sin…
DerekMiner Apr 10, 2024
4361148
Merge branch 'add_target_stabilizerstate_probabilities_single_bitstri…
DerekMiner Apr 10, 2024
47e0a05
Merge branch 'main' into add_target_stabilizerstate_probabilities_sin…
DerekMiner Apr 12, 2024
d60e0f0
Merge branch 'main' into add_target_stabilizerstate_probabilities_sin…
ShellyGarion Apr 25, 2024
2dcc0c2
Fixed isues in release notes
DerekMiner Apr 25, 2024
803f203
Merge branch 'add_target_stabilizerstate_probabilities_single_bitstri…
DerekMiner Apr 25, 2024
c7814a5
Corrected Targetted to targeted in stablizerstate
DerekMiner Apr 25, 2024
1d2864f
Updated commenting about target
DerekMiner Apr 25, 2024
bc60cf8
Moved helper function _get_probabilities_dict
DerekMiner Apr 25, 2024
6c67aa6
differentiated description for probabilities
DerekMiner Apr 25, 2024
9102795
Added test to test_stabilizerstate
DerekMiner Apr 25, 2024
52ee0cc
combined 2 test methods
DerekMiner Apr 25, 2024
ae9ca34
removed unnecessary test
DerekMiner Apr 25, 2024
a901982
fixed lint issues, renamed test method
DerekMiner Apr 26, 2024
56fe514
Merge branch 'main' into add_target_stabilizerstate_probabilities_sin…
DerekMiner Apr 26, 2024
636b53c
fixed type for targetting in stabilizerstate
DerekMiner May 8, 2024
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
161 changes: 126 additions & 35 deletions qiskit/quantum_info/states/stabilizerstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,8 +386,17 @@ def probabilities(self, qargs: None | list = None, decimals: None | int = None)

return probs

def probabilities_dict(self, qargs: None | list = None, decimals: None | int = None) -> dict:
"""Return the subsystem measurement probability dictionary.
def probabilities_dict_from_bitstring(
self,
outcome_bitstring: str,
qargs: None | list = None,
decimals: None | int = None,
) -> dict[str, float]:
"""Return the subsystem measurement probability dictionary utilizing
a targeted outcome_bitstring to perform the measurement for. This
will calculate a probability for only a single targeted
outcome_bitstring value, giving a performance boost over calculating
all possible outcomes.

Measurement probabilities are with respect to measurement in the
DerekMiner marked this conversation as resolved.
Show resolved Hide resolved
computation (diagonal) basis.
Expand All @@ -398,30 +407,44 @@ def probabilities_dict(self, qargs: None | list = None, decimals: None | int = N
inserted between integers so that subsystems can be distinguished.

Args:
outcome_bitstring (None or str): targeted outcome bitstring
to perform a measurement calculation for, this will significantly
reduce the number of calculation performed (Default: None)
qargs (None or list): subsystems to return probabilities for,
if None return for all subsystems (Default: None).
if None return for all subsystems (Default: None).
decimals (None or int): the number of decimal places to round
values. If None no rounding is done (Default: None).
values. If None no rounding is done (Default: None)

Returns:
dict: The measurement probabilities in dict (ket) form.
dict[str, float]: The measurement probabilities in dict (ket) form.
"""
if qargs is None:
qubits = range(self.clifford.num_qubits)
else:
qubits = qargs
return self._get_probabilities_dict(
outcome_bitstring=outcome_bitstring, qargs=qargs, decimals=decimals
)

outcome = ["X"] * len(qubits)
outcome_prob = 1.0
probs = {} # probabilities dictionary
def probabilities_dict(
self, qargs: None | list = None, decimals: None | int = None
) -> dict[str, float]:
"""Return the subsystem measurement probability dictionary.

self._get_probabilities(qubits, outcome, outcome_prob, probs)
Measurement probabilities are with respect to measurement in the
computation (diagonal) basis.

if decimals is not None:
for key, value in probs.items():
probs[key] = round(value, decimals)
This dictionary representation uses a Ket-like notation where the
dictionary keys are qudit strings for the subsystem basis vectors.
If any subsystem has a dimension greater than 10 comma delimiters are
inserted between integers so that subsystems can be distinguished.

return probs
Args:
qargs (None or list): subsystems to return probabilities for,
if None return for all subsystems (Default: None).
decimals (None or int): the number of decimal places to round
values. If None no rounding is done (Default: None).

Returns:
dict: The measurement probabilities in dict (key) form.
"""
return self._get_probabilities_dict(outcome_bitstring=None, qargs=qargs, decimals=decimals)

def reset(self, qargs: list | None = None) -> StabilizerState:
"""Reset state or subsystems to the 0-state.
Expand Down Expand Up @@ -644,22 +667,48 @@ def _rowsum_deterministic(clifford, aux_pauli, row):
# -----------------------------------------------------------------------
# Helper functions for calculating the probabilities
# -----------------------------------------------------------------------
def _get_probabilities(self, qubits, outcome, outcome_prob, probs):
"""Recursive helper function for calculating the probabilities"""
def _get_probabilities(
self,
qubits: range,
outcome: list[str],
outcome_prob: float,
probs: dict[str, float],
outcome_bitstring: str = None,
):
"""Recursive helper function for calculating the probabilities

qubit_for_branching = -1
ret = self.copy()
Args:
qubits (range): range of qubits
outcome (list[str]): outcome being built
outcome_prob (float): probabilitiy of the outcome
probs (dict[str, float]): holds the outcomes and probabilitiy results
outcome_bitstring (str): target outcome to measure which reduces measurements, None
if not targeting a specific target
"""
qubit_for_branching: int = -1

ret: StabilizerState = self.copy()

# Find outcomes for each qubit
for i in range(len(qubits)):
qubit = qubits[len(qubits) - i - 1]
if outcome[i] == "X":
is_deterministic = not any(ret.clifford.stab_x[:, qubit])
if is_deterministic:
single_qubit_outcome = ret._measure_and_update(qubit, 0)
if single_qubit_outcome:
outcome[i] = "1"
# Retrieve the qubit for the current measurement
qubit = qubits[(len(qubits) - i - 1)]
# Determine if the probabilitiy is deterministic
if not any(ret.clifford.stab_x[:, qubit]):
single_qubit_outcome: np.int64 = ret._measure_and_update(qubit, 0)
if outcome_bitstring is None or (
int(outcome_bitstring[i]) == single_qubit_outcome
):
# No outcome_bitstring target, or using outcome_bitstring target and
# the single_qubit_outcome equals the desired outcome_bitstring target value,
# then use current outcome_prob value
outcome[i] = str(single_qubit_outcome)
else:
outcome[i] = "0"
# If the single_qubit_outcome does not equal the outcome_bitsring target
# then we know that the probability will be 0
outcome[i] = str(outcome_bitstring[i])
outcome_prob = 0
else:
qubit_for_branching = i

Expand All @@ -668,15 +717,57 @@ def _get_probabilities(self, qubits, outcome, outcome_prob, probs):
probs[str_outcome] = outcome_prob
return

for single_qubit_outcome in range(0, 2):
for single_qubit_outcome in (
range(0, 2)
if (outcome_bitstring is None)
else [int(outcome_bitstring[qubit_for_branching])]
):
new_outcome = outcome.copy()
if single_qubit_outcome:
new_outcome[qubit_for_branching] = "1"
else:
new_outcome[qubit_for_branching] = "0"
new_outcome[qubit_for_branching] = str(single_qubit_outcome)

stab_cpy = ret.copy()
stab_cpy._measure_and_update(
qubits[len(qubits) - qubit_for_branching - 1], single_qubit_outcome
qubits[(len(qubits) - qubit_for_branching - 1)], single_qubit_outcome
)
stab_cpy._get_probabilities(
qubits, new_outcome, (0.5 * outcome_prob), probs, outcome_bitstring
)
stab_cpy._get_probabilities(qubits, new_outcome, 0.5 * outcome_prob, probs)

def _get_probabilities_dict(
self,
outcome_bitstring: None | str = None,
qargs: None | list = None,
decimals: None | int = None,
) -> dict[str, float]:
"""Helper Function for calculating the subsystem measurement probability dictionary.
When the targeted outcome_bitstring value is set, then only the single outcome_bitstring
probability will be calculated.

Args:
outcome_bitstring (None or str): targeted outcome bitstring
to perform a measurement calculation for, this will significantly
reduce the number of calculation performed (Default: None)
qargs (None or list): subsystems to return probabilities for,
if None return for all subsystems (Default: None).
decimals (None or int): the number of decimal places to round
values. If None no rounding is done (Default: None).

Returns:
dict: The measurement probabilities in dict (key) form.
"""
if qargs is None:
qubits = range(self.clifford.num_qubits)
else:
qubits = qargs

outcome = ["X"] * len(qubits)
outcome_prob = 1.0
probs: dict[str, float] = {} # Probabilities dict to return with the measured values

self._get_probabilities(qubits, outcome, outcome_prob, probs, outcome_bitstring)

if decimals is not None:
for key, value in probs.items():
probs[key] = round(value, decimals)

return probs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
features:
- |
The :class:'.StabilizerState' class now has a new method
:meth:'~.StabilizerState.probabilities_dict_from_bitstring' allowing the
user to pass single bitstring to measure an outcome for. Previouslly the
:meth:'~.StabilizerState.probabilities_dict' would be utilized and would
at worst case calculate (2^n) number of probabilbity calculations (depending
on the state), even if a user wanted a single result. With this new method
the user can calculate just the single outcome bitstring value a user passes
to measure the probability for. As the number of qubits increases, the more
prevelant the performance enhancement may be (depending on the state) as only
1 bitstring result is measured.
Loading
Loading