Skip to content

Commit 123cbf8

Browse files
authored
QVM - deprecate default gate_times_ns in noise_properties_from_calibration (#7399)
* `noise_properties_from_calibration` - show deprecation warning when called without `gate_times_ns` and introduce literal "legacy" as an alias for the old gate times default. * `load_device_noise_properties` - update to use legacy gate times for old virtual processors and make tests more comprehensive. Related to b/395705720
1 parent e27d883 commit 123cbf8

File tree

4 files changed

+99
-23
lines changed

4 files changed

+99
-23
lines changed

cirq-google/cirq_google/engine/calibration_to_noise_properties.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
calibration using the following pipeline:
2020
2121
>>> cal = cirq_google.engine.load_median_device_calibration("rainbow")
22-
>>> noise_props = cirq_google.engine.noise_properties_from_calibration(cal)
22+
>>> noise_props = cirq_google.engine.noise_properties_from_calibration(
23+
... cal, gate_times_ns="legacy")
2324
>>> noise_model = cirq_google.NoiseModelFromGoogleNoiseProperties(noise_props)
2425
>>> simulator = cirq.Simulator(noise=noise_model)
2526
>>> circuit = cirq.Circuit(cirq.X(cirq.GridQubit(5, 2)))
@@ -28,9 +29,9 @@
2829

2930
from __future__ import annotations
3031

31-
from typing import TYPE_CHECKING
32+
from typing import Literal, TYPE_CHECKING
3233

33-
from cirq import ops
34+
from cirq import _compat, ops
3435
from cirq.devices import noise_utils
3536
from cirq_google import engine, ops as cg_ops
3637
from cirq_google.devices import google_noise_properties
@@ -91,8 +92,9 @@ def _unpack_2q_from_calibration(
9192

9293
def noise_properties_from_calibration(
9394
calibration: engine.Calibration,
95+
*,
96+
gate_times_ns: dict[type[cirq.Gate], float] | Literal['legacy'] | None = None,
9497
zphase_data: util.ZPhaseDataType | None = None,
95-
gate_times_ns: dict[type[cirq.Gate], float] | None = None,
9698
) -> google_noise_properties.GoogleNoiseProperties:
9799
"""Translates between `cirq_google.Calibration` and NoiseProperties.
98100
@@ -103,26 +105,42 @@ def noise_properties_from_calibration(
103105
To manually override noise properties, call `with_params` on the output:
104106
105107
>>> cal = cirq_google.engine.load_median_device_calibration("rainbow")
108+
>>> noise_props = cirq_google.engine.noise_properties_from_calibration(
109+
... cal, gate_times_ns="legacy")
106110
>>> # noise_props with all gate durations set to 37ns.
107-
>>> noise_props = cirq_google.engine.noise_properties_from_calibration(cal).with_params(
108-
... gate_times_ns=37)
111+
>>> noise_props_37ns = noise_props.with_params(gate_times_ns=37)
109112
110113
See `cirq_google.GoogleNoiseProperties` for details.
111114
112115
Args:
113116
calibration: a Calibration object with hardware metrics.
117+
gate_times_ns: Map of gate durations in nanoseconds or "legacy"
118+
to use the Sycamore gate times listed in `known_devices.py`.
119+
Note this argument has changed from optional to mandatory and
120+
the "legacy" value was added as an alias for the old default.
114121
zphase_data: Optional data for Z phases not captured by Calibration -
115122
specifically, zeta and gamma. These values require Floquet
116123
calibration and can be provided here if available.
117-
gate_times_ns: Map of gate durations in nanoseconds. If not provided,
118-
defaults to the Sycamore gate times listed in `known_devices.py`.
119124
120125
Returns:
121126
A `cirq_google.GoogleNoiseProperties` which represents the error
122127
present in the given Calibration object.
123128
"""
124129
if gate_times_ns is None:
130+
_compat._warn_or_error(
131+
'Function noise_properties_from_calibration was called without the '
132+
'gate_times_ns argument.\n'
133+
'This argument will become mandatory in cirq_google v1.7.\n'
134+
'To continue using the old gate times default, please pass the "legacy" value.'
135+
)
136+
gate_times_ns = DEFAULT_GATE_NS
137+
elif gate_times_ns == 'legacy':
125138
gate_times_ns = DEFAULT_GATE_NS
139+
if not isinstance(gate_times_ns, dict):
140+
raise TypeError(
141+
f'gate_times_ns must be a dictionary or the "legacy" string. '
142+
f'Got {gate_times_ns} instead.'
143+
)
126144

127145
# Unpack all values from Calibration object
128146
# 1. Extract T1 for all qubits

cirq-google/cirq_google/engine/calibration_to_noise_properties_test.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,13 @@ def test_noise_properties_from_calibration():
237237
syc_angles,
238238
iswap_angles,
239239
)
240-
prop = cirq_google.noise_properties_from_calibration(calibration)
240+
with cirq.testing.assert_deprecated(
241+
"noise_properties_from_calibration was called without the gate_times_ns", deadline="v1.7"
242+
):
243+
prop = cirq_google.noise_properties_from_calibration(calibration)
244+
assert prop == cirq_google.noise_properties_from_calibration(
245+
calibration, gate_times_ns="legacy"
246+
)
241247

242248
for i, q in enumerate(qubits):
243249
assert np.isclose(
@@ -273,6 +279,9 @@ def test_noise_properties_from_calibration():
273279
assert prop.fsim_errors[OpIdentifier(gate, *qs)] == values[i]
274280
assert prop.fsim_errors[OpIdentifier(gate, *qs[::-1])] == values[i]
275281

282+
with pytest.raises(TypeError, match='gate_times_ns must be a dictionary'):
283+
_ = cirq_google.noise_properties_from_calibration(calibration, gate_times_ns=37)
284+
276285

277286
def test_zphase_data():
278287
qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0)]
@@ -317,7 +326,9 @@ def test_zphase_data():
317326
},
318327
}
319328

320-
prop = cirq_google.noise_properties_from_calibration(calibration, zphase_data)
329+
prop = cirq_google.noise_properties_from_calibration(
330+
calibration, gate_times_ns="legacy", zphase_data=zphase_data
331+
)
321332
for i, qs in enumerate(qubit_pairs):
322333
for gate, values in [
323334
(cirq_google.SycamoreGate, syc_angles),
@@ -418,4 +429,4 @@ def test_incomplete_calibration():
418429
# Create NoiseProperties object from Calibration
419430
calibration = cirq_google.Calibration(_CALIBRATION_DATA)
420431
with pytest.raises(ValueError, match='Keys specified for T1 and Tphi are not identical.'):
421-
_ = cirq_google.noise_properties_from_calibration(calibration)
432+
_ = cirq_google.noise_properties_from_calibration(calibration, gate_times_ns="legacy")

cirq-google/cirq_google/engine/virtual_engine_factory.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@
2727
from cirq_google.api import v2
2828
from cirq_google.devices import grid_device
2929
from cirq_google.devices.google_noise_properties import NoiseModelFromGoogleNoiseProperties
30-
from cirq_google.engine import calibration, engine_validator, simulated_local_processor, util
31-
from cirq_google.engine.calibration_to_noise_properties import noise_properties_from_calibration
30+
from cirq_google.engine import (
31+
calibration,
32+
calibration_to_noise_properties,
33+
engine_validator,
34+
simulated_local_processor,
35+
util,
36+
)
3237
from cirq_google.engine.simulated_local_engine import SimulatedLocalEngine
3338
from cirq_google.engine.simulated_local_processor import SimulatedLocalProcessor
3439
from cirq_google.ops import fsim_gate_family
@@ -124,9 +129,12 @@ def load_device_noise_properties(processor_id: str) -> cirq_google.GoogleNoisePr
124129
device = create_device_from_processor_id(processor_id)
125130
calibration = load_median_device_calibration(processor_id)
126131
zphase_data = load_sample_device_zphase(processor_id) if processor_id in ZPHASE_DATA else None
127-
gate_times_ns = extract_gate_times_ns_from_device(device)
128-
return noise_properties_from_calibration(
129-
calibration=calibration, zphase_data=zphase_data, gate_times_ns=gate_times_ns
132+
if processor_id in ('rainbow', 'weber'):
133+
gate_times_ns = calibration_to_noise_properties.DEFAULT_GATE_NS
134+
else:
135+
gate_times_ns = extract_gate_times_ns_from_device(device)
136+
return calibration_to_noise_properties.noise_properties_from_calibration(
137+
calibration=calibration, gate_times_ns=gate_times_ns, zphase_data=zphase_data
130138
)
131139

132140

@@ -444,10 +452,7 @@ def create_default_noisy_quantum_virtual_machine(
444452

445453
calibration = load_median_device_calibration(processor_id)
446454
device = create_device_from_processor_id(processor_id)
447-
gate_times_ns: dict[type[cirq.Gate], float] | None = None
448-
if processor_id == "willow_pink":
449-
gate_times_ns = extract_gate_times_ns_from_device(device)
450-
noise_properties = noise_properties_from_calibration(calibration, gate_times_ns=gate_times_ns)
455+
noise_properties = load_device_noise_properties(processor_id)
451456
noise_model = NoiseModelFromGoogleNoiseProperties(noise_properties)
452457
simulator = simulator_class(noise=noise_model, **kwargs) # type: ignore
453458

cirq-google/cirq_google/engine/virtual_engine_factory_test.py

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,19 @@
2525
import cirq_google.api.v2 as v2
2626
import cirq_google.engine.virtual_engine_factory as factory
2727

28+
# copy of cirq_google.engine.calibration_to_noise_properties.DEFAULT_GATE_NS
29+
OLD_QVM_DEFAULT_GATE_NS: dict[type[cirq.Gate], float] = {
30+
cirq.ZPowGate: 25.0,
31+
cirq.MeasurementGate: 4000.0,
32+
cirq.ResetChannel: 250.0,
33+
cirq.PhasedXZGate: 25.0,
34+
cirq.FSimGate: 32.0,
35+
cirq.ISwapPowGate: 32.0,
36+
cirq.CZPowGate: 32.0,
37+
cg.ops.SycamoreGate: 12.0,
38+
# ops.WaitGate is a special case.
39+
}
40+
2841

2942
def _test_processor(processor: cg.engine.abstract_processor.AbstractProcessor) -> None:
3043
"""Tests an engine instance with some standard commands.
@@ -62,15 +75,42 @@ def test_create_from_device() -> None:
6275
_test_processor(engine.get_processor('sycamore'))
6376

6477

65-
def test_load_device_noise_properties() -> None:
78+
def test_load_device_noise_properties_of_rainbow() -> None:
6679
noise_properties = factory.load_device_noise_properties("rainbow")
6780
assert noise_properties.readout_errors[cirq.GridQubit(9, 4)] == [0.0124, 0.0464]
68-
assert noise_properties.gate_times_ns[cirq.PhasedXZGate] == 25
81+
assert noise_properties.gate_times_ns == OLD_QVM_DEFAULT_GATE_NS
6982
op_id = cirq.OpIdentifier(cirq.ISwapPowGate, cirq.GridQubit(3, 2), cirq.GridQubit(4, 2))
7083
assert noise_properties.fsim_errors[op_id].zeta == -0.004952147720840733
7184
assert noise_properties.fsim_errors[op_id].gamma == -0.04094895320428251
7285

7386

87+
def test_load_device_noise_properties_of_weber() -> None:
88+
noise_properties = factory.load_device_noise_properties("weber")
89+
assert noise_properties.readout_errors[cirq.GridQubit(9, 4)] == [0.0086, 0.0634]
90+
assert noise_properties.gate_times_ns == OLD_QVM_DEFAULT_GATE_NS
91+
op_id = cirq.OpIdentifier(cirq.ISwapPowGate, cirq.GridQubit(3, 2), cirq.GridQubit(4, 2))
92+
assert noise_properties.fsim_errors[op_id].zeta == -0.10303422893651185
93+
assert noise_properties.fsim_errors[op_id].gamma == -0.0032040209641905903
94+
95+
96+
def test_load_device_noise_properties_of_willow_pink() -> None:
97+
noise_properties = factory.load_device_noise_properties("willow_pink")
98+
assert noise_properties.readout_errors[cirq.GridQubit(6, 5)] == [
99+
0.0016608771929824222,
100+
0.01175789473684208,
101+
]
102+
assert noise_properties.gate_times_ns[cirq.CZPowGate] == 42
103+
assert noise_properties.gate_times_ns[cirq.MeasurementGate] == 600
104+
assert noise_properties.gate_times_ns[cirq.PhasedXZGate] == 25
105+
assert noise_properties.gate_times_ns[cirq.ResetChannel] == 160
106+
op_id = cirq.OpIdentifier(cirq.CZPowGate, cirq.GridQubit(4, 6), cirq.GridQubit(5, 6))
107+
assert noise_properties.gate_pauli_errors[op_id] == 0.005621218474436904
108+
assert noise_properties.fsim_errors[op_id].theta == 0.04183530427211678
109+
assert noise_properties.fsim_errors[op_id].phi == 0.008106226272121209
110+
assert noise_properties.fsim_errors[op_id].zeta == 0
111+
assert noise_properties.fsim_errors[op_id].gamma == 0
112+
113+
74114
def test_median_rainbow_device() -> None:
75115
q0, q1 = cirq.GridQubit.rect(1, 2, 5, 3)
76116
cal = factory.load_median_device_calibration('rainbow')
@@ -241,7 +281,9 @@ def test_create_default_noisy_quantum_virtual_machine(
241281
assert device_specification is not None
242282
assert device_specification == expected
243283
with mock.patch.object(
244-
factory, "extract_gate_times_ns_from_device", return_value=None
284+
factory,
285+
"extract_gate_times_ns_from_device",
286+
wraps=factory.extract_gate_times_ns_from_device,
245287
) as mocked_extract:
246288
_ = factory.create_default_noisy_quantum_virtual_machine(
247289
processor_id=processor_id, simulator_class=cirq.Simulator

0 commit comments

Comments
 (0)