def measurement_func(request, test_qc): if request.param == 'wfn': return lambda expt: list(wfn_estimate_observables(n_qubits=2, tomo_expt=expt)) elif request.param == 'sampling': return lambda expt: list(estimate_observables(qc=test_qc, obs_expt=expt, num_shots=500)) else: raise ValueError()
def acquire_rb_data(qc: QuantumComputer, experiments: Iterable[ObservablesExperiment], num_shots: int = 500, active_reset: bool = False, show_progress_bar: bool = False) \ -> List[List[ExperimentResult]]: """ Runs each ObservablesExperiment and returns each group of resulting ExperimentResults :param qc: a quantum computer, e.g. QVM or QPU, that runs the experiments :param experiments: a list of Observables experiments :param num_shots: the number of shots to run each group of simultaneous ExperimentSettings :param active_reset: Boolean flag indicating whether experiments should begin with an active reset instruction (this can make the collection of experiments run a lot faster). :param show_progress_bar: displays a progress bar via tqdm if true. :return: a list of ExperimentResults for each ObservablesExperiment """ results = [] for expt in tqdm(experiments, disable=not show_progress_bar): results.append(list(estimate_observables(qc, expt, num_shots, active_reset=active_reset))) return results
def single_q_tomo_fixture(test_qc): qubits = [0] # Generate random unitary u_rand = haar_rand_unitary(2 ** 1, rs=np.random.RandomState(52)) state_prep = Program().defgate("RandUnitary", u_rand) state_prep.inst([("RandUnitary", qubits[0])]) # True state wfn = NumpyWavefunctionSimulator(n_qubits=1) psi = wfn.do_gate_matrix(u_rand, qubits=[0]).wf.reshape(-1) rho_true = np.outer(psi, psi.T.conj()) # Get data from QVM tomo_expt = generate_state_tomography_experiment(state_prep, qubits) results = list(estimate_observables(qc=test_qc, obs_expt=tomo_expt, num_shots=1000, symm_type=-1)) results = list(calibrate_observable_estimates(test_qc, results)) return results, rho_true
def test_expectations_at_depth(qvm): qvm.qam.random_seed = 5 q = 0 qubits = (q, ) expected_outcomes = [1., 0, -1., 0] for depth in [0, 1, 2, 3, 4]: prep, meas, settings = rpe.all_eigenvector_prep_meas_settings( qubits, I(q)) depth_many_rot = [RZ(pi / 2, q) for _ in range(depth)] program = Program(prep) + sum(depth_many_rot, Program()) + Program(meas) expt = ObservablesExperiment(list(settings), program) results = list(estimate_observables(qvm, expt)) for res in results: meas_dir = res.setting.observable[q] idx = ((depth - 1) if meas_dir == 'Y' else depth) % 4 expected = expected_outcomes[idx] exp = res.expectation assert np.allclose(expected, exp, atol=.05)
def acquire_qubit_spectroscopy_data(qc: QuantumComputer, experiments: Sequence[ObservablesExperiment], num_shots: int = 500, show_progress_bar: bool = False) \ -> List[List[ExperimentResult]]: """ A standard data acquisition method for all experiments in this module. Each input ObservablesExperiment is simply run in series, and a list of results are returned for each experiment in the corresponding order. :param qc: a quantum computer on which to run the experiments :param experiments: the ObservablesExperiments to run on the given qc :param num_shots: the number of shots to collect for each experiment. :param show_progress_bar: displays a progress bar via tqdm if true. :return: a list of ExperimentResults for each ObservablesExperiment, returned in order of the input sequence of experiments. """ results = [] for expt in tqdm(experiments, disable=not show_progress_bar): results.append(list(estimate_observables(qc, expt, num_shots))) return results
* 0 -- no symmetrization * 1 -- symmetrization using an OA with strength 1 * 2 -- symmetrization using an OA with strength 2 * 3 -- symmetrization using an OA with strength 3 :param calibrate_observables: boolean flag indicating whether observable estimates are calibrated using the same level of symmetrization as exhaustive_symmetrization. Likely, for the best (although slowest) results, symmetrization type should accommodate the maximum weight of any observable estimated. :param show_progress_bar: displays a progress bar via tqdm if true. :return: results from running the given DFE experiment. These can be passed to estimate_dfe """ res = list( estimate_observables(qc, expt, num_shots=num_shots, symm_type=symm_type, active_reset=active_reset, show_progress_bar=show_progress_bar)) if calibrate_observables: res = list( calibrate_observable_estimates(qc, res, num_shots=num_shots, symm_type=symm_type, active_reset=active_reset)) return res def estimate_dfe(results: List[ExperimentResult], kind: str) -> Tuple[float, float]:
def acquire_rpe_data(qc: QuantumComputer, experiments: Sequence[ObservablesExperiment], multiplicative_factor: float = 1.0, additive_error: Optional[float] = None, min_shots: int = 500, active_reset: bool = False, mitigate_readout_errors: bool = False, show_progress_bar: bool = False) \ -> List[List[ExperimentResult]]: """ Run each experiment in the sequence of experiments. The number of shots run at each depth can be modified indirectly by adjusting multiplicative_factor and additive_error. :param experiments: :param qc: a quantum computer, e.g. QVM or QPU, that runs the experiments :param multiplicative_factor: ad-hoc factor to multiply the number of shots per iteration. See num_trials() which computes the optimal number of shots per iteration. :param additive_error: estimate of the max additive error in the experiment, see num_trials() :param min_shots: the minimum number of shots used to estimate a particular observable; in contrast to the theoretical assumption that shot-rate is independent of number of shots, in practice the shot-rate is approximately proportional to the number of shots up to about 500 so taking fewer shots is sub-optimal. :param active_reset: Boolean flag indicating whether experiments should begin with an active reset instruction (this can make the collection of experiments run a lot faster). :param mitigate_readout_errors: Boolean flag indicating whether bias due to imperfect readout should be corrected :param show_progress_bar: displays a progress bar via tqdm if true. :return: a copy of the input experiments populated with results in each layer. """ depths = [2**idx for idx in range(len(experiments))] max_depth = max(depths) results = [] for depth, expt in zip(tqdm(depths, disable=not show_progress_bar), experiments): theoretical_optimum = num_trials(depth, max_depth, multiplicative_factor, additive_error) num_shots = max(min_shots, theoretical_optimum) # TODO: fix up mitigate_readout_errors. if mitigate_readout_errors: res = list( estimate_observables(qc, expt, num_shots=num_shots, active_reset=active_reset, symm_type=-1)) results.append( list( calibrate_observable_estimates(qc, res, num_shots=num_shots))) else: results.append( list( estimate_observables(qc, expt, num_shots=num_shots, active_reset=active_reset))) return results