main.c File Reference

This chunk of source code controls the NST using functions from utilities.c ; function prototypes are in header.h. More...

#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.


Detailed Description

This chunk of source code controls the NST using functions from utilities.c ; function prototypes are 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.


Function Documentation

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 }


Generated on Thu Sep 11 10:27:18 2008 for Numerical State Tomography by  doxygen 1.5.6