def test_variance_bootstrap(): qubits = [0, 1] qc = get_test_qc(n_qubits=len(qubits)) state_prep = Program([H(q) for q in qubits]) state_prep.inst(CZ(qubits[0], qubits[1])) tomo_expt = generate_state_tomography_experiment(state_prep, qubits) results = list( measure_observables(qc=qc, tomo_experiment=tomo_expt, n_shots=4000)) estimate, status = iterative_mle_state_estimate(results=results, qubits=qubits, dilution=0.5) rho_est = estimate.estimate.state_point_est purity = np.trace(rho_est @ rho_est) purity = np.real_if_close(purity) assert purity.imag == 0.0 def my_mle_estimator(_r, _q): return iterative_mle_state_estimate(results=_r, qubits=_q, dilution=0.5, entropy_penalty=0.0, beta=0.0)[0] boot_purity, boot_var = estimate_variance(results=results, qubits=qubits, tomo_estimator=my_mle_estimator, functional=dm.purity, n_resamples=5, project_to_physical=False) np.testing.assert_allclose(purity, boot_purity, atol=2 * np.sqrt(boot_var), rtol=0.01)
def test_generate_1q_state_tomography_experiment(): qubits = [0] prog = Program(I(qubits[0])) one_q_exp = generate_state_tomography_experiment(prog, qubits=qubits) dimension = 2**len(qubits) assert [one_q_exp[idx][0].out_operator[qubits[0]] for idx in range(0, dimension ** 2)] == \ ['I', 'X', 'Y', 'Z']
def test_generate_2q_state_tomography_experiment(): p = Program() p += H(0) p += CZ(0, 1) two_q_exp = generate_state_tomography_experiment(p, qubits=[0, 1]) dimension = 2**2 assert [str(two_q_exp[idx][0].out_operator) for idx in list(range(0, dimension ** 2))] == \ ['(1+0j)*I', '(1+0j)*X1', '(1+0j)*Y1', '(1+0j)*Z1', '(1+0j)*X0', '(1+0j)*X0*X1', '(1+0j)*X0*Y1', '(1+0j)*X0*Z1', '(1+0j)*Y0', '(1+0j)*Y0*X1', '(1+0j)*Y0*Y1', '(1+0j)*Y0*Z1', '(1+0j)*Z0', '(1+0j)*Z0*X1', '(1+0j)*Z0*Y1', '(1+0j)*Z0*Z1']
def run(qc: QuantumComputer, seq: List[Program], subgraph: List[List[int]], num_trials: int) -> np.ndarray: prog = merge_programs(seq) # TODO: parallelize results = [] for qubits in subgraph: state_prep = prog tomo_exp = generate_state_tomography_experiment(state_prep, qubits=qubits) _rs = list(measure_observables(qc, tomo_exp, num_trials)) # Inelegant shim from state tomo refactor. To clean up! expectations=[r.expectation for r in _rs[1:]] variances=[r.std_err ** 2 for r in _rs[1:]] results.append((expectations, variances)) return results
def single_q_tomo_fixture(): qubits = [0] qc = get_test_qc(n_qubits=len(qubits)) # 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(measure_observables(qc=qc, tomo_experiment=tomo_expt, n_shots=4000)) return results, rho_true
def two_q_tomo_fixture(test_qc): qubits = [0, 1] # Generate random unitary u_rand1 = haar_rand_unitary(2 ** 1, rs=np.random.RandomState(52)) u_rand2 = haar_rand_unitary(2 ** 1, rs=np.random.RandomState(53)) state_prep = Program().defgate("RandUnitary1", u_rand1).defgate("RandUnitary2", u_rand2) state_prep.inst(("RandUnitary1", qubits[0])).inst(("RandUnitary2", qubits[1])) # True state wfn = NumpyWavefunctionSimulator(n_qubits=2) psi = wfn \ .do_gate_matrix(u_rand1, qubits=[0]) \ .do_gate_matrix(u_rand2, qubits=[1]) \ .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