Skip to content

Commit

Permalink
unleash confusion map (#5717)
Browse files Browse the repository at this point in the history
Revert "Guard confusion_map usage (#5534)"

Assume measure() methods of SimulationState subclasses accept the
`confusion_map` argument.  Remove temporary workaround for methods
not taking `confusion_map`.

Also disable pylint check on missing argument which is required
in the base class but unknown to subclasses actually called.

This reverts commit 25388af.
  • Loading branch information
pavoljuhas committed Jul 11, 2022
1 parent f0bd1d5 commit fef9487
Show file tree
Hide file tree
Showing 3 changed files with 10 additions and 73 deletions.
14 changes: 1 addition & 13 deletions cirq-core/cirq/ops/measurement_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,19 +306,7 @@ def _act_on_(self, sim_state: 'cirq.SimulationStateBase', qubits: Sequence['cirq

if not isinstance(sim_state, SimulationState):
return NotImplemented
try:
sim_state.measure(
qubits, self.key, self.full_invert_mask(), confusion_map=self.confusion_map
)
except TypeError as e:
# Ensure that the error was due to confusion_map.
if not any("unexpected keyword argument 'confusion_map'" in arg for arg in e.args):
raise
_compat._warn_or_error(
"Starting in v0.16, SimulationState subclasses will be required to accept "
"a 'confusion_map' argument. See SimulationState.measure for details."
)
sim_state.measure(qubits, self.key, self.full_invert_mask())
sim_state.measure(qubits, self.key, self.full_invert_mask(), self.confusion_map)
return True


Expand Down
57 changes: 1 addition & 56 deletions cirq-core/cirq/ops/measurement_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Any, Dict, Optional, Sequence, Tuple, Union, cast
from typing import cast
import numpy as np
import pytest

import cirq
from cirq.type_workarounds import NotImplementedType


@pytest.mark.parametrize(
Expand Down Expand Up @@ -504,57 +503,3 @@ def test_act_on_qutrit():
)
cirq.act_on(m, args)
assert args.log_of_measurement_results == {'out': [0, 0]}


def test_act_on_no_confusion_map_deprecated():
class OldSimState(cirq.StateVectorSimulationState):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.measured = False

def _act_on_fallback_(
self, action: Any, qubits: Sequence['cirq.Qid'], allow_decompose: bool = True
) -> Union[bool, NotImplementedType]:
return NotImplemented # coverage: ignore

def measure( # type: ignore
self, qubits: Sequence['cirq.Qid'], key: str, invert_mask: Sequence[bool]
):
self.measured = True

qubits = cirq.LineQubit.range(2)
old_state = OldSimState(qubits=qubits)
m = cirq.measure(*qubits, key='test')
with cirq.testing.assert_deprecated('confusion_map', deadline='v0.16'):
cirq.act_on(m, old_state)
assert old_state.measured


def test_act_on_no_confusion_map_scope_limited():
error_msg = "error from deeper in measure"

class ErrorProneSimState(cirq.StateVectorSimulationState):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.measured = False

def _act_on_fallback_(
self, action: Any, qubits: Sequence['cirq.Qid'], allow_decompose: bool = True
) -> Union[bool, NotImplementedType]:
return NotImplemented # coverage: ignore

def measure(
self,
qubits: Sequence['cirq.Qid'],
key: str,
invert_mask: Sequence[bool],
confusion_map: Optional[Dict[Tuple[int, ...], np.ndarray]] = None,
):
raise TypeError(error_msg)

# Verify that the check doesn't prevent other errors from being raised
qubits = cirq.LineQubit.range(2)
sv_state = ErrorProneSimState(qubits=qubits)
m = cirq.measure(*qubits, key='test')
with pytest.raises(TypeError, match=error_msg):
cirq.act_on(m, sv_state)
12 changes: 8 additions & 4 deletions cirq-core/cirq/sim/simulation_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def measure(
qubits: Sequence['cirq.Qid'],
key: str,
invert_mask: Sequence[bool],
confusion_map: Optional[Dict[Tuple[int, ...], np.ndarray]] = None,
confusion_map: Dict[Tuple[int, ...], np.ndarray],
):
"""Measures the qubits and records to `log_of_measurement_results`.
Expand All @@ -100,8 +100,7 @@ def measure(
ValueError: If a measurement key has already been logged to a key.
"""
bits = self._perform_measurement(qubits)
if confusion_map is not None:
confused = self._confuse_result(bits, qubits, confusion_map)
confused = self._confuse_result(bits, qubits, confusion_map)
corrected = [bit ^ (bit < 2 and mask) for bit, mask in zip(confused, invert_mask)]
self._classical_data.record_measurement(
value.MeasurementKey.parse_serialized(key), corrected, qubits
Expand Down Expand Up @@ -184,10 +183,15 @@ def with_qubits(self: TSelf, qubits) -> TSelf:
Args:
qubits: The qubits to be added to the state space.
Regurns:
Returns:
A new subclass object containing the extended state space.
"""
# TODO(#5721): Fix inconsistent usage of the `state` argument in the
# SimulationState base (required) and in its derived classes (unknown
# in StateVectorSimulationState), then remove the pylint filter below.
# pylint: disable=missing-kwoa
new_space = type(self)(qubits=qubits) # type: ignore
# pylint: enable=missing-kwoa
return self.kronecker_product(new_space)

def factor(
Expand Down

0 comments on commit fef9487

Please sign in to comment.