def test_calibration_heatmap(): calibration = cg.Calibration(_CALIBRATION_DATA) heatmap = calibration.heatmap('t1') figure = mpl.figure.Figure() axes = figure.add_subplot(111) heatmap.plot(axes) assert axes.get_title() == 'T1' heatmap = calibration.heatmap('two_qubit_xeb') figure = mpl.figure.Figure() axes = figure.add_subplot(999) heatmap.plot(axes) assert axes.get_title() == 'Two Qubit Xeb' with pytest.raises(ValueError, match="one or two qubits.*multi_qubit"): multi_qubit_data = Merge( """metrics: [{ name: 'multi_qubit', targets: ['0_0', '0_1', '1_0'], values: [{double_val: 0.999}]}]""", v2.metrics_pb2.MetricsSnapshot(), ) cg.Calibration(multi_qubit_data).heatmap('multi_qubit') with pytest.raises(ValueError, match="single metric values.*multi_value"): multi_qubit_data = Merge( """metrics: [{ name: 'multi_value', targets: ['0_0'], values: [{double_val: 0.999}, {double_val: 0.001}]}]""", v2.metrics_pb2.MetricsSnapshot(), ) cg.Calibration(multi_qubit_data).heatmap('multi_value')
def test_to_proto(): calibration = cg.Calibration(_CALIBRATION_DATA) assert calibration == cg.Calibration(calibration.to_proto()) invalid_value = cg.Calibration( metrics={'metric': { (cirq.GridQubit(1, 1), ): [1.1, {}] }}) with pytest.raises(ValueError, match='Unsupported metric value'): invalid_value.to_proto()
def test_calibrations_with_string_key(): calibration = cg.Calibration(metrics={'metric1': {('alpha', ): [0.1]}}) expected_proto = Merge( """ metrics: [{ name: 'metric1' targets: ['alpha'] values: [{double_val: 0.1}] }] """, v2.metrics_pb2.MetricsSnapshot(), ) assert expected_proto == calibration.to_proto() assert calibration == cg.Calibration(expected_proto) assert calibration == cg.Calibration(calibration.to_proto())
def test_xeb_parse_result_failure(): gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0) request = XEBPhasedFSimCalibrationRequest( gate=gate, pairs=(), options=XEBPhasedFSimCalibrationOptions( fsim_options=XEBPhasedFSimCharacterizationOptions( characterize_theta=False, characterize_zeta=False, characterize_chi=False, characterize_gamma=False, characterize_phi=True, )), ) result = cirq_google.CalibrationResult( code=cirq_google.api.v2.calibration_pb2.ERROR_CALIBRATION_FAILED, error_message="Test message", token=None, valid_until=None, metrics=cirq_google.Calibration(), ) with pytest.raises(PhasedFSimCalibrationError, match='Test message'): request.parse_result(result)
def test_noise_from_metrics_unsupported(): # Attempt to generate a damping noise model (not yet supported). calibration = cirq_google.Calibration(_CALIBRATION_DATA) with pytest.raises(NotImplementedError, match='Gate damping is not yet supported.'): simple_noise_from_calibration_metrics(calibration=calibration, damping_noise=True)
def test_floquet_parse_result_bad_metric(): q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)] gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0) request = FloquetPhasedFSimCalibrationRequest( gate=gate, pairs=((q_00, q_01), (q_02, q_03)), options=FloquetPhasedFSimCalibrationOptions( characterize_theta=True, characterize_zeta=True, characterize_chi=False, characterize_gamma=False, characterize_phi=True, ), ) result = cirq_google.CalibrationResult( code=cirq_google.api.v2.calibration_pb2.SUCCESS, error_message=None, token=None, valid_until=None, metrics=cirq_google.Calibration( cirq_google.api.v2.metrics_pb2.MetricsSnapshot(metrics=[ cirq_google.api.v2.metrics_pb2.Metric( name='angles', targets=[ '1000gerbils', ], values=[ cirq_google.api.v2.metrics_pb2.Value(str_val='100_10'), ], ) ])), ) with pytest.raises(ValueError, match='Unknown metric name 1000gerbils'): _ = request.parse_result(result)
def test_calibration_timestamp_str(): calibration = cg.Calibration(_CALIBRATION_DATA) assert calibration.timestamp_str( tz=datetime.timezone.utc) == '2019-07-08 00:00:00.021021+00:00' assert (calibration.timestamp_str( tz=datetime.timezone(datetime.timedelta( hours=1))) == '2019-07-08 01:00:00.021021+01:00')
def test_calibration_plot_histograms(): calibration = cg.Calibration(_CALIBRATION_DATA) _, ax = mpl.pyplot.subplots(1, 1) calibration.plot_histograms(['t1', 'two_qubit_xeb'], ax, labels=['T1', 'XEB']) assert len(ax.get_lines()) == 4 with pytest.raises(ValueError, match="single metric values.*multi_value"): multi_qubit_data = Merge( """metrics: [{ name: 'multi_value', targets: ['0_0'], values: [{double_val: 0.999}, {double_val: 0.001}]}]""", v2.metrics_pb2.MetricsSnapshot(), ) cg.Calibration(multi_qubit_data).plot_histograms('multi_value')
def test_per_qubit_combined_noise_from_data(): # Generate the combined noise model from calibration data. calibration = cirq_google.Calibration(_CALIBRATION_DATA) noise_model = simple_noise_from_calibration_metrics( calibration=calibration, depol_noise=True, readout_error_noise=True, readout_decay_noise=True, ) # Create the circuit and apply the noise model. qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0)] program = cirq.Circuit( cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ]), ) noisy_circuit = cirq.Circuit(noise_model.noisy_moments(program, qubits)) # Insert channels explicitly to construct expected output. decay_prob = [ 1 - exp(-1 / 0.007), 1 - exp(-1 / 0.008), 1 - exp(-1 / 0.009) ] expected_program = cirq.Circuit( cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.DepolarizingChannel(DEPOL_001).on(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_002).on(qubits[1]), ]), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment([ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_003).on(qubits[2]), ]), cirq.Moment([ cirq.AmplitudeDampingChannel(decay_prob[i]).on(qubits[i]) for i in range(3) ]), cirq.Moment([ cirq.BitFlipChannel(0.004).on(qubits[0]), cirq.BitFlipChannel(0.005).on(qubits[1]), cirq.BitFlipChannel(0.006).on(qubits[2]), ]), cirq.Moment([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ]), ) assert_equivalent_op_tree(expected_program, noisy_circuit)
def test_calibrations(): now = datetime.datetime.now() future = int( (datetime.datetime.now() + datetime.timedelta(hours=2)).timestamp()) cal_proto1 = v2.metrics_pb2.MetricsSnapshot(timestamp_ms=10000) cal_proto2 = v2.metrics_pb2.MetricsSnapshot(timestamp_ms=20000) cal_proto3 = v2.metrics_pb2.MetricsSnapshot(timestamp_ms=future * 1000) cal1 = cirq_google.Calibration(cal_proto1) cal2 = cirq_google.Calibration(cal_proto2) cal3 = cirq_google.Calibration(cal_proto3) proc = SimulatedLocalProcessor(processor_id='test_proc', calibrations={ 10000: cal1, 20000: cal2, future: cal3 }) assert proc.get_calibration(10000) == cal1 assert proc.get_calibration(20000) == cal2 assert proc.get_calibration(future) == cal3 assert proc.get_current_calibration() == cal2 assert proc.list_calibrations(earliest_timestamp=5000, latest_timestamp=15000) == [cal1] assert proc.list_calibrations(earliest_timestamp=15000, latest_timestamp=25000) == [cal2] assert proc.list_calibrations(earliest_timestamp=now, latest_timestamp=now + datetime.timedelta(hours=2)) == [cal3] assert proc.list_calibrations(earliest_timestamp=datetime.date.today(), latest_timestamp=now + datetime.timedelta(hours=2)) == [cal3] cal_list = proc.list_calibrations(latest_timestamp=25000) assert len(cal_list) == 2 assert cal1 in cal_list assert cal2 in cal_list cal_list = proc.list_calibrations(earliest_timestamp=15000) assert len(cal_list) == 2 assert cal2 in cal_list assert cal3 in cal_list cal_list = proc.list_calibrations() assert len(cal_list) == 3 assert cal1 in cal_list assert cal2 in cal_list assert cal3 in cal_list
def test_get_calibration_from_job(): cal_proto = v2.metrics_pb2.MetricsSnapshot(timestamp_ms=10000) cal = cirq_google.Calibration(cal_proto) proc = SimulatedLocalProcessor(processor_id='test_proc', calibrations={10000: cal}) engine = SimulatedLocalEngine([proc]) job = engine.get_processor('test_proc').run_sweep(cirq.Circuit(), params={}, repetitions=100) assert job.get_processor() == proc assert job.get_calibration() == cal
def _load_xeb_results_textproto() -> cirq_google.CalibrationResult: with open(os.path.dirname(__file__) + '/test_data/xeb_results.textproto') as f: metrics_snapshot = text_format.Parse( f.read(), cirq_google.api.v2.metrics_pb2.MetricsSnapshot()) return cirq_google.CalibrationResult( code=cirq_google.api.v2.calibration_pb2.SUCCESS, error_message=None, token=None, valid_until=None, metrics=cirq_google.Calibration(metrics_snapshot), )
def test_xeb_parse_bad_fidelities(): metrics = cirq_google.Calibration( metrics={ 'initial_fidelities_depth_5': { ('layer_0', 'pair_0', cirq.GridQubit(0, 0), cirq.GridQubit( 1, 1)): [1.0], } }) df = _parse_xeb_fidelities_df(metrics, 'initial_fidelities') pd.testing.assert_frame_equal( df, pd.DataFrame({ 'cycle_depth': [5], 'layer_i': [0], 'pair_i': [0], 'fidelity': [1.0], 'pair': [(cirq.GridQubit(0, 0), cirq.GridQubit(1, 1))], }), ) metrics = cirq_google.Calibration( metrics={ 'initial_fidelities_depth_5x': { ('layer_0', 'pair_0', '0_0', '1_1'): [1.0], } }) df = _parse_xeb_fidelities_df(metrics, 'initial_fidelities') assert len(df) == 0, 'bad metric name ignored' metrics = cirq_google.Calibration( metrics={ 'initial_fidelities_depth_5': { ('bad_name_0', 'pair_0', '0_0', '1_1'): [1.0], } }) with pytest.raises(ValueError, match=r'Could not parse layer value for bad_name_0'): _parse_xeb_fidelities_df(metrics, 'initial_fidelities')
def test_per_qubit_depol_noise_from_data(): # Generate the depolarization noise model from calibration data. calibration = cirq_google.Calibration(_CALIBRATION_DATA) noise_model = simple_noise_from_calibration_metrics(calibration=calibration, depol_noise=True) # Create the circuit and apply the noise model. qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0)] program = cirq.Circuit( cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment([cirq.Z(qubits[1]).with_tags(cirq.VirtualTag())]), cirq.Moment( [ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ] ), ) noisy_circuit = cirq.Circuit(noise_model.noisy_moments(program, qubits)) # Insert channels explicitly to construct expected output. expected_program = cirq.Circuit( cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.DepolarizingChannel(DEPOL_001).on(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment( [ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_002).on(qubits[1]), ] ), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment( [ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_003).on(qubits[2]), ] ), cirq.Moment([cirq.Z(qubits[1]).with_tags(cirq.VirtualTag())]), cirq.Moment( [ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ] ), ) assert_equivalent_op_tree(expected_program, noisy_circuit)
def test_result_engine_calibration(_client): result = PhasedFSimCalibrationResult( parameters={}, gate=cirq.FSimGate(theta=np.pi / 4, phi=0.0), options=WITHOUT_CHI_FLOQUET_PHASED_FSIM_CHARACTERIZATION, project_id='project_id', program_id='program_id', job_id='job_id', ) test_calibration = cirq_google.Calibration() result.engine_job.get_calibration = lambda: test_calibration assert result.engine_calibration == test_calibration
def test_per_qubit_readout_error_from_data(): # Generate the readout error noise model from calibration data. calibration = cirq_google.Calibration(_CALIBRATION_DATA) noise_model = simple_noise_from_calibration_metrics( calibration=calibration, readout_error_noise=True ) # Create the circuit and apply the noise model. qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0)] program = cirq.Circuit( cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment( [ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ] ), ) noisy_circuit = cirq.Circuit(noise_model.noisy_moments(program, qubits)) # Insert channels explicitly to construct expected output. expected_program = cirq.Circuit( cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment( [ cirq.BitFlipChannel(0.004).on(qubits[0]), cirq.BitFlipChannel(0.005).on(qubits[1]), cirq.BitFlipChannel(0.006).on(qubits[2]), ] ), cirq.Moment( [ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ] ), ) assert_equivalent_op_tree(expected_program, noisy_circuit)
def test_calibration_metrics_dictionary(): calibration = cg.Calibration(_CALIBRATION_DATA) t1s = calibration['t1'] assert t1s == { (cirq.GridQubit(0, 0), ): [321], (cirq.GridQubit(0, 1), ): [911], (cirq.GridQubit(1, 0), ): [505], } assert len(calibration) == 3 assert 't1' in calibration assert 't2' not in calibration for qubits, values in t1s.items(): assert len(qubits) == 1 assert len(values) == 1 with pytest.raises(TypeError, match="was 1"): _ = calibration[1] with pytest.raises(KeyError, match='not-it'): _ = calibration['not-it']
def test_from_calibration_rb(): rb_pauli_1 = 0.001 rb_pauli_2 = 0.002 rb_pauli_3 = 0.003 _CALIBRATION_DATA_RB = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_0'], values: [{{ double_val: {rb_pauli_1} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_1'], values: [{{ double_val: {rb_pauli_2} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['1_0'], values: [{{ double_val: {rb_pauli_3} }}] }}] """, v2.metrics_pb2.MetricsSnapshot(), ) # Create NoiseProperties object from Calibration rb_calibration = cirq_google.Calibration(_CALIBRATION_DATA_RB) rb_noise_prop = noise_properties_from_calibration(rb_calibration) average_pauli_rb = np.mean([rb_pauli_1, rb_pauli_2, rb_pauli_3]) assert np.isclose(average_pauli_rb, rb_noise_prop.pauli_error)
def test_calibration_repr(): calibration = cg.Calibration(_CALIBRATION_DATA) cirq.testing.assert_equivalent_repr( calibration, setup_code="import cirq\nimport cirq_google")
def test_calibration_str(): calibration = cg.Calibration(_CALIBRATION_DATA) assert str(calibration ) == "Calibration(keys=['globalMetric', 't1', 'two_qubit_xeb'])"
def test_calibration_plot(): calibration = cg.Calibration(_CALIBRATION_DATA) _, axs = calibration.plot('two_qubit_xeb') assert axs[0].get_title() == 'Two Qubit Xeb' assert len(axs[1].get_lines()) == 2
def test_run_characterization(): q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)] gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0) request = FloquetPhasedFSimCalibrationRequest( gate=gate, pairs=((q_00, q_01), (q_02, q_03)), options=FloquetPhasedFSimCalibrationOptions( characterize_theta=True, characterize_zeta=True, characterize_chi=False, characterize_gamma=False, characterize_phi=True, ), ) result = cirq_google.CalibrationResult( code=cirq_google.api.v2.calibration_pb2.SUCCESS, error_message=None, token=None, valid_until=None, metrics=cirq_google.Calibration( cirq_google.api.v2.metrics_pb2.MetricsSnapshot(metrics=[ cirq_google.api.v2.metrics_pb2.Metric( name='angles', targets=[ '0_qubit_a', '0_qubit_b', '0_theta_est', '0_zeta_est', '0_phi_est', '1_qubit_a', '1_qubit_b', '1_theta_est', '1_zeta_est', '1_phi_est', ], values=[ cirq_google.api.v2.metrics_pb2.Value(str_val='0_0'), cirq_google.api.v2.metrics_pb2.Value(str_val='0_1'), cirq_google.api.v2.metrics_pb2.Value(double_val=0.1), cirq_google.api.v2.metrics_pb2.Value(double_val=0.2), cirq_google.api.v2.metrics_pb2.Value(double_val=0.3), cirq_google.api.v2.metrics_pb2.Value(str_val='0_2'), cirq_google.api.v2.metrics_pb2.Value(str_val='0_3'), cirq_google.api.v2.metrics_pb2.Value(double_val=0.4), cirq_google.api.v2.metrics_pb2.Value(double_val=0.5), cirq_google.api.v2.metrics_pb2.Value(double_val=0.6), ], ) ])), ) job = cirq_google.engine.EngineJob('', '', '', None) job._calibration_results = [result] engine = mock.MagicMock(spec=cirq_google.Engine) engine.run_calibration.return_value = job progress_calls = [] def progress(step: int, steps: int) -> None: progress_calls.append((step, steps)) actual = workflow.run_calibrations([request], engine, 'qproc', cirq_google.FSIM_GATESET, progress_func=progress) expected = [ PhasedFSimCalibrationResult( parameters={ (q_00, q_01): PhasedFSimCharacterization(theta=0.1, zeta=0.2, chi=None, gamma=None, phi=0.3), (q_02, q_03): PhasedFSimCharacterization(theta=0.4, zeta=0.5, chi=None, gamma=None, phi=0.6), }, gate=gate, options=FloquetPhasedFSimCalibrationOptions( characterize_theta=True, characterize_zeta=True, characterize_chi=False, characterize_gamma=False, characterize_phi=True, ), ) ] assert actual == expected assert progress_calls == [(1, 1)]
def test_noise_properties_from_calibration(): qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0)] pauli_error = [0.001, 0.002, 0.003] incoherent_error = [0.0001, 0.0002, 0.0003] p00_error = [0.004, 0.005, 0.006] p11_error = [0.007, 0.008, 0.009] t1_micros = [10, 20, 30] syc_pauli = [0.01, 0.02] iswap_pauli = [0.03, 0.04] syc_angles = [ cirq.PhasedFSimGate(theta=0.011, phi=-0.021), cirq.PhasedFSimGate(theta=-0.012, phi=0.022), ] iswap_angles = [ cirq.PhasedFSimGate(theta=-0.013, phi=0.023), cirq.PhasedFSimGate(theta=0.014, phi=-0.024), ] _CALIBRATION_DATA = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_0'], values: [{{ double_val: {pauli_error[0]} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_1'], values: [{{ double_val:{pauli_error[1]} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['1_0'], values: [{{ double_val:{pauli_error[2]} }}] }}, {{ name: 'single_qubit_rb_incoherent_error_per_gate', targets: ['0_0'], values: [{{ double_val: {incoherent_error[0]} }}] }}, {{ name: 'single_qubit_rb_incoherent_error_per_gate', targets: ['0_1'], values: [{{ double_val:{incoherent_error[1]} }}] }}, {{ name: 'single_qubit_rb_incoherent_error_per_gate', targets: ['1_0'], values: [{{ double_val:{incoherent_error[2]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_0'], values: [{{ double_val: {p00_error[0]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_1'], values: [{{ double_val: {p00_error[1]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['1_0'], values: [{{ double_val: {p00_error[2]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['0_0'], values: [{{ double_val: {p11_error[0]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['0_1'], values: [{{ double_val: {p11_error[1]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['1_0'], values: [{{ double_val: {p11_error[2]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_0'], values: [{{ double_val: {t1_micros[0]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_1'], values: [{{ double_val: {t1_micros[1]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['1_0'], values: [{{ double_val: {t1_micros[2]} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {syc_pauli[0]} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {syc_pauli[1]} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {iswap_pauli[0]} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {iswap_pauli[1]} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {syc_angles[0].theta} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {syc_angles[1].theta} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {iswap_angles[0].theta} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {iswap_angles[1].theta} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {syc_angles[0].phi} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {syc_angles[1].phi} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {iswap_angles[0].phi} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {iswap_angles[1].phi} }}] }}] """, cirq_google.api.v2.metrics_pb2.MetricsSnapshot(), ) # Create NoiseProperties object from Calibration calibration = cirq_google.Calibration(_CALIBRATION_DATA) prop = cirq_google.noise_properties_from_calibration(calibration) for i, q in enumerate(qubits): assert np.isclose( prop.gate_pauli_errors[OpIdentifier(cirq.PhasedXZGate, q)], pauli_error[i]) assert np.allclose(prop.readout_errors[q], np.array([p00_error[i], p11_error[i]])) assert np.isclose(prop.t1_ns[q], t1_micros[i] * 1000) microwave_time_ns = 25.0 tphi_err = incoherent_error[i] - microwave_time_ns / (3 * prop.t1_ns[q]) if tphi_err > 0: tphi_ns = microwave_time_ns / (3 * tphi_err) else: tphi_ns = 1e10 assert prop.tphi_ns[q] == tphi_ns qubit_pairs = [(qubits[0], qubits[1]), (qubits[0], qubits[2])] for i, qs in enumerate(qubit_pairs): for gate, values in [ (cirq_google.SycamoreGate, syc_pauli), (cirq.ISwapPowGate, iswap_pauli), ]: assert np.isclose(prop.gate_pauli_errors[OpIdentifier(gate, *qs)], values[i]) assert np.isclose( prop.gate_pauli_errors[OpIdentifier(gate, *qs[::-1])], values[i]) assert np.isclose(prop.gate_pauli_errors[OpIdentifier(gate, *qs)], values[i]) assert np.isclose( prop.gate_pauli_errors[OpIdentifier(gate, *qs[::-1])], values[i]) for gate, values in [ (cirq_google.SycamoreGate, syc_angles), (cirq.ISwapPowGate, iswap_angles), ]: assert prop.fsim_errors[OpIdentifier(gate, *qs)] == values[i] assert prop.fsim_errors[OpIdentifier(gate, *qs[::-1])] == values[i] assert prop.fsim_errors[OpIdentifier(gate, *qs)] == values[i] assert prop.fsim_errors[OpIdentifier(gate, *qs[::-1])] == values[i]
def test_floquet_parse_result(): q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)] gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0) request = FloquetPhasedFSimCalibrationRequest( gate=gate, pairs=((q_00, q_01), (q_02, q_03)), options=FloquetPhasedFSimCalibrationOptions( characterize_theta=True, characterize_zeta=True, characterize_chi=False, characterize_gamma=False, characterize_phi=True, ), ) result = cirq_google.CalibrationResult( code=cirq_google.api.v2.calibration_pb2.SUCCESS, error_message=None, token=None, valid_until=None, metrics=cirq_google.Calibration( cirq_google.api.v2.metrics_pb2.MetricsSnapshot(metrics=[ cirq_google.api.v2.metrics_pb2.Metric( name='angles', targets=[ '0_qubit_a', '0_qubit_b', '0_theta_est', '0_zeta_est', '0_phi_est', '1_qubit_a', '1_qubit_b', '1_theta_est', '1_zeta_est', '1_phi_est', ], values=[ cirq_google.api.v2.metrics_pb2.Value(str_val='0_0'), cirq_google.api.v2.metrics_pb2.Value(str_val='0_1'), cirq_google.api.v2.metrics_pb2.Value(double_val=0.1), cirq_google.api.v2.metrics_pb2.Value(double_val=0.2), cirq_google.api.v2.metrics_pb2.Value(double_val=0.3), cirq_google.api.v2.metrics_pb2.Value(str_val='0_2'), cirq_google.api.v2.metrics_pb2.Value(str_val='0_3'), cirq_google.api.v2.metrics_pb2.Value(double_val=0.4), cirq_google.api.v2.metrics_pb2.Value(double_val=0.5), cirq_google.api.v2.metrics_pb2.Value(double_val=0.6), ], ) ])), ) assert request.parse_result(result) == PhasedFSimCalibrationResult( parameters={ (q_00, q_01): PhasedFSimCharacterization(theta=0.1, zeta=0.2, chi=None, gamma=None, phi=0.3), (q_02, q_03): PhasedFSimCharacterization(theta=0.4, zeta=0.5, chi=None, gamma=None, phi=0.6), }, gate=gate, options=FloquetPhasedFSimCalibrationOptions( characterize_theta=True, characterize_zeta=True, characterize_chi=False, characterize_gamma=False, characterize_phi=True, ), )
def test_noise_properties_from_calibration(): xeb_error_1 = 0.999 xeb_error_2 = 0.996 p00_1 = 0.001 p00_2 = 0.002 p00_3 = 0.003 t1_1 = 0.005 t1_2 = 0.007 t1_3 = 0.003 _CALIBRATION_DATA = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'xeb', targets: ['0_0', '0_1'], values: [{{ double_val: {xeb_error_1} }}] }}, {{ name: 'xeb', targets: ['0_0', '1_0'], values: [{{ double_val:{xeb_error_2} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_0'], values: [{{ double_val: {p00_1} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_1'], values: [{{ double_val: {p00_2} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['1_0'], values: [{{ double_val: {p00_3} }}] }}, {{ name: 'single_qubit_readout_separation_error', targets: ['0_0'], values: [{{ double_val: .004 }}] }}, {{ name: 'single_qubit_readout_separation_error', targets: ['0_1'], values: [{{ double_val: .005 }}] }},{{ name: 'single_qubit_readout_separation_error', targets: ['1_0'], values: [{{ double_val: .006 }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_0'], values: [{{ double_val: {t1_1} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_1'], values: [{{ double_val: {t1_2} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['1_0'], values: [{{ double_val: {t1_3} }}] }}] """, v2.metrics_pb2.MetricsSnapshot(), ) # Create NoiseProperties object from Calibration calibration = cirq_google.Calibration(_CALIBRATION_DATA) prop = noise_properties_from_calibration(calibration) expected_t1_nanos = np.mean([t1_1, t1_2, t1_3]) * 1000 expected_xeb_fidelity = 1 - np.mean([xeb_error_1, xeb_error_2]) expected_p00 = np.mean([p00_1, p00_2, p00_3]) assert np.isclose(prop.t1_ns, expected_t1_nanos) assert np.isclose(prop.xeb, expected_xeb_fidelity) assert np.isclose(prop.p00, expected_p00)
def test_noise_from_metrics_requires_type(): # Attempt to generate a noise model without specifying a noise type. calibration = cirq_google.Calibration(_CALIBRATION_DATA) with pytest.raises(ValueError, match='At least one error type must be specified.'): simple_noise_from_calibration_metrics(calibration=calibration)
def test_run_floquet_characterization_for_moments(): q_00, q_01, q_02, q_03 = [cirq.GridQubit(0, index) for index in range(4)] gate = cirq.FSimGate(theta=np.pi / 4, phi=0.0) circuit = cirq.Circuit([gate.on(q_00, q_01), gate.on(q_02, q_03)]) options = FloquetPhasedFSimCalibrationOptions( characterize_theta=True, characterize_zeta=True, characterize_chi=False, characterize_gamma=False, characterize_phi=True, ) job = cirq_google.engine.EngineJob('', '', '', None) job._calibration_results = [ cirq_google.CalibrationResult( code=cirq_google.api.v2.calibration_pb2.SUCCESS, error_message=None, token=None, valid_until=None, metrics=cirq_google.Calibration( cirq_google.api.v2.metrics_pb2.MetricsSnapshot(metrics=[ cirq_google.api.v2.metrics_pb2.Metric( name='angles', targets=[ '0_qubit_a', '0_qubit_b', '0_theta_est', '0_zeta_est', '0_phi_est', '1_qubit_a', '1_qubit_b', '1_theta_est', '1_zeta_est', '1_phi_est', ], values=[ cirq_google.api.v2.metrics_pb2.Value( str_val='0_0'), cirq_google.api.v2.metrics_pb2.Value( str_val='0_1'), cirq_google.api.v2.metrics_pb2.Value( double_val=0.1), cirq_google.api.v2.metrics_pb2.Value( double_val=0.2), cirq_google.api.v2.metrics_pb2.Value( double_val=0.3), cirq_google.api.v2.metrics_pb2.Value( str_val='0_2'), cirq_google.api.v2.metrics_pb2.Value( str_val='0_3'), cirq_google.api.v2.metrics_pb2.Value( double_val=0.4), cirq_google.api.v2.metrics_pb2.Value( double_val=0.5), cirq_google.api.v2.metrics_pb2.Value( double_val=0.6), ], ) ])), ) ] engine = mock.MagicMock(spec=cirq_google.Engine) engine.run_calibration.return_value = job circuit_with_calibration, requests = workflow.run_floquet_characterization_for_moments( circuit, engine, 'qproc', cirq_google.FSIM_GATESET, options=options) assert requests == [ PhasedFSimCalibrationResult( parameters={ (q_00, q_01): PhasedFSimCharacterization(theta=0.1, zeta=0.2, chi=None, gamma=None, phi=0.3), (q_02, q_03): PhasedFSimCharacterization(theta=0.4, zeta=0.5, chi=None, gamma=None, phi=0.6), }, gate=gate, options=options, ) ] assert circuit_with_calibration.circuit == circuit assert circuit_with_calibration.moment_to_calibration == [0]
def test_validate_calibration(): # RB Pauli error and RB Average Error disagree rb_pauli_error = 0.05 rb_average_error = 0.1 decay_constant_pauli = 1 - rb_pauli_error / (1 - 1 / 4) decay_constant_average = 1 - rb_average_error / (1 - 1 / 2) _CALIBRATION_DATA_PAULI_AVERAGE = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_0'], values: [{{ double_val: {rb_pauli_error} }}] }}, {{ name: 'single_qubit_rb_average_error_per_gate', targets: ['0_1'], values: [{{ double_val: {rb_average_error} }}] }}] """, v2.metrics_pb2.MetricsSnapshot(), ) bad_calibration_pauli_average = cirq_google.Calibration( _CALIBRATION_DATA_PAULI_AVERAGE) with pytest.raises( ValueError, match=f'Decay constant from RB Pauli error: {decay_constant_pauli}, ' f'decay constant from RB Average error: {decay_constant_average}. ' 'If validation is disabled, RB Pauli error will be used.', ): noise_properties_from_calibration(bad_calibration_pauli_average) assert np.isclose( noise_properties_from_calibration(bad_calibration_pauli_average, validate=False).pauli_error, rb_pauli_error, ) # RB Pauli Error and XEB Fidelity disagree xeb_fidelity = 0.99 decay_constant_from_xeb = 1 - (1 - xeb_fidelity) / (1 - 1 / 4) _CALIBRATION_DATA_PAULI_XEB = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_0'], values: [{{ double_val: {rb_pauli_error} }}] }}, {{ name: 'xeb', targets: ['0_0', '1_0'], values: [{{ double_val:{1 - xeb_fidelity} }}] }}] """, v2.metrics_pb2.MetricsSnapshot(), ) bad_calibration_pauli_xeb = cirq_google.Calibration( _CALIBRATION_DATA_PAULI_XEB) with pytest.raises( ValueError, match=f'Decay constant from RB Pauli error: {decay_constant_pauli}, ' f'decay constant from XEB Fidelity: {decay_constant_from_xeb}. ' 'If validation is disabled, RB Pauli error will be used.', ): noise_properties_from_calibration(bad_calibration_pauli_xeb) # RB Average Error and XEB Fidelity disagree _CALIBRATION_DATA_AVERAGE_XEB = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_rb_average_error_per_gate', targets: ['0_0'], values: [{{ double_val: {rb_average_error} }}] }}, {{ name: 'xeb', targets: ['0_0', '1_0'], values: [{{ double_val:{1 - xeb_fidelity} }}] }}] """, v2.metrics_pb2.MetricsSnapshot(), ) bad_calibration_average_xeb = cirq_google.Calibration( _CALIBRATION_DATA_AVERAGE_XEB) with pytest.raises( ValueError, match= f'Decay constant from RB Average error: {decay_constant_average}, ' f'decay constant from XEB Fidelity: {decay_constant_from_xeb}. ' 'If validation is disabled, XEB Fidelity will be used.', ): noise_properties_from_calibration(bad_calibration_average_xeb) assert np.isclose( noise_properties_from_calibration(bad_calibration_average_xeb, validate=False).xeb, xeb_fidelity, ) # Calibration data with no RB error or XEB fidelity t1 = 2.0 # microseconds _CALIBRATION_DATA_T1 = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_idle_t1_micros', targets: ['0_0'], values: [{{ double_val: {t1} }}] }}] """, v2.metrics_pb2.MetricsSnapshot(), ) calibration_t1 = cirq_google.Calibration(_CALIBRATION_DATA_T1) assert np.isclose( noise_properties_from_calibration(calibration_t1).t1_ns, t1 * 1000)
def test_incomplete_calibration(): pauli_error = [0.001, 0.002, 0.003] p00_error = [0.004, 0.005, 0.006] p11_error = [0.007, 0.008, 0.009] t1_micros = [10, 20, 30] _CALIBRATION_DATA = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_0'], values: [{{ double_val: {pauli_error[0]} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_1'], values: [{{ double_val:{pauli_error[1]} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['1_0'], values: [{{ double_val:{pauli_error[2]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_0'], values: [{{ double_val: {p00_error[0]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_1'], values: [{{ double_val: {p00_error[1]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['1_0'], values: [{{ double_val: {p00_error[2]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['0_0'], values: [{{ double_val: {p11_error[0]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['0_1'], values: [{{ double_val: {p11_error[1]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['1_0'], values: [{{ double_val: {p11_error[2]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_0'], values: [{{ double_val: {t1_micros[0]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_1'], values: [{{ double_val: {t1_micros[1]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['1_0'], values: [{{ double_val: {t1_micros[2]} }}] }}] """, cirq_google.api.v2.metrics_pb2.MetricsSnapshot(), ) # Create NoiseProperties object from Calibration calibration = cirq_google.Calibration(_CALIBRATION_DATA) with pytest.raises( ValueError, match='Keys specified for T1 and Tphi are not identical.'): _ = cirq_google.noise_properties_from_calibration(calibration)
def get_mock_calibration( pauli_error, incoherent_error, p00_error, p11_error, t1_micros, syc_pauli, iswap_pauli, syc_angles, iswap_angles, ) -> cirq_google.Calibration: _CALIBRATION_DATA = Merge( f""" timestamp_ms: 1579214873, metrics: [{{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_0'], values: [{{ double_val: {pauli_error[0]} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['0_1'], values: [{{ double_val:{pauli_error[1]} }}] }}, {{ name: 'single_qubit_rb_pauli_error_per_gate', targets: ['1_0'], values: [{{ double_val:{pauli_error[2]} }}] }}, {{ name: 'single_qubit_rb_incoherent_error_per_gate', targets: ['0_0'], values: [{{ double_val: {incoherent_error[0]} }}] }}, {{ name: 'single_qubit_rb_incoherent_error_per_gate', targets: ['0_1'], values: [{{ double_val:{incoherent_error[1]} }}] }}, {{ name: 'single_qubit_rb_incoherent_error_per_gate', targets: ['1_0'], values: [{{ double_val:{incoherent_error[2]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_0'], values: [{{ double_val: {p00_error[0]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['0_1'], values: [{{ double_val: {p00_error[1]} }}] }}, {{ name: 'single_qubit_p00_error', targets: ['1_0'], values: [{{ double_val: {p00_error[2]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['0_0'], values: [{{ double_val: {p11_error[0]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['0_1'], values: [{{ double_val: {p11_error[1]} }}] }}, {{ name: 'single_qubit_p11_error', targets: ['1_0'], values: [{{ double_val: {p11_error[2]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_0'], values: [{{ double_val: {t1_micros[0]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['0_1'], values: [{{ double_val: {t1_micros[1]} }}] }}, {{ name: 'single_qubit_idle_t1_micros', targets: ['1_0'], values: [{{ double_val: {t1_micros[2]} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {syc_pauli[0]} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {syc_pauli[1]} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {iswap_pauli[0]} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_pauli_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {iswap_pauli[1]} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {syc_angles[0].theta} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {syc_angles[1].theta} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {iswap_angles[0].theta} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_theta_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {iswap_angles[1].theta} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {syc_angles[0].phi} }}] }}, {{ name: 'two_qubit_parallel_sycamore_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {syc_angles[1].phi} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '0_1'], values: [{{ double_val: {iswap_angles[0].phi} }}] }}, {{ name: 'two_qubit_parallel_sqrt_iswap_gate_xeb_entangler_phi_error_per_cycle', targets: ['0_0', '1_0'], values: [{{ double_val: {iswap_angles[1].phi} }}] }}] """, cirq_google.api.v2.metrics_pb2.MetricsSnapshot(), ) return cirq_google.Calibration(_CALIBRATION_DATA)