def sim_qubit_fid(n_meas, n_meas_rep, meas_dist, n_trials=100, n_particles=1000, n_rec=15): r"""Calculates the average fidelity of the optimal estimator (approximated by SMC) averaged over Haar random pure states and a random sample of measurement outcomes. The estimator is calculated at a given number of interim times throughout the tomographic process. :param n_meas: The number of copies of the system given in each tomographic run :type n_meas: Integer :param n_meas_rep: The number of measurement outcomes to average the fidelity over for each copy of the system in a tomographic run :type n_meas_rep: Integer :param meas_dist: Object defining the distribution from which to draw measurement directions :type meas_dist: Object possessing `sample(n)` function that returns a numpy.array((2, n)) of unit vectors in :math:`\mathbb{C}^2` :param n_trials: The number of tomographic runs (aka samples from the pure state prior) the fidelity is averaged over :type n_trials: Integer :param n_particles: Number of SMC particles to use :type n_particles: Integer :param n_rec: Number of places to record average fidelity (on a log scale) :type n_rec: Integer :returns: An array with the calculated average fidelities at the specified times for all tomographic runs :return type: numpy.array((n_trials, n_rec)) """ n_qubits = 1 # This function isn't guaranteed to generalize by changing # this value, but it is included here to aid readability and # aid any future generalization efforts dim = 2 * n_qubits # Record data on a logarithmic scale rec_idxs = np.unique(np.round(np.logspace(0, np.log10(n_meas), n_rec))) n_rec = rec_idxs.shape[0] # Allocate result array fidelities = np.empty((n_trials, n_rec)) # Instantiate model and state prior model = HaarTestModel(n_qubits=n_qubits) prior = HaarDistribution(n_qubits=n_qubits) # Sample all the measurement directions used at once (since some samplers # might be more efficient doing things this way) raw_meas_dirs = meas_dist.sample(n_trials * n_meas) # Reshape the measurement directions to be a n_trials x n_meas array of unit # vectors in C^2 meas_dirs = np.reshape(raw_meas_dirs.T, (n_trials, n_meas, 2)) for trial_idx in xrange(n_trials): # Pick a random true state and instantiate the Bayes updater true_state = prior.sample() true_vec = model.param2vec(true_state) updater = SMCUpdater(model, n_particles, prior, resampler=LiuWestResampler(a=0.95, h=None)) rec_idx = 0 for meas_idx in xrange(n_meas): meas_dir = meas_dirs[trial_idx, meas_idx] # Set the experimental parameters for the measurement expparams = np.array([(meas_dir, n_meas_rep)], dtype=model.expparams_dtype) # Simulate data and update data = model.simulate_experiment(true_state, expparams) updater.update(data, expparams) if meas_idx + 1 in rec_idxs: # Generate the estimated state -> average then maximal # eigenvector weights = updater.particle_weights locs = updater.particle_locations avg_state = 1j * np.zeros([dim, dim]) for idx_locs in xrange(n_particles): psi = model.param2vec(locs[idx_locs][np.newaxis]) avg_state += weights[idx_locs] * np.outer(psi, psi.conj()) eigs = la.eig(avg_state) max_eig = eigs[1][:, np.argmax(eigs[0])] fidelities[trial_idx, rec_idx] = model.fidelity(true_vec, max_eig) rec_idx += 1 # Give progress updates print(100 * ((trial_idx + 1) / n_trials)) return fidelities
def fid_smc(n_meas, K, n_qubits=1, n_trials=100, n_particles=1000, n_rec=15): """ Evaluates the average fidelity incurred by using sequential Monte Carlo (SMC) to estimate pure states. :param n_meas: The number of copies of the system given in each tomographic run :type n_meas: Integer :param K: Number of single-shot measurements :type K: Integer :param n_trials: Number of times to run the SMC estimation procedure. :type n_trials: Integer :param n_particles: Number of SMC particles to use. :type n_particles: Integer :param n_rec: Number of place to record data (on a log scale) :type n_rec: Integer :returns: Dictionary of various fidelities and timings :return type: Dictionary """ dim = int(2 ** n_qubits) # Record data on a logarithmic scale rec_idx = np.unique(np.round(np.logspace(0, np.log10(n_meas), n_rec))) n_rec = rec_idx.shape[0] # Allocate arrays to hold results. fidelity_mub = np.empty((n_trials, n_rec)) fidelity_opt = np.empty((n_trials, n_rec)) fidelity_WM = np.empty((n_trials, n_rec)) fidelity_DST = np.empty((n_trials, n_rec)) # Instantiate models and distributions model = HaarTestModel(n_qubits=n_qubits) prior = HaarDistribution(n_qubits=n_qubits) measMUB = MUBDistribution() measWM = WeakMeasDistribution(eps=0.05) measDST = DSTDistribution(0.1) timing = np.empty((n_trials,)) # Make and show a progress bar. """ prog = ProgressBar() prog.show() """ for idx_trial in xrange(n_trials): # Pick a random true state and instantiate the Bayes updater true_state = prior.sample() true_vec = model.param2vec(true_state) updater_opt = SMCUpdater(model, n_particles, prior, resampler=LiuWestResampler(a=0.95, h=None)) updater_mub = SMCUpdater(model, n_particles, prior, resampler=LiuWestResampler(a=0.95, h=None)) updater_WM = SMCUpdater(model, n_particles, prior, resampler=LiuWestResampler(a=0.95, h=None)) updater_DST = SMCUpdater(model, n_particles, prior, resampler=LiuWestResampler(a=0.95, h=None)) # Record the start time. tic = time.time() idx_rec = 0 for idx_meas in xrange(n_meas): # Choose a random measurement direction foo = prior.sample() meas_opt = model.param2vec(foo) meas_mub = measMUB.sample() meas_WM = measWM.sample()[:, 0] meas_DST = measDST.sample()[:, 0] expparams_opt = np.array([(meas_opt, K)], dtype=model.expparams_dtype) expparams_mub = np.array([(meas_mub, K)], dtype=model.expparams_dtype) expparams_WM = np.array([(meas_WM, K)], dtype=model.expparams_dtype) expparams_DST = np.array([(meas_DST, K)], dtype=model.expparams_dtype) # Simulate data and update data_opt = model.simulate_experiment(true_state, expparams_opt) updater_opt.update(data_opt, expparams_opt) data_mub = model.simulate_experiment(true_state, expparams_mub) updater_mub.update(data_mub, expparams_mub) data_WM = model.simulate_experiment(true_state, expparams_WM) updater_WM.update(data_WM, expparams_WM) data_DST = model.simulate_experiment(true_state, expparams_DST) updater_DST.update(data_DST, expparams_DST) if idx_meas + 1 in rec_idx: # Generate the estimated state -> average then maximal eigenvector weights = updater_opt.particle_weights locs = updater_opt.particle_locations ave_state = 1j * np.zeros([dim, dim]) for idx_locs in xrange(n_particles): psi = model.param2vec(locs[idx_locs][np.newaxis]) ave_state += weights[idx_locs] * np.outer(psi, psi.conj()) eigs = la.eig(ave_state) max_eig = eigs[1][:, np.argmax(eigs[0])] fidelity_opt[idx_trial, idx_rec] = model.fidelity(true_vec, max_eig) # MUB weights = updater_mub.particle_weights locs = updater_mub.particle_locations ave_state = 1j * np.zeros([dim, dim]) for idx_locs in xrange(n_particles): psi = model.param2vec(locs[idx_locs][np.newaxis]) ave_state += weights[idx_locs] * np.outer(psi, psi.conj()) eigs = la.eig(ave_state) max_eig = eigs[1][:, np.argmax(eigs[0])] fidelity_mub[idx_trial, idx_rec] = model.fidelity(true_vec, max_eig) # Weak Measurement weights = updater_WM.particle_weights locs = updater_WM.particle_locations ave_state = 1j * np.zeros([dim, dim]) for idx_locs in xrange(n_particles): psi = model.param2vec(locs[idx_locs][np.newaxis]) ave_state += weights[idx_locs] * np.outer(psi, psi.conj()) eigs = la.eig(ave_state) max_eig = eigs[1][:, np.argmax(eigs[0])] fidelity_WM[idx_trial, idx_rec] = model.fidelity(true_vec, max_eig) # DST Measurement weights = updater_DST.particle_weights locs = updater_DST.particle_locations ave_state = 1j * np.zeros([dim, dim]) for idx_locs in xrange(n_particles): psi = model.param2vec(locs[idx_locs][np.newaxis]) ave_state += weights[idx_locs] * np.outer(psi, psi.conj()) eigs = la.eig(ave_state) max_eig = eigs[1][:, np.argmax(eigs[0])] fidelity_DST[idx_trial, idx_rec] = model.fidelity(true_vec, max_eig) idx_rec += 1 # Record how long it took us. timing[idx_trial] = time.time() - tic print(100 * ((idx_trial + 1) / n_trials)) # prog.value = 100 * ((idx_trial + 1) / n_trials) return { "fidelity_opt": fidelity_opt, "fidelity_mub": fidelity_mub, "fidelity_WM": fidelity_WM, "fidelity_DST": fidelity_DST, "timing": timing, }