mirror of
https://github.com/libquantum/libquantum.git
synced 2025-10-03 16:51:37 +00:00
updated libquantum 0.1.0 source files
This commit is contained in:
71
INSTALL
Normal file
71
INSTALL
Normal 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
126
Makefile.in
Normal 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
21
README
Normal 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
113
classic.c
Normal 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
36
classic.h
Normal 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
73
complex.c
Normal 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
37
complex.h
Normal 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
1325
config.guess
vendored
Executable file
File diff suppressed because it is too large
Load Diff
65
config.h.in
Normal file
65
config.h.in
Normal 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
1460
config.sub
vendored
Executable file
File diff suppressed because it is too large
Load Diff
104
decoherence.c
Normal file
104
decoherence.c
Normal 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
32
decoherence.h
Normal 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
34
defs.h
Normal 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
28
expn.c
Normal 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
9
expn.h
Normal 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
484
gates.c
Normal 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
55
gates.h
Normal 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
251
install-sh
Executable 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
|
113
matrix.c
Normal file
113
matrix.c
Normal 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
48
matrix.h
Normal 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
175
measure.c
Normal 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
37
measure.h
Normal 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
312
oaddn.c
Normal 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
26
oaddn.h
Normal 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
60
omuln.c
Normal 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
15
omuln.h
Normal 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
49
qft.c
Normal 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
30
qft.h
Normal 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
117
quantum.h.in
Normal 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
337
qureg.c
Normal 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
153
qureg.h
Normal 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
125
shor.c
Normal 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;
|
||||||
|
}
|
Reference in New Issue
Block a user