Skip to content

Roll back the default on unitary to np.complex64, change default for final_state_vector #5636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 29, 2022
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
21 changes: 7 additions & 14 deletions cirq-core/cirq/circuits/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -1003,7 +1003,7 @@ def unitary(
qubit_order: 'cirq.QubitOrderOrList' = ops.QubitOrder.DEFAULT,
qubits_that_should_be_present: Iterable['cirq.Qid'] = (),
ignore_terminal_measurements: bool = True,
dtype: Type[np.complexfloating] = np.complex64,
dtype: Type[np.complexfloating] = np.complex128,
) -> np.ndarray:
"""Converts the circuit into a unitary matrix, if possible.

Expand All @@ -1018,10 +1018,11 @@ def unitary(
ignore_terminal_measurements: When set, measurements at the end of
the circuit are ignored instead of causing the method to
fail.
dtype: The numpy dtype for the returned unitary. `dtype` must be
a complex np.dtype, unless all operations in the circuit have
unitary matrices with exclusively real coefficients
(e.g. an H + TOFFOLI circuit).
dtype: The numpy dtype for the returned unitary. Defaults to
np.complex128. Specifying np.complex64 will run faster at the
cost of precision. `dtype` must be a complex np.dtype, unless
all operations in the circuit have unitary matrices with
exclusively real coefficients (e.g. an H + TOFFOLI circuit).

Returns:
A (possibly gigantic) 2d numpy array corresponding to a matrix
Expand Down Expand Up @@ -1093,7 +1094,7 @@ def final_state_vector(
qubit_order: 'cirq.QubitOrderOrList' = ops.QubitOrder.DEFAULT,
qubits_that_should_be_present: Iterable['cirq.Qid'] = (),
ignore_terminal_measurements: Optional[bool] = None,
dtype: Optional[Type[np.complexfloating]] = None,
dtype: Type[np.complexfloating] = np.complex128,
param_resolver: 'cirq.ParamResolverOrSimilarType' = None,
seed: 'cirq.RANDOM_STATE_OR_SEED_LIKE' = None,
) -> np.ndarray:
Expand Down Expand Up @@ -1143,14 +1144,6 @@ def final_state_vector(
)
ignore_terminal_measurements = True

if dtype is None:
_compat._warn_or_error(
'`dtype` will default to np.complex64 in v0.16. '
'To use the previous default, please explicitly include '
'`dtype=np.complex128` when calling this method.'
)
dtype = np.complex128

from cirq.sim.mux import final_state_vector

program = Circuit(cirq.I(q) for q in qubits_that_should_be_present) + self
Expand Down
56 changes: 0 additions & 56 deletions cirq-core/cirq/circuits/circuit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2957,62 +2957,6 @@ def test_final_state_vector(circuit_cls):
)


@pytest.mark.parametrize('circuit_cls', [cirq.Circuit, cirq.FrozenCircuit])
def test_final_state_vector_deprecated_params(circuit_cls):
a = cirq.NamedQubit('a')
b = cirq.NamedQubit('b')
# Extra qubits.
cirq.testing.assert_allclose_up_to_global_phase(
circuit_cls().final_state_vector(ignore_terminal_measurements=False, dtype=np.complex128),
np.array([1]),
atol=1e-8,
)
with cirq.testing.assert_deprecated("Inject identity operators", deadline="v0.16"):
cirq.testing.assert_allclose_up_to_global_phase(
circuit_cls().final_state_vector(
qubits_that_should_be_present=[a],
ignore_terminal_measurements=False,
dtype=np.complex128,
),
np.array([1, 0]),
atol=1e-8,
)
with cirq.testing.assert_deprecated("Inject identity operators", deadline="v0.16"):
cirq.testing.assert_allclose_up_to_global_phase(
circuit_cls(cirq.X(b)).final_state_vector(
qubits_that_should_be_present=[a],
ignore_terminal_measurements=False,
dtype=np.complex128,
),
np.array([0, 1, 0, 0]),
atol=1e-8,
)

with cirq.testing.assert_deprecated("To drop terminal measurements", deadline="v0.16"):
cirq.testing.assert_allclose_up_to_global_phase(
circuit_cls(cirq.X(a), cirq.measure(a)).final_state_vector(dtype=np.complex128),
np.array([0, 1]),
atol=1e-8,
)

with cirq.testing.assert_deprecated("`dtype` will default to np.complex64", deadline="v0.16"):
cirq.testing.assert_allclose_up_to_global_phase(
circuit_cls(cirq.X(a)).final_state_vector(ignore_terminal_measurements=False),
np.array([0, 1]),
atol=1e-8,
)

# Non-keyword args.
with cirq.testing.assert_deprecated("Only use keyword arguments", deadline="v0.16"):
cirq.testing.assert_allclose_up_to_global_phase(
circuit_cls(cirq.X(a) ** 0.5).final_state_vector(
1, ignore_terminal_measurements=False, dtype=np.complex128
),
np.array([1, 1j]) * np.sqrt(0.5),
atol=1e-8,
)


@pytest.mark.parametrize('circuit_cls', [cirq.Circuit, cirq.FrozenCircuit])
@pytest.mark.parametrize('resolve_fn', [cirq.resolve_parameters, cirq.resolve_parameters_once])
def test_is_parameterized(circuit_cls, resolve_fn):
Expand Down
4 changes: 1 addition & 3 deletions cirq-core/cirq/contrib/acquaintance/executor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,7 @@ def test_executor_random(
circuit.append(cca.LinearPermutationGate(num_qubits, permutation)(*qubits))
actual_unitary = circuit.unitary()

np.testing.assert_allclose(
actual=actual_unitary, desired=expected_unitary, verbose=True, atol=1e-6
)
np.testing.assert_allclose(actual=actual_unitary, desired=expected_unitary, verbose=True)


def test_acquaintance_operation():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,4 @@ def test_optimize_large_circuit():

c_opt = clifford_optimized_circuit(c_orig)

cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-7)
12 changes: 6 additions & 6 deletions cirq-core/cirq/contrib/paulistring/optimize_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,17 @@ def test_optimize():

c_opt = optimized_circuit(c_orig)

cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-7)

# TODO(#5546) Fix '[Z]^1' (should be 'Z')
cirq.testing.assert_has_diagram(
c_opt,
"""
0: ───X^0.5────────────@──────────────────────────────────────────────
0: ───X^0.5────────────@────────────────────────────────────────
1: ───@───────X^-0.5───@───@────────────────@───Z^-0.5────────────────
1: ───@───────X^-0.5───@───@────────────────@───Z^-0.5──────────
│ │ │
2: ───@────────────────────@───[X]^(-7/8)───@───[X]^-0.25───[Z]^(1)───
2: ───@────────────────────@───[X]^(-7/8)───@───[X]^-0.25───Z───
""",
)

Expand All @@ -69,7 +69,7 @@ def test_optimize_large_circuit():

c_opt = optimized_circuit(c_orig)

cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-7)

assert (
sum(
Expand All @@ -87,7 +87,7 @@ def test_repeat_limit():

c_opt = optimized_circuit(c_orig, repeat=1)

cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-7)

assert (
sum(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ def test_pauli_string_dag_from_circuit():
c_left_reordered = c_left_dag.to_circuit()

cirq.testing.assert_allclose_up_to_global_phase(
c_left.unitary(), c_left_reordered.unitary(), atol=1e-6
c_left.unitary(), c_left_reordered.unitary(), atol=1e-7
)
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_optimize():
c_opt = pauli_string_optimized_circuit(c_orig)

cirq.testing.assert_allclose_up_to_global_phase(
c_orig.unitary(), c_expected.unitary(), atol=1e-6
c_orig.unitary(), c_expected.unitary(), atol=1e-7
)

cirq.testing.assert_has_diagram(
Expand Down Expand Up @@ -81,4 +81,4 @@ def test_optimize_large_circuit():

c_opt = pauli_string_optimized_circuit(c_orig)

cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(c_orig.unitary(), c_opt.unitary(), atol=1e-7)
2 changes: 1 addition & 1 deletion cirq-core/cirq/contrib/paulistring/separate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def test_toffoli_separate():
c_left, c_right = convert_and_separate_circuit(circuit)

cirq.testing.assert_allclose_up_to_global_phase(
circuit.unitary(), (c_left + c_right).unitary(), atol=1e-6
circuit.unitary(), (c_left + c_right).unitary(), atol=1e-7
)

assert all(isinstance(op, cirq.PauliStringPhasor) for op in c_left.all_operations())
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/contrib/qasm_import/qasm_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,6 @@ def test_consistency_with_qasm_output_and_qiskit():
circuit2 = circuit_from_qasm(qasm)

cirq_unitary = cirq.unitary(circuit2)
ct.assert_allclose_up_to_global_phase(cirq_unitary, cirq.unitary(circuit1), atol=1e-6)
ct.assert_allclose_up_to_global_phase(cirq_unitary, cirq.unitary(circuit1), atol=1e-8)

cq.assert_qiskit_parsed_qasm_consistent_with_unitary(qasm, cirq_unitary)
2 changes: 1 addition & 1 deletion cirq-core/cirq/ion/convert_to_ion_gates_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_convert_to_ion_gates():
atol=1e-4,
)
assert cirq.allclose_up_to_global_phase(
cirq.unitary(cirq.Circuit(rcnot)), cirq.unitary(OtherCNOT().on(q0, q1)), atol=1e-6
cirq.unitary(cirq.Circuit(rcnot)), cirq.unitary(OtherCNOT().on(q0, q1)), atol=1e-7
)


Expand Down
14 changes: 3 additions & 11 deletions cirq-core/cirq/linalg/decompositions.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,8 +549,6 @@ def scatter_plot_normalized_kak_interaction_coefficients(
*,
include_frame: bool = True,
ax: Optional[plt.Axes] = None,
rtol: float = 1e-5,
atol: float = 1e-6,
**kwargs,
):
r"""Plots the interaction coefficients of many two-qubit operations.
Expand Down Expand Up @@ -592,12 +590,6 @@ def scatter_plot_normalized_kak_interaction_coefficients(
wireframe. Defaults to `True`.
ax: A matplotlib 3d axes object to plot into. If not specified, a new
figure is created, plotted, and shown.
rtol: Per-matrix-entry relative tolerance on equality used if the
kak decomposition is calculated from the `interactions`.
atol: Per-matrix-entry absolute tolerance on equality used if the
kak decomposition is calculated from the `interaction`s. T
This determines how close $k_x$ must be to π/4 to guarantee
$k_z$ ≥ 0. Must be non-negative.

**kwargs: Arguments forwarded into the call to `scatter` that plots the
points. Working arguments include color `c='blue'`, scale `s=2`,
Expand Down Expand Up @@ -671,7 +663,7 @@ def coord_transform(
else:
interactions_extracted = [interactions]

points = kak_vector(interactions_extracted, rtol=rtol, atol=atol) * 4 / np.pi
points = kak_vector(interactions_extracted) * 4 / np.pi

ax.scatter(*coord_transform(points), **kwargs)
ax.set_xlim(0, +1)
Expand Down Expand Up @@ -819,7 +811,7 @@ def kak_decomposition(
],
*,
rtol: float = 1e-5,
atol: float = 1e-6,
atol: float = 1e-8,
check_preconditions: bool = True,
) -> KakDecomposition:
"""Decomposes a 2-qubit unitary into 1-qubit ops and XX/YY/ZZ interactions.
Expand Down Expand Up @@ -955,7 +947,7 @@ def kak_vector(

if check_preconditions:
actual = np.einsum('...ba,...bc', unitary.conj(), unitary) - np.eye(4)
if not np.allclose(np.zeros_like(actual), actual, rtol=rtol, atol=atol):
if not np.allclose(actual, np.zeros_like(actual), rtol=rtol, atol=atol):
raise ValueError(
'Input must correspond to a 4x4 unitary matrix or tensor of '
f'unitary matrices. Received input:\n{unitary}'
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/linalg/decompositions_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -782,4 +782,4 @@ def test_extract_right_diag(u):
assert cirq.num_cnots_required(u) == 3
diag = cirq.linalg.extract_right_diag(u)
assert cirq.is_diagonal(diag)
assert cirq.num_cnots_required(u @ diag, atol=1e-6) == 2
assert cirq.num_cnots_required(u @ diag) == 2
8 changes: 4 additions & 4 deletions cirq-core/cirq/ops/diagonal_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_decomposition_unitary(n):

# For large qubit counts, the decomposed circuit is rather large, so we lose a lot of
# precision.
np.testing.assert_allclose(decomposed_f, expected_f, atol=5e-6)
np.testing.assert_allclose(decomposed_f, expected_f)


@pytest.mark.parametrize('n', [1, 2, 3, 4])
Expand All @@ -65,7 +65,7 @@ def test_diagonal_exponent(n):
sqrt_diagonal_gate = diagonal_gate**0.5

expected_angles = [prime / 2 for prime in diagonal_angles]
np.testing.assert_allclose(expected_angles, sqrt_diagonal_gate._diag_angles_radians, atol=1e-6)
np.testing.assert_allclose(expected_angles, sqrt_diagonal_gate._diag_angles_radians, atol=1e-8)

assert cirq.pow(cirq.DiagonalGate(diagonal_angles), "test", None) is None

Expand All @@ -80,7 +80,7 @@ def test_decomposition_diagonal_exponent(n):
expected_f = [np.exp(1j * angle / 2) for angle in diagonal_angles]
decomposed_f = cirq.unitary(decomposed_circ).diagonal()

np.testing.assert_allclose(decomposed_f, expected_f, atol=1e-6)
np.testing.assert_allclose(decomposed_f, expected_f)


@pytest.mark.parametrize('n', [1, 2, 3, 4])
Expand All @@ -99,7 +99,7 @@ def test_decomposition_with_parameterization(n):
resolved_op = cirq.resolve_parameters(parameterized_op, resolver)
resolved_circuit = cirq.resolve_parameters(decomposed_circuit, resolver)
np.testing.assert_allclose(
cirq.unitary(resolved_op), cirq.unitary(resolved_circuit), atol=1e-6
cirq.unitary(resolved_op), cirq.unitary(resolved_circuit), atol=1e-8
)


Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/ops/fsim_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def test_phased_fsim_from_fsim_rz(theta, phi, rz_angles_before, rz_angles_after)
cirq.rz(rz_angles_after[0]).on(q0),
cirq.rz(rz_angles_after[1]).on(q1),
)
cirq.testing.assert_allclose_up_to_global_phase(cirq.unitary(f), cirq.unitary(c), atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(cirq.unitary(f), cirq.unitary(c), atol=1e-8)


@pytest.mark.parametrize(
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/ops/matrix_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def __init__(
name: str = None,
qid_shape: Optional[Iterable[int]] = None,
unitary_check_rtol: float = 1e-5,
unitary_check_atol: float = 1e-6,
unitary_check_atol: float = 1e-8,
) -> None:
"""Initializes a matrix gate.

Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/ops/parallel_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def test_unitary(gate, num_copies, qubits):
step = gate.num_qubits()
qubit_lists = [qubits[i * step : (i + 1) * step] for i in range(num_copies)]
np.testing.assert_allclose(
cirq.unitary(g), cirq.unitary(cirq.Circuit(gate.on_each(qubit_lists))), atol=1e-6
cirq.unitary(g), cirq.unitary(cirq.Circuit(gate.on_each(qubit_lists))), atol=1e-8
)


Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/ops/phased_x_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def test_parameterize(resolve_fn, global_shift):
np.testing.assert_allclose(
cirq.unitary(resolved_gate(q)),
cirq.unitary(resolve_fn(parameterized_decomposed_circuit, resolver)),
atol=1e-6,
atol=1e-8,
)

unparameterized_gate = cirq.PhasedXPowGate(
Expand Down
1 change: 0 additions & 1 deletion cirq-core/cirq/ops/two_qubit_diagonal_gate_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ def test_parameterized_decompose():
np.testing.assert_allclose(
cirq.unitary(cirq.resolve_parameters(parameterized_op, resolver)),
cirq.unitary(cirq.resolve_parameters(decomposed_circuit, resolver)),
atol=1e-6,
)


Expand Down
4 changes: 2 additions & 2 deletions cirq-core/cirq/optimizers/merge_interactions_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def assert_optimization_not_broken(circuit):
cirq.MergeInteractions().optimize_circuit(circuit)
u_after = circuit.unitary()

cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-8)


def test_clears_paired_cnot():
Expand Down Expand Up @@ -254,4 +254,4 @@ def clean_up(operations):

u_before = c_orig.unitary()
u_after = circuit[1:-1].unitary()
cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-6)
cirq.testing.assert_allclose_up_to_global_phase(u_before, u_after, atol=1e-8)
3 changes: 1 addition & 2 deletions cirq-core/cirq/testing/circuit_compare_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,12 @@ def test_measuring_qubits():
'circuit', [cirq.testing.random_circuit(cirq.LineQubit.range(2), 4, 0.5) for _ in range(5)]
)
def test_random_same_matrix(circuit):
circuit_copy = circuit.copy()
a, b = cirq.LineQubit.range(2)
same = cirq.Circuit(
cirq.MatrixGate(circuit.unitary(qubits_that_should_be_present=[a, b])).on(a, b)
)

cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(circuit_copy, same)
cirq.testing.assert_circuits_with_terminal_measurements_are_equivalent(circuit, same)

mutable_circuit = circuit.copy()
mutable_circuit.append(cirq.measure(a))
Expand Down
4 changes: 2 additions & 2 deletions cirq-core/cirq/testing/consistent_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ def assert_decompose_is_consistent_with_unitary(val: Any, ignoring_global_phase:
actual = circuits.Circuit(dec).unitary(qubit_order=qubits)

if ignoring_global_phase:
lin_alg_utils.assert_allclose_up_to_global_phase(actual, expected, atol=1e-6)
lin_alg_utils.assert_allclose_up_to_global_phase(actual, expected, atol=1e-8)
else:
# coverage: ignore
np.testing.assert_allclose(actual, expected, atol=1e-6)
np.testing.assert_allclose(actual, expected, atol=1e-8)


def _known_gate_with_no_decomposition(val: Any):
Expand Down
Loading