Skip to content
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
10 changes: 9 additions & 1 deletion cirq-core/cirq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -452,12 +452,13 @@
ActOnStabilizerCHFormArgs,
ActOnStabilizerArgs,
ActOnStateVectorArgs,
StabilizerStateChForm,
CIRCUIT_LIKE,
CliffordSimulator,
CliffordState,
CliffordSimulatorStepResult,
CliffordTableauSimulationState,
CliffordTrialResult,
DensityMatrixSimulationState,
DensityMatrixSimulator,
DensityMatrixSimulatorState,
DensityMatrixStepResult,
Expand All @@ -477,13 +478,20 @@
SimulatesIntermediateState,
SimulatesIntermediateStateVector,
SimulatesSamples,
SimulationProductState,
SimulationState,
SimulationStateBase,
SimulationTrialResult,
SimulationTrialResultBase,
Simulator,
SimulatorBase,
SparseSimulatorStep,
StabilizerChFormSimulationState,
StabilizerSampler,
StabilizerSimulationState,
StabilizerStateChForm,
StateVectorMixin,
StateVectorSimulationState,
StateVectorSimulatorState,
StateVectorStepResult,
StateVectorTrialResult,
Expand Down
8 changes: 4 additions & 4 deletions cirq-core/cirq/circuits/circuit_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,17 +350,17 @@ def mapped_op(self, deep: bool = False) -> 'cirq.CircuitOperation':
def _decompose_(self) -> Iterator['cirq.Operation']:
return self.mapped_circuit(deep=False).all_operations()

def _act_on_(self, args: 'cirq.OperationTarget') -> bool:
def _act_on_(self, sim_state: 'cirq.SimulationStateBase') -> bool:
if self.repeat_until:
circuit = self._mapped_single_loop()
while True:
for op in circuit.all_operations():
protocols.act_on(op, args)
if self.repeat_until.resolve(args.classical_data):
protocols.act_on(op, sim_state)
if self.repeat_until.resolve(sim_state.classical_data):
break
else:
for op in self._decompose_():
protocols.act_on(op, args)
protocols.act_on(op, sim_state)
return True

# Methods for string representation of the operation.
Expand Down
14 changes: 7 additions & 7 deletions cirq-core/cirq/contrib/quimb/mps_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
from cirq import devices, protocols, qis, value
from cirq._compat import deprecated_parameter
from cirq.sim import simulator, simulator_base
from cirq.sim.act_on_args import ActOnArgs
from cirq.sim.simulation_state import SimulationState

if TYPE_CHECKING:
import cirq
Expand Down Expand Up @@ -115,14 +115,14 @@ def _create_partial_act_on_args(
classical_data=classical_data,
)

def _create_step_result(self, sim_state: 'cirq.OperationTarget[MPSState]'):
def _create_step_result(self, sim_state: 'cirq.SimulationStateBase[MPSState]'):
return MPSSimulatorStepResult(sim_state)

def _create_simulator_trial_result(
self,
params: 'cirq.ParamResolver',
measurements: Dict[str, np.ndarray],
final_simulator_state: 'cirq.OperationTarget[MPSState]',
final_simulator_state: 'cirq.SimulationStateBase[MPSState]',
) -> 'MPSTrialResult':
"""Creates a single trial results with the measurements.

Expand All @@ -148,7 +148,7 @@ def __init__(
self,
params: 'cirq.ParamResolver',
measurements: Dict[str, np.ndarray],
final_simulator_state: 'cirq.OperationTarget[MPSState]',
final_simulator_state: 'cirq.SimulationStateBase[MPSState]',
) -> None:
super().__init__(
params=params, measurements=measurements, final_simulator_state=final_simulator_state
Expand All @@ -175,10 +175,10 @@ def _repr_pretty_(self, p: Any, cycle: bool):
class MPSSimulatorStepResult(simulator_base.StepResultBase['MPSState']):
"""A `StepResult` that can perform measurements."""

def __init__(self, sim_state: 'cirq.OperationTarget[MPSState]'):
def __init__(self, sim_state: 'cirq.SimulationStateBase[MPSState]'):
"""Results of a step of the simulator.
Attributes:
sim_state: The qubit:ActOnArgs lookup for this step.
sim_state: The qubit:SimulationState lookup for this step.
"""
super().__init__(sim_state)

Expand Down Expand Up @@ -560,7 +560,7 @@ def sample(


@value.value_equality
class MPSState(ActOnArgs[_MPSHandler]):
class MPSState(SimulationState[_MPSHandler]):
"""A state of the MPS simulation."""

@deprecated_parameter(
Expand Down
4 changes: 2 additions & 2 deletions cirq-core/cirq/contrib/quimb/mps_simulator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def test_cnot_flipped():
)


def test_act_on_args():
def test_simulation_state():
q0, q1 = qubit_order = cirq.LineQubit.range(2)
circuit = cirq.Circuit(cirq.CNOT(q1, q0))
mps_simulator = ccq.mps_simulator.MPSSimulator()
Expand Down Expand Up @@ -537,7 +537,7 @@ def test_state_copy():
assert not np.shares_memory(x[i], y[i])


def test_state_act_on_args_initializer():
def test_simulation_state_initializer():
s = ccq.mps_simulator.MPSState(
qubits=(cirq.LineQubit(0),),
prng=np.random.RandomState(0),
Expand Down
6 changes: 3 additions & 3 deletions cirq-core/cirq/ops/classically_controlled_operation.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,9 @@ def _circuit_diagram_info_(
def _json_dict_(self) -> Dict[str, Any]:
return {'conditions': self._conditions, 'sub_operation': self._sub_operation}

def _act_on_(self, args: 'cirq.OperationTarget') -> bool:
if all(c.resolve(args.classical_data) for c in self._conditions):
protocols.act_on(self._sub_operation, args)
def _act_on_(self, sim_state: 'cirq.SimulationStateBase') -> bool:
if all(c.resolve(sim_state.classical_data) for c in self._conditions):
protocols.act_on(self._sub_operation, sim_state)
return True

def _with_measurement_key_mapping_(
Expand Down
24 changes: 13 additions & 11 deletions cirq-core/cirq/ops/clifford_gate.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,9 @@ def _generate_clifford_from_known_gate(
) -> Union['SingleQubitCliffordGate', 'CliffordGate']:
qubits = devices.LineQubit.range(num_qubits)
t = qis.CliffordTableau(num_qubits=num_qubits)
args = sim.ActOnCliffordTableauArgs(tableau=t, qubits=qubits, prng=np.random.RandomState())
args = sim.CliffordTableauSimulationState(
tableau=t, qubits=qubits, prng=np.random.RandomState()
)

protocols.act_on(gate, args, qubits, allow_decompose=False)
if num_qubits == 1:
Expand Down Expand Up @@ -339,7 +341,7 @@ def from_op_list(
)

base_tableau = qis.CliffordTableau(len(qubit_order))
args = sim.clifford.ActOnCliffordTableauArgs(
args = sim.clifford.CliffordTableauSimulationState(
tableau=base_tableau, qubits=qubit_order, prng=np.random.RandomState(0) # unused
)
for op in operations:
Expand Down Expand Up @@ -444,7 +446,7 @@ def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE':
)

def _act_on_(
self, args: 'cirq.OperationTarget', qubits: Sequence['cirq.Qid']
self, sim_state: 'cirq.SimulationStateBase', qubits: Sequence['cirq.Qid']
) -> Union[NotImplementedType, bool]:

# Note the computation complexity difference between _decompose_ and _act_on_.
Expand All @@ -453,15 +455,15 @@ def _act_on_(
# 1. Direct act_on is O(n^3) -- two matrices multiplication
# 2. Decomposition is O(m^3)+O(k*n^2) -- Decomposition complexity + k * One/two-qubits Ops
# So when m << n, the decomposition is more efficient.
if isinstance(args, sim.clifford.ActOnCliffordTableauArgs):
axes = args.get_axes(qubits)
if isinstance(sim_state, sim.clifford.CliffordTableauSimulationState):
axes = sim_state.get_axes(qubits)
# This padding is important and cannot be omitted.
padded_tableau = _pad_tableau(self._clifford_tableau, len(args.qubits), axes)
args._state = args.tableau.then(padded_tableau)
padded_tableau = _pad_tableau(self._clifford_tableau, len(sim_state.qubits), axes)
sim_state._state = sim_state.tableau.then(padded_tableau)
return True

if isinstance(args, sim.clifford.ActOnStabilizerCHFormArgs):
# Do we know how to apply CliffordTableau on ActOnStabilizerCHFormArgs?
if isinstance(sim_state, sim.clifford.StabilizerChFormSimulationState): # coverage: ignore
# Do we know how to apply CliffordTableau on StabilizerChFormSimulationState?
# It should be unlike because CliffordTableau ignores the global phase but CHForm
# is aimed to fix that.
return NotImplemented
Expand Down Expand Up @@ -706,10 +708,10 @@ def __pow__(self, exponent) -> 'SingleQubitCliffordGate':

def _act_on_(
self,
args: 'cirq.OperationTarget', # pylint: disable=unused-argument
sim_state: 'cirq.SimulationStateBase', # pylint: disable=unused-argument
qubits: Sequence['cirq.Qid'], # pylint: disable=unused-argument
):
# TODO(#5256) Add the implementation of _act_on_ with ActOnCliffordTableauArgs.
# TODO(#5256) Add the implementation of _act_on_ with CliffordTableauSimulationState.
return NotImplemented

# Single Clifford Gate decomposition is more efficient than the general Tableau decomposition.
Expand Down
14 changes: 7 additions & 7 deletions cirq-core/cirq/ops/clifford_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import pytest

import cirq
from cirq.protocols.act_on_protocol_test import DummyActOnArgs
from cirq.protocols.act_on_protocol_test import DummySimulationState
from cirq.testing import EqualsTester, assert_allclose_up_to_global_phase

_bools = (False, True)
Expand Down Expand Up @@ -783,10 +783,10 @@ def test_clifford_gate_act_on_small_case():
# Note this is also covered by the `from_op_list` one, etc.

qubits = cirq.LineQubit.range(5)
args = cirq.ActOnCliffordTableauArgs(
args = cirq.CliffordTableauSimulationState(
tableau=cirq.CliffordTableau(num_qubits=5), qubits=qubits, prng=np.random.RandomState()
)
expected_args = cirq.ActOnCliffordTableauArgs(
expected_args = cirq.CliffordTableauSimulationState(
tableau=cirq.CliffordTableau(num_qubits=5), qubits=qubits, prng=np.random.RandomState()
)
cirq.act_on(cirq.H, expected_args, qubits=[qubits[0]], allow_decompose=False)
Expand Down Expand Up @@ -818,8 +818,8 @@ def test_clifford_gate_act_on_large_case():
t1 = cirq.CliffordTableau(num_qubits=n)
t2 = cirq.CliffordTableau(num_qubits=n)
qubits = cirq.LineQubit.range(n)
args1 = cirq.ActOnCliffordTableauArgs(tableau=t1, qubits=qubits, prng=prng)
args2 = cirq.ActOnCliffordTableauArgs(tableau=t2, qubits=qubits, prng=prng)
args1 = cirq.CliffordTableauSimulationState(tableau=t1, qubits=qubits, prng=prng)
args2 = cirq.CliffordTableauSimulationState(tableau=t2, qubits=qubits, prng=prng)
ops = []
for _ in range(num_ops):
g = prng.randint(len(gate_candidate))
Expand All @@ -838,7 +838,7 @@ def test_clifford_gate_act_on_ch_form():
# Although we don't support CH_form from the _act_on_, it will fall back
# to the decomposititon method and apply it through decomposed ops.
# Here we run it for the coverage only.
args = cirq.ActOnStabilizerCHFormArgs(
args = cirq.StabilizerChFormSimulationState(
initial_state=cirq.StabilizerStateChForm(num_qubits=2, initial_state=1),
qubits=cirq.LineQubit.range(2),
prng=np.random.RandomState(),
Expand All @@ -849,4 +849,4 @@ def test_clifford_gate_act_on_ch_form():

def test_clifford_gate_act_on_fail():
with pytest.raises(TypeError, match="Failed to act"):
cirq.act_on(cirq.CliffordGate.X, DummyActOnArgs(), qubits=())
cirq.act_on(cirq.CliffordGate.X, DummySimulationState(), qubits=())
13 changes: 8 additions & 5 deletions cirq-core/cirq/ops/common_channels.py
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ def _qasm_(self, args: 'cirq.QasmArgs', qubits: Tuple['cirq.Qid', ...]) -> Optio
def _qid_shape_(self):
return (self._dimension,)

def _act_on_(self, args: 'cirq.OperationTarget', qubits: Sequence['cirq.Qid']):
def _act_on_(self, sim_state: 'cirq.SimulationStateBase', qubits: Sequence['cirq.Qid']):
if len(qubits) != 1:
return NotImplemented

Expand All @@ -734,12 +734,15 @@ def _unitary_(self):
u[:inc] = np.eye(self.dimension)[-inc:]
return u

from cirq.sim import act_on_args
from cirq.sim import simulation_state

if isinstance(args, act_on_args.ActOnArgs) and not args.can_represent_mixed_states:
result = args._perform_measurement(qubits)[0]
if (
isinstance(sim_state, simulation_state.SimulationState)
and not sim_state.can_represent_mixed_states
):
result = sim_state._perform_measurement(qubits)[0]
gate = PlusGate(self.dimension, self.dimension - result)
protocols.act_on(gate, args, qubits)
protocols.act_on(gate, sim_state, qubits)
return True

return NotImplemented
Expand Down
8 changes: 4 additions & 4 deletions cirq-core/cirq/ops/common_channels_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import pytest

import cirq
from cirq.protocols.act_on_protocol_test import DummyActOnArgs
from cirq.protocols.act_on_protocol_test import DummySimulationState

X = np.array([[0, 1], [1, 0]])
Y = np.array([[0, -1j], [1j, 0]])
Expand Down Expand Up @@ -489,9 +489,9 @@ def test_reset_channel_text_diagram():

def test_reset_act_on():
with pytest.raises(TypeError, match="Failed to act"):
cirq.act_on(cirq.ResetChannel(), DummyActOnArgs(), qubits=())
cirq.act_on(cirq.ResetChannel(), DummySimulationState(), qubits=())

args = cirq.ActOnStateVectorArgs(
args = cirq.StateVectorSimulationState(
available_buffer=np.empty(shape=(2, 2, 2, 2, 2), dtype=np.complex64),
qubits=cirq.LineQubit.range(5),
prng=np.random.RandomState(),
Expand Down Expand Up @@ -714,7 +714,7 @@ def test_bit_flip_channel_text_diagram():
def test_stabilizer_supports_depolarize():
with pytest.raises(TypeError, match="act_on"):
for _ in range(100):
cirq.act_on(cirq.depolarize(3 / 4), DummyActOnArgs(), qubits=())
cirq.act_on(cirq.depolarize(3 / 4), DummySimulationState(), qubits=())

q = cirq.LineQubit(0)
c = cirq.Circuit(cirq.depolarize(3 / 4).on(q), cirq.measure(q, key='m'))
Expand Down
Loading