def test_benchmark_2q_xeb_fidelities_parallel(): circuits = rqcg.generate_library_of_2q_circuits( n_library_circuits=5, two_qubit_gate=cirq.ISWAP**0.5, max_cycle_depth=4) cycle_depths = [2, 3, 4] graph = _gridqubits_to_graph_device(cirq.GridQubit.rect(2, 2)) combs = rqcg.get_random_combinations_for_device( n_library_circuits=len(circuits), n_combinations=2, device_graph=graph, random_state=10) sampled_df = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, combinations_by_layer=combs, ) fid_df = benchmark_2q_xeb_fidelities(sampled_df, circuits, cycle_depths) n_pairs = sum(len(c.pairs) for c in combs) assert len(fid_df) == len(cycle_depths) * n_pairs fit_df = fit_exponential_decays(fid_df) for _, row in fit_df.iterrows(): assert list(row['cycle_depths']) == list(cycle_depths) assert len(row['fidelities']) == len(cycle_depths)
def test_sample_2q_parallel_xeb_circuits_error_bad_qubits(): circuits = rqcg.generate_library_of_2q_circuits( n_library_circuits=5, two_qubit_gate=cirq.ISWAP**0.5, max_cycle_depth=10, q0=cirq.GridQubit(0, 0), q1=cirq.GridQubit(1, 1), ) cycle_depths = [10] graph = _gridqubits_to_graph_device(cirq.GridQubit.rect(3, 2)) combs = rqcg.get_random_combinations_for_device( n_library_circuits=len(circuits), n_combinations=5, device_graph=graph, random_state=10, ) with pytest.raises( ValueError, match=r'.*each operating on LineQubit\(0\) and LineQubit\(1\)'): _ = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, combinations_by_layer=combs, )
def test_sample_2q_xeb_circuits(): q0 = cirq.NamedQubit('a') q1 = cirq.NamedQubit('b') circuits = [ rqcg.random_rotations_between_two_qubit_circuit( q0, q1, depth=20, two_qubit_op_factory=lambda a, b, _: cirq.SQRT_ISWAP(a, b), ) for _ in range(2) ] cycle_depths = np.arange(3, 20, 6) df = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, shuffle=np.random.RandomState(10), ) assert len(df) == len(cycle_depths) * len(circuits) for (circuit_i, cycle_depth), row in df.iterrows(): assert 0 <= circuit_i < len(circuits) assert cycle_depth in cycle_depths assert len(row['sampled_probs']) == 4 assert np.isclose(np.sum(row['sampled_probs']), 1)
def test_sample_2q_parallel_xeb_circuits(): circuits = rqcg.generate_library_of_2q_circuits( n_library_circuits=5, two_qubit_gate=cirq.ISWAP**0.5, max_cycle_depth=10) cycle_depths = [10] graph = _gridqubits_to_graph_device(cirq.GridQubit.rect(3, 2)) combs = rqcg.get_random_combinations_for_device( n_library_circuits=len(circuits), n_combinations=5, device_graph=graph, random_state=10, ) df = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, combinations_by_layer=combs, ) n_pairs = sum(len(c.pairs) for c in combs) assert len(df) == len(cycle_depths) * len(circuits) * n_pairs for (circuit_i, cycle_depth), row in df.iterrows(): assert 0 <= circuit_i < len(circuits) assert cycle_depth in cycle_depths assert len(row['sampled_probs']) == 4 assert np.isclose(np.sum(row['sampled_probs']), 1) assert 0 <= row['layer_i'] < 4 assert 0 <= row[ 'pair_i'] < 2 # in 3x2 graph, there's a max of 2 pairs per layer assert len(df['pair'].unique()) == 7 # seven pairs in 3x2 graph
def test_benchmark_2q_xeb_fidelities(): q0, q1 = cirq.LineQubit.range(2) circuits = [ rqcg.random_rotations_between_two_qubit_circuit( q0, q1, depth=50, two_qubit_op_factory=lambda a, b, _: SQRT_ISWAP(a, b), seed=52) for _ in range(2) ] cycle_depths = np.arange(3, 50, 9) sampled_df = sample_2q_xeb_circuits(sampler=cirq.Simulator(seed=53), circuits=circuits, cycle_depths=cycle_depths) fid_df = benchmark_2q_xeb_fidelities(sampled_df, circuits, cycle_depths) assert len(fid_df) == len(cycle_depths) for _, row in fid_df.iterrows(): assert row['cycle_depth'] in cycle_depths assert row['fidelity'] > 0.98 fit_df = fit_exponential_decays(fid_df) for _, row in fit_df.iterrows(): assert list(row['cycle_depths']) == list(cycle_depths) assert len(row['fidelities']) == len(cycle_depths)
def test_sample_2q_xeb_circuits_error(): qubits = cirq.LineQubit.range(3) circuits = [cirq.testing.random_circuit(qubits, n_moments=5, op_density=0.8, random_state=52)] cycle_depths = np.arange(3, 50, 9) with pytest.raises(ValueError): # three qubit circuits _ = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths )
def test_sample_2q_xeb_circuits_no_progress(capsys): qubits = cirq.LineQubit.range(2) circuits = [cirq.testing.random_circuit(qubits, n_moments=7, op_density=0.8, random_state=52)] cycle_depths = np.arange(3, 4) _ = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, progress_bar=None ) captured = capsys.readouterr() assert captured.out == '' assert captured.err == ''
def circuits_cycle_depths_sampled_df(): q0, q1 = cirq.LineQubit.range(2) circuits = [ rqcg.random_rotations_between_two_qubit_circuit( q0, q1, depth=50, two_qubit_op_factory=lambda a, b, _: SQRT_ISWAP(a, b), seed=52 ) for _ in range(2) ] cycle_depths = np.arange(10, 40 + 1, 10) sampled_df = sample_2q_xeb_circuits( sampler=cirq.Simulator(seed=53), circuits=circuits, cycle_depths=cycle_depths ) return circuits, cycle_depths, sampled_df
def test_sample_2q_parallel_xeb_circuits(tmpdir): circuits = rqcg.generate_library_of_2q_circuits( n_library_circuits=5, two_qubit_gate=cirq.ISWAP**0.5, max_cycle_depth=10) cycle_depths = [5, 10] graph = _gridqubits_to_graph_device(cirq.GridQubit.rect(3, 2)) combs = rqcg.get_random_combinations_for_device( n_library_circuits=len(circuits), n_combinations=5, device_graph=graph, random_state=10, ) df = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, combinations_by_layer=combs, dataset_directory=f'{tmpdir}/my_dataset', ) n_pairs = sum(len(c.pairs) for c in combs) assert len(df) == len(cycle_depths) * len(circuits) * n_pairs for (circuit_i, cycle_depth), row in df.iterrows(): assert 0 <= circuit_i < len(circuits) assert cycle_depth in cycle_depths assert len(row['sampled_probs']) == 4 assert np.isclose(np.sum(row['sampled_probs']), 1) assert 0 <= row['layer_i'] < 4 assert 0 <= row[ 'pair_i'] < 2 # in 3x2 graph, there's a max of 2 pairs per layer assert len(df['pair'].unique()) == 7 # seven pairs in 3x2 graph # Test loading from dataset chunks = [ record for fn in glob.glob(f'{tmpdir}/my_dataset/*') for record in cirq.read_json(fn) ] df2 = pd.DataFrame(chunks).set_index(['circuit_i', 'cycle_depth']) df2['pair'] = [tuple(row['pair']) for _, row in df2.iterrows()] actual_index_names = ['layer_i', 'pair_i', 'combination_i', 'cycle_depth'] _assert_frame_approx_equal( df.reset_index().set_index(actual_index_names), df2.reset_index().set_index(actual_index_names), atol=1e-5, )
def test_characterize_phased_fsim_parameters_with_xeb(): q0, q1 = cirq.LineQubit.range(2) rs = np.random.RandomState(52) circuits = [ rqcg.random_rotations_between_two_qubit_circuit( q0, q1, depth=20, two_qubit_op_factory=lambda a, b, _: cirq.SQRT_ISWAP(a, b), seed=rs, ) for _ in range(2) ] cycle_depths = np.arange(3, 20, 6) sampled_df = sample_2q_xeb_circuits( sampler=cirq.Simulator(seed=rs), circuits=circuits, cycle_depths=cycle_depths, progress_bar=None, ) # only optimize theta so it goes faster. options = SqrtISwapXEBOptions( characterize_theta=True, characterize_gamma=False, characterize_chi=False, characterize_zeta=False, characterize_phi=False, ) p_circuits = [ parameterize_circuit(circuit, options) for circuit in circuits ] with multiprocessing.Pool() as pool: result = characterize_phased_fsim_parameters_with_xeb( sampled_df=sampled_df, parameterized_circuits=p_circuits, cycle_depths=cycle_depths, options=options, # speed up with looser tolerances: fatol=1e-2, xatol=1e-2, pool=pool, ) opt_res = result.optimization_results[(q0, q1)] assert np.abs(opt_res.x[0] + np.pi / 4) < 0.1 assert np.abs(opt_res.fun) < 0.1 # noiseless simulator assert len(result.fidelities_df) == len(cycle_depths) assert np.all(result.fidelities_df['fidelity'] > 0.95)
def test_sample_2q_parallel_xeb_circuits_bad_circuit_library(): circuits = rqcg.generate_library_of_2q_circuits( n_library_circuits=5, two_qubit_gate=cirq.ISWAP**0.5, max_cycle_depth=10 ) cycle_depths = [10] graph = _gridqubits_to_graph_device(cirq.GridQubit.rect(3, 2)) combs = rqcg.get_random_combinations_for_device( n_library_circuits=len(circuits) + 100, # !!! should cause invlaid input n_combinations=5, device_graph=graph, random_state=10, ) with pytest.raises(ValueError, match='.*invalid indices.*'): _ = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, combinations_by_layer=combs, )
def test_parallel_full_workflow(use_pool): circuits = rqcg.generate_library_of_2q_circuits( n_library_circuits=5, two_qubit_gate=cirq.ISWAP**0.5, max_cycle_depth=4, random_state=8675309, ) cycle_depths = [2, 3, 4] graph = _gridqubits_to_graph_device(cirq.GridQubit.rect(2, 2)) combs = rqcg.get_random_combinations_for_device( n_library_circuits=len(circuits), n_combinations=2, device_graph=graph, random_state=10) sampled_df = sample_2q_xeb_circuits( sampler=cirq.Simulator(), circuits=circuits, cycle_depths=cycle_depths, combinations_by_layer=combs, ) if use_pool: pool = multiprocessing.Pool() else: pool = None fids_df_0 = benchmark_2q_xeb_fidelities(sampled_df=sampled_df, circuits=circuits, cycle_depths=cycle_depths, pool=pool) options = SqrtISwapXEBOptions(characterize_zeta=False, characterize_gamma=False, characterize_chi=False) p_circuits = [ parameterize_circuit(circuit, options) for circuit in circuits ] result = characterize_phased_fsim_parameters_with_xeb_by_pair( sampled_df=sampled_df, parameterized_circuits=p_circuits, cycle_depths=cycle_depths, options=options, # super loose tolerances fatol=5e-2, xatol=5e-2, pool=pool, ) if pool is not None: pool.terminate() assert len(result.optimization_results) == graph.number_of_edges() for opt_res in result.optimization_results.values(): assert np.abs(opt_res.fun) < 0.1 # noiseless simulator assert len( result.fidelities_df) == len(cycle_depths) * graph.number_of_edges() assert np.all(result.fidelities_df['fidelity'] > 0.90) before_after_df = before_and_after_characterization( fids_df_0, characterization_result=result) for _, row in before_after_df.iterrows(): assert len(row['fidelities_0']) == len(cycle_depths) assert len(row['fidelities_c']) == len(cycle_depths) assert 0 <= row['a_0'] <= 1 assert 0 <= row['a_c'] <= 1 assert 0 <= row['layer_fid_0'] <= 1 assert 0 <= row['layer_fid_c'] <= 1
def run_local_xeb_calibration( calibration: LocalXEBPhasedFSimCalibrationRequest, sampler: cirq.Sampler) -> PhasedFSimCalibrationResult: """Run a calibration request using `cirq.experiments` XEB utilities and a sampler rather than `Engine.run_calibrations`. Args: calibration: A LocalXEBPhasedFSimCalibration request describing the XEB characterization to carry out. sampler: A sampler to execute circuits. """ options: LocalXEBPhasedFSimCalibrationOptions = calibration.options circuit = cirq.Circuit( [calibration.gate.on(*pair) for pair in calibration.pairs]) # 2. Set up XEB experiment cycle_depths = options.cycle_depths circuits = rqcg.generate_library_of_2q_circuits( n_library_circuits=options.n_library_circuits, two_qubit_gate=calibration.gate, max_cycle_depth=max(cycle_depths), ) combs_by_layer = rqcg.get_random_combinations_for_layer_circuit( n_library_circuits=len(circuits), n_combinations=options.n_combinations, layer_circuit=circuit, ) # 3. Sample data sampled_df = xebsamp.sample_2q_xeb_circuits( sampler=sampler, circuits=circuits, cycle_depths=cycle_depths, combinations_by_layer=combs_by_layer, ) # 4. Initial fidelities # initial_fids = xebf.benchmark_2q_xeb_fidelities( # sampled_df=sampled_df, # circuits=circuits, # cycle_depths=cycle_depths, # ) # 5. Characterize by fitting angles. if options.fsim_options.defaults_set(): fsim_options = options.fsim_options else: fsim_options = options.fsim_options.with_defaults_from_gate( calibration.gate) pcircuits = [ xebf.parameterize_circuit(circuit, fsim_options) for circuit in circuits ] fatol = options.fatol if options.fatol is not None else 5e-3 xatol = options.xatol if options.xatol is not None else 5e-3 with _maybe_multiprocessing_pool(n_processes=options.n_processes) as pool: char_results = xebf.characterize_phased_fsim_parameters_with_xeb_by_pair( sampled_df=sampled_df, parameterized_circuits=pcircuits, cycle_depths=cycle_depths, options=fsim_options, pool=pool, fatol=fatol, xatol=xatol, ) return PhasedFSimCalibrationResult( parameters={ pair: PhasedFSimCharacterization(**param_dict) for pair, param_dict in char_results.final_params.items() }, gate=calibration.gate, options=options, )