|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971 |
- // CHP: CNOT-Hadamard-Phase
- // Stabilizer Quantum Computer Simulator
- // by Scott Aaronson
- // Last modified June 30, 2004
-
- // Thanks to Simon Anders and Andrew Cross for bugfixes
-
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <Python.h>
- #include <time.h>
-
-
- #define CNOT 0
- #define HADAMARD 1
- #define PHASE 2
- #define MEASURE 3
-
-
-
- struct QProg
- // Quantum circuit
-
- {
-
- long n; // # of qubits
- long T; // # of gates
- char *a; // Instruction opcode
- long *b; // Qubit 1
- long *c; // Qubit 2 (target for CNOT)
- int DISPQSTATE; // whether to print the state (q for final state only, Q for every iteration)
- int DISPTIME; // whether to print the execution time
- int SILENT; // whether NOT to print measurement results
- int DISPPROG; // whether to print instructions being executed as they're executed
- int SUPPRESSM; // whether to suppress actual computation of determinate measurement results
-
- };
-
-
-
- struct QState
-
- // Quantum state
-
- {
-
- // To save memory and increase speed, the bits are packed 32 to an unsigned long
- long n; // # of qubits
- unsigned long **x; // (2n+1)*n matrix for stabilizer/destabilizer x bits (there's one "scratch row" at
- unsigned long **z; // (2n+1)*n matrix for z bits the bottom)
- int *r; // Phase bits: 0 for +1, 1 for i, 2 for -1, 3 for -i. Normally either 0 or 2.
- unsigned long pw[32]; // pw[i] = 2^i
- long over32; // floor(n/8)+1
-
- };
-
- // Globals
- struct QProg *h;
- struct QState *q;
-
- void error(int k)
-
- {
-
- if (k==0) printf("\nSyntax: chp [-options] <filename> [input]\n");
- if (k==1) printf("\nFile not found\n");
- exit(0);
-
- }
-
-
-
- void cnot(struct QState *q, long b, long c)
-
- // Apply a CNOT gate with control b and target c
-
- {
-
- long i;
- long b5;
- long c5;
- unsigned long pwb;
- unsigned long pwc;
-
- b5 = b>>5;
- c5 = c>>5;
- pwb = q->pw[b&31];
- pwc = q->pw[c&31];
- for (i = 0; i < 2*q->n; i++)
- {
- if (q->x[i][b5]&pwb) q->x[i][c5] ^= pwc;
- if (q->z[i][c5]&pwc) q->z[i][b5] ^= pwb;
- if ((q->x[i][b5]&pwb) && (q->z[i][c5]&pwc) &&
- (q->x[i][c5]&pwc) && (q->z[i][b5]&pwb))
- q->r[i] = (q->r[i]+2)%4;
- if ((q->x[i][b5]&pwb) && (q->z[i][c5]&pwc) &&
- !(q->x[i][c5]&pwc) && !(q->z[i][b5]&pwb))
- q->r[i] = (q->r[i]+2)%4;
- }
-
- return;
-
- }
-
-
-
- void hadamard(struct QState *q, long b)
-
- // Apply a Hadamard gate to qubit b
-
- {
-
- long i;
- unsigned long tmp;
- long b5;
- unsigned long pw;
-
- b5 = b>>5;
- pw = q->pw[b&31];
- for (i = 0; i < 2*q->n; i++)
- {
- tmp = q->x[i][b5];
- q->x[i][b5] ^= (q->x[i][b5] ^ q->z[i][b5]) & pw;
- q->z[i][b5] ^= (q->z[i][b5] ^ tmp) & pw;
- if ((q->x[i][b5]&pw) && (q->z[i][b5]&pw)) q->r[i] = (q->r[i]+2)%4;
- }
-
- return;
-
- }
-
-
-
- void phase(struct QState *q, long b)
-
- // Apply a phase gate (|0>->|0>, |1>->i|1>) to qubit b
-
- {
-
- long i;
- long b5;
- unsigned long pw;
-
- b5 = b>>5;
- pw = q->pw[b&31];
- for (i = 0; i < 2*q->n; i++)
- {
- if ((q->x[i][b5]&pw) && (q->z[i][b5]&pw)) q->r[i] = (q->r[i]+2)%4;
- q->z[i][b5] ^= q->x[i][b5]&pw;
- }
-
- return;
-
- }
-
-
-
- void rowcopy(struct QState *q, long i, long k)
-
- // Sets row i equal to row k
-
- {
-
- long j;
-
- for (j = 0; j < q->over32; j++)
- {
- q->x[i][j] = q->x[k][j];
- q->z[i][j] = q->z[k][j];
- }
- q->r[i] = q->r[k];
-
- return;
-
- }
-
-
-
- void rowswap(struct QState *q, long i, long k)
-
- // Swaps row i and row k
-
- {
-
- rowcopy(q, 2*q->n, k);
- rowcopy(q, k, i);
- rowcopy(q, i, 2*q->n);
-
- return;
-
- }
-
-
-
- void rowset(struct QState *q, long i, long b)
-
- // Sets row i equal to the bth observable (X_1,...X_n,Z_1,...,Z_n)
-
- {
-
- long j;
- long b5;
- unsigned long b31;
-
- for (j = 0; j < q->over32; j++)
- {
- q->x[i][j] = 0;
- q->z[i][j] = 0;
- }
- q->r[i] = 0;
- if (b < q->n)
- {
- b5 = b>>5;
- b31 = b&31;
- q->x[i][b5] = q->pw[b31];
- }
- else
- {
- b5 = (b - q->n)>>5;
- b31 = (b - q->n)&31;
- q->z[i][b5] = q->pw[b31];
- }
-
- return;
-
- }
-
-
-
- int clifford(struct QState *q, long i, long k)
-
- // Return the phase (0,1,2,3) when row i is LEFT-multiplied by row k
-
- {
-
- long j;
- long l;
- unsigned long pw;
- long e=0; // Power to which i is raised
-
- for (j = 0; j < q->over32; j++)
- for (l = 0; l < 32; l++)
- {
- pw = q->pw[l];
- if ((q->x[k][j]&pw) && (!(q->z[k][j]&pw))) // X
- {
- if ((q->x[i][j]&pw) && (q->z[i][j]&pw)) e++; // XY=iZ
- if ((!(q->x[i][j]&pw)) && (q->z[i][j]&pw)) e--; // XZ=-iY
- }
- if ((q->x[k][j]&pw) && (q->z[k][j]&pw)) // Y
- {
- if ((!(q->x[i][j]&pw)) && (q->z[i][j]&pw)) e++; // YZ=iX
- if ((q->x[i][j]&pw) && (!(q->z[i][j]&pw))) e--; // YX=-iZ
- }
- if ((!(q->x[k][j]&pw)) && (q->z[k][j]&pw)) // Z
- {
- if ((q->x[i][j]&pw) && (!(q->z[i][j]&pw))) e++; // ZX=iY
- if ((q->x[i][j]&pw) && (q->z[i][j]&pw)) e--; // ZY=-iX
- }
- }
-
- e = (e+q->r[i]+q->r[k])%4;
- if (e>=0) return e;
- else return e+4;
-
- }
-
-
-
- void rowmult(struct QState *q, long i, long k)
-
- // Left-multiply row i by row k
-
- {
-
- long j;
-
- q->r[i] = clifford(q,i,k);
- for (j = 0; j < q->over32; j++)
- {
- q->x[i][j] ^= q->x[k][j];
- q->z[i][j] ^= q->z[k][j];
- }
-
- return;
-
- }
-
-
-
- void printstate(struct QState *q)
-
- // Print the destabilizer and stabilizer for state q
-
- {
-
- long i;
- long j;
- long j5;
- unsigned long pw;
-
- for (i = 0; i < 2*q->n; i++)
- {
- if (i == q->n)
- {
- printf("\n");
- for (j = 0; j < q->n+1; j++)
- printf("-");
- }
- if (q->r[i]==2) printf("\n-");
- else printf("\n+");
- for (j = 0; j < q->n; j++)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- if ((!(q->x[i][j5]&pw)) && (!(q->z[i][j5]&pw))) printf("I");
- if ((q->x[i][j5]&pw) && (!(q->z[i][j5]&pw))) printf("X");
- if ((q->x[i][j5]&pw) && (q->z[i][j5]&pw)) printf("Y");
- if ((!(q->x[i][j5]&pw)) && (q->z[i][j5]&pw)) printf("Z");
- }
- }
- printf("\n");
-
- return;
-
- }
-
-
-
- int measure(struct QState *q, long b, int sup)
-
- // Measure qubit b
- // Return 0 if outcome would always be 0
- // 1 if outcome would always be 1
- // 2 if outcome was random and 0 was chosen
- // 3 if outcome was random and 1 was chosen
- // sup: 1 if determinate measurement results should be suppressed, 0 otherwise
-
- {
-
- int ran = 0;
- long i;
- long p; // pivot row in stabilizer
- long m; // pivot row in destabilizer
- long b5;
- unsigned long pw;
-
- b5 = b>>5;
- pw = q->pw[b&31];
- for (p = 0; p < q->n; p++) // loop over stabilizer generators
- {
- if (q->x[p+q->n][b5]&pw) ran = 1; // if a Zbar does NOT commute with Z_b (the
- if (ran) break; // operator being measured), then outcome is random
- }
-
- // If outcome is indeterminate
- if (ran)
- {
- rowcopy(q, p, p + q->n); // Set Xbar_p := Zbar_p
- rowset(q, p + q->n, b + q->n); // Set Zbar_p := Z_b
- q->r[p + q->n] = 2*(rand()%2); // moment of quantum randomness
- for (i = 0; i < 2*q->n; i++) // Now update the Xbar's and Zbar's that don't commute with
- if ((i!=p) && (q->x[i][b5]&pw)) // Z_b
- rowmult(q, i, p);
- if (q->r[p + q->n]) return 3;
- else return 2;
- }
-
- // If outcome is determinate
- if ((!ran) && (!sup))
- {
- for (m = 0; m < q->n; m++) // Before we were checking if stabilizer generators commute
- if (q->x[m][b5]&pw) break; // with Z_b; now we're checking destabilizer generators
- rowcopy(q, 2*q->n, m + q->n);
- for (i = m+1; i < q->n; i++)
- if (q->x[i][b5]&pw)
- rowmult(q, 2*q->n, i + q->n);
- if (q->r[2*q->n]) return 1;
- else return 0;
- /*for (i = m+1; i < q->n; i++)
- if (q->x[i][b5]&pw)
- {
- rowmult(q, m + q->n, i + q->n);
- rowmult(q, i, m);
- }
- return (int)q->r[m + q->n];*/
- }
-
- return 0;
-
- }
-
-
-
- long gaussian(struct QState *q)
-
- // Do Gaussian elimination to put the stabilizer generators in the following form:
- // At the top, a minimal set of generators containing X's and Y's, in "quasi-upper-triangular" form.
- // (Return value = number of such generators = log_2 of number of nonzero basis states)
- // At the bottom, generators containing Z's only in quasi-upper-triangular form.
-
- {
-
- long i = q->n;
- long k;
- long k2;
- long j;
- long j5;
- long g; // Return value
- unsigned long pw;
-
- for (j = 0; j < q->n; j++)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- for (k = i; k < 2*q->n; k++) // Find a generator containing X in jth column
- if (q->x[k][j5]&pw) break;
- if (k < 2*q->n)
- {
- rowswap(q, i, k);
- rowswap(q, i-q->n, k-q->n);
- for (k2 = i+1; k2 < 2*q->n; k2++)
- if (q->x[k2][j5]&pw)
- {
- rowmult(q, k2, i); // Gaussian elimination step
- rowmult(q, i-q->n, k2-q->n);
- }
- i++;
- }
- }
- g = i - q->n;
-
- for (j = 0; j < q->n; j++)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- for (k = i; k < 2*q->n; k++) // Find a generator containing Z in jth column
- if (q->z[k][j5]&pw) break;
- if (k < 2*q->n)
- {
- rowswap(q, i, k);
- rowswap(q, i-q->n, k-q->n);
- for (k2 = i+1; k2 < 2*q->n; k2++)
- if (q->z[k2][j5]&pw)
- {
- rowmult(q, k2, i);
- rowmult(q, i-q->n, k2-q->n);
- }
- i++;
- }
- }
-
- return g;
-
- }
-
-
-
- long innerprod(struct QState *q1, struct QState *q2)
-
- // Returns -1 if q1 and q2 are orthogonal
- // Otherwise, returns a nonnegative integer s such that the inner product is (1/sqrt(2))^s
-
- {
-
- return 0;
-
- }
-
-
-
- void printbasisstate(struct QState *q)
-
- // Prints the result of applying the Pauli operator in the "scratch space" of q to |0...0>
-
- {
-
- long j;
- long j5;
- unsigned long pw;
- int e = q->r[2*q->n];
-
- for (j = 0; j < q->n; j++)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- if ((q->x[2*q->n][j5]&pw) && (q->z[2*q->n][j5]&pw)) // Pauli operator is "Y"
- e = (e+1)%4;
- }
- if (e==0) printf("\n +|");
- if (e==1) printf("\n+i|");
- if (e==2) printf("\n -|");
- if (e==3) printf("\n-i|");
-
- for (j = 0; j < q->n; j++)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- if (q->x[2*q->n][j5]&pw) printf("1");
- else printf("0");
- }
- printf(">");
-
- return;
-
- }
-
-
- void dumpbasisstate(struct QState *q, PyObject *output, int index)
-
- // Prints the result of applying the Pauli operator in the "scratch space" of q to |0...0>
-
- {
-
- long j;
- long j5;
- unsigned long pw;
- int e = q->r[2*q->n];
- char buffer[1024];
- strcpy(buffer, "");
-
- for (j = 0; j < q->n; j++)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- if ((q->x[2*q->n][j5]&pw) && (q->z[2*q->n][j5]&pw)) // Pauli operator is "Y"
- e = (e+1)%4;
- }
- if (e==0) strcat(buffer, "+|");
- if (e==1) strcat(buffer, "+i|");
- if (e==2) strcat(buffer, "-|");
- if (e==3) strcat(buffer, "-i|");
-
-
- for (j = 0; j < q->n; j++)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- if (q->x[2*q->n][j5]&pw) strcat(buffer, "1");
- else strcat(buffer, "0");
- }
-
- strcat(buffer, ">");
-
- PyList_SetItem(output, index, Py_BuildValue("s", buffer));
- return;
- }
-
-
-
- void seed(struct QState *q, long g)
-
- // Finds a Pauli operator P such that the basis state P|0...0> occurs with nonzero amplitude in q, and
- // writes P to the scratch space of q. For this to work, Gaussian elimination must already have been
- // performed on q. g is the return value from gaussian(q).
-
- {
-
- long i;
- long j;
- long j5;
- unsigned long pw;
- int f;
- long min=0;
-
- q->r[2*q->n] = 0;
- for (j = 0; j < q->over32; j++)
- {
- q->x[2*q->n][j] = 0; // Wipe the scratch space clean
- q->z[2*q->n][j] = 0;
- }
- for (i = 2*q->n - 1; i >= q->n + g; i--)
- {
- f = q->r[i];
- for (j = q->n - 1; j >= 0; j--)
- {
- j5 = j>>5;
- pw = q->pw[j&31];
- if (q->z[i][j5]&pw)
- {
- min = j;
- if (q->x[2*q->n][j5]&pw) f = (f+2)%4;
- }
- }
- if (f==2)
- {
- j5 = min>>5;
- pw = q->pw[min&31];
- q->x[2*q->n][j5] ^= pw; // Make the seed consistent with the ith equation
- }
- }
-
- return;
-
- }
-
- static char act_hadamard_docs[] = "act_hadamard(): Do a Hadamard";
- static PyObject* act_hadamard(PyObject* self, PyObject* args)
- {
- int which;
- if (!PyArg_ParseTuple(args, "i", &which)) { return NULL; }
- hadamard(q, which);
-
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- static char act_phase_docs[] = "act_phase(): Do a phase";
- static PyObject* act_phase(PyObject* self, PyObject* args)
- {
- int which;
- if (!PyArg_ParseTuple(args, "i", &which)) { return NULL; }
- phase(q, which);
-
- Py_INCREF(Py_None);
- return Py_None;
- }
-
-
- static char act_cnot_docs[] = "act_cnot(): Do a CNOT";
- static PyObject* act_cnot(PyObject* self, PyObject* args)
- {
- int a, b;
- if (!PyArg_ParseTuple(args, "ii", &a, &b)) { return NULL; }
- cnot(q, a, b);
-
- Py_INCREF(Py_None);
- return Py_None;
- }
-
-
-
- static char get_ket_docs[] = "get_ket(): Get the state vector";
- static PyObject* get_ket(PyObject* self, PyObject* noarg)
-
- // Print the state in ket notation (warning: could be huge!)
-
- {
-
- long g; // log_2 of number of nonzero basis states
- unsigned long t;
- unsigned long t2;
- long i;
-
- g = gaussian(q);
-
- PyObject *output = PyList_New(g+1);
- if (g > 30) { return output; }
-
- seed(q, g);
- dumpbasisstate(q, output, 0);
- for (t = 0; t < q->pw[g]-1; t++)
- {
- t2 = t ^ (t+1);
- for (i = 0; i < g; i++)
- if (t2 & q->pw[i])
- rowmult(q, 2*q->n, q->n + i);
- dumpbasisstate(q, output, t+1);
- }
- return output;
- }
-
- void printket(struct QState *q)
-
- // Print the state in ket notation (warning: could be huge!)
-
- {
-
- long g; // log_2 of number of nonzero basis states
- unsigned long t;
- unsigned long t2;
- long i;
-
- g = gaussian(q);
- printf("\n2^%ld nonzero basis states", g);
- if (g > 31)
- {
- printf("\nState is WAY too big to print");
- return;
- }
-
- seed(q, g);
- printbasisstate(q);
- for (t = 0; t < q->pw[g]-1; t++)
- {
- t2 = t ^ (t+1);
- for (i = 0; i < g; i++)
- if (t2 & q->pw[i])
- rowmult(q, 2*q->n, q->n + i);
- printbasisstate(q);
- }
- printf("\n");
-
- return;
-
- }
-
-
-
- void runprog(struct QProg *h, struct QState *q)
-
- // Simulate the quantum circuit
-
- {
-
- long t;
- int m; // measurement result
- time_t tp;
- double dt;
- char mvirgin = 1;
-
- time(&tp);
- for (t = 0; t < h->T; t++)
- {
- if (h->a[t]==CNOT) cnot(q,h->b[t],h->c[t]);
- if (h->a[t]==HADAMARD) hadamard(q,h->b[t]);
- if (h->a[t]==PHASE) phase(q,h->b[t]);
- if (h->a[t]==MEASURE)
- {
- if (mvirgin && h->DISPTIME)
- {
- dt = difftime(time(0),tp);
- printf("\nGate time: %lf seconds", dt);
- printf("\nTime per 10000 gates: %lf seconds", dt*10000.0f/(h->T - h->n));
- time(&tp);
- }
- mvirgin = 0;
- m = measure(q,h->b[t],h->SUPPRESSM);
- if (!h->SILENT)
- {
- printf("\nOutcome of measuring qubit %ld: ", h->b[t]);
- if (m>1) printf("%d (random)", m-2);
- else printf("%d", m);
- }
- }
- if (h->DISPPROG)
- {
- if (h->a[t]==CNOT) printf("\nCNOT %ld->%ld", h->b[t], h->c[t]);
- if (h->a[t]==HADAMARD) printf("\nHadamard %ld", h->b[t]);
- if (h->a[t]==PHASE) printf("\nPhase %ld", h->b[t]);
- }
- }
- printf("\n");
- if (h->DISPTIME)
- {
- dt = difftime(time(0),tp);
- printf("\nMeasurement time: %lf seconds", dt);
- printf("\nTime per 10000 measurements: %lf seconds\n", dt*10000.0f/h->n);
- }
- if (h->DISPQSTATE)
- {
- printf("\nFinal state:");
- printstate(q);
- gaussian(q);
- printstate(q);
- printket(q);
- }
- return;
-
- }
-
-
-
- void preparestate(struct QState *q, char *s)
-
- // Prepare the initial state's "input"
-
- {
-
- long l;
- long b;
-
- l = strlen(s);
- for (b = 0; b < l; b++)
- {
- if (s[b]=='Z')
- {
- hadamard(q,b);
- phase(q,b);
- phase(q,b);
- hadamard(q,b);
- }
- if (s[b]=='x') hadamard(q,b);
- if (s[b]=='X')
- {
- hadamard(q,b);
- phase(q,b);
- phase(q,b);
- }
- if (s[b]=='y')
- {
- hadamard(q,b);
- phase(q,b);
- }
- if (s[b]=='Y')
- {
- hadamard(q,b);
- phase(q,b);
- phase(q,b);
- phase(q,b);
- }
- }
-
- return;
-
- }
-
-
-
- void initstae_(struct QState *q, long n, char *s)
-
- // Initialize state q to have n qubits, and input specified by s
-
- {
-
- long i;
- long j;
-
- q->n = n;
- q->x = malloc((2*q->n + 1) * sizeof(unsigned long*));
- q->z = malloc((2*q->n + 1) * sizeof(unsigned long*));
- q->r = malloc((2*q->n + 1) * sizeof(int));
- q->over32 = (q->n>>5) + 1;
- q->pw[0] = 1;
- for (i = 1; i < 32; i++)
- q->pw[i] = 2*q->pw[i-1];
- for (i = 0; i < 2*q->n + 1; i++)
- {
- q->x[i] = malloc(q->over32 * sizeof(unsigned long));
- q->z[i] = malloc(q->over32 * sizeof(unsigned long));
- for (j = 0; j < q->over32; j++)
- {
- q->x[i][j] = 0;
- q->z[i][j] = 0;
- }
- if (i < q->n)
- q->x[i][i>>5] = q->pw[i&31];
- else if (i < 2*q->n)
- {
- j = i-q->n;
- q->z[i][j>>5] = q->pw[j&31];
- }
- q->r[i] = 0;
- }
- if (s) preparestate(q, s);
-
- return;
-
- }
-
-
-
- void readprog(struct QProg *h, char *fn, char *params)
-
- // Read a quantum circuit from filename fn, with optional parameters params
-
- {
-
- long t;
- char fn2[255];
- FILE *fp;
- char c=0;
- long val;
- long l;
-
- h->DISPQSTATE = 0;
- h->DISPTIME = 0;
- h->SILENT = 0;
- h->DISPPROG = 0;
- h->SUPPRESSM = 0;
- if (params)
- {
- l = strlen(params);
- for (t = 1; t < l; t++)
- {
- if ((params[t]=='q')||(params[t]=='Q')) h->DISPQSTATE = 1;
- if ((params[t]=='p')||(params[t]=='P')) h->DISPPROG = 1;
- if ((params[t]=='t')||(params[t]=='T')) h->DISPTIME = 1;
- if ((params[t]=='s')||(params[t]=='S')) h->SILENT = 1;
- if ((params[t]=='m')||(params[t]=='M')) h->SUPPRESSM = 1;
- }
- }
-
- sprintf(fn2, "%s", fn);
- fp = fopen(fn2, "r");
- if (!fp)
- {
- sprintf(fn2, "%s.chp", fn);
- fp = fopen(fn2, "r");
- if (!fp) error(1);
- }
- while (!feof(fp)&&(c!='#'))
- fscanf(fp, "%c", &c);
- if (c!='#') error(2);
- h->T = 0;
- h->n = 0;
- while (!feof(fp))
- {
- fscanf(fp, "%c", &c);
- if ((c=='\r')||(c=='\n'))
- continue;
- fscanf(fp, "%ld", &val);
- if (val+1 > h->n) h->n = val+1;
- if ((c=='c')||(c=='C'))
- {
- fscanf(fp, "%ld", &val);
- if (val+1 > h->n) h->n = val+1;
- }
- h->T++;
- }
- fclose(fp);
- h->a = malloc(h->T * sizeof(char));
- h->b = malloc(h->T * sizeof(long));
- h->c = malloc(h->T * sizeof(long));
- fp = fopen(fn2, "r");
- while (!feof(fp)&&(c!='#'))
- fscanf(fp, "%c", &c);
- t=0;
- while (!feof(fp))
- {
- fscanf(fp, "%c", &c);
- if ((c=='\r')||(c=='\n'))
- continue;
- if ((c=='c')||(c=='C')) h->a[t] = CNOT;
- if ((c=='h')||(c=='H')) h->a[t] = HADAMARD;
- if ((c=='p')||(c=='P')) h->a[t] = PHASE;
- if ((c=='m')||(c=='M')) h->a[t] = MEASURE;
- fscanf(fp, "%ld", &h->b[t]);
- if (h->a[t]==CNOT) fscanf(fp, "%ld", &h->c[t]);
- t++;
- }
- fclose(fp);
-
- return;
-
- }
-
-
- static char init_docs[] = "init(nqubits): Initialize with n qubits";
- static PyObject* init(PyObject* self, PyObject* args)
- {
- int nqubits;
- if (!PyArg_ParseTuple(args, "i", &nqubits)) { return NULL; }
-
- srand(time(0));
-
- h = malloc(sizeof(struct QProg));
- q = malloc(sizeof(struct QState));
- initstae_(q,nqubits,NULL);
- PyObject *response = Py_BuildValue("i", nqubits);
- return response;
- }
-
- static PyMethodDef chp_funcs[] = {
- {"init", (PyCFunction)init, METH_VARARGS, init_docs},
- {"get_ket", (PyCFunction)get_ket, METH_NOARGS, get_ket_docs},
- {"act_hadamard", (PyCFunction)act_hadamard, METH_VARARGS, act_hadamard_docs},
- {"act_cnot", (PyCFunction)act_cnot, METH_VARARGS, act_cnot_docs},
- {"act_phase", (PyCFunction)act_phase, METH_VARARGS, act_phase_docs},
- {NULL}
- };
-
-
- void initchp(int argc, char **argv)
- {
- Py_InitModule3("chp", chp_funcs, "CHP");
- }
-
|