|
1 | | -# Tutorial |
| 1 | +--- |
| 2 | +file_format: mystnb |
| 3 | +kernelspec: |
| 4 | + name: python3 |
| 5 | +--- |
| 6 | + |
| 7 | +# Tutorial |
| 8 | + |
| 9 | +```{code-cell} ipython3 |
| 10 | +from pytket import Circuit |
| 11 | +from pytket.circuit.display import render_circuit_jupyter |
| 12 | +
|
| 13 | +circ = Circuit(2,2).H(0).CX(0,1).measure_all() |
| 14 | +render_circuit_jupyter(circ) |
| 15 | +``` |
| 16 | + |
| 17 | +```{code-cell} ipython3 |
| 18 | +import pandas as pd |
| 19 | +import seaborn as sns |
| 20 | +import matplotlib.pyplot as plt |
| 21 | +
|
| 22 | +def plot_state_probs(state): |
| 23 | + state_dict = {'State':[i for i in range(len(result_state))], 'Probability':abs(state)**2} |
| 24 | + state_df = pd.DataFrame(state_dict) |
| 25 | + sns.catplot(x='State', y='Probability', kind='bar', data=state_df, aspect = 3, height=2) |
| 26 | + plt.show() |
| 27 | + |
| 28 | +def plot_counts(counts): |
| 29 | + counts_record = [{"State":str(state), "Count":count} for state, count in counts.items()] |
| 30 | + count_df = pd.DataFrame().from_records(counts_record) |
| 31 | + sns.catplot(x='State', y='Count', kind='bar', data=count_df, aspect = 3, height=2) |
| 32 | + plt.show() |
| 33 | +``` |
| 34 | + |
| 35 | +```{code-cell} ipython3 |
| 36 | +import qiskit_aer.noise as noise |
| 37 | +
|
| 38 | +def depolarizing_noise_model(n_qubits, prob_1, prob_2, prob_ro): |
| 39 | +
|
| 40 | + noise_model = noise.NoiseModel() |
| 41 | +
|
| 42 | + error_2 = noise.depolarizing_error(prob_2, 2) |
| 43 | + for edge in [[i,j] for i in range(n_qubits) for j in range(i)]: |
| 44 | + noise_model.add_quantum_error(error_2, ['cx'], [edge[0], edge[1]]) |
| 45 | + noise_model.add_quantum_error(error_2, ['cx'], [edge[1], edge[0]]) |
| 46 | +
|
| 47 | + error_1 = noise.depolarizing_error(prob_1, 1) |
| 48 | + for node in range(n_qubits): |
| 49 | + noise_model.add_quantum_error(error_1, ['h', 'rx', 'rz', 'u'], [node]) |
| 50 | + |
| 51 | + probabilities = [[1-prob_ro, prob_ro],[prob_ro, 1-prob_ro]] |
| 52 | + error_ro = noise.ReadoutError(probabilities) |
| 53 | + for i in range(n_qubits): |
| 54 | + noise_model.add_readout_error(error_ro, [i]) |
| 55 | + |
| 56 | + return noise_model |
| 57 | +``` |
| 58 | + |
| 59 | +```{code-cell} ipython3 |
| 60 | +from qermit.taskgraph.mitex import gen_compiled_MitRes |
| 61 | +from pytket.extensions.qiskit import AerBackend |
| 62 | +from qermit import CircuitShots |
| 63 | +
|
| 64 | +n_shots = 100000 |
| 65 | +noisy_backend = AerBackend( |
| 66 | + depolarizing_noise_model(5, 0.001, 0.01, 0.05) |
| 67 | +) |
| 68 | +noisy_mitres = gen_compiled_MitRes(noisy_backend, optimisation_level=0) |
| 69 | +
|
| 70 | +circ_shots_list = [CircuitShots(circ, n_shots)] |
| 71 | +
|
| 72 | +noisy_result_list = noisy_mitres.run(circ_shots_list) |
| 73 | +noisy_result_counts = noisy_result_list[0].get_counts() |
| 74 | +plot_counts(noisy_result_counts) |
| 75 | +``` |
| 76 | + |
| 77 | +```{code-cell} ipython3 |
| 78 | +noisy_mitres.get_task_graph() |
| 79 | +``` |
| 80 | + |
| 81 | +```{code-cell} ipython3 |
| 82 | +from qermit.spam import gen_UnCorrelated_SPAM_MitRes |
| 83 | +
|
| 84 | +spam_mr = gen_UnCorrelated_SPAM_MitRes(noisy_backend, n_shots) |
| 85 | +spam_result_list = spam_mr.run(circ_shots_list) |
| 86 | +spam_result_counts = spam_result_list[0].get_counts() |
| 87 | +plot_counts(spam_result_counts) |
| 88 | +``` |
| 89 | + |
| 90 | +```{code-cell} ipython3 |
| 91 | +spam_mr.get_task_graph() |
| 92 | +``` |
| 93 | + |
| 94 | +```{code-cell} ipython3 |
| 95 | +import numpy as np |
| 96 | +from scipy.stats import unitary_group |
| 97 | +from pytket.circuit import Unitary2qBox |
| 98 | +
|
| 99 | +def random_circ(n_qubits: int, depth: int, seed:int = None) -> Circuit: |
| 100 | + |
| 101 | + np.random.seed(seed) |
| 102 | +
|
| 103 | + c = Circuit(n_qubits) |
| 104 | +
|
| 105 | + for _ in range(depth): |
| 106 | +
|
| 107 | + qubits = np.random.permutation([i for i in range(n_qubits)]) |
| 108 | + qubit_pairs = [[qubits[i], qubits[i + 1]] for i in range(0, n_qubits - 1, 2)] |
| 109 | +
|
| 110 | + for pair in qubit_pairs: |
| 111 | +
|
| 112 | + # Generate random 4x4 unitary matrix. |
| 113 | + SU4 = unitary_group.rvs(4) # random unitary in SU4 |
| 114 | + SU4 = SU4 / (np.linalg.det(SU4) ** 0.25) |
| 115 | + SU4 = np.matrix(SU4) |
| 116 | +
|
| 117 | + # Add gate corresponding to unitary. |
| 118 | + c.add_unitary2qbox(Unitary2qBox(SU4), *pair) |
| 119 | +
|
| 120 | + return c |
| 121 | +``` |
| 122 | + |
| 123 | +```{code-cell} ipython3 |
| 124 | +n_qubits = 4 |
| 125 | +rand_circ = random_circ(n_qubits,n_qubits,seed=23126) |
| 126 | +render_circuit_jupyter(rand_circ) |
| 127 | +``` |
| 128 | + |
| 129 | +```{code-cell} ipython3 |
| 130 | +from pytket.utils import QubitPauliOperator |
| 131 | +from qermit import ( |
| 132 | + AnsatzCircuit, SymbolsDict, |
| 133 | + ObservableExperiment, ObservableTracker, |
| 134 | + MitEx |
| 135 | +) |
| 136 | +from pytket.pauli import Pauli, QubitPauliString |
| 137 | +from pytket import Qubit |
| 138 | +
|
| 139 | +ideal_backend = AerBackend() |
| 140 | +ideal_mitex = MitEx(ideal_backend) |
| 141 | +
|
| 142 | +qps = QubitPauliString( |
| 143 | + [Qubit(i) for i in range(n_qubits)], |
| 144 | + [Pauli.Z for i in range(n_qubits)] |
| 145 | +) |
| 146 | +
|
| 147 | +obs_exp = ObservableExperiment( |
| 148 | + AnsatzCircuit(rand_circ, n_shots, SymbolsDict()), |
| 149 | + ObservableTracker(QubitPauliOperator({qps:1})) |
| 150 | +) |
| 151 | +obs_exp_list = [obs_exp] |
| 152 | +
|
| 153 | +ideal_expectation = ideal_mitex.run(obs_exp_list) |
| 154 | +print(f"Ideal expectation: {ideal_expectation[0]}") |
| 155 | +``` |
| 156 | + |
| 157 | +```{code-cell} ipython3 |
| 158 | +noisy_mitex = MitEx(noisy_backend) |
| 159 | +
|
| 160 | +noisy_expectation = noisy_mitex.run(obs_exp_list) |
| 161 | +print(f"Noisy expectation: {noisy_expectation[0]}") |
| 162 | +``` |
| 163 | + |
| 164 | +```{code-cell} ipython3 |
| 165 | +from qermit.zero_noise_extrapolation import ( |
| 166 | + gen_ZNE_MitEx, Fit, Folding |
| 167 | +) |
| 168 | +
|
| 169 | +zne_me = gen_ZNE_MitEx( |
| 170 | + backend=noisy_backend, |
| 171 | + noise_scaling_list=[9,7,5,3,1], |
| 172 | + fit_type=Fit.exponential, |
| 173 | + folding_type=Folding.circuit, |
| 174 | + show_fit=True, |
| 175 | +) |
| 176 | +``` |
| 177 | + |
| 178 | +```{code-cell} ipython3 |
| 179 | +import seaborn as sns |
| 180 | +sns.set_style("whitegrid") |
| 181 | +``` |
| 182 | + |
| 183 | +```{code-cell} ipython3 |
| 184 | +zne_me.get_task_graph() |
| 185 | +``` |
| 186 | + |
| 187 | +```{code-cell} ipython3 |
| 188 | +zne_me.run(obs_exp_list) |
| 189 | +``` |
| 190 | + |
| 191 | +```{code-cell} ipython3 |
| 192 | +zne_spam_me = gen_ZNE_MitEx( |
| 193 | + backend=noisy_backend, |
| 194 | + noise_scaling_list=[9,7,5,3,1], |
| 195 | + fit_type=Fit.exponential, |
| 196 | + show_fit=True, |
| 197 | + experiment_mitres=spam_mr, |
| 198 | +) |
| 199 | +``` |
| 200 | + |
| 201 | +```{code-cell} ipython3 |
| 202 | +zne_spam_me.run(obs_exp_list) |
| 203 | +``` |
| 204 | + |
| 205 | +```{code-cell} ipython3 |
| 206 | +zne_spam_me.get_task_graph() |
| 207 | +``` |
0 commit comments