updated libquantum 0.1.0 source files

This commit is contained in:
libquantum
2016-10-27 04:09:05 +09:00
parent 617e4b91f3
commit fb55e54b6e
34 changed files with 20389 additions and 0 deletions

71
INSTALL Normal file
View File

@@ -0,0 +1,71 @@
libquantum 0.1.0 installation guide
-----------------------------------
Contents:
0. Requirements
1. Configure and make
2. Installation of the library
3. Write your own programs
0. Requirements
---------------
libquantum needs a C compiler with complex number support (C99
prefered). A recent gcc (>=2.9.5) will do the job. Furthermore, the
host must support 64-bit integers, even if it is not a 64-bit machine.
If you encounter any difficulties while building, installing or using
libquantum, we would like to hear from you. Just send a mail to
libquantum@enyo.de.
1. Configure and Make
---------------------
As libquantum was created using autoconf and libtool, this step should
not be a major problem. Simply extract the tarball to a directory:
tar xzvf libquantum-0.1.0.tar.gz
Next, run the configure script:
./configure
Now you can build the beast:
make
By now, you can create a sample program which implements Shor's
factoring algorithm:
make shor
The number to be factored is given on the command line as the first
parameter. To factor 15, simply type:
./shor 15
2. Installation of the library
------------------------------
For this step you will need to have superuser privileges. Just type
make install
to get libquantum installed into the default directory, which is
usually /usr/local/bin. Note that on some systems this directories is
not in the standard search path. Take a look at the output of the last
command to get some advice on how to deal with this.
3. Writing your own programs
----------------------------
You can use libquantum as any other C library. Just #include
<quantum.h> in your source file and link the library into your program
with the linker flag -lquantum.
For a detailed guide on programming with libquantum take a look at
http://www.enyo.de/libquantum.

126
Makefile.in Normal file
View File

@@ -0,0 +1,126 @@
# Makefile: Build libquantum
#
# Copyright 2003 Bjoern Butscher, Hendrik Weimer
#
# This file is part of libquantum
#
# libquantum 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; either version 2 of the License,
# or (at your option) any later version.
#
# libquantum is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with libquantum; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
# Every Makefile should contain this line
SHELL=/bin/sh
# Target directory prefix
PREFIX=@prefix@
# Other directories
LIBDIR=${PREFIX}/lib
INCLUDEDIR=${PREFIX}/include
top_builddir=.
# Release information
MAJOR=0
MINOR=1
RELEASE=0
# Tools needed to build libquantum
CC=@CC@
INSTALL=@INSTALL@
LIBTOOL=@LIBTOOL@
# Flags passed to C compiler
CFLAGS=@CFLAGS@
LDFLAGS=-rpath $(LIBDIR) -version-info 1:0:1
# Dependencies
all: libquantum.la
libquantum.la: complex.lo measure.lo matrix.lo gates.lo qft.lo classic.lo\
qureg.lo decoherence.lo oaddn.lo omuln.lo expn.lo Makefile
$(LIBTOOL) $(CC) $(LDFLAGS) -o libquantum.la complex.lo measure.lo\
matrix.lo gates.lo oaddn.lo omuln.lo expn.lo qft.lo classic.lo\
qureg.lo decoherence.lo -lm
complex.lo: complex.c complex.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c complex.c
measure.lo: measure.c measure.h matrix.h qureg.h config.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c measure.c
matrix.lo: matrix.c matrix.h complex.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c matrix.c
gates.lo: gates.c gates.h matrix.h defs.h qureg.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c gates.c
oaddn.lo: oaddn.c matrix.h defs.h gates.h qureg.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c oaddn.c
omuln.lo: omuln.c matrix.h gates.h oaddn.h defs.h qureg.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c omuln.c
expn.lo: expn.c expn.h matrix.h gates.h oaddn.h omuln.h qureg.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c expn.c
qft.lo: qft.c qft.h matrix.h gates.h qureg.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c qft.c
classic.lo: classic.c classic.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c classic.c
qureg.lo: qureg.c qureg.h matrix.h config.h complex.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c qureg.c
decoherence.lo: decoherence.c decoherence.h measure.h gates.h qureg.h config.h\
Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c decoherence.c
# Bring this savage back home
install: libquantum.la
$(LIBTOOL) $(INSTALL) -m 0644 libquantum.la $(LIBDIR)
$(INSTALL) -m 0644 quantum.h $(INCLUDEDIR)
# Build a demo showing Shor's factoring algorithm
shor: libquantum.la shor.c Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -o shor shor.c -I./ -lquantum -lm
# Make everything neat and tidy
clean:
-rm -rf .libs
rm shor libquantum.la *.lo *.o
distclean:
-rm -rf .libs
rm shor *.lo *.o config.h quantum.h config.status config.log\
libquantum.la
dist:
mkdir libquantum-$(MAJOR).$(MINOR).$(RELEASE)
cp *.c *.h quantum.h.in Makefile.in config.h.in configure COPYING\
install-sh ltmain.sh config.sub config.guess README INSTALL\
libquantum-$(MAJOR).$(MINOR).$(RELEASE)
tar czf libquantum-$(MAJOR).$(MINOR).$(RELEASE).tar.gz\
libquantum-$(MAJOR).$(MINOR).$(RELEASE)/
rm -rf libquantum-$(MAJOR).$(MINOR).$(RELEASE)

21
README Normal file
View File

@@ -0,0 +1,21 @@
libquantum 0.1.0 README file
----------------------------
libquantum is a C library for quantum computing. It provides quantum
registers, unitary operations and measurement functions. The main goal
is a physically precise simulation of a quantum computer with high
performance.
An implementation of Shor's factoring algorithm is included with this
release.
See the file INSTALL for help on the installation.
guardian is distributed under the terms of the GNU General Public
License (GPL), which is located in the file COPYING.
Send inquiries, comments, bug reports, suggestions, patches, etc. to:
libquantum@enyo.de
See also the guardian website:
http://www.enyo.de/libquantum

113
classic.c Normal file
View File

@@ -0,0 +1,113 @@
/* classic.c: Classic operations used in libquantum
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <math.h>
/* Calculate A^B with A and B as integers */
int
quantum_ipow(int a, int b)
{
int i;
int r=1;
for(i=0; i<b ;i++)
r*=a;
return r;
}
/* Calculate the greatest common divisor with Euclid's algorithm */
int
quantum_gcd(int u, int v)
{
int r;
while(v)
{
r = u % v;
u = v;
v = r;
}
return u;
}
/* Fractional approximation of a decimal value */
void
quantum_frac_approx(int *a, int *b, int width)
{
float f = (float) *a / *b;
float g=f;
int i, num2=0, den2=1, num1=1, den1=0, num=0, den=0;
do
{
i = (int) (g+0.000005);
g -= i-0.000005;
g = 1.0/g;
if (i * den1 + den2 > 1<<width)
break;
num = i * num1 + num2;
den = i * den1 + den2;
num2 = num1;
den2 = den1;
num1 = num;
den1 = den;
} while(fabsf(((float) num / den) - f) > 1.0 / (2 * (1 << width)));
*a = num;
*b = den;
return;
}
/* Calculates the number of qubits required to store N */
int
quantum_getwidth(int n)
{
int i;
for(i=1; 1<<i<n; i++);
return i;
}
/* Calculate the inverse modulus of N and C */
int
quantum_inverse_mod(int n, int c)
{
int i;
for(i=1; (i*c)%n!=1; i++);
return i;
}

36
classic.h Normal file
View File

@@ -0,0 +1,36 @@
/* classic.h: Declarations for classic.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __CLASSIC_H
#define __CLASSIC_H
extern int quantum_ipow(int a, int b);
extern int quantum_gcd(int u, int v);
extern void quantum_frac_approx(int *a, int *b, int width);
extern int quantum_getwidth(int n);
extern int quantum_inverse_mod(int n, int c);
#endif

73
complex.c Normal file
View File

@@ -0,0 +1,73 @@
/* complex.c: Complex number functions
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <math.h>
#include "complex.h"
#include "config.h"
/* Return the real part of a complex number */
float
quantum_real(COMPLEX_FLOAT a)
{
float *p = (float *) &a;
return p[0];
}
/* Return the imaginary part of a complex number */
float
quantum_imag(COMPLEX_FLOAT a)
{
float *p = (float *) &a;
return p[1];
}
/* Return the complex conjugate of a complex number */
COMPLEX_FLOAT
quantum_conj(COMPLEX_FLOAT a)
{
float r, i;
r = quantum_real(a);
i = quantum_imag(a);
return r - IMAGINARY * i;
}
/* Calculate the square of a complex number (i.e. the probability) */
float
quantum_prob(COMPLEX_FLOAT a)
{
return (float) (a * quantum_conj(a));
}
/* Calculate e^(i * phi) */
COMPLEX_FLOAT quantum_cexp(float phi)
{
return cos(phi) + IMAGINARY * sin(phi);
}

37
complex.h Normal file
View File

@@ -0,0 +1,37 @@
/* complex.h: Declarations for complex.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __COMPLEX_H
#define __COMPLEX_H
#include "config.h"
extern float quantum_real(COMPLEX_FLOAT a);
extern float quantum_imag(COMPLEX_FLOAT a);
extern COMPLEX_FLOAT quantum_conj(COMPLEX_FLOAT a);
extern float quantum_prob (COMPLEX_FLOAT a);
extern COMPLEX_FLOAT quantum_cexp(float phi);
#endif

1325
config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

65
config.h.in Normal file
View File

@@ -0,0 +1,65 @@
/* config.h.in. Generated from configure.in by autoheader. */
/* Complex data type */
#undef COMPLEX_FLOAT
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `m' library (-lm). */
#undef HAVE_LIBM
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Imaginary unit */
#undef IMAGINARY
/* Integer type for quantum registers */
#undef MAX_UNSIGNED
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define as `__inline' if that's what the C compiler calls it, or to nothing
if it is not supported. */
#undef inline

1460
config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

9361
configure vendored Executable file

File diff suppressed because it is too large Load Diff

104
decoherence.c Normal file
View File

@@ -0,0 +1,104 @@
/* decoherence.c: Simulation of decoherence effects
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "measure.h"
#include "qureg.h"
#include "gates.h"
#include "complex.h"
/* Status of the decoherence simulation. Non-zero means enabled and
decoherence effects will be simulated. */
int status = 0;
/* Decoherence parameter. The higher the value, the greater the
decoherence impact. */
float lambda = 0;
/* Initialize the decoherence simulation and set the decoherence
parameter. */
void
quantum_set_decoherence(float l)
{
if(l)
{
status = 1;
lambda = l;
}
else
status = 0;
}
/* Perform the actual decoherence of a quantum register for a single
step of time. This is done by applying a phase shift by a normal
distributed angle with the variance LAMBDA. */
void
quantum_decohere(quantum_reg *reg)
{
float u, v, s, x;
COMPLEX_FLOAT c0, c1;
int i, j;
/* Increase the gate counter */
quantum_gate_counter(1);
if(status)
{
for(j=0; j<reg->width; j++)
{
/* Generate a normal distributed random number */
do {
u = 2 * quantum_frand() - 1;
v = 2 * quantum_frand() - 1;
s = u * u + v * v;
} while (s >= 1);
x = u * sqrt(-2 * log(s) / s);
x *= sqrt(2 * lambda);
/* Apply the phase shift gate for decoherence simulation */
c0 = quantum_cexp(-x / 2);
c1 = quantum_cexp(x / 2);
for(i=0; i<reg->size; i++)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << j))
reg->node[i].amplitude *= c1;
else
reg->node[i].amplitude *= c0;
}
}
}
}

32
decoherence.h Normal file
View File

@@ -0,0 +1,32 @@
/* decoherence.h: Declarations for decoherence.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __DECOHERENCE_H
#define __DECOHERENCE_H
extern void quantum_set_decoherence(float lambda);
extern void quantum_decohere(quantum_reg *reg);
#endif

34
defs.h Normal file
View File

@@ -0,0 +1,34 @@
/* defs.h: Global definitions
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __DEFS_H
#define __DEFS_H
#define pi 3.141592654
#define byte unsigned char
#define num_regs 4
#endif

28
expn.c Normal file
View File

@@ -0,0 +1,28 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "defs.h"
#include "gates.h"
#include "omuln.h"
#include "qureg.h"
void
quantum_exp_mod_n(int N, int x, int width_input, int width, quantum_reg *reg)
{
int i, j, f;
quantum_sigma_x(2*width+2, reg);
for (i=1; i<=width_input;i++){
f=x%N; //compute
for (j=1;j<i;j++)
{
f*=f; //x^2^(i-1)
f= f%N;
}
mul_mod_n(N,f,3*width+1+i, width, reg);
}
}

9
expn.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef __EXPN_H
#define __EXPN_H
#include "qureg.h"
extern void quantum_exp_mod_n(int, int, int, int, quantum_reg *);
#endif

484
gates.c Normal file
View File

@@ -0,0 +1,484 @@
/* gates.c: Basic gates for quantum register manipulation
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "matrix.h"
#include "defs.h"
#include "complex.h"
#include "qureg.h"
#include "decoherence.h"
/* Apply a controlled-not gate */
void
quantum_cnot(int control, int target, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
{
/* Flip the target bit of a base state if the control bit is set */
if((reg->node[i].state & ((MAX_UNSIGNED) 1 << control)))
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
quantum_decohere(reg);
}
/* Apply a toffoli (or controlled-controlled-not) gate */
void
quantum_toffoli(int control1, int control2, int target, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
{
/* Flip the target bit of a base state if both control bits are
set */
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control1))
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control2))
{
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
}
}
quantum_decohere(reg);
}
/* Apply a sigma_x (or not) gate */
void
quantum_sigma_x(int target, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
{
/* Flip the target bit of each base state */
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
quantum_decohere(reg);
}
/* Apply a sigma_y gate */
void
quantum_sigma_y(int target, int width, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size;i++)
{
/* Flip the target bit of each base state and multiply with
+/- i */
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[i].amplitude *= IMAGINARY;
else
reg->node[i].amplitude *= -IMAGINARY;
}
quantum_decohere(reg);
}
/* Apply a sigma_y gate */
void
quantum_sigma_z(int target, int width, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
{
/* Multiply with -1 if the target bit is set */
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[i].amplitude *= -1;
}
quantum_decohere(reg);
}
/* Swap the first WIDTH bits of the quantum register. This is done
classically by renaming the bits. */
void
quantum_swaptheleads(int width, quantum_reg *reg)
{
int i, j;
int pat1, pat2;
MAX_UNSIGNED l;
for(i=0; i<reg->size; i++)
{
/* calculate left bit pattern */
pat1 = reg->node[i].state % ((MAX_UNSIGNED) 1 << width);
/*calculate right but pattern */
pat2 = 0;
for(j=0; j<width; j++)
pat2 += reg->node[i].state & ((MAX_UNSIGNED) 1 << (width + j));
/* construct the new base state */
l = reg->node[i].state - (pat1 + pat2);
l += (pat1 << width);
l += (pat2 >> width);
reg->node[i].state = l;
}
}
/* Swap WIDTH bits starting at WIDTH and 2*WIDTH+2 controlled by
CONTROL */
void
quantum_swaptheleads_omuln_controlled(int control, int width, quantum_reg *reg)
{
int i;
for(i=0; i<width; i++)
{
quantum_toffoli(control, width+i, 2*width+i+2, reg);
quantum_toffoli(control, 2*width+i+2, width+i, reg);
quantum_toffoli(control, width+i, 2*width+i+2, reg);
}
}
/* Apply the 2x2 matrix M to the target bit. M should be unitary and
having a determinant of 1. */
void
quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
{
int i, j, k;
int addsize=0, decsize=0;
COMPLEX_FLOAT t, tnot=0;
char *done;
quantum_reg out;
quantum_reg_hash *p;
if((m.cols != 2) || (m.rows != 2))
{
printf("Matrix is not a 2x2 matrix!\n");
exit(1);
}
/* Build hash table */
for(i=0; i<(1 << reg->hashw); i++)
{
while(reg->hash[i])
{
p = reg->hash[i]->next;
free(reg->hash[i]);
quantum_memman(-sizeof(quantum_reg_hash));
reg->hash[i] = p;
}
}
for(i=0; i<reg->size; i++)
quantum_add_hash(reg->node[i].state, i, reg);
/* calculate the number of base states to be added */
for(i=0; i<reg->size; i++)
{
j = quantum_get_state(reg->node[i].state ^ ((MAX_UNSIGNED) 1 << target),
*reg);
if(j == -1)
{
if((m.t[1] != 0) && (reg->node[i].state
& ((MAX_UNSIGNED) 1 << target)))
addsize++;
if((m.t[2] != 0) && !(reg->node[i].state
& ((MAX_UNSIGNED) 1 << target)))
addsize++;
}
}
/* allocate memory for the new base states */
reg->node = realloc(reg->node,
(reg->size + addsize) * sizeof(quantum_reg_node));
if(!reg->node)
{
printf("Not enough memory for %i-sized qubit!\n", reg->size + addsize);
exit(1);
}
quantum_memman(addsize*sizeof(quantum_reg_node));
for(i=0; i<addsize; i++)
{
reg->node[i+reg->size].state = 0;
reg->node[i+reg->size].amplitude = 0;
}
done = calloc(reg->size + addsize, sizeof(char));
if(!done)
{
printf("Not enough memory for %i bytes array!\n",
(reg->size + addsize) * sizeof(char));
exit(1);
}
quantum_memman(reg->size + addsize * sizeof(char));
k = reg->size;
/* perform the actual matrix multiplication */
for(i=0; i<reg->size; i++)
{
if(!done[i])
{
tnot = 0;
j = quantum_get_state(reg->node[i].state
^ ((MAX_UNSIGNED) 1<<target), *reg);
t = reg->node[i].amplitude;
if(j >= 0)
tnot = reg->node[j].amplitude;
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[i].amplitude = m.t[2] * tnot + m.t[3] * t;
else
reg->node[i].amplitude = m.t[0] * t + m.t[1] * tnot;
if(j >= 0)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[j].amplitude = m.t[0] * tnot + m.t[1] * t;
else
reg->node[j].amplitude = m.t[2] * t + m.t[3] * tnot;
}
else /* new base state will be created */
{
if((m.t[1] == 0)
&& (reg->node[i].state & ((MAX_UNSIGNED) 1 << target)))
break;
if((m.t[2] == 0)
&& !(reg->node[i].state & ((MAX_UNSIGNED) 1 << target)))
break;
reg->node[k].state = reg->node[i].state
^ ((MAX_UNSIGNED) 1 << target);
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[k].amplitude = m.t[1] * t;
else
reg->node[k].amplitude = m.t[2] * t;
k++;
}
if(j >= 0)
done[j] = 1;
if(!reg->node[i].amplitude)
decsize++;
if(j >= 0)
{
if(!reg->node[j].amplitude)
decsize++;
}
}
}
reg->size += addsize;
free(done);
quantum_memman(-reg->size * sizeof(char));
/* remove base states with zero amplitude */
if(decsize)
{
out.width = reg->width;
out.size = reg->size - decsize;
out.node = calloc(out.size, sizeof(quantum_reg_node));
if(!out.node)
{
printf("Not enough memory for %i-sized qubit!\n", out.size);
exit(1);
}
quantum_memman(out.size * sizeof(quantum_reg_node));
out.hashw = reg->hashw;
out.hash = reg->hash;
for(i=0, j=0; i<reg->size; i++)
{
if(reg->node[i].amplitude)
{
out.node[j].state = reg->node[i].state;
out.node[j].amplitude = reg->node[i].amplitude;
j++;
}
}
quantum_delete_qureg(reg);
*reg = out;
}
quantum_decohere(reg);
}
/* Apply a hadamard gate */
void
quantum_hadamard(int target, quantum_reg *reg)
{
quantum_matrix m;
m = quantum_new_matrix(2, 2);
m.t[0] = sqrt(1.0/2); m.t[1] = sqrt(1.0/2);
m.t[2] = sqrt(1.0/2); m.t[3] = -sqrt(1.0/2);
quantum_gate1(target, m, reg);
quantum_delete_matrix(&m);
}
/* Apply a walsh-hadamard gate */
void
quantum_walsh(int target, quantum_reg *reg)
{
quantum_matrix m;
m = quantum_new_matrix(2, 2);
m.t[0] = IMAGINARY*sqrt(1.0/2); m.t[1] = IMAGINARY*sqrt(1.0/2);
m.t[2] = IMAGINARY*sqrt(1.0/2); m.t[3] = -IMAGINARY*sqrt(1.0/2);
quantum_gate1(target, m, reg);
quantum_delete_matrix(&m);
}
/* Apply a rotation about the x-axis by the angle GAMMA */
void
quantum_r_x(int target, float gamma, quantum_reg *reg)
{
quantum_matrix m;
m = quantum_new_matrix(2, 2);
m.t[0] = cos(gamma / 2); m.t[1] = IMAGINARY * sin(gamma / 2);
m.t[2] = IMAGINARY * sin(gamma / 2); m.t[3] = cos(gamma / 2);
quantum_gate1(target, m, reg);
quantum_delete_matrix(&m);
}
/* Apply a rotation about the y-axis by the angle GAMMA */
void
quantum_r_y(int target, float gamma, quantum_reg *reg)
{
quantum_matrix m;
m = quantum_new_matrix(2, 2);
m.t[0] = cos(gamma / 2); m.t[1] = -sin(gamma / 2);
m.t[2] = sin(gamma / 2); m.t[3] = cos(gamma / 2);
quantum_gate1(target, m, reg);
quantum_delete_matrix(&m);
}
/* Apply a phase kick by the angle GAMMA */
void
quantum_phase_kick(int target, float gamma, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[i].amplitude *= quantum_cexp(gamma);
}
quantum_decohere(reg);
}
/* Apply a conditional phase shift by PI / 2^(CONTROL - TARGET) */
void
quantum_cond_phase(int control, int target, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control))
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[i].amplitude
*= quantum_cexp(pi / ((MAX_UNSIGNED) 1 << (control - target)));
}
}
quantum_decohere(reg);
}
/* Increase the gate counter by INC steps or reset it if INC < 0. The
current value of the counter is returned. */
int
quantum_gate_counter(int inc)
{
static int counter = 0;
if(inc > 0)
counter += inc;
else if(inc < 0)
counter = 0;
return counter;
}

55
gates.h Normal file
View File

@@ -0,0 +1,55 @@
/* gates.h: Declarations for gates.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __GATES_H
#define __GATES_H
#include "matrix.h"
#include "qureg.h"
extern void quantum_cnot(int control, int target, quantum_reg *reg);
extern void quantum_toffoli(int control1, int control2, int target,
quantum_reg *reg);
extern void quantum_sigma_x(int target, quantum_reg *reg);
extern void quantum_sigma_y(int target, quantum_reg *reg);
extern void quantum_sigma_z(int target, quantum_reg *reg);
extern void quantum_swaptheleads(int width, quantum_reg *reg);
extern void quantum_swaptheleads_omuln_controlled(int control, int width,
quantum_reg *);
extern void quantum_gate1(int target, quantum_matrix m, quantum_reg *reg);
extern void quantum_r_x(int a, float gamma, quantum_reg *reg);
extern void quantum_r_y(int a, float gamma, quantum_reg *reg);
extern void quantum_hadamard(int a, quantum_reg *reg);
extern void quantum_walsh(int a, quantum_reg *reg);
extern void quantum_phase_kick(int a, float gamma, quantum_reg *reg);
extern void quantum_cond_phase(int a, int b, quantum_reg *reg);
extern int quantum_gate_counter(int inc);
#endif

251
install-sh Executable file
View File

@@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0

5107
ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

113
matrix.c Normal file
View File

@@ -0,0 +1,113 @@
/* matrix.c: Matrix operations
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <stdlib.h>
#include <stdio.h>
#include "matrix.h"
#include "config.h"
#include "complex.h"
/* Statistics of the memory consumption */
unsigned long quantum_memman(long change)
{
static long mem = 0, max = 0;
mem += change;
if(mem > max)
max = mem;
return max;
}
/* Create a new COLS x ROWS matrix */
quantum_matrix
quantum_new_matrix(int cols, int rows)
{
quantum_matrix m;
m.rows = rows;
m.cols = cols;
m.t = calloc(cols * rows, sizeof(COMPLEX_FLOAT));
#if (DEBUG_MEM)
printf("allocating %i bytes of memory for %ix%i matrix at 0x%X\n",
sizeof(COMPLEX_FLOAT) * cols * rows, cols, rows, (int) m.t);
#endif
if(!m.t)
{
printf("Not enogh memory for %ix%i-Matrix!",rows,cols);
exit(1);
}
quantum_memman(sizeof(COMPLEX_FLOAT) * cols * rows);
return m;
}
/* Delete a matrix */
void
quantum_delete_matrix(quantum_matrix *m)
{
#if (DEBUG_MEM)
printf("freeing %i bytes of memory for %ix%i matrix at 0x%X\n",
sizeof(COMPLEX_FLOAT) * m->cols * m->rows, m->cols, m->rows,
(int) m->t);
#endif
free(m->t);
quantum_memman(-sizeof(COMPLEX_FLOAT) * m->cols * m->rows);
m->t=0;
}
/* Print the contents of a matrix to stdout */
void
quantum_print_matrix(quantum_matrix m)
{
int i, j, l, z=0;
while ((1 << z++) < m.rows);
z--;
for(i=0; i<m.rows; i++)
{
for (l=z-1; l>=0; l--)
{
if ((l % 4 == 3))
printf(" ");
printf("%i", (i >> l) & 1);
}
printf(" | ");
for(j=0; j<m.cols; j++)
printf("%f %fi ", quantum_real(M(m, j, i)), quantum_imag(M(m, j, i)));
printf("|\n");
}
printf("\n");
}

48
matrix.h Normal file
View File

@@ -0,0 +1,48 @@
/* matrix.h: Declarations for matrix.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __MATRIX_H
#define __MATRIX_H
#include "config.h"
/* A ROWS x COLS matrix with complex elements */
struct quantum_matrix_struct {
int rows;
int cols;
COMPLEX_FLOAT *t;
};
typedef struct quantum_matrix_struct quantum_matrix;
#define M(m,x,y) m.t[x+y*m.cols]
extern unsigned long quantum_memman(long change);
extern quantum_matrix quantum_new_matrix(int cols, int rows);
extern void quantum_delete_matrix(quantum_matrix *m);
extern void quantum_print_matrix(quantum_matrix m);
#endif

175
measure.c Normal file
View File

@@ -0,0 +1,175 @@
/* measure.c: Quantum register measurement
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <stdio.h>
#include "qureg.h"
#include "complex.h"
#include "config.h"
/* Generate a uniformly distributed random number between 0 and 1 */
double
quantum_frand()
{
return (double) rand() / RAND_MAX;
}
/* Measure the contents of a quantum register */
MAX_UNSIGNED
quantum_measure(quantum_reg reg)
{
double r;
int i;
/* Get a random number between 0 and 1 */
r = quantum_frand();
for (i=0; i<reg.size; i++)
{
/* If the random number is less than the probability of the
given base state - r, return the base state as the
result. Otherwise, continue with the next base state. */
r -= quantum_prob(reg.node[i].amplitude);
if(quantum_prob(reg.node[i].amplitude) >= r)
return reg.node[i].state;
}
/* The sum of all probabilities is less than 1. Usually, the cause
for this is the application of a non-normalized matrix, but there
is a slim chance that rounding errors may lead to this as
well. */
return -1;
}
/* Measure a single bit of a quantum register. The bit measured is
indicated by its position POS, starting with 0 as the least
significant bit. The new state of the quantum register depends on
the result of the measurement. */
int
quantum_bmeasure(int pos, quantum_reg *reg)
{
int i, j, k;
int size=0, result=0;
double d=0, pa=0, r;
MAX_UNSIGNED lpat=0, rpat=0, pos2;
quantum_reg out;
pos2 = 1 << pos;
/* Sum up the probability for 0 being the result */
for(i=0; i<reg->size; i++)
{
if(!(reg->node[i].state & pos2))
pa += quantum_prob(reg->node[i].amplitude);
}
/* Compare the probability for 0 with a random number and determine
the result of the measurement */
r = quantum_frand();
if (r > pa)
result = 1;
/* Eradicate all amplitudes of base states which have been ruled out
by the measurement and get the absolute of the new register */
for(i=0;i<reg->size;i++)
{
if(reg->node[i].state & pos2)
{
if(!result)
reg->node[i].amplitude = 0;
else
{
d += quantum_prob(reg->node[i].amplitude);
size++;
}
}
else
{
if(result)
reg->node[i].amplitude = 0;
else
{
d += quantum_prob(reg->node[i].amplitude);
size++;
}
}
}
/* Build the new quantum register */
out.width = reg->width-1;
out.size = size;
out.node = calloc(size, sizeof(quantum_reg_node));
if(!out.node)
{
printf("Not enough memory for %i-sized qubit!\n", size);
exit(1);
}
quantum_memman(size * sizeof(quantum_reg_node));
out.hashw = reg->hashw;
out.hash = reg->hash;
/* Determine the numbers of the new base states and norm the quantum
register */
for(i=0, j=0; i<reg->size; i++)
{
if(reg->node[i].amplitude)
{
for(k=0, rpat=0; k<pos; k++)
rpat += (MAX_UNSIGNED) 1 << k;
rpat &= reg->node[i].state;
for(k=sizeof(MAX_UNSIGNED)*8-1, lpat=0; k>pos; k--)
lpat += (MAX_UNSIGNED) 1 << k;
lpat &= reg->node[i].state;
out.node[j].state = (lpat >> 1) | rpat;
out.node[j].amplitude = reg->node[i].amplitude * 1 / (float) sqrt(d);
j++;
}
}
quantum_delete_qureg(reg);
*reg = out;
return result;
}

37
measure.h Normal file
View File

@@ -0,0 +1,37 @@
/* measure.h: Declarations for measure.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __MEASURE_H
#define __MEASURE_H
#include "matrix.h"
#include "qureg.h"
#include "config.h"
extern double quantum_frand();
extern MAX_UNSIGNED quantum_measure(quantum_reg reg);
extern int quantum_bmeasure(int pos, quantum_reg *reg);
#endif

312
oaddn.c Normal file
View File

@@ -0,0 +1,312 @@
/* oaddn.c: Addition modulo an integer N
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "matrix.h"
#include "measure.h"
#include "defs.h"
#include "gates.h"
#include "qureg.h"
#include "config.h"
/* if bit "compare" - the global enable bit - is set, test_sums
checks, if the sum of the c-number and the q-number in register
add_sum is greater than n and sets the next lower bit to "compare" */
void
test_sum(int compare, int width, quantum_reg *reg)
{
int i;
if (compare & ((MAX_UNSIGNED) 1 << (width - 1)))
{
quantum_cnot(2*width-1, width-1, reg);
quantum_sigma_x(2*width-1, reg);
quantum_cnot(2*width-1, 0, reg);
}
else
{
quantum_sigma_x(2*width-1, reg);
quantum_cnot(2*width-1,width-1, reg);
}
for (i = (width-2);i>0;i--)
{
if (compare & (1<<i))
{//is bit i set in compare?
quantum_toffoli(i+1,width+i,i, reg);
quantum_sigma_x(width+i, reg);
quantum_toffoli(i+1,width+i,0, reg);
}
else
{
quantum_sigma_x(width+i, reg);
quantum_toffoli(i+1,width+i,i, reg);
}
}
if (compare & 1)
{
quantum_sigma_x(width, reg);
quantum_toffoli(width,1,0, reg);
}
quantum_toffoli(2*width+1,0,2*width, reg);//set output to 1 if enabled and b < compare
if (compare & 1)
{
quantum_toffoli(width,1,0, reg);
quantum_sigma_x(width, reg);
}
for (i = 1;i<=(width-2);i++)
{
if (compare & (1<<i))
{//is bit i set in compare?
quantum_toffoli(i+1,width+i,0, reg);
quantum_sigma_x(width+i, reg);
quantum_toffoli(i+1,width+i,i, reg);
}
else
{
quantum_toffoli(i+1,width+i,i, reg);
quantum_sigma_x(width+i, reg);
}
}
if (compare & (1<<(width-1)))
{
quantum_cnot(2*width-1,0, reg);
quantum_sigma_x(2*width-1, reg);
quantum_cnot(2*width-1,width-1, reg);
}
else
{
quantum_cnot(2*width-1,width-1, reg);
quantum_sigma_x(2*width-1, reg);
}
}
//This is a semi-quantum fulladder. It adds to b_in
//a c-number. Carry-in bit is c_in and carry_out is
//c_out. xlt-l and L are enablebits. See documentation
//for further information
void muxfa(int a, int b_in, int c_in, int c_out, int xlt_l,int L, int total,quantum_reg *reg){//a,
if(a==0){//00
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_cnot(b_in,c_in, reg);
}
if(a==3){//11
quantum_toffoli(L,c_in,c_out, reg);
quantum_cnot(L,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_cnot(b_in,c_in, reg);
}
if(a==1){//01
quantum_toffoli(L,xlt_l,b_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,b_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_cnot(b_in,c_in, reg);
}
if(a==2){//10
quantum_sigma_x(xlt_l, reg);
quantum_toffoli(L,xlt_l,b_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,b_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_cnot(b_in,c_in, reg);
quantum_sigma_x(xlt_l, reg);
}
}
//This is just the inverse operation of the semi-quantum fulladder
void muxfa_inv(int a,int b_in,int c_in,int c_out, int xlt_l,int L,int total,quantum_reg *reg){//a,
if(a==0){//00
quantum_cnot(b_in,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
}
if(a==3){//11
quantum_cnot(b_in,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_cnot(L,c_in, reg);
quantum_toffoli(L,c_in,c_out, reg);
}
if(a==1){//01
quantum_cnot(b_in,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,b_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,b_in, reg);
}
if(a==2){//10
quantum_sigma_x(xlt_l, reg);
quantum_cnot(b_in,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,c_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,b_in, reg);
quantum_toffoli(b_in,c_in,c_out, reg);
quantum_toffoli(L,xlt_l,b_in, reg);
quantum_sigma_x(xlt_l, reg);
}
}
//This is a semi-quantum halfadder. It adds to b_in
//a c-number. Carry-in bit is c_in and carry_out is
//not necessary. xlt-l and L are enablebits. See
//documentation for further information
void muxha(int a,int b_in,int c_in, int xlt_l, int L,int total,quantum_reg *reg){//a,
if(a==0){//00
quantum_cnot(b_in,c_in, reg);
}
if(a==3){//11
quantum_cnot(L,c_in, reg);
quantum_cnot(b_in,c_in, reg);
}
if(a==1){//01
quantum_toffoli(L,xlt_l,c_in, reg);
quantum_cnot(b_in,c_in, reg);
}
if(a==2){//10
quantum_sigma_x(xlt_l, reg);
quantum_toffoli(L,xlt_l,c_in, reg);
quantum_cnot(b_in,c_in, reg);
quantum_sigma_x(xlt_l, reg);
}
}
//just the inverse of the semi quantum-halfadder
void muxha_inv(int a,int b_in,int c_in, int xlt_l, int L, int total,quantum_reg *reg){//a,
if(a==0){//00
quantum_cnot(b_in,c_in, reg);
}
if(a==3){//11
quantum_cnot(b_in,c_in, reg);
quantum_cnot(L,c_in, reg);
}
if(a==1){//01
quantum_cnot(b_in,c_in, reg);
quantum_toffoli(L,xlt_l,c_in, reg);
}
if(a==2){//10
quantum_sigma_x(xlt_l, reg);
quantum_cnot(b_in,c_in, reg);
quantum_toffoli(L,xlt_l,c_in, reg);
quantum_sigma_x(xlt_l, reg);
}
}
//
void madd(int a,int a_inv,int width,quantum_reg *reg){
int i,j;
int total;
total = num_regs*width+2;
for (i = 0; i< width-1; i++){
if((1<<i) & a) j= 1<<1;
else j=0;
if((1<<i) & a_inv) j+=1;
muxfa(j,width+i,i,i+1,2*width,2*width+1, total, reg);
}
j=0;
if((1<<(width-1)) & a) j= 2;
if((1<<(width-1)) & a_inv) j+=1;
muxha(j,2*width-1,width-1,2*width,2*width+1, total, reg);
}
void madd_inv(int a,int a_inv,int width,quantum_reg *reg){
int i,j;
int total;
total = num_regs*width+2;
j=0;
if((1<<(width-1)) & a) j= 2;
if((1<<(width-1)) & a_inv) j+=1;
muxha_inv(j,width-1,2*width-1,2*width, 2*width+1, total, reg);
for (i = width-2; i>=0; i--){
if((1<<i) & a) j= 1<<1;
else j=0;
if((1<<i) & a_inv) j+=1;
muxfa_inv(j,i,width+i,width+1+i,2*width, 2*width+1, total, reg);
}
}
void addn(int N,int a,int width, quantum_reg *reg){//add a to register reg (mod N)
test_sum(N-a,width,reg); //xlt N-a
madd((1<<(width))+a-N,a,width,reg);//madd 2^K+a-N
}
void addn_inv(int N,int a,int width, quantum_reg *reg){//inverse of add a to register reg (mod N)
quantum_cnot(2*width+1,2*width,reg);//Attention! cnot gate instead of not, as in description
madd_inv((1<<(width))-a,N-a,width,reg);//madd 2^K+(N-a)-N = 2^K-a
quantum_swaptheleads(width,reg);
test_sum(a,width,reg);
}
void add_mod_n(int N,int a,int width, quantum_reg *reg){//add a to register reg (mod N) and clear the scratch bits
addn(N, a, width, reg);
addn_inv(N, a, width, reg);
}

26
oaddn.h Normal file
View File

@@ -0,0 +1,26 @@
#ifndef __OADDN_H
#define __OADDN_H
#include "qureg.h"
extern void test_sum(int, int, quantum_reg *);
extern void muxfa(int, int, int, int, int, int, int, quantum_reg *);
extern void muxfa_inv(int, int, int, int, int, int, int, quantum_reg *);
extern void muxha(int, int, int, int, int, int, quantum_reg *);
extern void muxha_inv(int, int, int, int, int, int, quantum_reg *);
extern void madd(int, int, int, quantum_reg *);
extern void madd_inv(int, int, int,quantum_reg *);
extern void addn(int,int,int, quantum_reg *);
extern void addn_inv(int, int, int, quantum_reg *);
extern void add_mod_n(int, int, int, quantum_reg *);
#endif

60
omuln.c Normal file
View File

@@ -0,0 +1,60 @@
#include "defs.h"
#include "matrix.h"
#include "gates.h"
#include "oaddn.h"
#include "classic.h"
void emul(int a, int L, int width, quantum_reg *reg){
int i;
for(i=width-1;i>=0;i--) if ((a>>i) & 1) {
quantum_toffoli(2*width+2,L,width+i,reg);
}
}
void muln(int N, int a, int ctl, int width, quantum_reg *reg){//ctl tells, which bit is the external enable bit
int i;
int L = 2*width+1;
quantum_toffoli(ctl,2*width+2,L,reg);
emul(a%N, L, width, reg);
quantum_toffoli(ctl,2*width+2,L,reg);
for(i=1;i<width;i++){
quantum_toffoli(ctl,2*width+2+i,L,reg);
add_mod_n(N,((1<<i)*a)%N,width,reg);
quantum_toffoli(ctl,2*width+2+i,L,reg);
}
}
void muln_inv(int N, int a, int ctl, int width, quantum_reg *reg){//ctl tells, which bit is the external enable bit
int i;
int L = 2*width+1;
a=quantum_inverse_mod(N,a);
for(i=width-1;i>0;i--){
quantum_toffoli(ctl,2*width+2+i,L,reg);
add_mod_n(N,N-((1<<i)*a)%N,width,reg);
quantum_toffoli(ctl,2*width+2+i,L,reg);
}
quantum_toffoli(ctl,2*width+2,L,reg);
emul(a%N, L, width, reg);
quantum_toffoli(ctl,2*width+2,L,reg);
}
void mul_mod_n(int N, int a, int ctl, int width, quantum_reg *reg)
{
muln(N,a,ctl,width,reg);
quantum_swaptheleads_omuln_controlled(ctl, width, reg);
muln_inv(N,a,ctl,width,reg);
}

15
omuln.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef __OMULN_H
#define __OMULN_H
#include "qureg.h"
void emul(int, int, int, quantum_reg *);
void muln(int, int, int, int, quantum_reg *);
void muln_inv(int, int, int, int, quantum_reg *);
void mul_mod_n(int, int, int, int, quantum_reg *);
#endif

49
qft.c Normal file
View File

@@ -0,0 +1,49 @@
/* qft.c: Quantum Fourier Transform
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include "gates.h"
#include "qureg.h"
/* Perform a QFT on a quantum register. This is done by application of
conditional phase shifts and hadamard gates. At the end, the
position of the bits is reversed. */
void quantum_qft(int width, quantum_reg *reg)
{
int i, j;
for(i=width-1; i>=0; i--)
{
for(j=width-1; j>i; j--)
quantum_cond_phase(j, i, reg);
quantum_hadamard(i, reg);
}
for(i=0; i<width/2; i++)
{
quantum_cnot(i, width-i-1, reg);
quantum_cnot(width-i-1, i, reg);
quantum_cnot(i, width-i-1, reg);
}
}

30
qft.h Normal file
View File

@@ -0,0 +1,30 @@
/* qft.c: Declarations for qft.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __QFT_H
#define __QFT_H
extern void quantum_qft(int width, quantum_reg *reg);
#endif

117
quantum.h.in Normal file
View File

@@ -0,0 +1,117 @@
/* quantum.h: Header file for libquantum
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __QUANTUM_H
#define __QUANTUM_H
#define COMPLEX_FLOAT @CF_TYPE@
#define MAX_UNSIGNED @MU_TYPE@
/* A ROWS x COLS matrix with complex elements */
struct quantum_matrix_struct {
int rows;
int cols;
COMPLEX_FLOAT *t;
};
typedef struct quantum_matrix_struct quantum_matrix;
struct quantum_reg_node_struct
{
COMPLEX_FLOAT amplitude; /* alpha_j */
MAX_UNSIGNED state; /* j */
};
typedef struct quantum_reg_node_struct quantum_reg_node;
/* One element of the hash table */
struct quantum_reg_hash_struct
{
int i;
struct quantum_reg_hash_struct *next;
};
typedef struct quantum_reg_hash_struct quantum_reg_hash;
/* The quantum register */
struct quantum_reg_struct
{
int width; /* number of qubits in the qureg */
int size; /* number of non-zero vectors */
int hashw; /* width of the hash array */
quantum_reg_node *node;
quantum_reg_hash **hash;
};
typedef struct quantum_reg_struct quantum_reg;
extern quantum_reg quantum_new_qureg(MAX_UNSIGNED initval, int width);
extern void quantum_delete_qureg(quantum_reg *reg);
extern void quantum_print_qureg(quantum_reg reg);
extern void quantum_addscratch(int bits, quantum_reg *reg);
extern void quantum_cnot(int, int, quantum_reg *);
extern void quantum_toffoli(int, int, int, quantum_reg *);
extern void quantum_X_gate(int, quantum_reg *);
extern void quantum_Y_gate(int a, quantum_reg *reg);
extern void quantum_Z_gate(int a, quantum_reg *reg);
extern void quantum_gate1(quantum_matrix m, int a, quantum_reg *reg);
extern void quantum_r_x(int a, float gamma, quantum_reg *reg);
extern void quantum_r_y(int a, float gamma, quantum_reg *reg);
extern void quantum_phase_kick(int a, float gamma, quantum_reg *reg);
extern void quantum_hadamard(int a, quantum_reg *reg);
extern void quantum_walsh(int a, quantum_reg *reg);
extern void quantum_cond_phase(int a, int b, quantum_reg *reg);
extern int quantum_gate_counter(int inc);
extern void quantum_qft(int width, quantum_reg *reg);
extern void quantum_exp_mod_n(int, int, int, int, quantum_reg *);
extern MAX_UNSIGNED quantum_measure(quantum_reg reg);
extern int quantum_bmeasure(int pos, quantum_reg *reg);
extern quantum_matrix quantum_new_matrix(int ,int );
extern void quantum_delete_matrix(quantum_matrix *m);
extern int quantum_ipow(int a, int b);
extern int quantum_gcd(int u, int v);
extern void quantum_cancel(int *a, int *b);
extern void quantum_frac_approx(int *a, int *b, int width);
extern int quantum_getwidth(int n);
extern float quantum_prob(COMPLEX_FLOAT a);
extern void quantum_set_decoherence(float lambda);
extern void quantum_decohere(quantum_reg *reg);
extern void quantum_add_hash(MAX_UNSIGNED a, int pos, quantum_reg *reg);
extern quantum_reg quantum_matrix2qureg(quantum_matrix *m, int width);
extern quantum_matrix quantum_qureg2matrix(quantum_reg reg);
#endif

337
qureg.c Normal file
View File

@@ -0,0 +1,337 @@
/* qureg.c: Quantum register management
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "matrix.h"
#include "qureg.h"
#include "config.h"
#include "complex.h"
/* Convert a vector to a quantum register */
quantum_reg
quantum_matrix2qureg(quantum_matrix *m, int width)
{
quantum_reg reg;
int i, j, size=0;
if(m->cols != 1)
{
printf("Error! Cannot convert a multi-column-matrix (%i)!\n", m->cols);
exit(1);
}
reg.width = width;
/* Determine the size of the quantum register */
for(i=0; i<m->rows; i++)
{
if(m->t[i])
size++;
}
/* Allocate the required memory */
reg.size = size;
reg.hashw = width + 2;
reg.node = calloc(size, sizeof(quantum_reg_node));
if(!reg.node)
{
printf("Not enough memory for %i-sized qubit!\n", size);
exit(1);
}
quantum_memman(size * sizeof(quantum_reg_node));
/* Allocate the hash table */
reg.hash = calloc(1 << reg.hashw, sizeof(quantum_reg_hash *));
if(!reg.hash)
{
printf("Not enough memory for %i-sized hash!\n", 1 << reg.hashw);
exit(1);
}
quantum_memman((1 << reg.hashw) * sizeof(quantum_reg_hash *));
/* Copy the nonzero amplitudes of the vector into the quantum
register */
for(i=0, j=0; i<m->rows; i++)
{
if(m->t[i])
{
reg.node[j].state = i;
reg.node[j].amplitude = m->t[i];
j++;
}
}
/* Initialize the PRNG */
srandom(time(0));
return reg;
}
/* Create a new quantum register from scratch */
quantum_reg
quantum_new_qureg(MAX_UNSIGNED initval, int width)
{
quantum_reg reg;
reg.width = width;
reg.size = 1;
reg.hashw = width + 2;
/* Allocate memory for 1 base state */
reg.node = calloc(1, sizeof(quantum_reg_node));
if(!reg.node)
{
printf("Not enough memory for %i-sized qubit!\n", 1);
exit(1);
}
quantum_memman(sizeof(quantum_reg_node));
/* Allocate the hash table */
reg.hash = calloc(1 << reg.hashw, sizeof(quantum_reg_hash *));
if(!reg.hash)
{
printf("Not enough memory for %i-sized hash!\n", 1 << reg.hashw);
exit(1);
}
quantum_memman((1 << reg.hashw) * sizeof(quantum_reg_hash *));
/* Initialize the quantum register */
reg.node[0].state = initval;
reg.node[0].amplitude = 1;
/* Initialize the PRNG */
srandom(time(0));
return reg;
}
/* Convert a quantum register to a vector */
quantum_matrix
quantum_qureg2matrix(quantum_reg reg)
{
quantum_matrix m;
int i;
m = quantum_new_matrix(1, 1 << reg.width);
for(i=0; i<reg.size; i++)
m.t[reg.node[i].state] = reg.node[i].amplitude;
return m;
}
/* Delete a quantum register. Note that the hash table is still
alive. */
void
quantum_delete_qureg(quantum_reg *reg)
{
free(reg->node);
quantum_memman(-reg->size * sizeof(quantum_reg_node));
reg->node = 0;
}
/* Print the contents of a quantum register to stdout */
void
quantum_print_qureg(quantum_reg reg)
{
int i;
for(i=0; i<reg.size; i++)
{
printf("%f %+fi|%lli>\n", quantum_real(reg.node[i].amplitude),
quantum_imag(reg.node[i].amplitude), reg.node[i].state);
}
printf("\n");
}
/* Print the output of the modular exponentation algorithm */
void
quantum_print_expn(quantum_reg reg)
{
int i;
for(i=0; i<reg.size; i++)
{
printf("%i: %lli\n", i, reg.node[i].state - i * (1 << (reg.width / 2)));
}
}
/* Add additional space to a qureg. It is initialized to zero and can
be used as scratch space. Note that the space gets added at the LSB */
void
quantum_addscratch(int bits, quantum_reg *reg)
{
int i, oldwidth;
MAX_UNSIGNED l;
oldwidth = reg->width;
reg->width += bits;
for(i=0; i<reg->size; i++)
{
l = reg->node[i].state << bits;
reg->node[i].state = l;
}
}
/* Add an element to the hash table */
void
quantum_add_hash(MAX_UNSIGNED a, int pos, quantum_reg *reg)
{
int i;
quantum_reg_hash *p;
i = quantum_hash64(a, reg->hashw);
p = calloc(1, sizeof(quantum_reg_hash));
if(!p)
{
printf("Not enough memory for hash element!\n");
exit(1);
}
quantum_memman(sizeof(quantum_reg_hash));
p->i = pos;
p->next = reg->hash[i];
reg->hash[i] = p;
}
/* Remove an element from the hash table */
void
delete_hash(MAX_UNSIGNED a, int pos, quantum_reg *reg)
{
int i;
quantum_reg_hash *p, *q=0;
i = quantum_hash64(a, reg->hashw);
p = reg->hash[i];
while(p->i != pos)
{
q = p;
p = p->next;
}
if(q)
{
q->next = p->next;
free(p);
}
else
{
if(p)
{
reg->hash[i] = p->next;
free(p);
}
else
{
reg->hash[i] = 0;
free(reg->hash[i]);
}
}
}
/* Print the hash table to stdout and test if the hash table is
corrupted */
void
print_hash(quantum_reg reg)
{
int i;
quantum_reg_hash *p;
char *done;
done = calloc(reg.size, sizeof(char));
if(!done)
{
printf("Not enough memory for %i bytes array!\n",
(reg.size)*sizeof(char));
exit(1);
}
for(i=0; i < (1 << reg.hashw); i++)
{
printf("%i: ", i);
if(reg.hash[i])
{
p = reg.hash[i];
while(p->next)
{
printf("%llu ", reg.node[p->i].state);
if(quantum_hash64(reg.node[p->i].state, reg.hashw) != i)
printf(" Corrupted hash table!\n... ");
done[p->i] = 1;
p = p->next;
}
printf("%llu", reg.node[p->i].state);
if(quantum_hash64(reg.node[p->i].state, reg.hashw) != i)
printf(" Corrupted hash table!");
done[p->i] = 1;
}
printf("\n");
}
/* Test if there are elements in the quantum register which are not
in the hash table */
for(i=0; i<reg.size; i++)
{
if(!done[i])
printf("Corrupted hash table: %llu is detached!\n", reg.node[i].state);
}
free(done);
}

153
qureg.h Normal file
View File

@@ -0,0 +1,153 @@
/* qureg.h: Declarations for qureg.c and inline hashing functions
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum 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; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#ifndef __QUREG_H
#define __QUREG_H
#include <sys/types.h>
#include "config.h"
#include "matrix.h"
/* Representation of a base state of a quantum register: alpha_j |j> */
struct quantum_reg_node_struct
{
COMPLEX_FLOAT amplitude; /* alpha_j */
MAX_UNSIGNED state; /* j */
};
typedef struct quantum_reg_node_struct quantum_reg_node;
/* One element of the hash table */
struct quantum_reg_hash_struct
{
int i;
struct quantum_reg_hash_struct *next;
};
typedef struct quantum_reg_hash_struct quantum_reg_hash;
/* The quantum register */
struct quantum_reg_struct
{
int width; /* number of qubits in the qureg */
int size; /* number of non-zero vectors */
int hashw; /* width of the hash array */
quantum_reg_node *node;
quantum_reg_hash **hash;
};
typedef struct quantum_reg_struct quantum_reg;
extern quantum_reg quantum_matrix2qureg(quantum_matrix *m, int width);
extern quantum_reg quantum_new_qureg(MAX_UNSIGNED initval, int width);
extern quantum_matrix quantum_qureg2matrix(quantum_reg reg);
extern void quantum_delete_qureg(quantum_reg *reg);
extern void quantum_print_qureg(quantum_reg reg);
extern void quantum_print_expn(quantum_reg reg);
extern void quantum_addscratch(int bits, quantum_reg *reg);
extern void quantum_add_hash(MAX_UNSIGNED a, int pos, quantum_reg *reg);
extern void quantum_delete_hash(MAX_UNSIGNED a, int pos, quantum_reg *reg);
extern void quantum_print_hash(quantum_reg reg);
/* Our 64-bit multiplicative hash function */
static inline unsigned int
quantum_hash64(MAX_UNSIGNED key, int width)
{
unsigned int k32;
k32 = (key & 0xFFFFFFFF) ^ (key >> 32);
k32 *= 0x9e370001UL;
k32 = k32 >> (32-width);
return k32;
}
/* Get the position of a given base state via the hash table */
static inline int
quantum_get_state(MAX_UNSIGNED a, quantum_reg reg)
{
int i;
quantum_reg_hash *p;
i = quantum_hash64(a, reg.hashw);
if(reg.hash[i])
{
p = reg.hash[i];
do
{
if(reg.node[p->i].state == a)
return p->i;
if(p->next)
p = p->next;
} while(p->next);
if(reg.node[p->i].state == a)
return p->i;
}
return -1;
}
/* Update an element of the hash table */
static inline void
quantum_change_hash(MAX_UNSIGNED a, int oldpos, MAX_UNSIGNED b, int pos,
quantum_reg *reg)
{
int i, j;
quantum_reg_hash *p, *q=0;
i = quantum_hash64(a, reg->hashw);
p = reg->hash[i];
q = reg->hash[i];
j = p->i;
while(p->i != oldpos)
p = p->next;
p->i = j;
reg->hash[i] = q->next;
i = quantum_hash64(b, reg->hashw);
q->next = reg->hash[i];
reg->hash[i] = q;
q->i = pos;
}
#endif

125
shor.c Normal file
View File

@@ -0,0 +1,125 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <quantum.h>
int main(int argc, char **argv) {
quantum_reg qr;
int i;
int width, swidth;
int x;
int N;
int c,q,a,b, factor;
srandom(time(0));
if(argc==1)
{
printf("Usage: sim [number]\n\n");
return 3;
}
N=atoi(argv[1]);
if(N<15)
{
printf("Invalid number\n\n");
return 3;
}
width=quantum_getwidth(N*N);
swidth=quantum_getwidth(N);
printf("N = %i, %i qubits required\n", N, width+3*swidth+2);
do
{
x = random() % N;
} while((quantum_gcd(N, x) > 1) || (x < 2));
printf("Random seed: %i\n", x);
qr=quantum_new_qureg(0, width);
for(i=0;i<width;i++)
quantum_hadamard(i, &qr);
quantum_addscratch(3*swidth+2, &qr);
quantum_exp_mod_n(N, x, width, swidth, &qr);
for(i=0;i<3*swidth+2;i++)
{
quantum_bmeasure(0, &qr);
}
quantum_qft(width, &qr);
// quantum_print_qureg(qr);
c=quantum_measure(qr);
if(c==-1)
{
printf("Impossible Measurement!\n");
exit(1);
}
if(c==0)
{
printf("Measured zero, try again.\n");
exit(2);
}
q = 1<<(width);
printf("Measured %i (%f), ", c, (float)c/q);
quantum_frac_approx(&c, &q, width);
printf("fractional approximation is %i/%i.\n", c, q);
if((q % 2 == 1) && (2*q<(1<<width)))
{
printf("Odd denominator, trying to expand by 2.\n");
q *= 2;
}
if(q % 2 == 1)
{
printf("Odd period, try again.\n");
exit(2);
}
printf("Possible period is %i.\n", q);
a = quantum_ipow(x, q/2) + 1 % N;
b = quantum_ipow(x, q/2) - 1 % N;
a = quantum_gcd(N, a);
b = quantum_gcd(N, b);
if(a>b)
factor=a;
else
factor=b;
if((factor < N) && (factor > 1))
{
printf("%i = %i * %i\n", N, factor, N/factor);
}
else
{
printf("Unable to determine factors, try again.\n");
exit(2);
}
quantum_delete_qureg(&qr);
// printf("Memory usage: %i bytes\n", (int )memman(0));
return 0;
}