#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
#include <gsl/gsl_complex.h>
#include <gsl/gsl_complex_math.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_vector.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
#include <gsl/gsl_eigen.h>
#include <gsl/gsl_linalg.h>
#include <gsl/gsl_multimin.h>
#include "header.h"
Go to the source code of this file.
Functions | |
void | apply_noise (gsl_vector *n) |
Applies Poisson shot noise to measurements stored in n. | |
void | fill_tangle_entropy_plane () |
Routine which is used to fill the entire entropy-tangle plane for 2 qubits and perform all tomography routines on each state, this is described in detail in the paper. | |
void | find_N () |
Locates the first lowest value of N (the number of times the experiment has to be performed in real life) for tomography to yield a sufficiently high fidelity value in practice. | |
void | init () |
Main initialisation function that loads all the data into memory. | |
void | linear_estimate (gsl_vector *n, gsl_matrix_complex *density_linear) |
Performs linear reconstruction of the underlying density matrix into density_linear from measurements in n. | |
void | load_basis () |
Initialisation function which loads hard-coded values of projection and Pauli operators into memory. | |
int | main (void) |
Main function of the program. | |
void | measure_state (gsl_matrix_complex *density_matrix, gsl_vector *n) |
Simulates experimental measurements of a particular state, characterised by density_matrix, writes measurement outcomes into pre-allocated n. | |
void | MLE (gsl_vector *n, gsl_matrix_complex *density_physical, gsl_matrix_complex *density_linear, gsl_matrix_complex *density_mle, gsl_matrix *fidelities, gsl_matrix *times, gsl_matrix *f_vals, gsl_matrix *abs_gradient, int trial) |
Performs MLE tomography on measurements stored in n, output in density_mle. See detailed docs for other arguments. | |
void | my_df (const gsl_vector *x, void *params, gsl_vector *g) |
Analytic gradient of the MLE function, also used by GSL optimisation routine, refer to GNU manual for parameter meaning. | |
double | my_f (const gsl_vector *x, void *params) |
MLE function used by GSL for optimisation, refer to GNU manual for this. | |
void | my_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *g) |
MLE function and analytic gradient computed together, this saves time so that GSL doesn't have to call each function separately, refer to GSL manual for parameter meaning. | |
void | prepare_state (gsl_matrix_complex *density_matrix) |
Responsible for directing which particular tomography to simulate and how. This is guided by the STATE global variable selector in header.h. | |
void | quick_and_dirty (gsl_matrix_complex *density_linear, gsl_matrix_complex *density_quick) |
Quick and Dirty Procedure as discussed in the paper, where eigenvalues of density_linear are corrected into density_quick. | |
void | quick_and_dirty_2 (gsl_matrix_complex *density_linear, gsl_matrix_complex *density_quick) |
Forced Purity routine as discussed in the paper, the naming is somewhat misleading, here density_quick is the resultant FP density matrix. | |
void | states_1_to_10 () |
Groups anything that has to do with values 1-10 of STATE global variable described in header.h. |
Numerical State Tomography Using GSL -> www.gnu.org/software/gsl Copyright (C) 2007 Max S Kaznady
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation;
AUTHOR Max S Kaznady, [EMAIL PROTECTED] max.kaznady@gmail.com Summer, 2007
Definition in file main.c.
void init | ( | ) |
Main initialisation function that loads all the data into memory.
scale parameter - number of times experiment is performed
Definition at line 1835 of file main.c.
References kron(), load_basis(), mu_array, mu_cell, N, NQ, one, ones, sig_array, sigma_cell, and zero.
Referenced by main().
01835 { 01836 //gsl_matrix_complex *mu_array = load_basis(); 01837 load_basis(); 01838 //init constants 01839 GSL_SET_COMPLEX(&zero, 0, 0); 01840 GSL_SET_COMPLEX(&one, 1, 0); 01841 ones = gsl_matrix_complex_alloc(pow(2, NQ), pow(2, NQ)); 01842 gsl_matrix_complex_set_all(ones, one); 01843 //allocate mu_cell 01844 int i; 01845 mu_cell[0] = gsl_matrix_complex_alloc(2, 2); 01846 gsl_matrix_complex_memcpy(mu_cell[0], mu_array[0]); 01847 for (i=1; i<NQ; i++) { 01848 mu_cell[i] = gsl_matrix_complex_alloc((mu_cell[i-1]->size1)*2, (mu_cell[i-1]->size2)*2); 01849 //printf("entering kron\n"); 01850 //printf("rows mu_cell[i-1] : rows %d\n", mu_cell[i-1]->size1); 01851 //printf("rows mu_array[0] : rows %d\n", mu_array[0]->size1); 01852 kron(mu_cell[i-1], mu_array[0], mu_cell[i]); 01853 } 01854 01855 //initialize sigma_cell 01856 sigma_cell[0] = gsl_matrix_complex_alloc(2,2); 01857 gsl_matrix_complex_memcpy(sigma_cell[0], sig_array[0]); 01858 for (i=1; i<NQ; i++) { 01859 sigma_cell[i] = gsl_matrix_complex_alloc((sigma_cell[i-1]->size1)*2, (sigma_cell[i-1]->size2)*2); 01860 kron(sigma_cell[i-1], sig_array[0], sigma_cell[i]); 01861 } 01862 01863 //! scale parameter - number of times experiment is performed 01864 N = 1000000; 01865 }
void MLE | ( | gsl_vector * | n, | |
gsl_matrix_complex * | density_physical, | |||
gsl_matrix_complex * | density_linear, | |||
gsl_matrix_complex * | density_mle, | |||
gsl_matrix * | fidelities, | |||
gsl_matrix * | times, | |||
gsl_matrix * | f_vals, | |||
gsl_matrix * | abs_gradient, | |||
int | trial | |||
) |
Performs MLE tomography on measurements stored in n, output in density_mle. See detailed docs for other arguments.
Detailed description:
n - vector containing experimental measurements.
density_physical - actual density matrix of the underlying state with state error applied to it, used to compute fidelity.
density_linear - entries of this matrix are used as an initial guess, the name is misleading, because the argument in the calling program is actually density_quick, so we are in fact using the values of the Quick and Dirty routine as a starting point for MLE.
density_mle - density matrix obtained using MLE is stored here.
fidelities - stores fidelities between density_physical and density_mle at each step of the iteration as it progresses.
times - vector of runtimes for each iteration.
f_vals - values of the MLE function for each iteration.
abs_gradient - absolute value of the gradient of the MLE function for each iteration.
trial - number of trials to be performed.
Definition at line 1166 of file main.c.
References abs_val(), CUT_ITER, fidelity(), KEEP_GOING, make_T(), MAX_FIDELITY, MAXITER, MILLION, my_df(), my_f(), my_fdf(), NQ, one, trace(), VERBOSE, and zero.
Referenced by fill_tangle_entropy_plane(), and states_1_to_10().
01166 { 01167 01168 //first perform Cholesky Decomposition 01169 // FIX THIS! use a guess for now 01170 gsl_vector *x = gsl_vector_alloc(pow(4,NQ)); 01171 //gsl_vector_set_all(x, -100); 01172 01173 int counter, limiter, nu; 01174 counter = 1; 01175 for (limiter = 0; limiter < pow(2, NQ); limiter++) { 01176 for (nu=1+limiter; nu <= pow(2, NQ); nu++) { 01177 if (counter<=pow(2, NQ)) { 01178 gsl_vector_set(x, counter-1, GSL_REAL(gsl_matrix_complex_get(density_linear, nu-1, nu-1))); 01179 } else { 01180 gsl_vector_set(x, counter-1, GSL_REAL(gsl_matrix_complex_get(density_linear, nu-1, nu-1-limiter))); 01181 gsl_vector_set(x, counter, GSL_IMAG(gsl_matrix_complex_get(density_linear, nu-1, nu-1-limiter))); 01182 //nu++; 01183 counter++; 01184 01185 } 01186 counter++; 01187 } 01188 } 01189 //display_vector_real(x); 01190 //display_matrix(density_linear); 01191 01192 // for (nu=0; nu<pow(4,NQ); nu++) 01193 // gsl_vector_set(x, nu, abs(gsl_vector_get(x,nu))); 01194 01195 //gsl_vector_set_all(x, -100); 01196 gsl_vector_set(x, 0, pow(4, -NQ)); 01197 01198 //initialize the minimizer 01199 const gsl_multimin_fdfminimizer_type *T; 01200 gsl_multimin_fdfminimizer *s; 01201 //T = gsl_multimin_fdfminimizer_conjugate_fr; //minimizer type 01202 //T = gsl_multimin_fdfminimizer_conjugate_pr; 01203 //T = gsl_multimin_fdfminimizer_steepest_descent; 01204 //T = gsl_multimin_fdfminimizer_vector_bfgs; 01205 T = gsl_multimin_fdfminimizer_vector_bfgs2; 01206 01207 s = gsl_multimin_fdfminimizer_alloc(T, pow(4,NQ)); 01208 gsl_multimin_function_fdf my_func; 01209 size_t iter = 0; 01210 int status; 01211 01212 my_func.f = &my_f; 01213 my_func.df = &my_df; 01214 my_func.fdf = &my_fdf; 01215 //my_func.fdf = NULL; 01216 my_func.n = pow(4,NQ); 01217 my_func.params = n; 01218 01219 // Function: int gsl_multimin_fdfminimizer_set (gsl_multimin_fdfminimizer * s, gsl_multimin_function_fdf * fdf, const gsl_vector * x, double step_size, double tol) 01220 // 01221 // This function initializes the minimizer s to minimize the function fdf starting from the initial point x. The size of the first trial step is given by step_size. The accuracy of the line minimization is specified by tol. The precise meaning of this parameter depends on the method used. Typically the line minimization is considered successful if the gradient of the function g is orthogonal to the current search direction p to a relative accuracy of tol, where dot(p,g) < tol |p| |g|. A tol value of 0.1 is suitable for most purposes, since line minimization only needs to be carried out approximately. Note that setting tol to zero will force the use of “exact” line-searches, which are extremely expensive. — Function: int gsl_multimin_fminimizer_set (gsl_multimin_fminimizer * s, gsl_multimin_function * f, const gsl_vector * x, const gsl_vector * step_size) 01222 01223 gsl_multimin_fdfminimizer_set (s, &my_func, x, 0.01, 1e-4); 01224 //gsl_multimin_fdfminimizer_set (s, &my_func, x, 1e-15, 1e-15); 01225 //gsl_multimin_fdfminimizer_set (s, &my_func, x, 0.0001, 1e-5); 01226 //gsl_multimin_fdfminimizer_set (s, &my_func, x, 0.0001, 0); 01227 //gsl_multimin_fdfminimizer_set (s, &my_func, x, pow(1,-10^(NQ+4)), 1e-4); 01228 01229 int truth=1; 01230 01231 //temporary MLE matrix 01232 gsl_matrix_complex *temp_mle = gsl_matrix_complex_alloc(pow(2, NQ), pow(2, NQ)); 01233 //temporary T matrix, used to construct temporary MLE matrix 01234 gsl_matrix_complex *T_mat = gsl_matrix_complex_alloc(pow(2, NQ), pow(2, NQ)); 01235 01236 //init a timer 01237 //struct timeval tpstart, tpend; 01238 //double timedif; 01239 01240 struct timeval tpstart_iter, tpend_iter; 01241 double timedif_iter; 01242 01243 double temp_fid; 01244 01245 //allocate previous fidelity value - will be overwritten later 01246 double previous_fidelity = -999.0; 01247 double previous_f_value = -1.0; //for first iteration 01248 gsl_vector *previous_t = gsl_vector_alloc(pow(4, NQ)); 01249 01250 do { 01251 01252 gettimeofday(&tpstart_iter, NULL); 01253 01254 status = gsl_multimin_fdfminimizer_iterate (s); 01255 //printf("HERE\n"); 01256 01257 if (status) 01258 break; 01259 01260 status = gsl_multimin_test_gradient (s->gradient, 1e-3); 01261 //status = gsl_multimin_test_gradient (s->gradient, 0); 01262 01263 if (status == GSL_SUCCESS) 01264 printf ("Minimum found.\n"); 01265 01266 if (VERBOSE) 01267 printf("%d: f() = %7.3f \n", iter, s->f); 01268 01269 //end timer 01270 gettimeofday(&tpend_iter, NULL); 01271 timedif_iter = (double) MILLION*(tpend_iter.tv_sec - tpstart_iter.tv_sec) + tpend_iter.tv_usec - tpstart_iter.tv_usec; 01272 01273 //construct temporaty density matrix, check its fidelity 01274 make_T(s->x, T_mat); 01275 gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, one, T_mat, T_mat, zero, temp_mle); 01276 gsl_matrix_complex_scale(temp_mle, gsl_complex_rect(1.0/GSL_REAL(trace(temp_mle)), 0)); 01277 01278 //calculate temporary fidelity 01279 temp_fid = fidelity(temp_mle, density_physical); 01280 //printf("fidelity : %e\n", temp_fid); 01281 01282 //termination criteria 01283 if (temp_fid >= MAX_FIDELITY && KEEP_GOING==0) 01284 truth = 0; 01285 01286 //stop minimizing if func value difference is less than 1 01287 if (CUT_ITER == 1) { 01288 if (iter>0) { //make sure this is not the first iteration 01289 if ((previous_f_value - s->f) <= 1.0) { 01290 truth = 0; 01291 } 01292 } 01293 } 01294 //update function value 01295 previous_f_value = s->f; 01296 01297 if (KEEP_GOING == 0) { //if we want to exit at highest fidelity 01298 //fidelity is starting to decrease 01299 //so stop the iteration, return to previous fidelity state 01300 if (previous_fidelity > temp_fid) { 01301 truth = 0; 01302 gsl_vector_memcpy(s->x, previous_t); 01303 } 01304 } 01305 01306 //update fidelity and t_vector 01307 previous_fidelity = temp_fid; 01308 gsl_vector_memcpy(previous_t, s->x); 01309 01310 //Record outcomes for this iteration 01311 //if (trial<NUMTRIALS) { 01312 gsl_matrix_set(fidelities, trial, iter, temp_fid); 01313 gsl_matrix_set(times, trial, iter, timedif_iter); 01314 gsl_matrix_set(f_vals, trial, iter, s->f); 01315 gsl_matrix_set(abs_gradient, trial, iter, abs_val(s->gradient)); 01316 //} 01317 01318 //another termination criteria 01319 if ((s->f) == GSL_POSINF) { 01320 printf("Either no point in using MLE or we have a bad guess\n"); 01321 truth = 0; 01322 } 01323 01324 //update iteration number 01325 iter++; 01326 01327 } while (status == GSL_CONTINUE && truth && iter<MAXITER); 01328 01329 if (!VERBOSE) 01330 printf("%d: f() = %7.3f \n", iter, s->f); 01331 01332 //construct temporaty density matrix, check its fidelity 01333 make_T(s->x, T_mat); 01334 gsl_blas_zgemm(CblasConjTrans, CblasNoTrans, one, T_mat, T_mat, zero, density_mle); 01335 gsl_matrix_complex_scale(density_mle, gsl_complex_rect(1.0/GSL_REAL(trace(density_mle)), 0)); 01336 01337 //deallocate memory 01338 gsl_multimin_fdfminimizer_free(s); 01339 gsl_vector_free(x); 01340 gsl_vector_free(previous_t); 01341 gsl_matrix_complex_free(T_mat); 01342 gsl_matrix_complex_free(temp_mle); 01343 01344 }