7 #include "supplement.h"
10 /****************************************************************************
11 * SPARSIFY procedure introduced by Bravyi et al.
12 * (S. Bravyi, D. Browne, P. Calpin, E. Campbell, D. Gosset, and
13 * M. Howard, Simulation of Quantum Circuits by Low-Rank Sta-
14 * bilizer Decompositions, Quantum 3, 181 (2019).)
15 * Outputs stabilizer state indices in stabStateIndices
16 * as understood by weaksim.c in the tilde'd "computational" basis.
17 ***Needs address of stabStateIndices since it allocates it.***
18 * 'numStabStates' is the number of stabilizer state indices,
19 * 'T' is the number of T-gate magic states, 'phi' is the angle of the
20 * intermediate diagonal magic state, and 'delta' is the additive
22 * For phi=pi/4 this should give you a uniform distro over [0,2^T-1].
23 ****************************************************************************/
25 // Note: Make sure you seed the random number generator before calling this!
26 // i.e. srand((unsigned)time(NULL));
27 int sparsify(long **stabStateIndices, int *numStabStates, int T, double phi, double delta, int coherentSampling) {
31 double L1Norm = pow(sqrt(1-sin(phi)) + sqrt(1-cos(phi)),T);
32 //printf("L1Norm squared (= stabilizer extent) = %lf\n", pow(L1Norm,2.0));
34 printf("delta = %lf\n", delta);
36 //printf("L1Norm = %lf\n", L1Norm);
41 if(coherentSampling) {
42 printf("Performing coherent sampling!\n");
43 gamma = 1.0 + (1.0 - 1.0/pow(2.0,0.02*T))*T;
44 // since we will be taking a multiple of (T+1) samples, we round numStabStates up to the nearest multiple of (T+1)
45 *numStabStates = ceil(((pow(L1Norm,2.0)-gamma)/pow(delta,2.0))/((double)(T+1)))*(T+1);
48 //gamma = 1.0 + (1.0 - 1.0/pow(2.0,0.02*T))*T;
49 //*numStabStates = ceil(((pow(L1Norm,2.0)-gamma)/pow(delta,2.0))/((double)(T+1)))*(T+1);
51 *numStabStates = ceil((pow(L1Norm,2.0)-gamma)/pow(delta,2.0));
56 printf("numStabStates = %d\n", *numStabStates);
59 double cumL1Norm, sum;
61 int shiftCounter, digit;
63 *stabStateIndices = calloc(*numStabStates,sizeof(long));
65 for(i=0; i<*numStabStates; i=i+increment) {
66 // We will pick our stabilizer index by first selecting how many tilde'd 1s it will have
67 // by randomly sampling weighted by the binomial expansion of that in the L1norm,
68 // and then uniformly randomly picking which digits to make that many tilde 1's
70 // Get random number and scale by the L_1 norm of the t-qubit full stabilizer decomposition
71 cumL1Norm = ((((double)rand())/((double)(RAND_MAX)))*L1Norm); // this is the "cumulative" L1 norm of the randomly selected state if you index by the tilde'd computational basis states truncated to an integer
73 //printf("%d cumL1Norm = %lf\n", i, cumL1Norm);
75 // add cumulative L1 norm to sum until you are greater than cumL1Norm of random state
76 //printf("binomcoeff(%d,%d)=%lf\n", T, j, binomcoeff(T,j));
78 sum += binomcoeff(T,j)*(sqrt(1.0-cos(phi)))*pow(sqrt(1.0 - cos(0.25*PI)),T-1-j)*pow(sqrt(1.0-sin(phi)),j);
80 sum += pow((sqrt(1.0-sin(phi))),T);
81 //printf("%d sum=%lf\n", j, sum);
82 if(cumL1Norm <= sum) {
83 // the randomly chosen tilde'd computational state will have j tilde'd 1s
84 // Now uniformly randomly choose a state with j tilde'd 1s
85 //printf("%d tilde'd ones\n", (T-j));
87 for(k=0; k<(T-j); k++) {
88 digit = (int)((((double)rand())/((double)(RAND_MAX)))*(T-k));
89 //printf("digit=%d\n", digit);
92 // first shift past leading 1's
93 while(tmpIndex%2 == 1) {
94 tmpIndex /= 2; // keep shifting to the left past any 1's that have already been assigned
97 // now shift past 'digit' 0's
98 for(l=0; l<digit; l++){
99 tmpIndex /= 2; // shift to the left by one (base 2 arithmetic)
101 while(tmpIndex%2 == 1) {
102 tmpIndex /= 2; // keep shifting to the left past any 1's that have already been assigned
106 //printf("shiftCounter = %d\n", shiftCounter);
107 index += pow(2,shiftCounter);
109 (*stabStateIndices)[i] = index;
110 //printf("first index = %d\n", index);
113 //(*stabStateIndices)[i+k] = index ^ (long)pow(2,k-1); // flip the (k-1)th bit index
114 supplement(&(*stabStateIndices)[i], T);
117 //printf("%lf\n", sum);
119 //printf("index:%ld\n ", index);
120 //printf("(*stabStateIndices)[%d]:%ld\n ", i, (*stabStateIndices)[i]);
128 // binomial coefficient
129 double binomcoeff(int m, int n) {
130 //((double)fac(T))/((double)(fac(j)*fac(T-j)))
134 for(i=n+1;i<=m;i++) {
135 coeff *= (double)i/((double)i-n);
136 //printf("%lf ", coeff);