Skip to content
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

Fix #6706 – Update sources for compatibility with NumPy 2 #6724

Merged
merged 30 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
844a345
Explicitly convert NumPy ndarray of np.bool to Python bool
mhucka Sep 10, 2024
216e926
Avoid a construct deprecated in NumPy 2
mhucka Sep 10, 2024
6ab7b00
Avoid implicitly converting 2-D arrays of single value to scalars
mhucka Sep 10, 2024
6613ca4
Add pytest option --warn-numpy-data-promotion
mhucka Sep 11, 2024
eb98361
Update requirements to use NumPy 2
mhucka Sep 15, 2024
6011e60
Address NumPy 2 data type promotion warnings
mhucka Sep 15, 2024
ef5e04f
NumPy 2 data promotion + minor refactoring
mhucka Sep 15, 2024
53bfd27
Adjust dtypes per mypy warnings
mhucka Sep 16, 2024
12fd3de
Fix Rigetti check for Aspen family device kind (#6734)
pavoljuhas Sep 18, 2024
d83b1c2
Adjustment for mypy: change 2 places where types are declared
mhucka Sep 18, 2024
0f52831
Avoid getting NumPy dtypes in printed (string) scalar values
mhucka Sep 11, 2024
9f4b761
Don't force Numpy 2; maintain compatibility with 1
mhucka Sep 18, 2024
5caaebc
Bump serve-static and express in /cirq-web/cirq_ts (#6731)
dependabot[bot] Sep 18, 2024
8a4ab93
Silence pytest warnings about asyncio fixture scope
mhucka Sep 19, 2024
101df32
chore: merge branch
mhucka Sep 19, 2024
a64a044
Fix wrong number of arguments to reshape()
mhucka Sep 19, 2024
d474edb
Fix formatting issues flagged by check/format-incremental
mhucka Sep 19, 2024
0daa139
Add coverage tests for changes in format_real()
mhucka Sep 19, 2024
e5d45e5
Merge branch 'quantumlib:main' into mhucka-numpy2-migration
mhucka Sep 20, 2024
6f8b8a7
Remove import of kahypar after all
mhucka Sep 20, 2024
ef92604
Simplify proper_repr
pavoljuhas Sep 20, 2024
0a2fe35
No need to use bool from builtins
pavoljuhas Sep 20, 2024
881fecf
Restore numpy casting to the state as in main
pavoljuhas Sep 20, 2024
58dac7b
Fix failing test_run_repetitions_terminal_measurement_stochastic
pavoljuhas Sep 20, 2024
7aedd86
Simplify CircuitDiagramInfoArgs.format_radians
pavoljuhas Sep 20, 2024
de6078e
`.item()` already collapses dimensions and converts to int
pavoljuhas Sep 20, 2024
dc5d44e
Exclude cirq_rigetti from json_serialization_test when using numpy-2
pavoljuhas Sep 20, 2024
98cde11
pytest - apply warn_numpy_data_promotion option before test collection
pavoljuhas Sep 20, 2024
628329d
Add temporary requirements file for NumPy-2.0
pavoljuhas Sep 20, 2024
cab0fb2
Adjust requirements for cirq-core
pavoljuhas Sep 20, 2024
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
3 changes: 3 additions & 0 deletions cirq-core/cirq/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ def _print(self, expr, **kwargs):
if hasattr(value, "__qualname__"):
return f"{value.__module__}.{value.__qualname__}"

if isinstance(value, np.number):
return str(value)

return repr(value)


Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/contrib/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ ply>=3.6
pylatex~=1.4

# quimb
quimb~=1.7
quimb>=1.8
opt_einsum
2 changes: 2 additions & 0 deletions cirq-core/cirq/protocols/circuit_diagram_info_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,8 @@ def format_radians(self, radians: Union[sympy.Basic, int, float]) -> str:
if self.precision is not None and not isinstance(radians, sympy.Basic):
quantity = self.format_real(radians / np.pi)
return quantity + unit
if isinstance(radians, np.number):
return str(radians)
return repr(radians)

def copy(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ def test_format_real():
assert args.format_real(sympy.Symbol('t')) == 't'
assert args.format_real(sympy.Symbol('t') * 2 + 1) == '2*t + 1'

assert args.format_real(np.float64(1.1)) == '1.1'
assert args.format_real(np.int32(1)) == '1'

args.precision = None
assert args.format_real(1) == '1'
assert args.format_real(1.1) == '1.1'
Expand Down Expand Up @@ -252,6 +255,7 @@ def test_format_radians_without_precision():
assert args.format_radians(-np.pi) == '-pi'
assert args.format_radians(1.1) == '1.1'
assert args.format_radians(1.234567) == '1.234567'
assert args.format_radians(np.float32(1.234567)) == '1.234567'
assert args.format_radians(1 / 7) == repr(1 / 7)
assert args.format_radians(sympy.Symbol('t')) == 't'
assert args.format_radians(sympy.Symbol('t') * 2 + 1) == '2*t + 1'
Expand All @@ -261,6 +265,7 @@ def test_format_radians_without_precision():
assert args.format_radians(-np.pi) == '-π'
assert args.format_radians(1.1) == '1.1'
assert args.format_radians(1.234567) == '1.234567'
assert args.format_radians(np.float32(1.234567)) == '1.234567'
assert args.format_radians(1 / 7) == repr(1 / 7)
assert args.format_radians(sympy.Symbol('t')) == 't'
assert args.format_radians(sympy.Symbol('t') * 2 + 1) == '2*t + 1'
Expand Down
7 changes: 7 additions & 0 deletions cirq-core/cirq/protocols/json_serialization_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,13 @@ class _ModuleDeprecation:
'non_existent_should_be_fine': None,
}

# TODO(#6706) remove after cirq_rigetti supports NumPy 2.0
if np.__version__.startswith("2."): # pragma: no cover
warnings.warn(
"json_serialization_test - ignoring cirq_rigetti due to incompatibility with NumPy 2.0"
)
del TESTED_MODULES["cirq_rigetti"]


def _get_testspecs_for_modules() -> List[ModuleJsonTestSpec]:
modules = []
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/qis/states.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ def quantum_state(
dtype = DEFAULT_COMPLEX_DTYPE
data = one_hot(index=state, shape=(dim,), dtype=dtype)
else:
data = np.array(state, copy=False)
data = np.asarray(state)
if qid_shape is None:
qid_shape = infer_qid_shape(state)
if data.ndim == 1 and data.dtype.kind != 'c':
Expand Down
2 changes: 1 addition & 1 deletion cirq-core/cirq/sim/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -912,7 +912,7 @@ def __repr__(self) -> str:
def __str__(self) -> str:
def bitstring(vals):
separator = ' ' if np.max(vals) >= 10 else ''
return separator.join(str(int(v)) for v in vals)
return separator.join(str(v.item()) for v in vals)

results = sorted([(key, bitstring(val)) for key, val in self.measurements.items()])
if not results:
Expand Down
8 changes: 4 additions & 4 deletions cirq-core/cirq/sim/sparse_simulator_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def test_run_repetitions_terminal_measurement_stochastic():
q = cirq.LineQubit(0)
c = cirq.Circuit(cirq.H(q), cirq.measure(q, key='q'))
results = cirq.Simulator().run(c, repetitions=10000)
assert 1000 <= sum(v[0] for v in results.measurements['q']) < 9000
assert 1000 <= np.count_nonzero(results.measurements['q']) < 9000


@pytest.mark.parametrize('dtype', [np.complex64, np.complex128])
Expand Down Expand Up @@ -255,7 +255,7 @@ def test_run_mixture(dtype: Type[np.complexfloating], split: bool):
simulator = cirq.Simulator(dtype=dtype, split_untangled_states=split)
circuit = cirq.Circuit(cirq.bit_flip(0.5)(q0), cirq.measure(q0))
result = simulator.run(circuit, repetitions=100)
assert 20 < sum(result.measurements['q(0)'])[0] < 80
assert 20 < np.count_nonzero(result.measurements['q(0)']) < 80


@pytest.mark.parametrize('dtype', [np.complex64, np.complex128])
Expand All @@ -265,8 +265,8 @@ def test_run_mixture_with_gates(dtype: Type[np.complexfloating], split: bool):
simulator = cirq.Simulator(dtype=dtype, split_untangled_states=split, seed=23)
circuit = cirq.Circuit(cirq.H(q0), cirq.phase_flip(0.5)(q0), cirq.H(q0), cirq.measure(q0))
result = simulator.run(circuit, repetitions=100)
assert sum(result.measurements['q(0)'])[0] < 80
assert sum(result.measurements['q(0)'])[0] > 20
assert np.count_nonzero(result.measurements['q(0)']) < 80
assert np.count_nonzero(result.measurements['q(0)']) > 20


@pytest.mark.parametrize('dtype', [np.complex64, np.complex128])
Expand Down
4 changes: 2 additions & 2 deletions cirq-core/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ attrs>=21.3.0
duet>=0.2.8
matplotlib~=3.0
networkx>=2.4
numpy~=1.22
numpy>=1.24
pandas
sortedcontainers~=2.0
scipy~=1.0
scipy~=1.8
sympy
typing_extensions>=4.2
tqdm
6 changes: 3 additions & 3 deletions cirq-google/cirq_google/serialization/arg_func_langs.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,9 +474,9 @@ def clifford_tableau_arg_to_proto(
msg = v2.program_pb2.CliffordTableau() if out is None else out
msg.num_qubits = value.n
msg.initial_state = value.initial_state
msg.xs.extend(value.xs.flatten())
msg.rs.extend(value.rs.flatten())
msg.zs.extend(value.zs.flatten())
msg.xs.extend(map(bool, value.xs.flatten()))
msg.rs.extend(map(bool, value.rs.flatten()))
msg.zs.extend(map(bool, value.zs.flatten()))
return msg


Expand Down
14 changes: 14 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.

import pytest
import numpy as np


def pytest_addoption(parser):
Expand All @@ -25,6 +26,19 @@
parser.addoption(
"--enable-slow-tests", action="store_true", default=False, help="run slow tests"
)
parser.addoption(
"--warn-numpy-data-promotion",
action="store_true",
default=False,
help="enable NumPy 2 data type promotion warnings",
)


def pytest_configure(config):
# If requested, globally enable verbose NumPy 2 warnings about data type
# promotion. See https://numpy.org/doc/2.0/numpy_2_0_migration_guide.html.
if config.option.warn_numpy_data_promotion:
np._set_promotion_state("weak_and_warn")

Check warning on line 41 in conftest.py

View check run for this annotation

Codecov / codecov/patch

conftest.py#L41

Added line #L41 was not covered by tests


def pytest_collection_modifyitems(config, items):
Expand Down
17 changes: 17 additions & 0 deletions dev_tools/requirements/dev-np2.env.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This file describes a development environment for cirq with NumPy-2
# It skips cirq_rigetti which has dependencies incompatible with NumPy-2.
#
# TODO(#6706) remove this file after cirq_rigetti supports NumPy 2.0

# dev.env.txt expanded without cirq-rigetti ----------------------------------

-r ../../cirq-aqt/requirements.txt
-r ../../cirq-core/requirements.txt
-r ../../cirq-google/requirements.txt
-r ../../cirq-core/cirq/contrib/requirements.txt

-r deps/dev-tools.txt

# own rules ------------------------------------------------------------------

numpy>=2
6 changes: 3 additions & 3 deletions examples/bb84.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def main(num_qubits=8):
repetitions = 1

result = cirq.Simulator().run(program=circuit, repetitions=repetitions)
result_bitstring = bitstring([int(result.measurements[str(q)]) for q in qubits])
result_bitstring = bitstring([result.measurements[str(q)].item() for q in qubits])

# Take only qubits where bases match
obtained_key = ''.join(
Expand Down Expand Up @@ -158,14 +158,14 @@ def main(num_qubits=8):
# Run simulations.
repetitions = 1
result = cirq.Simulator().run(program=alice_eve_circuit, repetitions=repetitions)
eve_state = [int(result.measurements[str(q)]) for q in qubits]
eve_state = [result.measurements[str(q)].item() for q in qubits]

eve_bob_circuit = make_bb84_circ(num_qubits, eve_basis, bob_basis, eve_state)

# Run simulations.
repetitions = 1
result = cirq.Simulator().run(program=eve_bob_circuit, repetitions=repetitions)
result_bitstring = bitstring([int(result.measurements[str(q)]) for q in qubits])
result_bitstring = bitstring([result.measurements[str(q)].item() for q in qubits])

# Take only qubits where bases match
obtained_key = ''.join(
Expand Down