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