def test_get_engine_sampler(monkeypatch): monkeypatch.setenv('GOOGLE_CLOUD_PROJECT', 'myproj') with mock.patch.object( cirq_google.engine.client.quantum, 'QuantumEngineServiceClient', autospec=True ): sampler = cg.get_engine_sampler(processor_id='hi mom', gate_set_name='sqrt_iswap') assert hasattr(sampler, 'run_sweep') with pytest.raises(ValueError): sampler = cg.get_engine_sampler(processor_id='hi mom', gate_set_name='ccz')
def test_get_engine_sampler(): with mock.patch.object(cirq_google.engine.client.quantum, 'QuantumEngineServiceClient', autospec=True): with mock.patch('google.auth.default', lambda: (None, 'myproj')): sampler = cg.get_engine_sampler(processor_id='hi mom', gate_set_name='sqrt_iswap') assert hasattr(sampler, 'run_sweep') with pytest.raises(ValueError): sampler = cg.get_engine_sampler(processor_id='hi mom', gate_set_name='ccz')
def test_get_engine_sampler(): with mock.patch.object(cirq_google.cloud.quantum, 'QuantumEngineServiceClient', autospec=True): with mock.patch('google.auth.default', lambda: (None, 'myproj')): sampler = cg.get_engine_sampler(processor_id='hi mom') assert hasattr(sampler, 'run_sweep')
def test_get_engine_sampler_explicit_project_id(): with mock.patch.object(cirq_google.cloud.quantum, 'QuantumEngineServiceClient', autospec=True): sampler = cg.get_engine_sampler(processor_id='hi mom', project_id='myproj') assert hasattr(sampler, 'run_sweep')
def get_qcs_objects_for_notebook( project_id: Optional[str] = None, processor_id: Optional[str] = None) -> QCSObjectsForNotebook: """Authenticates on Google Cloud, can return a Device and Simulator. Args: project_id: Optional explicit Google Cloud project id. Otherwise, this defaults to the environment variable GOOGLE_CLOUD_PROJECT. By using an environment variable, you can avoid hard-coding personal project IDs in shared code. processor_id: Engine processor ID (from Cloud console or ``Engine.list_processors``). Returns: An instance of DeviceSamplerInfo. """ # Converting empty strings to None for form field inputs if project_id == "": project_id = None if processor_id == "": processor_id = None google_cloud_signin_failed: bool = False if project_id is None: if 'GOOGLE_CLOUD_PROJECT' not in os.environ: print( "No project_id provided and environment variable GOOGLE_CLOUD_PROJECT not set." ) google_cloud_signin_failed = True else: # pragma: no cover os.environ['GOOGLE_CLOUD_PROJECT'] = project_id # Following code runs the user through the Colab OAuth process. # Checks for Google Application Default Credentials and runs # interactive login if the notebook is executed in Colab. In # case the notebook is executed in Jupyter notebook or other # IPython runtimes, no interactive login is provided, it is # assumed that the `GOOGLE_APPLICATION_CREDENTIALS` env var is # set or `gcloud auth application-default login` was executed # already. For more information on using Application Default Credentials # see https://cloud.google.com/docs/authentication/production in_colab = False try: from IPython import get_ipython in_colab = 'google.colab' in str(get_ipython()) if in_colab: from google.colab import auth print("Getting OAuth2 credentials.") print("Press enter after entering the verification code.") auth.authenticate_user(clear_output=False) print("Authentication complete.") else: print("Notebook isn't executed with Colab, assuming " "Application Default Credentials are setup.") except: pass # End of Google Colab Authentication segment device: cirq.Device sampler: Union[PhasedFSimEngineSimulator, QuantumEngineSampler] if google_cloud_signin_failed or processor_id is None: print("Using a noisy simulator.") sampler = PhasedFSimEngineSimulator.create_with_random_gaussian_sqrt_iswap( mean=SQRT_ISWAP_INV_PARAMETERS, sigma=PhasedFSimCharacterization(theta=0.01, zeta=0.10, chi=0.01, gamma=0.10, phi=0.02), ) device = Sycamore else: # pragma: no cover device = get_engine_device(processor_id) sampler = get_engine_sampler(processor_id, gate_set_name="sqrt_iswap") return QCSObjectsForNotebook( device=device, sampler=sampler, signed_in=not google_cloud_signin_failed, )
def main(): # Set the random seed for the OTOC circuits. np.random.seed(0) # Specify project ID and processor name. processor_name = "rainbow" sampler = cg.get_engine_sampler(processor_id=processor_name, gate_set_name="fsim") # Specify qubits to measure. The qubits must form a line. The ancilla qubit # must be connected to the first qubit. qubit_locs = [(3, 3), (2, 3), (2, 4), (2, 5), (1, 5), (0, 5), (0, 6), (1, 6)] qubits = [cirq.GridQubit(*idx) for idx in qubit_locs] ancilla_loc = (3, 2) ancilla = cirq.GridQubit(*ancilla_loc) num_qubits = len(qubits) # Specify how the qubits interact. For the 1D chain in this example, only two # layers of two-qubit gates (CZ is used here) is needed to enact all # interactions. int_sets = [ {(qubits[i], qubits[i + 1]) for i in range(0, num_qubits - 1, 2)}, {(qubits[i], qubits[i + 1]) for i in range(1, num_qubits - 1, 2)}, ] forward_ops = {(qubit_locs[i], qubit_locs[i + 1]): cirq.Circuit([cirq.CZ(qubits[i], qubits[i + 1])]) for i in range(num_qubits - 1)} reverse_ops = forward_ops # Build two random circuit instances (each having 12 cycles). circuit_list = [] cycles = range(12) num_trials = 2 for i in range(num_trials): rand_nums = np.random.choice(8, (num_qubits, max(cycles))) circuits_i = [] for cycle in cycles: circuits_ic = [] for k, q_b in enumerate(qubits[1:]): circs = build_otoc_circuits( qubits, ancilla, cycle, int_sets, forward_ops=forward_ops, reverse_ops=reverse_ops, butterfly_qubits=q_b, cycles_per_echo=2, sq_gates=rand_nums, use_physical_cz=True, ) # If q_b is the measurement qubit, add both the normalization circuits and the # circuits with X as the butterfly operator. Otherwise only add circuits with Y # being the butterfly operator. if k == 0: circuits_ic.extend(circs.butterfly_I) circuits_ic.extend(circs.butterfly_X) else: circuits_ic.extend(circs.butterfly_X) circuits_i.append(circuits_ic) circuit_list.append(circuits_i) # Measure the OTOCs of the two random circuits. results = [] for i, circuits_i in enumerate(circuit_list): results_i = np.zeros((num_qubits, len(cycles))) for c, circuits_ic in enumerate(circuits_i): print("Measuring circuit instance {}, cycle {}...".format(i, c)) stats = int(2000 + 10000 * (c / max(cycles))**3) params = [{} for _ in range(len(circuits_ic))] job = sampler.run_batch(programs=circuits_ic, params_list=params, repetitions=stats) for d in range(num_qubits): p = np.mean(job[4 * d][0].measurements["z"]) p -= np.mean(job[4 * d + 1][0].measurements["z"]) p -= np.mean(job[4 * d + 2][0].measurements["z"]) p += np.mean(job[4 * d + 3][0].measurements["z"]) results_i[d, c] = 0.5 * p results.append(results_i) # Average the data for the two random circuits and plot out results. results_ave = np.mean(results, axis=0) fig = plt.figure() plt.plot(results_ave[0, :], "ko-", label="Normalization") for i in range(1, num_qubits): plt.plot(results_ave[i, :], "o-", label="Qubit {}".format(i + 1)) plt.xlabel("Cycles") plt.ylabel(r"$\langle \sigma_y \rangle$") plt.legend()
def main(): # Specify a working directory, project ID and processor name. dir_str = os.getcwd() processor_name = "rainbow" sampler = cg.get_engine_sampler(processor_id=processor_name, gate_set_name="fsim") # Specify qubits to measure. Here we choose the qubits to be on a line. qubit_locs = [(3, 3), (2, 3), (2, 4), (2, 5), (1, 5), (0, 5), (0, 6), (1, 6)] qubits = [cirq.GridQubit(*idx) for idx in qubit_locs] num_qubits = len(qubits) # Specify the gate layers to calibrate. For qubits on a line, all two-qubit # gates can be calibrated in two layers. int_layers = [ {(qubit_locs[i], qubit_locs[i + 1]) for i in range(0, num_qubits - 1, 2)}, {(qubit_locs[i], qubit_locs[i + 1]) for i in range(1, num_qubits - 1, 2)}, ] xeb_configs = [ [ cirq.Moment([ cirq.ISWAP(qubits[i], qubits[i + 1])**0.5 for i in range(0, num_qubits - 1, 2) ]) ], [ cirq.Moment([ cirq.ISWAP(qubits[i], qubits[i + 1])**0.5 for i in range(1, num_qubits - 1, 2) ]) ], ] # Specify the number of random circuits in parallel XEB the cycles at which # fidelities are to be measured. num_circuits = 10 num_num_cycles = range(3, 75, 10) num_cycles = len(num_num_cycles) # Generate random XEB circuits, measure the resulting bit-strings, and save # the data as well as random circuit information. all_bits = [] all_sq_gates = [] for xeb_config in xeb_configs: bits = [] sq_gates = [] for i in range(num_circuits): print(i) circuits, sq_gate_indices_i = build_xeb_circuits(qubits, num_num_cycles, xeb_config, random_seed=i) sq_gates.append(sq_gate_indices_i) for c in circuits: c.append(cirq.measure(*qubits, key="z")) sweep_params = [{} for _ in range(len(circuits))] job = sampler.run_batch(programs=circuits, params_list=sweep_params, repetitions=5000) bits.append( [job[j][0].measurements["z"] for j in range(num_cycles)]) all_bits.append(bits) all_sq_gates.append(sq_gates) # Perform fits on each qubit pair to miminize the cycle errors. The fitting # results are saved to the working directory. fsim_angles_init = { "theta": -0.25 * np.pi, "delta_plus": 0, "delta_minus_off_diag": 0, "delta_minus_diag": 0, "phi": 0.0, } xeb_results = parallel_xeb_fidelities( qubit_locs, num_num_cycles, all_bits, all_sq_gates, fsim_angles_init, interaction_sequence=int_layers, gate_to_fit="sqrt-iswap", num_restarts=5, ) plot_xeb_results(xeb_results) save_data(xeb_results.correction_gates, dir_str + "/gate_corrections")