Skip to content

Commit 9ee5533

Browse files
Updated calls to np.prod to use dtype=np.int64. (quantumlib#4363)
Fixes quantumlib#4346 . Liberally upgraded a lot of the calls to `np.prod` to use ~~`dtype=int`~~ `dtype=np.int64` that didn't already have it. I opted to keep the calls to `np.prod` instead of doing something like `reduce(mul, <stuff>)` because using basic numpy, we can only really comfortably create and index arrays with sizes up to the max value of a C type `long`. ~~Confirmed `dtype=int` will give us that:~~ ~~https://numpy.org/doc/stable/reference/arrays.dtypes.html#specifying-and-constructing-data-types~~ ~~https://numpy.org/doc/stable/reference/arrays.scalars.html#numpy.int_~~
1 parent 7a09ae2 commit 9ee5533

23 files changed

+77
-59
lines changed

cirq/circuits/circuit.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ def unitary(
10001000

10011001
# Force qubits to have dimension at least 2 for backwards compatibility.
10021002
qid_shape = self.qid_shape(qubit_order=qs)
1003-
side_len = np.product(qid_shape, dtype=int)
1003+
side_len = np.prod(qid_shape, dtype=np.int64)
10041004

10051005
state = qis.eye_tensor(qid_shape, dtype=dtype)
10061006

@@ -1083,7 +1083,7 @@ def final_state_vector(
10831083

10841084
# Force qubits to have dimension at least 2 for backwards compatibility.
10851085
qid_shape = self.qid_shape(qubit_order=qs)
1086-
state_len = np.product(qid_shape, dtype=int)
1086+
state_len = np.prod(qid_shape, dtype=np.int64)
10871087

10881088
state = qis.to_valid_state_vector(initial_state, qid_shape=qid_shape, dtype=dtype).reshape(
10891089
qid_shape

cirq/experiments/fidelity_estimation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ def xeb_fidelity(
185185
ValueError: Circuit is inconsistent with qubit order or one of the
186186
bitstrings is inconsistent with the number of qubits.
187187
"""
188-
dim = np.product(circuit.qid_shape())
188+
dim = np.prod(circuit.qid_shape(), dtype=np.int64)
189189

190190
if isinstance(bitstrings, tuple):
191191
bitstrings = list(bitstrings)

cirq/experiments/fidelity_estimation_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def sample_noisy_bitstrings(
2525
circuit: cirq.Circuit, qubit_order: Sequence[cirq.Qid], depolarization: float, repetitions: int
2626
) -> np.ndarray:
2727
assert 0 <= depolarization <= 1
28-
dim = np.product(circuit.qid_shape())
28+
dim = np.prod(circuit.qid_shape(), dtype=np.int64)
2929
n_incoherent = int(depolarization * repetitions)
3030
n_coherent = repetitions - n_incoherent
3131
incoherent_samples = np.random.randint(dim, size=n_incoherent)

cirq/interop/quirk/cells/input_rotation_cells.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def _apply_unitary_(self, args: 'cirq.ApplyUnitaryArgs'):
162162

163163
target_axes = transposed_args.axes[: len(self.base_operation.qubits)]
164164
control_axes = transposed_args.axes[len(self.base_operation.qubits) :]
165-
control_max = np.product([q.dimension for q in self.register]).item()
165+
control_max = np.prod([q.dimension for q in self.register], dtype=np.int64).item()
166166

167167
for i in range(control_max):
168168
operation = self.base_operation ** (self.exponent_sign * i / control_max)

cirq/ops/arithmetic_operation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,12 @@ def _apply_unitary_(self, args: 'cirq.ApplyUnitaryArgs'):
192192
shape.append(1)
193193
overflow_sizes.append(register + 1)
194194
else:
195-
size = int(np.product([q.dimension for q in register]).item())
195+
size = int(np.prod([q.dimension for q in register], dtype=np.int64).item())
196196
shape.append(size)
197197
input_ranges.append(range(size))
198198
overflow_sizes.append(size)
199199

200-
leftover = args.target_tensor.size // np.product(shape).item()
200+
leftover = args.target_tensor.size // np.prod(shape, dtype=np.int64).item()
201201
new_shape = (*shape, leftover)
202202

203203
transposed_args = args.with_axes_transposed_to_start()

cirq/ops/controlled_operation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def _extend_matrix(self, sub_matrix: np.ndarray) -> np.ndarray:
137137
for control_vals in itertools.product(*self.control_values):
138138
active = (*(v for v in control_vals), *(slice(None),) * sub_n) * 2
139139
tensor[active] = sub_tensor
140-
return tensor.reshape((np.prod(qid_shape, dtype=int).item(),) * 2)
140+
return tensor.reshape((np.prod(qid_shape, dtype=np.int64).item(),) * 2)
141141

142142
def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
143143
sub_matrix = protocols.unitary(self.sub_operation, None)

cirq/ops/fourier_transform.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _apply_unitary_(self, args: 'cirq.ApplyUnitaryArgs'):
117117
if isinstance(self.exponent, sympy.Basic):
118118
return NotImplemented
119119

120-
n = int(np.product([args.target_tensor.shape[k] for k in args.axes]))
120+
n = int(np.prod([args.target_tensor.shape[k] for k in args.axes], dtype=np.int64))
121121
for i in range(n):
122122
p = 1j ** (4 * i / n * self.exponent)
123123
args.target_tensor[args.subspace_index(big_endian_bits_int=i)] *= p

cirq/ops/identity.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def _has_unitary_(self) -> bool:
7777
return True
7878

7979
def _unitary_(self) -> np.ndarray:
80-
return np.identity(np.prod(self._qid_shape, dtype=int).item())
80+
return np.identity(np.prod(self._qid_shape, dtype=np.int64).item())
8181

8282
def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs') -> Optional[np.ndarray]:
8383
return args.target_tensor

cirq/ops/matrix_gates.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def __init__(
6161
self._matrix = matrix
6262
self._qid_shape = tuple(qid_shape)
6363
self._name = name
64-
m = int(np.prod(self._qid_shape))
64+
m = int(np.prod(self._qid_shape, dtype=np.int64))
6565
if self._matrix.shape != (m, m):
6666
raise ValueError(
6767
'Wrong matrix shape for qid_shape.\n'

cirq/ops/measurement_gate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def _measurement_key_(self):
130130
return self.key
131131

132132
def _kraus_(self):
133-
size = np.prod(self._qid_shape, dtype=int)
133+
size = np.prod(self._qid_shape, dtype=np.int64)
134134

135135
def delta(i):
136136
result = np.zeros((size, size))

cirq/ops/projector.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def matrix(self, projector_qids: Optional[Iterable[raw_types.Qid]] = None) -> cs
6868
for qid in projector_qids
6969
]
7070

71-
total_d = np.prod([qid.dimension for qid in projector_qids])
71+
total_d = np.prod([qid.dimension for qid in projector_qids], dtype=np.int64)
7272

7373
ones_idx = []
7474
for idx in itertools.product(*idx_to_keep):

cirq/ops/random_gate_channel.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ def _mixture_(self):
9595
if mixture is None:
9696
return None
9797

98-
do_nothing = np.eye(np.product(protocols.qid_shape(self.sub_gate)), dtype=np.float64)
98+
do_nothing = np.eye(
99+
np.prod(protocols.qid_shape(self.sub_gate), dtype=np.int64), dtype=np.float64
100+
)
99101
result = [(p * float(self.probability), m) for p, m in mixture]
100102
result.append((1 - float(self.probability), do_nothing))
101103
return result
@@ -108,7 +110,9 @@ def _kraus_(self):
108110
if channel is None:
109111
return NotImplemented
110112

111-
do_nothing = np.eye(np.product(protocols.qid_shape(self.sub_gate)), dtype=np.float64)
113+
do_nothing = np.eye(
114+
np.prod(protocols.qid_shape(self.sub_gate), dtype=np.int64), dtype=np.float64
115+
)
112116
result = [e * np.sqrt(self.probability) for e in channel]
113117
result.append(np.sqrt(1 - float(self.probability)) * do_nothing)
114118
return result

cirq/ops/random_gate_channel_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ def num_qubits(self) -> int:
160160
def assert_channel_sums_to_identity(val):
161161
m = cirq.kraus(val)
162162
s = sum(np.conj(e.T) @ e for e in m)
163-
np.testing.assert_allclose(s, np.eye(np.product(cirq.qid_shape(val))), atol=1e-8)
163+
np.testing.assert_allclose(s, np.eye(np.prod(cirq.qid_shape(val), dtype=np.int64)), atol=1e-8)
164164

165165

166166
def test_channel():

cirq/ops/raw_types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ def _commutes_(
586586

587587
# Don't create gigantic matrices.
588588
shape = protocols.qid_shape_protocol.qid_shape(circuit12)
589-
if np.product(shape) > 2 ** 10:
589+
if np.prod(shape, dtype=np.int64) > 2 ** 10:
590590
return NotImplemented # coverage: ignore
591591

592592
m12 = protocols.unitary_protocol.unitary(circuit12, default=None)

cirq/protocols/unitary_protocol.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ def _strat_unitary_from_apply_unitary(val: Any) -> Optional[np.ndarray]:
178178

179179
if result is NotImplemented or result is None:
180180
return result
181-
state_len = np.prod(val_qid_shape, dtype=int)
181+
state_len = np.prod(val_qid_shape, dtype=np.int64)
182182
return result.reshape((state_len, state_len))
183183

184184

@@ -199,5 +199,5 @@ def _strat_unitary_from_decompose(val: Any) -> Optional[np.ndarray]:
199199
# Package result.
200200
if result is None:
201201
return None
202-
state_len = np.prod(val_qid_shape, dtype=int)
202+
state_len = np.prod(val_qid_shape, dtype=np.int64)
203203
return result.reshape((state_len, state_len))

cirq/qis/channels.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121

2222
def kraus_to_choi(kraus_operators: Sequence[np.ndarray]) -> np.ndarray:
2323
"""Returns the unique Choi matrix corresponding to a Kraus representation of a channel."""
24-
d = np.prod(kraus_operators[0].shape)
24+
d = np.prod(kraus_operators[0].shape, dtype=np.int64)
2525
c = np.zeros((d, d), dtype=np.complex128)
2626
for k in kraus_operators:
2727
v = np.reshape(k, d)

cirq/qis/measures.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def _validate_int_state(state: int, qid_shape: Optional[Tuple[int, ...]]) -> Non
4444
f'but {state} was given.'
4545
)
4646
if qid_shape is not None:
47-
dim = np.prod(qid_shape)
47+
dim = np.prod(qid_shape, dtype=np.int64)
4848
if state >= dim:
4949
raise ValueError(
5050
'Invalid state for given qid shape: '
@@ -155,10 +155,10 @@ def _numpy_arrays_to_state_vectors_or_density_matrices(
155155
) -> Tuple[np.ndarray, np.ndarray]:
156156
if state1.ndim > 2 or (state1.ndim == 2 and state1.shape[0] != state1.shape[1]):
157157
# State tensor, convert to state vector
158-
state1 = np.reshape(state1, (np.prod(state1.shape).item(),))
158+
state1 = np.reshape(state1, (np.prod(state1.shape, dtype=np.int64).item(),))
159159
if state2.ndim > 2 or (state2.ndim == 2 and state2.shape[0] != state2.shape[1]):
160160
# State tensor, convert to state vector
161-
state2 = np.reshape(state2, (np.prod(state2.shape).item(),))
161+
state2 = np.reshape(state2, (np.prod(state2.shape, dtype=np.int64).item(),))
162162
if state1.ndim == 2 and state2.ndim == 2:
163163
# Must be square matrices
164164
if state1.shape == state2.shape:
@@ -171,32 +171,44 @@ def _numpy_arrays_to_state_vectors_or_density_matrices(
171171
)
172172
if state1.shape == qid_shape:
173173
# State tensors, convert to state vectors
174-
state1 = np.reshape(state1, (np.prod(qid_shape).item(),))
175-
state2 = np.reshape(state2, (np.prod(qid_shape).item(),))
174+
state1 = np.reshape(state1, (np.prod(qid_shape, dtype=np.int64).item(),))
175+
state2 = np.reshape(state2, (np.prod(qid_shape, dtype=np.int64).item(),))
176176
elif state1.shape[0] < state2.shape[0]:
177177
# state1 is state tensor and state2 is density matrix.
178178
# Convert state1 to state vector
179-
state1 = np.reshape(state1, (np.prod(state1.shape).item(),))
179+
state1 = np.reshape(state1, (np.prod(state1.shape, dtype=np.int64).item(),))
180180
else: # state1.shape[0] > state2.shape[0]
181181
# state2 is state tensor and state1 is density matrix.
182182
# Convert state2 to state vector
183-
state2 = np.reshape(state2, (np.prod(state2.shape).item(),))
184-
elif state1.ndim == 2 and state2.ndim < 2 and np.prod(state1.shape) == np.prod(state2.shape):
183+
state2 = np.reshape(state2, (np.prod(state2.shape, dtype=np.int64).item(),))
184+
elif (
185+
state1.ndim == 2
186+
and state2.ndim < 2
187+
and np.prod(state1.shape, dtype=np.int64) == np.prod(state2.shape, dtype=np.int64)
188+
):
185189
# state1 is state tensor, convert to state vector
186-
state1 = np.reshape(state1, (np.prod(state1.shape).item(),))
187-
elif state1.ndim < 2 and state2.ndim == 2 and np.prod(state1.shape) == np.prod(state2.shape):
190+
state1 = np.reshape(state1, (np.prod(state1.shape, dtype=np.int64).item(),))
191+
elif (
192+
state1.ndim < 2
193+
and state2.ndim == 2
194+
and np.prod(state1.shape, dtype=np.int64) == np.prod(state2.shape, dtype=np.int64)
195+
):
188196
# state2 is state tensor, convert to state vector
189-
state2 = np.reshape(state2, (np.prod(state2.shape).item(),))
197+
state2 = np.reshape(state2, (np.prod(state2.shape, dtype=np.int64).item(),))
190198

191199
if validate:
192-
dim1: int = state1.shape[0] if state1.ndim == 2 else np.prod(state1.shape).item()
193-
dim2: int = state2.shape[0] if state2.ndim == 2 else np.prod(state2.shape).item()
200+
dim1: int = (
201+
state1.shape[0] if state1.ndim == 2 else np.prod(state1.shape, dtype=np.int64).item()
202+
)
203+
dim2: int = (
204+
state2.shape[0] if state2.ndim == 2 else np.prod(state2.shape, dtype=np.int64).item()
205+
)
194206
if dim1 != dim2:
195207
raise ValueError('Mismatched dimensions in given states: ' f'{dim1} and {dim2}.')
196208
if qid_shape is None:
197209
qid_shape = (dim1,)
198210
else:
199-
expected_dim = np.prod(qid_shape)
211+
expected_dim = np.prod(qid_shape, dtype=np.int64)
200212
if dim1 != expected_dim:
201213
raise ValueError(
202214
'Invalid state dimension for given qid shape: '

cirq/qis/states.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def __init__(
9696
qid_shape = infer_qid_shape(data)
9797
self._data = data
9898
self._qid_shape = qid_shape
99-
self._dim = np.prod(self.qid_shape, dtype=int).item()
99+
self._dim = np.prod(self.qid_shape, dtype=np.int64).item()
100100
if validate:
101101
self.validate(dtype=dtype, atol=atol)
102102

@@ -263,7 +263,7 @@ def quantum_state(
263263
'Please specify the qid shape explicitly using '
264264
'the qid_shape argument.'
265265
)
266-
dim = np.prod(qid_shape, dtype=int).item()
266+
dim = np.prod(qid_shape, dtype=np.int64).item()
267267
if not 0 <= state < dim:
268268
raise ValueError(
269269
f'Computational basis state is out of range.\n'
@@ -281,7 +281,7 @@ def quantum_state(
281281
if qid_shape is None:
282282
qid_shape = infer_qid_shape(state)
283283
if data.ndim == 1 and data.dtype.kind != 'c':
284-
if len(qid_shape) == np.prod(qid_shape, dtype=int):
284+
if len(qid_shape) == np.prod(qid_shape, dtype=np.int64):
285285
raise ValueError(
286286
'Because len(qid_shape) == product(qid_shape), it is '
287287
'ambiguous whether the given state contains '
@@ -412,7 +412,7 @@ def infer_qid_shape(*states: 'cirq.QUANTUM_STATE_LIKE') -> Tuple[int, ...]:
412412
)
413413

414414
# check if the shape is compatible with the states specified as integers
415-
if integer_states and np.prod(qid_shape, dtype=int) <= max(integer_states):
415+
if integer_states and np.prod(qid_shape, dtype=np.int64) <= max(integer_states):
416416
raise ValueError(
417417
'Failed to infer the qid shape of the given states. '
418418
f'The given integer state {max(integer_states)} is too high for the '
@@ -566,7 +566,7 @@ def _intersection_explicit_with_unfactorized_qid_shapes(
566566
return {
567567
qid_shape
568568
for qid_shape in explicit_qid_shapes
569-
if np.prod(qid_shape, dtype=int) == unfactorized_total_dimension
569+
if np.prod(qid_shape, dtype=np.int64) == unfactorized_total_dimension
570570
}
571571

572572

@@ -698,7 +698,7 @@ def density_matrix_from_state_vector(
698698
sum_inds.tolist(),
699699
indices + sum_inds[indices].tolist(),
700700
)
701-
new_shape = np.prod([shape[i] for i in indices], dtype=int)
701+
new_shape = np.prod([shape[i] for i in indices], dtype=np.int64)
702702

703703
return rho.reshape((new_shape, new_shape))
704704

@@ -887,10 +887,10 @@ def validate_normalized_state_vector(
887887
dtype, state_vector.dtype
888888
)
889889
)
890-
if state_vector.size != np.prod(qid_shape, dtype=int):
890+
if state_vector.size != np.prod(qid_shape, dtype=np.int64):
891891
raise ValueError(
892892
'state_vector has incorrect size. Expected {} but was {}.'.format(
893-
np.prod(qid_shape, dtype=int), state_vector.size
893+
np.prod(qid_shape, dtype=np.int64), state_vector.size
894894
)
895895
)
896896
norm = np.sum(np.abs(state_vector) ** 2)
@@ -914,7 +914,7 @@ def validate_qid_shape(
914914
size = state_vector.size
915915
if qid_shape is None:
916916
qid_shape = (2,) * (size.bit_length() - 1)
917-
if size != np.prod(qid_shape, dtype=int):
917+
if size != np.prod(qid_shape, dtype=np.int64):
918918
raise ValueError(
919919
'state_vector.size ({}) is not a power of two or is not a product '
920920
'of the qid shape {!r}.'.format(size, qid_shape)
@@ -1006,7 +1006,7 @@ def validate_density_matrix(
10061006
f'Incorrect dtype for density matrix: Expected {dtype} '
10071007
f'but has dtype {density_matrix.dtype}.'
10081008
)
1009-
expected_shape = (np.prod(qid_shape, dtype=int),) * 2
1009+
expected_shape = (np.prod(qid_shape, dtype=np.int64),) * 2
10101010
if density_matrix.shape != expected_shape:
10111011
raise ValueError(
10121012
f'Incorrect shape for density matrix: Expected {expected_shape} '
@@ -1083,6 +1083,6 @@ def eye_tensor(half_shape: Tuple[int, ...], *, dtype: 'DTypeLike') -> np.ndarray
10831083
Returns:
10841084
The created numpy array with shape `half_shape + half_shape`.
10851085
"""
1086-
identity = np.eye(np.prod(half_shape, dtype=int).item(), dtype=dtype)
1086+
identity = np.eye(np.prod(half_shape, dtype=np.int64).item(), dtype=dtype)
10871087
identity.shape = half_shape * 2
10881088
return identity

cirq/sim/density_matrix_simulator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ def density_matrix(self, copy=True):
352352
state = self._merged_sim_state
353353
if state is not None:
354354
matrix = state.target_tensor
355-
size = int(np.sqrt(np.prod(matrix.shape, dtype=int)))
355+
size = int(np.sqrt(np.prod(matrix.shape, dtype=np.int64)))
356356
self._density_matrix = np.reshape(matrix, (size, size))
357357
return self._density_matrix.copy() if copy else self._density_matrix
358358

@@ -435,7 +435,7 @@ def __init__(
435435
super().__init__(
436436
params=params, measurements=measurements, final_simulator_state=final_simulator_state
437437
)
438-
size = np.prod(protocols.qid_shape(self), dtype=int)
438+
size = np.prod(protocols.qid_shape(self), dtype=np.int64)
439439
self.final_density_matrix = np.reshape(
440440
final_simulator_state.density_matrix.copy(), (size, size)
441441
)

0 commit comments

Comments
 (0)