From c6ef69c59f08a45fc8267eabb26393f656b45558 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 13:40:59 -0700 Subject: [PATCH 01/12] add basic sim --- cirq-core/cirq/sim/simulator_base.py | 6 +- cirq-core/cirq/sim/simulator_base_test.py | 79 ++++++++++++++++++++++- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base.py b/cirq-core/cirq/sim/simulator_base.py index a8bae957bfd..d55ad4b34fa 100644 --- a/cirq-core/cirq/sim/simulator_base.py +++ b/cirq-core/cirq/sim/simulator_base.py @@ -397,9 +397,7 @@ def _create_simulation_state( ) -class StepResultBase( - Generic[TSimulationState], StepResult[SimulationStateBase[TSimulationState]], abc.ABC -): +class StepResultBase(Generic[TSimulationState], StepResult[SimulationStateBase[TSimulationState]]): """A base class for step results.""" def __init__(self, sim_state: SimulationStateBase[TSimulationState]): @@ -435,7 +433,7 @@ def sample( class SimulationTrialResultBase( - SimulationTrialResult[SimulationStateBase[TSimulationState]], Generic[TSimulationState], abc.ABC + SimulationTrialResult[SimulationStateBase[TSimulationState]], Generic[TSimulationState] ): """A base class for trial results.""" diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index a6eb70b46a0..24b3cc4e53b 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -11,14 +11,91 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import abc import math -from typing import Any, Dict, List, Sequence, Tuple +from typing import Any, Dict, Generic, List, Sequence, Tuple, TypeVar import numpy as np import pytest import sympy import cirq +from cirq.qis.clifford_tableau import TSelf + +TSimulationState = TypeVar('TSimulationState', bound=cirq.SimulationState) + + +class BasicSimulator( + cirq.SimulatorBase[ + cirq.StepResultBase[TSimulationState], + cirq.SimulationTrialResultBase[TSimulationState], + TSimulationState, + ], + Generic[TSimulationState], + abc.ABC, +): + def _create_simulator_trial_result( + self, + params: cirq.ParamResolver, + measurements: Dict[str, np.ndarray], + final_simulator_state: 'cirq.SimulationStateBase[TSimulationState]', + ) -> cirq.SimulationTrialResultBase[TSimulationState]: + return cirq.SimulationTrialResultBase( + params, measurements, final_simulator_state=final_simulator_state + ) + + def _create_step_result( + self, sim_state: cirq.SimulationStateBase[TSimulationState] + ) -> cirq.StepResultBase[TSimulationState]: + return cirq.StepResultBase(sim_state) + + +class BasisState(cirq.qis.QuantumStateRepresentation): + def __init__(self, initial_state): + self.state = initial_state + + def copy(self: TSelf, deep_copy_buffers: bool = True) -> TSelf: + return BasisState(self.state) + + def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): + return [self.state[i] for i in axes] + + +class BasisSimState(cirq.SimulationState[BasisState]): + def __init__(self, initial_state, qubits, classical_data): + initial_state = cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits)) + super().__init__( + state=BasisState(initial_state), qubits=qubits, classical_data=classical_data + ) + + def _act_on_fallback_( + self, action: Any, qubits: Sequence['cirq.Qid'], allow_decompose: bool = True + ) -> bool: + gate = action.gate if isinstance(action, cirq.Operation) else action + if isinstance(gate, cirq.XPowGate): + i = self.qubit_map[qubits[0]] + self._state.state[i] = 1 - self._state.state[i] + return True + return NotImplemented + + +class BasisSimulator(BasicSimulator[BasisSimState]): + def _create_partial_simulation_state( + self, + initial_state: Any, + qubits: Sequence['cirq.Qid'], + classical_data: cirq.ClassicalDataStore, + ) -> BasisSimState: + return BasisSimState(initial_state, qubits, classical_data) + + +def test_state(): + q0, q1 = cirq.LineQubit.range(2) + sim = BasisSimulator() + c = cirq.Circuit(cirq.X(q0), cirq.X(q1), cirq.measure(q0)) + r = sim.simulate(c) + print(r._final_simulator_state._state.state) + print(r.measurements) class CountingState(cirq.qis.QuantumStateRepresentation): From ccc0ce2a28bfcece8b5f94b10b1e8b230f84b92a Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 13:52:02 -0700 Subject: [PATCH 02/12] mypy --- cirq-core/cirq/sim/simulator_base_test.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index 24b3cc4e53b..a555fdd9235 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -13,19 +13,17 @@ # limitations under the License. import abc import math -from typing import Any, Dict, Generic, List, Sequence, Tuple, TypeVar +from typing import Any, Dict, Generic, List, Sequence, Tuple import numpy as np import pytest import sympy import cirq -from cirq.qis.clifford_tableau import TSelf +from cirq.sim.simulation_state import TSimulationState -TSimulationState = TypeVar('TSimulationState', bound=cirq.SimulationState) - -class BasicSimulator( +class ThirdPartySimulatorBase( cirq.SimulatorBase[ cirq.StepResultBase[TSimulationState], cirq.SimulationTrialResultBase[TSimulationState], @@ -51,13 +49,15 @@ def _create_step_result( class BasisState(cirq.qis.QuantumStateRepresentation): - def __init__(self, initial_state): + def __init__(self, initial_state: List[int]): self.state = initial_state - def copy(self: TSelf, deep_copy_buffers: bool = True) -> TSelf: + def copy(self, deep_copy_buffers: bool = True) -> 'BasisState': return BasisState(self.state) - def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): + def measure( + self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None + ) -> List[int]: return [self.state[i] for i in axes] @@ -79,7 +79,7 @@ def _act_on_fallback_( return NotImplemented -class BasisSimulator(BasicSimulator[BasisSimState]): +class BasisSimulator(ThirdPartySimulatorBase[BasisSimState]): def _create_partial_simulation_state( self, initial_state: Any, From c53e891947bd6d6d37c39a759c521f2716ec320b Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 13:58:58 -0700 Subject: [PATCH 03/12] move --- cirq-core/cirq/sim/simulator_base.py | 25 +++++++++++++++++++ cirq-core/cirq/sim/simulator_base_test.py | 30 ++--------------------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base.py b/cirq-core/cirq/sim/simulator_base.py index d55ad4b34fa..fb7d2446e9a 100644 --- a/cirq-core/cirq/sim/simulator_base.py +++ b/cirq-core/cirq/sim/simulator_base.py @@ -482,3 +482,28 @@ def _get_merged_sim_state(self) -> TSimulationState: if self._merged_sim_state_cache is None: self._merged_sim_state_cache = self._final_simulator_state.create_merged_state() return self._merged_sim_state_cache + + +class ThirdPartySimulatorBase( + SimulatorBase[ + StepResultBase[TSimulationState], + SimulationTrialResultBase[TSimulationState], + TSimulationState, + ], + Generic[TSimulationState], + abc.ABC, +): + def _create_simulator_trial_result( + self, + params: 'cirq.ParamResolver', + measurements: Dict[str, np.ndarray], + final_simulator_state: 'cirq.SimulationStateBase[TSimulationState]', + ) -> 'cirq.SimulationTrialResultBase[TSimulationState]': + return SimulationTrialResultBase( + params, measurements, final_simulator_state=final_simulator_state + ) + + def _create_step_result( + self, sim_state: 'cirq.SimulationStateBase[TSimulationState]' + ) -> 'cirq.StepResultBase[TSimulationState]': + return StepResultBase(sim_state) diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index a555fdd9235..fb4b5909245 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -11,41 +11,15 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import abc import math -from typing import Any, Dict, Generic, List, Sequence, Tuple +from typing import Any, Dict, List, Sequence, Tuple import numpy as np import pytest import sympy import cirq -from cirq.sim.simulation_state import TSimulationState - - -class ThirdPartySimulatorBase( - cirq.SimulatorBase[ - cirq.StepResultBase[TSimulationState], - cirq.SimulationTrialResultBase[TSimulationState], - TSimulationState, - ], - Generic[TSimulationState], - abc.ABC, -): - def _create_simulator_trial_result( - self, - params: cirq.ParamResolver, - measurements: Dict[str, np.ndarray], - final_simulator_state: 'cirq.SimulationStateBase[TSimulationState]', - ) -> cirq.SimulationTrialResultBase[TSimulationState]: - return cirq.SimulationTrialResultBase( - params, measurements, final_simulator_state=final_simulator_state - ) - - def _create_step_result( - self, sim_state: cirq.SimulationStateBase[TSimulationState] - ) -> cirq.StepResultBase[TSimulationState]: - return cirq.StepResultBase(sim_state) +from cirq.sim.simulator_base import ThirdPartySimulatorBase class BasisState(cirq.qis.QuantumStateRepresentation): From d67aa6d1ffab7e19e77e228ac94d45cd1ae478b2 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 17:49:29 -0700 Subject: [PATCH 04/12] move --- cirq-core/cirq/sim/simulator_base.py | 13 +++++++++- cirq-core/cirq/sim/simulator_base_test.py | 31 +++++------------------ 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base.py b/cirq-core/cirq/sim/simulator_base.py index fb7d2446e9a..037adb09de5 100644 --- a/cirq-core/cirq/sim/simulator_base.py +++ b/cirq-core/cirq/sim/simulator_base.py @@ -491,8 +491,11 @@ class ThirdPartySimulatorBase( TSimulationState, ], Generic[TSimulationState], - abc.ABC, ): + def __init__(self, state_type: Type[TSimulationState]): + super().__init__() + self.state_type = state_type + def _create_simulator_trial_result( self, params: 'cirq.ParamResolver', @@ -507,3 +510,11 @@ def _create_step_result( self, sim_state: 'cirq.SimulationStateBase[TSimulationState]' ) -> 'cirq.StepResultBase[TSimulationState]': return StepResultBase(sim_state) + + def _create_partial_simulation_state( + self, + initial_state: Any, + qubits: Sequence['cirq.Qid'], + classical_data: 'cirq.ClassicalDataStore', + ) -> TSimulationState: + return self.state_type(initial_state, qubits, classical_data) diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index fb4b5909245..0f0dfc5bf1d 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -29,43 +29,26 @@ def __init__(self, initial_state: List[int]): def copy(self, deep_copy_buffers: bool = True) -> 'BasisState': return BasisState(self.state) - def measure( - self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None - ) -> List[int]: + def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): return [self.state[i] for i in axes] class BasisSimState(cirq.SimulationState[BasisState]): def __init__(self, initial_state, qubits, classical_data): - initial_state = cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits)) - super().__init__( - state=BasisState(initial_state), qubits=qubits, classical_data=classical_data - ) + state = BasisState(cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits))) + super().__init__(state=state, qubits=qubits, classical_data=classical_data) - def _act_on_fallback_( - self, action: Any, qubits: Sequence['cirq.Qid'], allow_decompose: bool = True - ) -> bool: - gate = action.gate if isinstance(action, cirq.Operation) else action - if isinstance(gate, cirq.XPowGate): + def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: bool = True): + if isinstance(action.gate, cirq.XPowGate): i = self.qubit_map[qubits[0]] - self._state.state[i] = 1 - self._state.state[i] + self._state.state[i] = (1 + self._state.state[i]) % qubits[0].dimension return True return NotImplemented -class BasisSimulator(ThirdPartySimulatorBase[BasisSimState]): - def _create_partial_simulation_state( - self, - initial_state: Any, - qubits: Sequence['cirq.Qid'], - classical_data: cirq.ClassicalDataStore, - ) -> BasisSimState: - return BasisSimState(initial_state, qubits, classical_data) - - def test_state(): + sim = ThirdPartySimulatorBase(BasisSimState) q0, q1 = cirq.LineQubit.range(2) - sim = BasisSimulator() c = cirq.Circuit(cirq.X(q0), cirq.X(q1), cirq.measure(q0)) r = sim.simulate(c) print(r._final_simulator_state._state.state) From a5ffd00d8cc133971193176d415d1f545465de49 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 17:50:36 -0700 Subject: [PATCH 05/12] move --- cirq-core/cirq/sim/simulator_base.py | 2 +- cirq-core/cirq/sim/simulator_base_test.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base.py b/cirq-core/cirq/sim/simulator_base.py index 037adb09de5..9382cb9f6c5 100644 --- a/cirq-core/cirq/sim/simulator_base.py +++ b/cirq-core/cirq/sim/simulator_base.py @@ -484,7 +484,7 @@ def _get_merged_sim_state(self) -> TSimulationState: return self._merged_sim_state_cache -class ThirdPartySimulatorBase( +class SimpleSimulator( SimulatorBase[ StepResultBase[TSimulationState], SimulationTrialResultBase[TSimulationState], diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index 0f0dfc5bf1d..0adfde7c338 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -19,7 +19,7 @@ import sympy import cirq -from cirq.sim.simulator_base import ThirdPartySimulatorBase +from cirq.sim.simulator_base import SimpleSimulator class BasisState(cirq.qis.QuantumStateRepresentation): @@ -47,7 +47,7 @@ def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: def test_state(): - sim = ThirdPartySimulatorBase(BasisSimState) + sim = SimpleSimulator(BasisSimState) q0, q1 = cirq.LineQubit.range(2) c = cirq.Circuit(cirq.X(q0), cirq.X(q1), cirq.measure(q0)) r = sim.simulate(c) From 87ed7e93794984b6e851d78bcfc9043201c7578d Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 18:19:45 -0700 Subject: [PATCH 06/12] sv --- cirq-core/cirq/sim/simulator_base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cirq-core/cirq/sim/simulator_base.py b/cirq-core/cirq/sim/simulator_base.py index 9382cb9f6c5..71d90e1eadd 100644 --- a/cirq-core/cirq/sim/simulator_base.py +++ b/cirq-core/cirq/sim/simulator_base.py @@ -517,4 +517,6 @@ def _create_partial_simulation_state( qubits: Sequence['cirq.Qid'], classical_data: 'cirq.ClassicalDataStore', ) -> TSimulationState: - return self.state_type(initial_state, qubits, classical_data) + return self.state_type( + initial_state=initial_state, qubits=qubits, classical_data=classical_data + ) From 7f16305c760f097193243d723ae2ad7bd7f32064 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 19:11:25 -0700 Subject: [PATCH 07/12] sv --- cirq-core/cirq/sim/simulator_base_test.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index 0adfde7c338..5570668a9ee 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -39,20 +39,24 @@ def __init__(self, initial_state, qubits, classical_data): super().__init__(state=state, qubits=qubits, classical_data=classical_data) def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: bool = True): - if isinstance(action.gate, cirq.XPowGate): + gate = action.gate if isinstance(action, cirq.Operation) else action + if isinstance(gate, cirq.XPowGate): i = self.qubit_map[qubits[0]] - self._state.state[i] = (1 + self._state.state[i]) % qubits[0].dimension + self._state.state[i] = int(gate.exponent + self._state.state[i]) % qubits[0].dimension return True return NotImplemented def test_state(): sim = SimpleSimulator(BasisSimState) - q0, q1 = cirq.LineQubit.range(2) - c = cirq.Circuit(cirq.X(q0), cirq.X(q1), cirq.measure(q0)) + q0, q1 = cirq.LineQid.range(2, dimension=3) + x = cirq.XPowGate(dimension=3) + c = cirq.Circuit( + x(q0), x(q1), cirq.measure(q0, key='a'), x(q0).with_classical_controls('a'), cirq.reset(q1) + ) r = sim.simulate(c) - print(r._final_simulator_state._state.state) - print(r.measurements) + assert r._final_simulator_state._state.state == [2, 0] + assert r.measurements == {'a': np.array([1], dtype=np.uint8)} class CountingState(cirq.qis.QuantumStateRepresentation): From c96847bde9b1ff611696bf3c0e1b97776172e2a1 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 22:30:42 -0700 Subject: [PATCH 08/12] sv --- cirq-core/cirq/sim/simulator_base_test.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index 5570668a9ee..2e96505dbe6 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -47,16 +47,25 @@ def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: return NotImplemented -def test_state(): - sim = SimpleSimulator(BasisSimState) +def test_simple_simulator(): q0, q1 = cirq.LineQid.range(2, dimension=3) x = cirq.XPowGate(dimension=3) c = cirq.Circuit( x(q0), x(q1), cirq.measure(q0, key='a'), x(q0).with_classical_controls('a'), cirq.reset(q1) ) + + sim = SimpleSimulator(BasisSimState) r = sim.simulate(c) + assert r.measurements == {'a': np.array([1], dtype=np.uint8)} assert r._final_simulator_state._state.state == [2, 0] + + # works for the built-in states too, you just lose the custom step/trial results. + sim = SimpleSimulator(cirq.StateVectorSimulationState) + r = sim.simulate(c) assert r.measurements == {'a': np.array([1], dtype=np.uint8)} + assert np.allclose( + r._final_simulator_state._state._state_vector, [[0, 0, 0], [0, 0, 0], [1, 0, 0]] + ) class CountingState(cirq.qis.QuantumStateRepresentation): From ee6cad4d7d1284f9c1565adc01ba83a78ce5a164 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Thu, 26 May 2022 23:03:49 -0700 Subject: [PATCH 09/12] more --- cirq-core/cirq/sim/simulator_base_test.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index 2e96505dbe6..b0567c50c69 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -51,20 +51,27 @@ def test_simple_simulator(): q0, q1 = cirq.LineQid.range(2, dimension=3) x = cirq.XPowGate(dimension=3) c = cirq.Circuit( - x(q0), x(q1), cirq.measure(q0, key='a'), x(q0).with_classical_controls('a'), cirq.reset(q1) + x(q0), + cirq.measure(q0, key='a'), + x(q0).with_classical_controls('a'), + cirq.CircuitOperation( + cirq.FrozenCircuit(x(q1), cirq.measure(q1, key='b')), + repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol('b'), 2)), + use_repetition_ids=False, + ), ) sim = SimpleSimulator(BasisSimState) r = sim.simulate(c) - assert r.measurements == {'a': np.array([1], dtype=np.uint8)} - assert r._final_simulator_state._state.state == [2, 0] + assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} + assert r._final_simulator_state._state.state == [2, 2] # works for the built-in states too, you just lose the custom step/trial results. sim = SimpleSimulator(cirq.StateVectorSimulationState) r = sim.simulate(c) - assert r.measurements == {'a': np.array([1], dtype=np.uint8)} + assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} assert np.allclose( - r._final_simulator_state._state._state_vector, [[0, 0, 0], [0, 0, 0], [1, 0, 0]] + r._final_simulator_state._state._state_vector, [[0, 0, 0], [0, 0, 0], [0, 0, 1]] ) From 65477b1d61394ec59216a19b432d59807ce54c08 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Fri, 27 May 2022 22:51:25 -0700 Subject: [PATCH 10/12] noise --- cirq-core/cirq/sim/simulator_base.py | 12 ++++++-- cirq-core/cirq/sim/simulator_base_test.py | 34 +++++++++++++++++------ 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/cirq-core/cirq/sim/simulator_base.py b/cirq-core/cirq/sim/simulator_base.py index 71d90e1eadd..42d74a6beca 100644 --- a/cirq-core/cirq/sim/simulator_base.py +++ b/cirq-core/cirq/sim/simulator_base.py @@ -484,7 +484,7 @@ def _get_merged_sim_state(self) -> TSimulationState: return self._merged_sim_state_cache -class SimpleSimulator( +class ThirdPartySimulator( SimulatorBase[ StepResultBase[TSimulationState], SimulationTrialResultBase[TSimulationState], @@ -492,8 +492,14 @@ class SimpleSimulator( ], Generic[TSimulationState], ): - def __init__(self, state_type: Type[TSimulationState]): - super().__init__() + def __init__( + self, + state_type: Type[TSimulationState], + *, + noise: 'cirq.NOISE_MODEL_LIKE' = None, + split_untangled_states=False, + ): + super().__init__(noise=noise, split_untangled_states=split_untangled_states) self.state_type = state_type def _create_simulator_trial_result( diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index b0567c50c69..867727fc0f4 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -19,23 +19,25 @@ import sympy import cirq -from cirq.sim.simulator_base import SimpleSimulator +from cirq.sim.simulator_base import ThirdPartySimulator -class BasisState(cirq.qis.QuantumStateRepresentation): +class ComputationalBaisisState(cirq.qis.QuantumStateRepresentation): def __init__(self, initial_state: List[int]): self.state = initial_state - def copy(self, deep_copy_buffers: bool = True) -> 'BasisState': - return BasisState(self.state) + def copy(self, deep_copy_buffers: bool = True) -> 'ComputationalBaisisState': + return ComputationalBaisisState(self.state) def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): return [self.state[i] for i in axes] -class BasisSimState(cirq.SimulationState[BasisState]): +class ComputationalBaisisSimState(cirq.SimulationState[ComputationalBaisisState]): def __init__(self, initial_state, qubits, classical_data): - state = BasisState(cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits))) + state = ComputationalBaisisState( + cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits)) + ) super().__init__(state=state, qubits=qubits, classical_data=classical_data) def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: bool = True): @@ -61,19 +63,35 @@ def test_simple_simulator(): ), ) - sim = SimpleSimulator(BasisSimState) + sim = ThirdPartySimulator(ComputationalBaisisSimState) r = sim.simulate(c) assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} assert r._final_simulator_state._state.state == [2, 2] + # test noise + sim = ThirdPartySimulator(ComputationalBaisisSimState, noise=x**2) + r = sim.simulate(c) + assert r.measurements == {'a': np.array([2]), 'b': np.array([2])} + assert r._final_simulator_state._state.state == [1, 2] + # works for the built-in states too, you just lose the custom step/trial results. - sim = SimpleSimulator(cirq.StateVectorSimulationState) + sim = ThirdPartySimulator(cirq.StateVectorSimulationState) r = sim.simulate(c) assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} assert np.allclose( r._final_simulator_state._state._state_vector, [[0, 0, 0], [0, 0, 0], [0, 0, 1]] ) + # product state mode works. + sim = ThirdPartySimulator(cirq.StateVectorSimulationState, split_untangled_states=True) + r = sim.simulate(c) + assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} + assert len(r._final_simulator_state) == 3 + assert np.allclose( + r._final_simulator_state.create_merged_state()._state._state_vector, + [[0, 0, 0], [0, 0, 0], [0, 0, 1]], + ) + class CountingState(cirq.qis.QuantumStateRepresentation): def __init__(self, data, gate_count=0, measurement_count=0): From 40d0603a66dc7481f0b9b81304c76f24b9025982 Mon Sep 17 00:00:00 2001 From: daxfohl Date: Sat, 28 May 2022 10:42:09 -0700 Subject: [PATCH 11/12] Move to contrib --- .../custom_state_simulator.py | 91 +++++++++ .../custom_state_simulator_test.py | 192 ++++++++++++++++++ cirq-core/cirq/sim/simulator_base.py | 50 +---- cirq-core/cirq/sim/simulator_base_test.py | 72 ------- 4 files changed, 287 insertions(+), 118 deletions(-) create mode 100644 cirq-core/cirq/contrib/custom_simulators/custom_state_simulator.py create mode 100644 cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py diff --git a/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator.py b/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator.py new file mode 100644 index 00000000000..c9e3c175505 --- /dev/null +++ b/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator.py @@ -0,0 +1,91 @@ +# Copyright 2022 The Cirq Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import Any, Dict, Generic, Sequence, Type, TYPE_CHECKING + +import numpy as np + +from cirq import sim +from cirq.sim.simulation_state import TSimulationState + +if TYPE_CHECKING: + import cirq + + +class CustomStateStepResult(sim.StepResultBase[TSimulationState], Generic[TSimulationState]): + """The step result provided by `CustomStateSimulator.simulate_moment_steps`.""" + + pass + + +class CustomStateTrialResult( + sim.SimulationTrialResultBase[TSimulationState], Generic[TSimulationState] +): + """The trial result provided by `CustomStateSimulator.simulate`.""" + + pass + + +class CustomStateSimulator( + sim.SimulatorBase[ + CustomStateStepResult[TSimulationState], + CustomStateTrialResult[TSimulationState], + TSimulationState, + ], + Generic[TSimulationState], +): + """A simulator that can be used to simulate custom states.""" + + def __init__( + self, + state_type: Type[TSimulationState], + *, + noise: 'cirq.NOISE_MODEL_LIKE' = None, + split_untangled_states: bool = False, + ): + """Initializes a CustomStateSimulator. + + Args: + state_type: The class that represents the simulation state this simulator should use. + noise: The noise model used by the simulator. + split_untangled_states: True to run the simulation as a product state. This is only + supported if the `state_type` supports it via an implementation of `kron` and + `factor` methods. Otherwise a runtime error will occur during simulation.""" + super().__init__(noise=noise, split_untangled_states=split_untangled_states) + self.state_type = state_type + + def _create_simulator_trial_result( + self, + params: 'cirq.ParamResolver', + measurements: Dict[str, np.ndarray], + final_simulator_state: 'cirq.SimulationStateBase[TSimulationState]', + ) -> 'CustomStateTrialResult[TSimulationState]': + return CustomStateTrialResult( + params, measurements, final_simulator_state=final_simulator_state + ) + + def _create_step_result( + self, sim_state: 'cirq.SimulationStateBase[TSimulationState]' + ) -> 'CustomStateStepResult[TSimulationState]': + return CustomStateStepResult(sim_state) + + def _create_partial_simulation_state( + self, + initial_state: Any, + qubits: Sequence['cirq.Qid'], + classical_data: 'cirq.ClassicalDataStore', + ) -> TSimulationState: + return self.state_type( + initial_state=initial_state, qubits=qubits, classical_data=classical_data + ) diff --git a/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py b/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py new file mode 100644 index 00000000000..07e944d3805 --- /dev/null +++ b/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py @@ -0,0 +1,192 @@ +# Copyright 2022 The Cirq Developers +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from typing import List, Sequence, Tuple + +import numpy as np +import sympy + +import cirq +from cirq.contrib.custom_simulators.custom_state_simulator import CustomStateSimulator + + +class ComputationalBaisisState(cirq.qis.QuantumStateRepresentation): + def __init__(self, initial_state: List[int]): + self.basis = initial_state + + def copy(self, deep_copy_buffers: bool = True) -> 'ComputationalBaisisState': + return ComputationalBaisisState(self.basis) + + def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): + return [self.basis[i] for i in axes] + + +class ComputationalBaisisSimState(cirq.SimulationState[ComputationalBaisisState]): + def __init__(self, initial_state, qubits, classical_data): + state = ComputationalBaisisState( + cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits)) + ) + super().__init__(state=state, qubits=qubits, classical_data=classical_data) + + def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: bool = True): + gate = action.gate if isinstance(action, cirq.Operation) else action + if isinstance(gate, cirq.XPowGate): + i = self.qubit_map[qubits[0]] + self._state.basis[i] = int(gate.exponent + self._state.basis[i]) % qubits[0].dimension + return True + return NotImplemented + + +def create_test_circuit(): + q0, q1 = cirq.LineQid.range(2, dimension=3) + x = cirq.XPowGate(dimension=3) + return cirq.Circuit( + x(q0), + cirq.measure(q0, key='a'), + x(q0).with_classical_controls('a'), + cirq.CircuitOperation( + cirq.FrozenCircuit(x(q1), cirq.measure(q1, key='b')), + repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol('b'), 2)), + use_repetition_ids=False, + ), + ) + + +def test_basis_state_simulator(): + sim = CustomStateSimulator(ComputationalBaisisSimState) + circuit = create_test_circuit() + r = sim.simulate(circuit) + assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} + assert r._final_simulator_state._state.basis == [2, 2] + + +def test_built_in_states(): + # Verify this works for the built-in states too, you just lose the custom step/trial results. + sim = CustomStateSimulator(cirq.StateVectorSimulationState) + circuit = create_test_circuit() + r = sim.simulate(circuit) + assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} + assert np.allclose( + r._final_simulator_state._state._state_vector, [[0, 0, 0], [0, 0, 0], [0, 0, 1]] + ) + + +def test_product_state_mode_built_in_state(): + sim = CustomStateSimulator(cirq.StateVectorSimulationState, split_untangled_states=True) + circuit = create_test_circuit() + r = sim.simulate(circuit) + assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} + + # Ensure the state is in product-state mode, and it's got three states (q0, q1, phase) + assert isinstance(r._final_simulator_state, cirq.SimulationProductState) + assert len(r._final_simulator_state.sim_states) == 3 + + assert np.allclose( + r._final_simulator_state.create_merged_state()._state._state_vector, + [[0, 0, 0], [0, 0, 0], [0, 0, 1]], + ) + + +def test_noise(): + x = cirq.XPowGate(dimension=3) + sim = CustomStateSimulator(ComputationalBaisisSimState, noise=x**2) + circuit = create_test_circuit() + r = sim.simulate(circuit) + assert r.measurements == {'a': np.array([2]), 'b': np.array([2])} + assert r._final_simulator_state._state.basis == [1, 2] + + +def test_run(): + sim = CustomStateSimulator(ComputationalBaisisSimState) + circuit = create_test_circuit() + r = sim.run(circuit) + assert np.allclose(r.records['a'], np.array([[1]])) + assert np.allclose(r.records['b'], np.array([[1], [2]])) + + +def test_parameterized_repetitions(): + q = cirq.LineQid(0, dimension=5) + x = cirq.XPowGate(dimension=5) + circuit = cirq.Circuit( + cirq.CircuitOperation( + cirq.FrozenCircuit(x(q), cirq.measure(q, key='a')), + repetitions=sympy.Symbol('r'), + use_repetition_ids=False, + ) + ) + + sim = CustomStateSimulator(ComputationalBaisisSimState) + r = sim.run_sweep(circuit, [{'r': i} for i in range(1, 5)]) + assert np.allclose(r[0].records['a'], np.array([[1]])) + assert np.allclose(r[1].records['a'], np.array([[1], [2]])) + assert np.allclose(r[2].records['a'], np.array([[1], [2], [3]])) + assert np.allclose(r[3].records['a'], np.array([[1], [2], [3], [4]])) + + +class ComputationalBasisProductState(cirq.qis.QuantumStateRepresentation): + def __init__(self, initial_state: List[int]): + self.basis = initial_state + + def copy(self, deep_copy_buffers: bool = True) -> 'ComputationalBasisProductState': + return ComputationalBasisProductState(self.basis) + + def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): + return [self.basis[i] for i in axes] + + def kron(self, other: 'ComputationalBasisProductState') -> 'ComputationalBasisProductState': + return ComputationalBasisProductState(self.basis + other.basis) + + def factor( + self, axes: Sequence[int], *, validate=True, atol=1e-07 + ) -> Tuple['ComputationalBasisProductState', 'ComputationalBasisProductState']: + extracted = ComputationalBasisProductState([self.basis[i] for i in axes]) + remainder = ComputationalBasisProductState( + [self.basis[i] for i in range(len(self.basis)) if i not in axes] + ) + return extracted, remainder + + def reindex(self, axes: Sequence[int]) -> 'ComputationalBasisProductState': + return ComputationalBasisProductState([self.basis[i] for i in axes]) + + @property + def supports_factor(self) -> bool: + return True + + +class ComputationalBasisSimProductState(cirq.SimulationState[ComputationalBasisProductState]): + def __init__(self, initial_state, qubits, classical_data): + state = ComputationalBasisProductState( + cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits)) + ) + super().__init__(state=state, qubits=qubits, classical_data=classical_data) + + def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: bool = True): + gate = action.gate if isinstance(action, cirq.Operation) else action + if isinstance(gate, cirq.XPowGate): + i = self.qubit_map[qubits[0]] + self._state.basis[i] = int(gate.exponent + self._state.basis[i]) % qubits[0].dimension + return True + return NotImplemented + + +def test_product_state_mode(): + sim = CustomStateSimulator(ComputationalBasisSimProductState, split_untangled_states=True) + circuit = create_test_circuit() + r = sim.simulate(circuit) + assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} + + # Ensure the state is in product-state mode, and it's got three states (q0, q1, phase) + assert isinstance(r._final_simulator_state, cirq.SimulationProductState) + assert len(r._final_simulator_state.sim_states) == 3 + assert r._final_simulator_state.create_merged_state()._state.basis == [2, 2] diff --git a/cirq-core/cirq/sim/simulator_base.py b/cirq-core/cirq/sim/simulator_base.py index 42d74a6beca..a8bae957bfd 100644 --- a/cirq-core/cirq/sim/simulator_base.py +++ b/cirq-core/cirq/sim/simulator_base.py @@ -397,7 +397,9 @@ def _create_simulation_state( ) -class StepResultBase(Generic[TSimulationState], StepResult[SimulationStateBase[TSimulationState]]): +class StepResultBase( + Generic[TSimulationState], StepResult[SimulationStateBase[TSimulationState]], abc.ABC +): """A base class for step results.""" def __init__(self, sim_state: SimulationStateBase[TSimulationState]): @@ -433,7 +435,7 @@ def sample( class SimulationTrialResultBase( - SimulationTrialResult[SimulationStateBase[TSimulationState]], Generic[TSimulationState] + SimulationTrialResult[SimulationStateBase[TSimulationState]], Generic[TSimulationState], abc.ABC ): """A base class for trial results.""" @@ -482,47 +484,3 @@ def _get_merged_sim_state(self) -> TSimulationState: if self._merged_sim_state_cache is None: self._merged_sim_state_cache = self._final_simulator_state.create_merged_state() return self._merged_sim_state_cache - - -class ThirdPartySimulator( - SimulatorBase[ - StepResultBase[TSimulationState], - SimulationTrialResultBase[TSimulationState], - TSimulationState, - ], - Generic[TSimulationState], -): - def __init__( - self, - state_type: Type[TSimulationState], - *, - noise: 'cirq.NOISE_MODEL_LIKE' = None, - split_untangled_states=False, - ): - super().__init__(noise=noise, split_untangled_states=split_untangled_states) - self.state_type = state_type - - def _create_simulator_trial_result( - self, - params: 'cirq.ParamResolver', - measurements: Dict[str, np.ndarray], - final_simulator_state: 'cirq.SimulationStateBase[TSimulationState]', - ) -> 'cirq.SimulationTrialResultBase[TSimulationState]': - return SimulationTrialResultBase( - params, measurements, final_simulator_state=final_simulator_state - ) - - def _create_step_result( - self, sim_state: 'cirq.SimulationStateBase[TSimulationState]' - ) -> 'cirq.StepResultBase[TSimulationState]': - return StepResultBase(sim_state) - - def _create_partial_simulation_state( - self, - initial_state: Any, - qubits: Sequence['cirq.Qid'], - classical_data: 'cirq.ClassicalDataStore', - ) -> TSimulationState: - return self.state_type( - initial_state=initial_state, qubits=qubits, classical_data=classical_data - ) diff --git a/cirq-core/cirq/sim/simulator_base_test.py b/cirq-core/cirq/sim/simulator_base_test.py index 867727fc0f4..a6eb70b46a0 100644 --- a/cirq-core/cirq/sim/simulator_base_test.py +++ b/cirq-core/cirq/sim/simulator_base_test.py @@ -19,78 +19,6 @@ import sympy import cirq -from cirq.sim.simulator_base import ThirdPartySimulator - - -class ComputationalBaisisState(cirq.qis.QuantumStateRepresentation): - def __init__(self, initial_state: List[int]): - self.state = initial_state - - def copy(self, deep_copy_buffers: bool = True) -> 'ComputationalBaisisState': - return ComputationalBaisisState(self.state) - - def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): - return [self.state[i] for i in axes] - - -class ComputationalBaisisSimState(cirq.SimulationState[ComputationalBaisisState]): - def __init__(self, initial_state, qubits, classical_data): - state = ComputationalBaisisState( - cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits)) - ) - super().__init__(state=state, qubits=qubits, classical_data=classical_data) - - def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: bool = True): - gate = action.gate if isinstance(action, cirq.Operation) else action - if isinstance(gate, cirq.XPowGate): - i = self.qubit_map[qubits[0]] - self._state.state[i] = int(gate.exponent + self._state.state[i]) % qubits[0].dimension - return True - return NotImplemented - - -def test_simple_simulator(): - q0, q1 = cirq.LineQid.range(2, dimension=3) - x = cirq.XPowGate(dimension=3) - c = cirq.Circuit( - x(q0), - cirq.measure(q0, key='a'), - x(q0).with_classical_controls('a'), - cirq.CircuitOperation( - cirq.FrozenCircuit(x(q1), cirq.measure(q1, key='b')), - repeat_until=cirq.SympyCondition(sympy.Eq(sympy.Symbol('b'), 2)), - use_repetition_ids=False, - ), - ) - - sim = ThirdPartySimulator(ComputationalBaisisSimState) - r = sim.simulate(c) - assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} - assert r._final_simulator_state._state.state == [2, 2] - - # test noise - sim = ThirdPartySimulator(ComputationalBaisisSimState, noise=x**2) - r = sim.simulate(c) - assert r.measurements == {'a': np.array([2]), 'b': np.array([2])} - assert r._final_simulator_state._state.state == [1, 2] - - # works for the built-in states too, you just lose the custom step/trial results. - sim = ThirdPartySimulator(cirq.StateVectorSimulationState) - r = sim.simulate(c) - assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} - assert np.allclose( - r._final_simulator_state._state._state_vector, [[0, 0, 0], [0, 0, 0], [0, 0, 1]] - ) - - # product state mode works. - sim = ThirdPartySimulator(cirq.StateVectorSimulationState, split_untangled_states=True) - r = sim.simulate(c) - assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} - assert len(r._final_simulator_state) == 3 - assert np.allclose( - r._final_simulator_state.create_merged_state()._state._state_vector, - [[0, 0, 0], [0, 0, 0], [0, 0, 1]], - ) class CountingState(cirq.qis.QuantumStateRepresentation): From d63b958549e24eb8f3eafe65fd36473f85a77d6b Mon Sep 17 00:00:00 2001 From: daxfohl Date: Sat, 28 May 2022 13:34:31 -0700 Subject: [PATCH 12/12] coverage --- .../custom_state_simulator_test.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py b/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py index 07e944d3805..fd547779340 100644 --- a/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py +++ b/cirq-core/cirq/contrib/custom_simulators/custom_state_simulator_test.py @@ -21,20 +21,20 @@ from cirq.contrib.custom_simulators.custom_state_simulator import CustomStateSimulator -class ComputationalBaisisState(cirq.qis.QuantumStateRepresentation): +class ComputationalBasisState(cirq.qis.QuantumStateRepresentation): def __init__(self, initial_state: List[int]): self.basis = initial_state - def copy(self, deep_copy_buffers: bool = True) -> 'ComputationalBaisisState': - return ComputationalBaisisState(self.basis) + def copy(self, deep_copy_buffers: bool = True) -> 'ComputationalBasisState': + return ComputationalBasisState(self.basis) def measure(self, axes: Sequence[int], seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None): return [self.basis[i] for i in axes] -class ComputationalBaisisSimState(cirq.SimulationState[ComputationalBaisisState]): +class ComputationalBasisSimState(cirq.SimulationState[ComputationalBasisState]): def __init__(self, initial_state, qubits, classical_data): - state = ComputationalBaisisState( + state = ComputationalBasisState( cirq.big_endian_int_to_bits(initial_state, bit_count=len(qubits)) ) super().__init__(state=state, qubits=qubits, classical_data=classical_data) @@ -45,7 +45,7 @@ def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: i = self.qubit_map[qubits[0]] self._state.basis[i] = int(gate.exponent + self._state.basis[i]) % qubits[0].dimension return True - return NotImplemented + pass def create_test_circuit(): @@ -64,7 +64,7 @@ def create_test_circuit(): def test_basis_state_simulator(): - sim = CustomStateSimulator(ComputationalBaisisSimState) + sim = CustomStateSimulator(ComputationalBasisSimState) circuit = create_test_circuit() r = sim.simulate(circuit) assert r.measurements == {'a': np.array([1]), 'b': np.array([2])} @@ -100,7 +100,7 @@ def test_product_state_mode_built_in_state(): def test_noise(): x = cirq.XPowGate(dimension=3) - sim = CustomStateSimulator(ComputationalBaisisSimState, noise=x**2) + sim = CustomStateSimulator(ComputationalBasisSimState, noise=x**2) circuit = create_test_circuit() r = sim.simulate(circuit) assert r.measurements == {'a': np.array([2]), 'b': np.array([2])} @@ -108,7 +108,7 @@ def test_noise(): def test_run(): - sim = CustomStateSimulator(ComputationalBaisisSimState) + sim = CustomStateSimulator(ComputationalBasisSimState) circuit = create_test_circuit() r = sim.run(circuit) assert np.allclose(r.records['a'], np.array([[1]])) @@ -126,7 +126,7 @@ def test_parameterized_repetitions(): ) ) - sim = CustomStateSimulator(ComputationalBaisisSimState) + sim = CustomStateSimulator(ComputationalBasisSimState) r = sim.run_sweep(circuit, [{'r': i} for i in range(1, 5)]) assert np.allclose(r[0].records['a'], np.array([[1]])) assert np.allclose(r[1].records['a'], np.array([[1], [2]])) @@ -177,7 +177,7 @@ def _act_on_fallback_(self, action, qubits: Sequence[cirq.Qid], allow_decompose: i = self.qubit_map[qubits[0]] self._state.basis[i] = int(gate.exponent + self._state.basis[i]) % qubits[0].dimension return True - return NotImplemented + pass def test_product_state_mode():