Skip to content

Commit

Permalink
Implemented one, two, and three bit quantum gates
Browse files Browse the repository at this point in the history
Added a source file for testing
Created a Makefile for the project
Modified the quantum_reg to contain an arraylist of quantum_state structs
  • Loading branch information
lwwinter committed Mar 14, 2012
1 parent 49027f6 commit 9152e45
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 78 deletions.
23 changes: 23 additions & 0 deletions Makefile
@@ -0,0 +1,23 @@
CC=gcc
CFLAGS=-g
LDFLAGS=-lm

all: libquantum.a

libquantum.a: complex.o quantum_reg.o quantum_gates.o
ar rcs libquantum.a complex.o quantum_reg.o quantum_gates.o

complex.o: complex.c complex.h
$(CC) $(CFLAGS) -c complex.c

quantum_reg.o: quantum_reg.c quantum_reg.h
$(CC) $(CFLAGS) -c quantum_reg.c

quantum_gates.o: quantum_gates.c quantum_gates.h complex.h
$(CC) $(CFLAGS) -c quantum_gates.c

test: libquantum.a test.c complex.h quantum_reg.h quantum_gates.h
$(CC) $(CFLAGS) $(LDFLAGS) -o test test.c libquantum.a

clean:
rm test libquantum.a *.o
12 changes: 0 additions & 12 deletions complex.c
Expand Up @@ -13,18 +13,6 @@ int QUDA_BRANCH_CUT_LOWER = -1.0*QUDA_PI;
int QUDA_BRANCH_CUT_UPPER = QUDA_PI;
#endif

/*
int main() { // testing only
complex_t op1,op2;
op1.real = 1;
op1.imag = 1;
op2.real = 2;
op2.imag = -0.5;
quda_complex_add(op1,op2);
return 0;
};
*/

#ifdef __QUDA_USE_BRANCH_CUT
void quda_complex_set_branch_cut(float lower) {
QUDA_BRANCH_CUT_LOWER = lower;
Expand Down
161 changes: 161 additions & 0 deletions quantum_gates.c
Expand Up @@ -2,3 +2,164 @@
*/

#include "quantum_gates.h"
#include "complex.h"

int quda_quantum_hadamard_gate(int target, quantum_reg* qreg) {
// If needed, enlarge qreg to make room for state splits resulting from this gate
int diff = 2*qreg->num_states - qreg->size;
if(diff > 0) {
if(quda_quantum_reg_enlarge(qreg,&diff) == -1) return -1;
}

uint64_t mask = 1 << target;
int i;
for(i=0;i<qreg->num_states;i++) {
// Flipped state must be created
qreg->states[qreg->num_states+i].state = qreg->states[i].state ^ mask;
qreg->states[qreg->num_states+i].amplitude = quda_complex_rmul(
qreg->states[i].amplitude,ONE_OVER_SQRT_2);

// For this state, must just modify amplitude
qreg->states[i].amplitude = quda_complex_rmul(qreg->states[i].amplitude,
ONE_OVER_SQRT_2);

// TODO: Look at overhead of conditional rmul vs negation
if(qreg->states[i].state & mask) {
qreg->states[i].amplitude = quda_complex_neg(qreg->states[i].amplitude);
}
}

// TODO: Ideally, make this call optional or conditional
quda_quantum_reg_coalesce(qreg);

return 0;
}

void quda_quantum_pauli_x_gate(int target, quantum_reg* qreg) {
int i;
uint64_t mask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
qreg->states[i].state = qreg->states[i].state ^ mask;
}
}

void quda_quantum_pauli_y_gate(int target, quantum_reg* qreg) {
int i;
uint64_t mask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
qreg->states[i].state = qreg->states[i].state ^ mask;
qreg->states[i].amplitude = quda_complex_mul_i(qreg->states[i].amplitude);

// TODO: Look at overhead of conditional mul_ni vs negation
if(qreg->states[i].state & mask) {
qreg->states[i].amplitude = quda_complex_neg(qreg->states[i].amplitude);
}
}
}

void quda_quantum_pauli_z_gate(int target, quantum_reg* qreg) {
int i;
uint64_t mask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
if(qreg->states[i].state & mask) {
qreg->states[i].amplitude = quda_complex_neg(qreg->states[i].amplitude);
}
}
}

void quda_quantum_phase_gate(int target, quantum_reg* qreg) {
int i;
uint64_t mask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
if(qreg->states[i].state & mask) {
qreg->states[i].amplitude = quda_complex_mul_i(qreg->states[i].amplitude);
}
}
}

void quda_quantum_pi_over_8_gate(int target, quantum_reg* qreg) {
complex_t c = { .real = ONE_OVER_SQRT_2, .imag = ONE_OVER_SQRT_2 };
int i;
uint64_t mask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
if(qreg->states[i].state & mask) {
qreg->states[i].amplitude = quda_complex_mul(qreg->states[i].amplitude,c);
}
}
}

void quda_quantum_swap_gate(int target1, int target2, quantum_reg* qreg) {
int i;
uint64_t mask = 1 << target1;
mask |= 1 << target2;
for(i=0;i<qreg->num_states;i++) {
if((qreg->states[i].state & mask != 0) && (~qreg->states[i].state & mask != 0)) {
qreg->states[i].state = qreg->states[i].state ^ mask;
}
}
}

void quda_quantum_controlled_not_gate(int control, int target, quantum_reg* qreg) {
int i;
uint64_t cmask = 1 << control;
uint64_t tmask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
if(qreg->states[i].state & cmask) {
qreg->states[i].state = qreg->states[i].state ^ tmask;
}
}
}

void quda_quantum_controlled_y_gate(int control,int target, quantum_reg* qreg) {
int i;
uint64_t cmask = 1 << control;
uint64_t tmask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
// TODO: Look for ways to avoid nested conditionals
if(qreg->states[i].state & cmask) {
qreg->states[i].state = qreg->states[i].state ^ tmask;
qreg->states[i].amplitude = quda_complex_mul_i(qreg->states[i].amplitude);

// TODO: Look at overhead of conditional mul_ni vs negation
if(qreg->states[i].state & tmask) {
qreg->states[i].amplitude = quda_complex_neg(qreg->states[i].amplitude);
}
}
}
}

void quda_quantum_controlled_z_gate(int control, int target, quantum_reg* qreg) {
int i;
uint64_t mask = 1 << control;
mask |= 1 << target;
for(i=0;i<qreg->num_states;i++) {
if(qreg->states[i].state & mask) {
qreg->states[i].amplitude = quda_complex_neg(qreg->states[i].amplitude);
}
}
}

void quda_quantum_toffoli_gate(int control1, int control2, int target, quantum_reg* qreg) {
int i;
uint64_t cmask = 1 << control1;
cmask |= 1 << control2;
uint64_t tmask = 1 << target;
for(i=0;i<qreg->num_states;i++) {
if(qreg->states[i].state & cmask) {
qreg->states[i].state = qreg->states[i].state ^ tmask;
}
}
}

void quda_quantum_fredkin_gate(int control, int target1, int target2, quantum_reg* qreg) {
int i;
uint64_t cmask = 1 << control;
uint64_t tmask = 1 << target1;
tmask |= 1 << target2;
for(i=0;i<qreg->num_states;i++) {
if((qreg->states[i].state & cmask) && (qreg->states[i].state & tmask != 0)
&& (~qreg->states[i].state & tmask != 0)) {
qreg->states[i].state = qreg->states[i].state ^ tmask;
}
}
}
72 changes: 72 additions & 0 deletions quantum_gates.h
Expand Up @@ -4,6 +4,78 @@
#ifndef __QUDA_QUANTUM_GATES_H
#define __QUDA_QUANTUM_GATES_H

#include "quantum_reg.h"

#define ONE_OVER_SQRT_2 0.707106781f

// One-bit quantum gates

/* Applies the quantum Hadamard gate to the target bit of a quantum register.
* Puts the target bit into a superposition of two states.
* |0> -> k(|0> + |1>); |1> -> k(|0>-|1>) where k=1/sqrt(2)
* Returns -1 on failure if a register expansion was necessary but failed.
* Returns 0 on success;
*/
int quda_quantum_hadamard_gate(int target, quantum_reg* qreg);

/* Applies the quantum Pauli X gate to the target bit of a quantum register.
* Also known as the Sigma X gate or the Quantum Not gate.
*/
void quda_quantum_pauli_x_gate(int target, quantum_reg* qreg);

/* Applies the quantum Pauli Y gate to the target bit of a quantum register.
* Also known as the Sigma Y gate.
*/
void quda_quantum_pauli_y_gate(int target, quantum_reg* qreg);

/* Applies the quantum Pauli Z gate to the target bit of a quantum register.
* Also known as the Sigma Z gate.
*/
void quda_quantum_pauli_z_gate(int target, quantum_reg* qreg);

/* Applies the quantum Phase gate to the target bit of a quantum register.
* This is the square root of the Pauli/Sigma Z gate.
*/
void quda_quantum_phase_gate(int target, quantum_reg* qreg);

/* Applies the quantum PI/8 gate to the target bit of a quantum register.
* This is the square root of the Phase gate.
*/
void quda_quantum_pi_over_8_gate(int target, quantum_reg* qreg);

// Two-bit quantum gates

/* Applies the quantum Swap gate to exchange the states of the two target bits of a
* quantum register.
*/
void quda_quantum_swap_gate(int target1, int target2, quantum_reg* qreg);

/* Applies the quantum Controlled-Not gate to the target bit of a quantum register
* if the control bit is set.
* Also known as the Controlled-X gate.
*/
void quda_quantum_controlled_not_gate(int control, int target, quantum_reg* qreg);

/* Applies the Controlled-Y gate to the target bit of a quantum register if the
* control bit is set.
*/
void quda_quantum_controlled_y_gate(int control,int target, quantum_reg* qreg);

/* Applies the Controlled-Z gate to the target bit of a quantum register if the
* control bit is set.
*/
void quda_quantum_controlled_z_gate(int control, int target, quantum_reg* qreg);

// Three-bit quantum gates

/* Applies the quantum Toffoli gate (Controlled-Controlled-Not) to the
* target bit of a quantum register if both control1 and control2 are set.
*/
void quda_quantum_toffoli_gate(int control1, int control2, int target, quantum_reg* qreg);

/* Applies the quantum Fredkin gate (Controlled-Swap) to exchange the two
* target bits of a quantum register.
*/
void quda_quantum_fredkin_gate(int control, int target1, int target2, quantum_reg* qreg);

#endif // __QUDA_QUANTUM_GATES_H

0 comments on commit 9152e45

Please sign in to comment.