Skip to content

Commit

Permalink
Cirq monofsv cleanup (#5685)
Browse files Browse the repository at this point in the history
Fixes #3494.

This PR bundles together a bunch of cleanup around `[final_]state_vector` deprecations.
  • Loading branch information
95-martin-orion authored Jul 11, 2022
1 parent e1f7cb7 commit b6ce68d
Show file tree
Hide file tree
Showing 15 changed files with 59 additions and 116 deletions.
16 changes: 3 additions & 13 deletions cirq-core/cirq/circuits/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1091,12 +1091,11 @@ def _superoperator_(self) -> np.ndarray:
)
def final_state_vector(
self,
# TODO(v0.16): Force kwargs and match order found in:
# cirq-core/cirq/sim/mux.py:final_state_vector
*,
initial_state: 'cirq.STATE_VECTOR_LIKE' = 0,
qubit_order: 'cirq.QubitOrderOrList' = ops.QubitOrder.DEFAULT,
qubits_that_should_be_present: Iterable['cirq.Qid'] = (),
ignore_terminal_measurements: Optional[bool] = None,
ignore_terminal_measurements: bool = False,
dtype: Type[np.complexfloating] = np.complex128,
param_resolver: 'cirq.ParamResolverOrSimilarType' = None,
seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
Expand All @@ -1120,7 +1119,7 @@ def final_state_vector(
regardless when generating the matrix.
ignore_terminal_measurements: When set, measurements at the end of
the circuit are ignored instead of causing the method to
fail.
fail. Defaults to False.
dtype: The `numpy.dtype` used by the simulation. Typically one of
`numpy.complex64` or `numpy.complex128`.
param_resolver: Parameters to run with the program.
Expand All @@ -1138,15 +1137,6 @@ def final_state_vector(
ValueError: If the program doesn't have a well defined final state
because it has non-unitary gates.
"""
if ignore_terminal_measurements is None:
if self.has_measurements():
_compat._warn_or_error(
'`ignore_terminal_measurements` will default to False in v0.16. '
'To drop terminal measurements, please explicitly include '
'`ignore_terminal_measurements=True` when calling this method.'
)
ignore_terminal_measurements = True

from cirq.sim.mux import final_state_vector

program = Circuit(cirq.I(q) for q in qubits_that_should_be_present) + self
Expand Down
34 changes: 17 additions & 17 deletions cirq-core/cirq/circuits/circuit_operation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def test_recursive_params():

# First example should behave like an X when simulated
result = cirq.Simulator().simulate(cirq.Circuit(circuitop), param_resolver=outer_params)
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])


@pytest.mark.parametrize('add_measurements', [True, False])
Expand Down Expand Up @@ -345,9 +345,9 @@ def test_repeat_zero_times(add_measurements, use_repetition_ids, initial_reps):
subcircuit.freeze(), repetitions=initial_reps, use_repetition_ids=use_repetition_ids
)
result = cirq.Simulator().simulate(cirq.Circuit(op))
assert np.allclose(result.state_vector(copy=False), [0, 1] if initial_reps % 2 else [1, 0])
assert np.allclose(result.state_vector(), [0, 1] if initial_reps % 2 else [1, 0])
result = cirq.Simulator().simulate(cirq.Circuit(op**0))
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])


def test_no_repetition_ids():
Expand Down Expand Up @@ -377,13 +377,13 @@ def test_parameterized_repeat():
assert cirq.parameter_names(op) == {'a'}
assert not cirq.has_unitary(op)
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 0})
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1})
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 2})
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': -1})
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])
with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'):
cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5})
with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'):
Expand All @@ -392,13 +392,13 @@ def test_parameterized_repeat():
assert cirq.parameter_names(op) == {'a'}
assert not cirq.has_unitary(op)
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 0})
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1})
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 2})
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': -1})
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])
with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'):
cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5})
with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'):
Expand All @@ -407,11 +407,11 @@ def test_parameterized_repeat():
assert cirq.parameter_names(op) == {'a', 'b'}
assert not cirq.has_unitary(op)
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 1})
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 2, 'b': 1})
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 2})
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])
with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'):
cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5, 'b': 1})
with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'):
Expand All @@ -420,11 +420,11 @@ def test_parameterized_repeat():
assert cirq.parameter_names(op) == {'a', 'b'}
assert not cirq.has_unitary(op)
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 1})
assert np.allclose(result.state_vector(copy=False), [1, 0])
assert np.allclose(result.state_vector(), [1, 0])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5, 'b': 1})
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])
result = cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1, 'b': 1.5})
assert np.allclose(result.state_vector(copy=False), [0, 1])
assert np.allclose(result.state_vector(), [0, 1])
with pytest.raises(TypeError, match='Only integer or sympy repetitions are allowed'):
cirq.Simulator().simulate(cirq.Circuit(op), param_resolver={'a': 1.5, 'b': 1.5})
with pytest.raises(ValueError, match='Circuit contains ops whose symbols were not specified'):
Expand Down
6 changes: 2 additions & 4 deletions cirq-core/cirq/contrib/quantum_volume/quantum_volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,12 @@ def compute_heavy_set(circuit: cirq.Circuit) -> List[int]:
# output is defined in terms of probabilities, where our wave function is in
# terms of amplitudes. We convert it by using the Born rule: squaring each
# amplitude and taking their absolute value
median = np.median(np.abs(results.state_vector(copy=False) ** 2))
median = np.median(np.abs(results.state_vector() ** 2))

# The output wave function is a vector from the result value (big-endian) to
# the probability of that bit-string. Return all of the bit-string
# values that have a probability greater than the median.
return [
idx for idx, amp in enumerate(results.state_vector(copy=False)) if np.abs(amp**2) > median
]
return [idx for idx, amp in enumerate(results.state_vector()) if np.abs(amp**2) > median]


@dataclass
Expand Down
3 changes: 1 addition & 2 deletions cirq-core/cirq/experiments/xeb_simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ def __call__(self, task: _Simulate2qXEBTask) -> List[Dict[str, Any]]:
if cycle_depth not in cycle_depths:
continue

# copy=False is safe because state_vector_to_probabilities will copy anyways
psi = step_result.state_vector(copy=False)
psi = step_result.state_vector()
pure_probs = value.state_vector_to_probabilities(psi)

records += [
Expand Down
6 changes: 1 addition & 5 deletions cirq-core/cirq/ops/boolean_hamiltonian_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,7 @@ def test_circuit(boolean_str):

circuit.append(hamiltonian_gate.on(*qubits))

phi = (
cirq.Simulator()
.simulate(circuit, qubit_order=qubits, initial_state=0)
.state_vector(copy=False)
)
phi = cirq.Simulator().simulate(circuit, qubit_order=qubits, initial_state=0).state_vector()
actual = np.arctan2(phi.real, phi.imag) - math.pi / 2.0 > 0.0

# Compare the two:
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/sim/mux.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def final_state_vector(
param_resolver=param_resolver,
)

return result.state_vector(copy=False)
return result.state_vector()


def sample_sweep(
Expand Down
4 changes: 1 addition & 3 deletions cirq-core/cirq/sim/simulator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,9 +430,7 @@ def _kraus_(self):
cirq.Circuit(Reset11To00().on(*cirq.LineQubit.range(2))), initial_state=k
)
np.testing.assert_allclose(
out.state_vector(copy=False),
cirq.one_hot(index=k % 3, shape=4, dtype=np.complex64),
atol=1e-8,
out.state_vector(), cirq.one_hot(index=k % 3, shape=4, dtype=np.complex64), atol=1e-8
)


Expand Down
10 changes: 2 additions & 8 deletions cirq-core/cirq/sim/sparse_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import numpy as np

from cirq import _compat, ops
from cirq import ops
from cirq.sim import simulator, state_vector, state_vector_simulator, state_vector_simulation_state

if TYPE_CHECKING:
Expand Down Expand Up @@ -236,7 +236,7 @@ def __init__(
self._dtype = dtype
self._state_vector: Optional[np.ndarray] = None

def state_vector(self, copy: Optional[bool] = None):
def state_vector(self, copy: bool = False):
"""Return the state vector at this point in the computation.
The state is returned in the computational basis with these basis
Expand Down Expand Up @@ -269,12 +269,6 @@ def state_vector(self, copy: Optional[bool] = None):
parameters from the state vector and store then using False
can speed up simulation by eliminating a memory copy.
"""
if copy is None:
_compat._warn_or_error(
"Starting in v0.16, state_vector will not copy the state by default. "
"Explicitly set copy=True to copy the state."
)
copy = True
if self._state_vector is None:
self._state_vector = np.array([1])
state = self._merged_sim_state
Expand Down
31 changes: 10 additions & 21 deletions cirq-core/cirq/sim/sparse_simulator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,17 +558,6 @@ def test_simulate_moment_steps(dtype: Type[np.complexfloating], split: bool):
np.testing.assert_almost_equal(step.state_vector(copy=True), np.array([1, 0, 0, 0]))


def test_simulate_moment_steps_implicit_copy_deprecated():
q0 = cirq.LineQubit(0)
simulator = cirq.Simulator()
steps = list(simulator.simulate_moment_steps(cirq.Circuit(cirq.X(q0))))

with cirq.testing.assert_deprecated(
"state_vector will not copy the state by default", deadline="v0.16"
):
_ = steps[0].state_vector()


@pytest.mark.parametrize('dtype', [np.complex64, np.complex128])
@pytest.mark.parametrize('split', [True, False])
def test_simulate_moment_steps_empty_circuit(dtype: Type[np.complexfloating], split: bool):
Expand Down Expand Up @@ -726,8 +715,8 @@ def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs):

initial_state = np.array([np.sqrt(0.5), np.sqrt(0.5)], dtype=np.complex64)
result = simulator.simulate(circuit, initial_state=initial_state)
np.testing.assert_array_almost_equal(result.state_vector(copy=False), initial_state)
assert not initial_state is result.state_vector(copy=False)
np.testing.assert_array_almost_equal(result.state_vector(), initial_state)
assert not initial_state is result.state_vector()


def test_does_not_modify_initial_state():
Expand All @@ -751,7 +740,7 @@ def _apply_unitary_(self, args: cirq.ApplyUnitaryArgs):
result = simulator.simulate(circuit, initial_state=initial_state)
np.testing.assert_array_almost_equal(np.array([1, 0], dtype=np.complex64), initial_state)
np.testing.assert_array_almost_equal(
result.state_vector(copy=False), np.array([0, 1], dtype=np.complex64)
result.state_vector(), np.array([0, 1], dtype=np.complex64)
)


Expand Down Expand Up @@ -803,7 +792,7 @@ def test_simulates_composite():
np.testing.assert_allclose(
c.final_state_vector(ignore_terminal_measurements=False, dtype=np.complex64), expected
)
np.testing.assert_allclose(cirq.Simulator().simulate(c).state_vector(copy=False), expected)
np.testing.assert_allclose(cirq.Simulator().simulate(c).state_vector(), expected)


def test_simulate_measurement_inversions():
Expand All @@ -820,15 +809,15 @@ def test_works_on_pauli_string_phasor():
a, b = cirq.LineQubit.range(2)
c = cirq.Circuit(np.exp(0.5j * np.pi * cirq.X(a) * cirq.X(b)))
sim = cirq.Simulator()
result = sim.simulate(c).state_vector(copy=False)
result = sim.simulate(c).state_vector()
np.testing.assert_allclose(result.reshape(4), np.array([0, 0, 0, 1j]), atol=1e-8)


def test_works_on_pauli_string():
a, b = cirq.LineQubit.range(2)
c = cirq.Circuit(cirq.X(a) * cirq.X(b))
sim = cirq.Simulator()
result = sim.simulate(c).state_vector(copy=False)
result = sim.simulate(c).state_vector()
np.testing.assert_allclose(result.reshape(4), np.array([0, 0, 0, 1]), atol=1e-8)


Expand Down Expand Up @@ -1325,7 +1314,7 @@ def _apply_unitary_(self, args):
vectors = []
copy_of_vectors = []
for step in sim.simulate_moment_steps(circuit):
state_vector = step.state_vector(copy=False)
state_vector = step.state_vector()
vectors.append(state_vector)
copy_of_vectors.append(state_vector.copy())
assert any(not np.array_equal(x, y) for x, y in zip(vectors, copy_of_vectors))
Expand All @@ -1338,9 +1327,9 @@ def test_final_state_vector_is_not_last_object():
initial_state = np.array([1, 0], dtype=np.complex64)
circuit = cirq.Circuit(cirq.wait(q))
result = sim.simulate(circuit, initial_state=initial_state)
assert result.state_vector(copy=False) is not initial_state
assert not np.shares_memory(result.state_vector(copy=False), initial_state)
np.testing.assert_equal(result.state_vector(copy=False), initial_state)
assert result.state_vector() is not initial_state
assert not np.shares_memory(result.state_vector(), initial_state)
np.testing.assert_equal(result.state_vector(), initial_state)


def test_deterministic_gate_noise():
Expand Down
10 changes: 4 additions & 6 deletions cirq-core/cirq/sim/state_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def _qid_shape_(self) -> Tuple[int, ...]:
return self._qid_shape

@abc.abstractmethod
def state_vector(self, copy: Optional[bool] = False) -> np.ndarray:
def state_vector(self, copy: bool = False) -> np.ndarray:
"""Return the state vector (wave function).
The vector is returned in the computational basis with these basis
Expand Down Expand Up @@ -101,9 +101,7 @@ def dirac_notation(self, decimals: int = 2) -> str:
Returns:
A pretty string consisting of a sum of computational basis kets
and non-zero floats of the specified accuracy."""
return qis.dirac_notation(
self.state_vector(copy=False), decimals, qid_shape=self._qid_shape
)
return qis.dirac_notation(self.state_vector(), decimals, qid_shape=self._qid_shape)

def density_matrix_of(self, qubits: List['cirq.Qid'] = None) -> np.ndarray:
r"""Returns the density matrix of the state.
Expand Down Expand Up @@ -139,7 +137,7 @@ def density_matrix_of(self, qubits: List['cirq.Qid'] = None) -> np.ndarray:
corresponding to the state.
"""
return qis.density_matrix_from_state_vector(
self.state_vector(copy=False),
self.state_vector(),
[self.qubit_map[q] for q in qubits] if qubits is not None else None,
qid_shape=self._qid_shape,
)
Expand All @@ -164,7 +162,7 @@ def bloch_vector_of(self, qubit: 'cirq.Qid') -> np.ndarray:
corresponding to the state.
"""
return qis.bloch_vector_from_state_vector(
self.state_vector(copy=False), self.qubit_map[qubit], qid_shape=self._qid_shape
self.state_vector(), self.qubit_map[qubit], qid_shape=self._qid_shape
)


Expand Down
17 changes: 9 additions & 8 deletions cirq-core/cirq/sim/state_vector_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import numpy as np

from cirq import _compat, ops, value, qis
from cirq import ops, value, qis
from cirq._compat import proper_repr
from cirq.sim import simulator, state_vector, simulator_base

Expand Down Expand Up @@ -130,7 +130,7 @@ def final_state_vector(self) -> np.ndarray:
self._final_state_vector = tensor
return self._final_state_vector

def state_vector(self, copy: bool = None) -> np.ndarray:
def state_vector(self, copy: bool = False) -> np.ndarray:
"""Return the state vector at the end of the computation.
The state is returned in the computational basis with these basis
Expand All @@ -155,13 +155,14 @@ def state_vector(self, copy: bool = None) -> np.ndarray:
| 5 | 1 | 0 | 1 |
| 6 | 1 | 1 | 0 |
| 7 | 1 | 1 | 1 |
Args:
copy: If True, the returned state vector will be a copy of that
stored by the object. This is potentially expensive for large
state vectors, but prevents mutation of the object state, e.g. for
operating on intermediate states of a circuit.
Defaults to False.
"""
if copy is None:
_compat._warn_or_error(
"Starting in v0.16, state_vector will not copy the state by default. "
"Explicitly set copy=True to copy the state."
)
copy = True
return self.final_state_vector.copy() if copy else self.final_state_vector

def _value_equality_values_(self):
Expand Down
Loading

0 comments on commit b6ce68d

Please sign in to comment.