Skip to content

Commit eebcfa0

Browse files
authored
Use list for GoogleNoiseProperties.readout_errors values (#7392)
Problem: The values in `SuperconductingQubitsNoiseProperties.readout_errors` and `GoogleNoiseProperties.readout_errors` dictionaries are declared as `np.ndarray` in docstrings, but annotated as`list[float]` in the code, and can be set to either type. JSON serialization fails when assigned a list. Solution: Always convert to `list[float]` following the type annotation. This fixes serialization failure for `GoogleNoiseProperties` objects created with `noise_properties_from_calibration`.
1 parent 123cbf8 commit eebcfa0

3 files changed

Lines changed: 59 additions & 7 deletions

File tree

cirq-core/cirq/devices/superconducting_qubits_noise_properties.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class SuperconductingQubitsNoiseProperties(devices.NoiseProperties, abc.ABC):
3838
quantum hardware. Used with t(1|phi)_ns to specify thermal noise.
3939
t1_ns: dict[cirq.Qid, float] of qubits to their T_1 time, in ns.
4040
tphi_ns: dict[cirq.Qid, float] of qubits to their T_phi time, in ns.
41-
readout_errors: dict[cirq.Qid, np.ndarray] of qubits to their readout
41+
readout_errors: dict[cirq.Qid, list[float]] of qubits to their readout
4242
errors in matrix form: [P(read |1> from |0>), P(read |0> from |1>)].
4343
Used to prepend amplitude damping errors to measurements.
4444
gate_pauli_errors: dict of noise_utils.OpIdentifiers (a gate and the qubits it

cirq-google/cirq_google/devices/google_noise_properties.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class GoogleNoiseProperties(devices.SuperconductingQubitsNoiseProperties):
5454
thermal noise.
5555
t1_ns: dict[`cirq.Qid`, float] of qubits to their T_1 time, in ns.
5656
tphi_ns: dict[`cirq.Qid`, float] of qubits to their T_phi time, in ns.
57-
readout_errors: dict[`cirq.Qid`, np.ndarray] of qubits to their readout
57+
readout_errors: dict[`cirq.Qid`, list[float]] of qubits to their readout
5858
errors in matrix form: [P(read |1> from |0>), P(read |0> from |1>)].
5959
Used to prepend amplitude damping errors to measurements.
6060
gate_pauli_errors: dict of `noise_utils.OpIdentifiers` (a gate and the
@@ -129,7 +129,7 @@ def with_params(
129129
t1_ns: float or dict[`cirq.Qid`, float].
130130
tphi_ns: float or dict[`cirq.Qid`, float].
131131
readout_errors: Sequence or dict[`cirq.Qid`, Sequence]. Converted to
132-
np.ndarray if not provided in that format.
132+
list[float] if not provided in that format.
133133
gate_pauli_errors: float or dict[`cirq.OpIdentifier`, float].
134134
Dict key can also be type[`cirq.Gate`]; this will apply the given
135135
error to all placements of that gate that appear in the original
@@ -150,11 +150,11 @@ def with_params(
150150
if readout_errors is not None:
151151
if isinstance(readout_errors, dict):
152152
replace_args['readout_errors'] = _with_values(
153-
self.readout_errors, {k: np.array(v) for k, v in readout_errors.items()}
153+
self.readout_errors, {k: list(v) for k, v in readout_errors.items()}
154154
)
155155
else:
156156
replace_args['readout_errors'] = _with_values(
157-
self.readout_errors, np.array(readout_errors)
157+
self.readout_errors, list(readout_errors)
158158
)
159159
if gate_pauli_errors is not None:
160160
if isinstance(gate_pauli_errors, dict):
@@ -274,7 +274,7 @@ def _json_dict_(self):
274274
'gate_times_ns': tuple(storage_gate_times.items()),
275275
't1_ns': tuple(self.t1_ns.items()),
276276
'tphi_ns': tuple(self.tphi_ns.items()),
277-
'readout_errors': tuple((k, v.tolist()) for k, v in self.readout_errors.items()),
277+
'readout_errors': tuple(self.readout_errors.items()),
278278
'gate_pauli_errors': tuple(self.gate_pauli_errors.items()),
279279
'fsim_errors': tuple(self.fsim_errors.items()),
280280
'validate': self.validate,
@@ -298,7 +298,7 @@ def _from_json_dict_(
298298
gate_times_ns=gate_type_times,
299299
t1_ns=dict(t1_ns),
300300
tphi_ns=dict(tphi_ns),
301-
readout_errors={k: np.array(v) for k, v in readout_errors},
301+
readout_errors=dict(readout_errors),
302302
gate_pauli_errors=dict(gate_pauli_errors),
303303
fsim_errors=dict(fsim_errors),
304304
validate=validate,

cirq-google/cirq_google/engine/calibration_to_noise_properties_test.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,58 @@ def test_zphase_data():
340340
assert prop.fsim_errors[OpIdentifier(gate, *qs[::-1])] == values[i]
341341

342342

343+
def test_json_serde_works():
344+
qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0)]
345+
pauli_error = [0.001, 0.002, 0.003]
346+
incoherent_error = [0.0001, 0.0002, 0.0003]
347+
p00_error = [0.004, 0.005, 0.006]
348+
p11_error = [0.007, 0.008, 0.009]
349+
t1_micros = [10, 20, 30]
350+
syc_pauli = [0.01, 0.02]
351+
iswap_pauli = [0.03, 0.04]
352+
syc_angles = [
353+
cirq.PhasedFSimGate(theta=0.011, phi=-0.021, zeta=-0.031, gamma=0.043),
354+
cirq.PhasedFSimGate(theta=-0.012, phi=0.022, zeta=0.032, gamma=-0.044),
355+
]
356+
iswap_angles = [
357+
cirq.PhasedFSimGate(theta=-0.013, phi=0.023, zeta=0.031, gamma=-0.043),
358+
cirq.PhasedFSimGate(theta=0.014, phi=-0.024, zeta=-0.032, gamma=0.044),
359+
]
360+
361+
# Create NoiseProperties object from Calibration
362+
calibration = get_mock_calibration(
363+
pauli_error,
364+
incoherent_error,
365+
p00_error,
366+
p11_error,
367+
t1_micros,
368+
syc_pauli,
369+
iswap_pauli,
370+
syc_angles,
371+
iswap_angles,
372+
)
373+
374+
qubit_pairs = [(qubits[0], qubits[1]), (qubits[0], qubits[2])]
375+
zphase_data = {
376+
"syc": {
377+
"zeta": {qubit_pairs[0]: syc_angles[0].zeta, qubit_pairs[1]: syc_angles[1].zeta},
378+
"gamma": {qubit_pairs[0]: syc_angles[0].gamma, qubit_pairs[1]: syc_angles[1].gamma},
379+
},
380+
"sqrt_iswap": {
381+
"zeta": {qubit_pairs[0]: iswap_angles[0].zeta, qubit_pairs[1]: iswap_angles[1].zeta},
382+
"gamma": {qubit_pairs[0]: iswap_angles[0].gamma, qubit_pairs[1]: iswap_angles[1].gamma},
383+
},
384+
}
385+
386+
prop = cirq_google.noise_properties_from_calibration(
387+
calibration, gate_times_ns='legacy', zphase_data=zphase_data
388+
)
389+
390+
json_text = cirq.to_json(prop)
391+
prop1 = cirq.read_json(json_text=json_text)
392+
assert prop1 == prop
393+
394+
343395
def test_incomplete_calibration():
344396
pauli_error = [0.001, 0.002, 0.003]
345397
p00_error = [0.004, 0.005, 0.006]

0 commit comments

Comments
 (0)