Repository: quantumlib/Cirq

Issue:
Can we deprecate StateVectorStepResult.set_state()?
**Is your design idea/issue related to a use case or problem? Please describe.**

`StateVectorStepResult.set_state()` and `DensityMatrixStepResult.set_state()` allow replacing the running simulation state with a new one. This ends up requiring a fair amount of code overhead to maintain. But I'm not sure this if this is a useful function, as it seems a user could just start a new simulation on the remaining circuit and the existing state. I'm guessing this function is just an artifact of an old design. If so, I think we should remove it.

**Describe your design idea/issue**

Deprecate this function, take advantage of cleanups it allows (StateVectorStepResult would no longer have to contain a simulator. SimulatorBase.core_iterator should no longer have to set sim_state after yielding the step result).

Obviously if we decide to do #4771 (remove the StepResult classes completely), then this is no longer relevant.


Discussion:
From cirq sync: 

Looks like an artefact of old times and should be deprecated. Let's ask around and see if anyone is still using this. 

cc @Strilanc @mpharrigan 
I don't know anything about this

Resolving patch:
diff --git a/cirq-core/cirq/sim/density_matrix_simulator.py b/cirq-core/cirq/sim/density_matrix_simulator.py
--- a/cirq-core/cirq/sim/density_matrix_simulator.py
+++ b/cirq-core/cirq/sim/density_matrix_simulator.py
@@ -17,7 +17,7 @@
 import numpy as np
 
 from cirq import ops, protocols, qis, study, value
-from cirq._compat import proper_repr
+from cirq._compat import deprecated, proper_repr
 from cirq.sim import (
     simulator,
     act_on_density_matrix_args,
@@ -302,6 +302,11 @@ def __init__(
     def _simulator_state(self) -> 'cirq.DensityMatrixSimulatorState':
         return DensityMatrixSimulatorState(self.density_matrix(copy=False), self._qubit_mapping)
 
+    # TODO: When removing, also remove `simulator` from the constructor, and the line
+    # `sim_state = step_result._sim_state` from `SimulatorBase._core_iterator()`.
+    @deprecated(
+        deadline="v0.15", fix='Use `initial_state` to prepare a new simulation on the suffix.'
+    )
     def set_density_matrix(self, density_matrix_repr: Union[int, np.ndarray]):
         """Set the density matrix to a new density matrix.
 
diff --git a/cirq-core/cirq/sim/sparse_simulator.py b/cirq-core/cirq/sim/sparse_simulator.py
--- a/cirq-core/cirq/sim/sparse_simulator.py
+++ b/cirq-core/cirq/sim/sparse_simulator.py
@@ -29,6 +29,7 @@
 import numpy as np
 
 from cirq import ops, protocols, qis
+from cirq._compat import deprecated
 from cirq.sim import (
     simulator,
     state_vector,
@@ -316,6 +317,11 @@ def state_vector(self, copy: bool = True):
                 self._state_vector = np.reshape(vector, size)
         return self._state_vector.copy() if copy else self._state_vector
 
+    # TODO: When removing, also remove `simulator` from the constructor, and the line
+    # `sim_state = step_result._sim_state` from `SimulatorBase._core_iterator()`.
+    @deprecated(
+        deadline="v0.15", fix='Use `initial_state` to prepare a new simulation on the suffix.'
+    )
     def set_state_vector(self, state: 'cirq.STATE_VECTOR_LIKE'):
         """Set the state vector.
 


Test patch:
diff --git a/cirq-core/cirq/sim/density_matrix_simulator_test.py b/cirq-core/cirq/sim/density_matrix_simulator_test.py
--- a/cirq-core/cirq/sim/density_matrix_simulator_test.py
+++ b/cirq-core/cirq/sim/density_matrix_simulator_test.py
@@ -841,7 +841,7 @@ def test_simulate_moment_steps_empty_circuit(dtype: Type[np.number], split: bool
 
 
 @pytest.mark.parametrize('dtype', [np.complex64, np.complex128])
-def test_simulate_moment_steps_set_state(dtype: Type[np.number]):
+def test_simulate_moment_steps_set_state_deprecated(dtype: Type[np.number]):
     q0, q1 = cirq.LineQubit.range(2)
     circuit = cirq.Circuit(cirq.H(q0), cirq.H(q1), cirq.H(q0), cirq.H(q1))
     simulator = cirq.DensityMatrixSimulator(dtype=dtype)
@@ -850,7 +850,8 @@ def test_simulate_moment_steps_set_state(dtype: Type[np.number]):
         if i == 0:
             zero_zero = np.zeros((4, 4), dtype=dtype)
             zero_zero[0, 0] = 1
-            step.set_density_matrix(zero_zero)
+            with cirq.testing.assert_deprecated('initial_state', deadline='v0.15'):
+                step.set_density_matrix(zero_zero)
 
 
 @pytest.mark.parametrize('dtype', [np.complex64, np.complex128])
diff --git a/cirq-core/cirq/sim/sparse_simulator_test.py b/cirq-core/cirq/sim/sparse_simulator_test.py
--- a/cirq-core/cirq/sim/sparse_simulator_test.py
+++ b/cirq-core/cirq/sim/sparse_simulator_test.py
@@ -580,14 +580,15 @@ def test_simulate_moment_steps_empty_circuit(dtype: Type[np.number], split: bool
 
 
 @pytest.mark.parametrize('dtype', [np.complex64, np.complex128])
-def test_simulate_moment_steps_set_state(dtype):
+def test_simulate_moment_steps_set_state_deprecated(dtype):
     q0, q1 = cirq.LineQubit.range(2)
     circuit = cirq.Circuit(cirq.H(q0), cirq.H(q1), cirq.H(q0), cirq.H(q1))
     simulator = cirq.Simulator(dtype=dtype)
     for i, step in enumerate(simulator.simulate_moment_steps(circuit)):
         np.testing.assert_almost_equal(step.state_vector(), np.array([0.5] * 4))
         if i == 0:
-            step.set_state_vector(np.array([1, 0, 0, 0], dtype=dtype))
+            with cirq.testing.assert_deprecated('initial_state', deadline='v0.15'):
+                step.set_state_vector(np.array([1, 0, 0, 0], dtype=dtype))
 
 
 @pytest.mark.parametrize('dtype', [np.complex64, np.complex128])