updated libquantum 0.2.1 source files

This commit is contained in:
libquantum
2016-10-27 04:14:06 +09:00
parent dc03271227
commit ce2bb44638
22 changed files with 473 additions and 346 deletions

12
CHANGES
View File

@@ -1,3 +1,15 @@
libquantum 0.2.1:
- Completed GNU/Hurd and FreeBSD ports
- Added unbounded toffoli gate
- Changed hashing method to linear probing (breaks backward
compatibility)
- Optimized quantum_gate1 and gates using quantum_cexp
- Added a bit measurement function that does not remove the
measured bit
- Corrected qft, added qft_inv and adjusted shor
- Corrected the implementation of the Walsh-Hadamard transform
- Supplied version information
libquantum 0.2.0:
- Added Quantum Error Correction
- Included an Implementation of Grover's algorithm

View File

@@ -1,4 +1,4 @@
libquantum 0.2.0 installation guide
libquantum 0.2.1 installation guide
-----------------------------------
Contents:
@@ -13,7 +13,7 @@ Contents:
---------------
libquantum needs a C compiler with complex number support (C99
prefered). A recent gcc (>=2.9.5) will do the job. Furthermore, the
prefered). A recent gcc (>=2.95) 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
@@ -27,7 +27,7 @@ libquantum@enyo.de.
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
tar xzvf libquantum-0.2.1.tar.gz
Next, run the configure script:

View File

@@ -26,44 +26,44 @@ SHELL=/bin/sh
# Target directory prefix
PREFIX=@prefix@
EPREFIX=${PREFIX}
# Other directories
LIBDIR=${PREFIX}/lib
LIBDIR=${EPREFIX}/lib
INCLUDEDIR=${PREFIX}/include
top_builddir=.
# Release information
# Version information
MAJOR=0
MINOR=2
RELEASE=0
VERSION=@PACKAGE_VERSION@
# Tools needed to build libquantum
CC=@CC@ -O2 -g -pg
CC=@CC@
INSTALL=@INSTALL@
LIBTOOL=@LIBTOOL@
# Flags passed to C compiler
CFLAGS=@CFLAGS@
LDFLAGS=-rpath $(LIBDIR) -version-info 2:0:2
LDFLAGS=-rpath $(LIBDIR) -version-info 3:0:0
# 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 qec.lo Makefile
qureg.lo decoherence.lo oaddn.lo omuln.lo expn.lo qec.lo version.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 qec.lo -lm
qureg.lo decoherence.lo qec.lo version.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
measure.lo: measure.c measure.h matrix.h qureg.h complex.h config.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c measure.c
matrix.lo: matrix.c matrix.h complex.h Makefile
@@ -94,14 +94,11 @@ decoherence.lo: decoherence.c decoherence.h measure.h gates.h qureg.h\
complex.h config.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c decoherence.c
qec.lo: qec.c qec.h gates.h qureg.h config.h Makefile
qec.lo: qec.c qec.h gates.h qureg.h decoherence.h measure.h config.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c qec.c
# Bring this savage back home
install: libquantum.la
$(LIBTOOL) $(INSTALL) -m 0644 libquantum.la $(LIBDIR)
$(INSTALL) -m 0644 quantum.h $(INCLUDEDIR)
version.lo: version.c version.h config.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c version.c
# Build demos of Shor's and Grover's algorithms
@@ -114,6 +111,12 @@ grover: libquantum.la grover.c Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -o grover grover.c -I./ -lquantum -static\
-lm
# Bring this savage back home
install: libquantum.la
$(LIBTOOL) $(INSTALL) -m 0644 libquantum.la $(LIBDIR)
$(INSTALL) -m 0644 quantum.h $(INCLUDEDIR)
# Make everything neat and tidy
clean:
@@ -127,10 +130,9 @@ distclean:
dist:
-rm quantum.h config.h
mkdir libquantum-$(MAJOR).$(MINOR).$(RELEASE)
mkdir libquantum-$(VERSION)
cp *.c *.h quantum.h.in Makefile.in config.h.in configure configure.in\
COPYING install-sh ltmain.sh config.sub config.guess README INSTALL\
CHANGES libquantum-$(MAJOR).$(MINOR).$(RELEASE)
tar czf libquantum-$(MAJOR).$(MINOR).$(RELEASE).tar.gz\
libquantum-$(MAJOR).$(MINOR).$(RELEASE)/
rm -rf libquantum-$(MAJOR).$(MINOR).$(RELEASE)
CHANGES libquantum-$(VERSION)
tar czf libquantum-$(VERSION).tar.gz libquantum-$(VERSION)/
rm -rf libquantum-$(VERSION)

2
README
View File

@@ -1,4 +1,4 @@
libquantum 0.2.0 README file
libquantum 0.2.1 README file
----------------------------
libquantum is a C library for quantum computing. It provides quantum

View File

@@ -26,24 +26,6 @@
#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
@@ -62,7 +44,7 @@ quantum_conj(COMPLEX_FLOAT a)
float
quantum_prob(COMPLEX_FLOAT a)
{
return (float) (a * quantum_conj(a));
return quantum_prob_inline(a);
}
/* Calculate e^(i * phi) */

View File

@@ -27,11 +27,40 @@
#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);
/* Return the real part of a complex number */
static inline float
quantum_real(COMPLEX_FLOAT a)
{
float *p = (float *) &a;
return p[0];
}
/* Return the imaginary part of a complex number */
static inline float
quantum_imag(COMPLEX_FLOAT a)
{
float *p = (float *) &a;
return p[1];
}
/* Calculate the square of a complex number (i.e. the probability) */
static inline float
quantum_prob_inline(COMPLEX_FLOAT a)
{
float r, i;
r = quantum_real(a);
i = quantum_imag(a);
return r * r + i * i;
}
#endif

48
configure vendored
View File

@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.57 for libquantum 0.2.0.
# Generated by GNU Autoconf 2.57 for libquantum 0.2.1.
#
# Report bugs to <libquantum@enyo.de>.
#
@@ -427,8 +427,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='libquantum'
PACKAGE_TARNAME='libquantum'
PACKAGE_VERSION='0.2.0'
PACKAGE_STRING='libquantum 0.2.0'
PACKAGE_VERSION='0.2.1'
PACKAGE_STRING='libquantum 0.2.1'
PACKAGE_BUGREPORT='libquantum@enyo.de'
ac_unique_file="classic.c"
@@ -938,7 +938,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures libquantum 0.2.0 to adapt to many kinds of systems.
\`configure' configures libquantum 0.2.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -999,7 +999,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of libquantum 0.2.0:";;
short | recursive ) echo "Configuration of libquantum 0.2.1:";;
esac
cat <<\_ACEOF
@@ -1010,6 +1010,7 @@ Optional Features:
--enable-static=PKGS build static libraries default=yes
--enable-fast-install=PKGS optimize for fast installation default=yes
--disable-libtool-lock avoid locking (might break parallel builds)
--enable-profiling compile with profiling support
Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
@@ -1092,7 +1093,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
libquantum configure 0.2.0
libquantum configure 0.2.1
generated by GNU Autoconf 2.57
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
@@ -1107,7 +1108,7 @@ cat >&5 <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by libquantum $as_me 0.2.0, which was
It was created by libquantum $as_me 0.2.1, which was
generated by GNU Autoconf 2.57. Invocation command line was
$ $0 $@
@@ -2225,12 +2226,12 @@ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(exit $ac_status); }; }; then
for ac_declaration in \
''\
'#include <stdlib.h>' \
'extern "C" void std::exit (int) throw (); using std::exit;' \
'extern "C" void std::exit (int); using std::exit;' \
'extern "C" void exit (int) throw ();' \
'extern "C" void exit (int);' \
'void exit (int);'
'void exit (int);' \
'#include <stdlib.h>'
do
cat >conftest.$ac_ext <<_ACEOF
#line $LINENO "configure"
@@ -4130,7 +4131,7 @@ test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
case $host in
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 4133 "configure"' > conftest.$ac_ext
echo '#line 4134 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -4673,7 +4674,7 @@ chmod -w .
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -o out/conftest2.$ac_objext"
compiler_c_o=no
if { (eval echo configure:4676: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
if { (eval echo configure:4677: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.$ac_objext; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings
if test -s out/conftest.err; then
@@ -6556,7 +6557,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 6559 "configure"
#line 6560 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -6654,7 +6655,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
#line 6657 "configure"
#line 6658 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -7391,7 +7392,6 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool'
# Checks for libraries.
# FIXME: Replace `main' with a function in `-lm':
echo "$as_me:$LINENO: checking for sqrt in -lm" >&5
echo $ECHO_N "checking for sqrt in -lm... $ECHO_C" >&6
@@ -8255,9 +8255,24 @@ fi
echo "$as_me:$LINENO: result: $I" >&5
echo "${ECHO_T}$I" >&6
# Substitute fields in quantum.h.in
# Profiling check
# Check whether --enable-profiling or --disable-profiling was given.
if test "${enable_profiling+set}" = set; then
enableval="$enable_profiling"
CFLAGS="$CFLAGS -pg"
fi;
# Enable -Wall for gcc
if test $CC = "gcc"
then
CFLAGS="$CFLAGS -Wall"
fi
# Write the output files
ac_config_files="$ac_config_files Makefile quantum.h"
cat >confcache <<\_ACEOF
@@ -8620,7 +8635,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
This file was extended by libquantum $as_me 0.2.0, which was
This file was extended by libquantum $as_me 0.2.1, which was
generated by GNU Autoconf 2.57. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8680,7 +8695,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
libquantum config.status 0.2.0
libquantum config.status 0.2.1
configured by $0, generated by GNU Autoconf 2.57,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
@@ -9358,3 +9373,4 @@ if test "$no_create" != yes; then
# would make configure fail if this is the last instruction.
$ac_cs_success || { (exit 1); exit 1; }
fi

View File

@@ -1,5 +1,5 @@
# Process this file with autoconf to produce a configure script.
AC_INIT([libquantum], [0.2.0], [libquantum@enyo.de])
AC_INIT([libquantum], [0.2.1], [libquantum@enyo.de])
AC_CONFIG_SRCDIR([classic.c])
AC_CONFIG_HEADER([config.h])
@@ -12,7 +12,6 @@ AC_PROG_INSTALL
AC_PROG_LIBTOOL
# Checks for libraries.
# FIXME: Replace `main' with a function in `-lm':
AC_CHECK_LIB([m], [sqrt])
# Checks for header files.
@@ -72,8 +71,22 @@ then
fi
AC_MSG_RESULT($I)
# Substitute fields in quantum.h.in
AC_SUBST(MU_TYPE)
AC_SUBST(CF_TYPE)
# Profiling check
AC_ARG_ENABLE(profiling,
[ --enable-profiling compile with profiling support],
[CFLAGS="$CFLAGS -pg"],
[])
# Enable -Wall for gcc
if test $CC = "gcc"
then
CFLAGS="$CFLAGS -Wall"
fi
# Write the output files
AC_CONFIG_FILES([Makefile quantum.h])
AC_OUTPUT
AC_OUTPUT

194
gates.c
View File

@@ -1,4 +1,4 @@
/* gates.c: Basic gates for quantum register manipulation
/* gates.c: Basic gates for quantum register manipulation
Copyright 2003 Bjoern Butscher, Hendrik Weimer
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include "matrix.h"
#include "defs.h"
@@ -48,7 +49,7 @@ quantum_cnot(int control, int target, quantum_reg *reg)
{
for(i=0; i<reg->size; i++)
{
/* Flip the target bit of a base state if the control bit is set */
/* Flip the target bit of a basis state if the control bit is set */
if((reg->node[i].state & ((MAX_UNSIGNED) 1 << control)))
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
@@ -73,7 +74,7 @@ quantum_toffoli(int control1, int control2, int target, quantum_reg *reg)
{
for(i=0; i<reg->size; i++)
{
/* Flip the target bit of a base state if both control bits are
/* Flip the target bit of a basis state if both control bits are
set */
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control1))
@@ -88,6 +89,53 @@ quantum_toffoli(int control1, int control2, int target, quantum_reg *reg)
}
}
/* Apply an unbounded toffoli gate. This gate is not considered
elementary and is not available on all physical realizations of a
quantum computer. Be sure to pass the function the correct number of
controlling qubits. The target is given in the last argument. */
void
quantum_unbounded_toffoli(int controlling, quantum_reg *reg, ...)
{
va_list bits;
int target;
int *controls;
int i, j;
controls = malloc(controlling * sizeof(int));
if(!controls)
{
printf("Error allocating %i-element int array!\n", controlling);
exit(1);
}
quantum_memman(controlling * sizeof(int));
va_start(bits, reg);
for(i=0; i<controlling; i++)
controls[i] = va_arg(bits, int);
target = va_arg(bits, int);
va_end(bits);
for(i=0; i<reg->size; i++)
{
for(j=0; (j < controlling) &&
(reg->node[i].state & (MAX_UNSIGNED) 1 << controls[j]); j++);
if(j == controlling) /* all control bits are set */
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
free(controls);
quantum_memman(-controlling * sizeof(int));
quantum_decohere(reg);
}
/* Apply a sigma_x (or not) gate */
void
@@ -104,7 +152,7 @@ quantum_sigma_x(int target, quantum_reg *reg)
{
for(i=0; i<reg->size; i++)
{
/* Flip the target bit of each base state */
/* Flip the target bit of each basis state */
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
@@ -121,7 +169,7 @@ quantum_sigma_y(int target, quantum_reg *reg)
for(i=0; i<reg->size;i++)
{
/* Flip the target bit of each base state and multiply with
/* Flip the target bit of each basis state and multiply with
+/- i */
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
@@ -221,12 +269,12 @@ quantum_swaptheleads_omuln_controlled(int control, int width, quantum_reg *reg)
void
quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
{
int i, j, k;
int i, j, k, iset;
int addsize=0, decsize=0;
COMPLEX_FLOAT t, tnot=0;
float limit;
char *done;
quantum_reg out;
quantum_reg_hash *p;
// quantum_reg_hash *p;
if((m.cols != 2) || (m.rows != 2))
{
@@ -238,19 +286,20 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
for(i=0; i<(1 << reg->hashw); i++)
{
while(reg->hash[i])
/* while(reg->hash[i])
{
p = reg->hash[i]->next;
free(reg->hash[i]);
quantum_memman(-sizeof(quantum_reg_hash));
reg->hash[i] = p;
}
}*/
reg->hash[i] = 0;
}
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 */
/* calculate the number of basis states to be added */
for(i=0; i<reg->size; i++)
{
@@ -267,7 +316,7 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
}
}
/* allocate memory for the new base states */
/* allocate memory for the new basis states */
reg->node = realloc(reg->node,
(reg->size + addsize) * sizeof(quantum_reg_node));
@@ -295,12 +344,18 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
k = reg->size;
limit = (1.0 / ((MAX_UNSIGNED) 1 << reg->width)) / 1000000;
/* perform the actual matrix multiplication */
for(i=0; i<reg->size; i++)
{
if(!done[i])
{
/* determine if the target of the basis state is set */
iset = reg->node[i].state & ((MAX_UNSIGNED) 1 << target);
tnot = 0;
j = quantum_get_state(reg->node[i].state
^ ((MAX_UNSIGNED) 1<<target), *reg);
@@ -309,7 +364,7 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
if(j >= 0)
tnot = reg->node[j].amplitude;
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
if(iset)
reg->node[i].amplitude = m.t[2] * tnot + m.t[3] * t;
else
@@ -317,7 +372,7 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
if(j >= 0)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
if(iset)
reg->node[j].amplitude = m.t[0] * tnot + m.t[1] * t;
else
@@ -325,20 +380,18 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
}
else /* new base state will be created */
else /* new basis state will be created */
{
if((m.t[1] == 0)
&& (reg->node[i].state & ((MAX_UNSIGNED) 1 << target)))
if((m.t[1] == 0) && (iset))
break;
if((m.t[2] == 0)
&& !(reg->node[i].state & ((MAX_UNSIGNED) 1 << target)))
if((m.t[2] == 0) && !(iset))
break;
reg->node[k].state = reg->node[i].state
^ ((MAX_UNSIGNED) 1 << target);
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
if(iset)
reg->node[k].amplitude = m.t[1] * t;
else
@@ -350,14 +403,6 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
if(j >= 0)
done[j] = 1;
if(!reg->node[i].amplitude)
decsize++;
if(j >= 0)
{
if(!reg->node[j].amplitude)
decsize++;
}
}
}
@@ -366,34 +411,33 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
free(done);
quantum_memman(-reg->size * sizeof(char));
/* remove base states with zero amplitude */
/* remove basis states with extremely small amplitude */
for(i=0, j=0; i<reg->size; i++)
{
if(quantum_prob_inline(reg->node[i].amplitude) < limit)
{
j++;
decsize++;
}
else if(j)
{
reg->node[i-j].state = reg->node[i].state;
reg->node[i-j].amplitude = reg->node[i].amplitude;
}
}
if(decsize)
{
out.width = reg->width;
out.size = reg->size - decsize;
out.node = calloc(out.size, sizeof(quantum_reg_node));
if(!out.node)
reg->size -= decsize;
reg->node = realloc(reg->node, reg->size * sizeof(quantum_reg_node));
if(!reg->node)
{
printf("Not enough memory for %i-sized qubit!\n", out.size);
printf("Not enough memory for %i-sized qubit!\n",
reg->size + addsize);
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_hashpreserve(reg);
*reg = out;
}
quantum_decohere(reg);
@@ -417,21 +461,15 @@ quantum_hadamard(int target, quantum_reg *reg)
}
/* Apply a walsh-hadamard gate */
/* Apply a walsh-hadamard transform */
void
quantum_walsh(int target, quantum_reg *reg)
quantum_walsh(int width, quantum_reg *reg)
{
quantum_matrix m;
int i;
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);
for(i=0; i<width; i++)
quantum_hadamard(i, reg);
}
@@ -477,13 +515,16 @@ void
quantum_r_z(int target, float gamma, quantum_reg *reg)
{
int i;
COMPLEX_FLOAT z;
z = quantum_cexp(gamma/2);
for(i=0; i<reg->size; i++)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[i].amplitude *= quantum_cexp(gamma/2);
reg->node[i].amplitude *= z;
else
reg->node[i].amplitude *= quantum_cexp(-gamma/2);
reg->node[i].amplitude /= z;
}
quantum_decohere(reg);
@@ -495,10 +536,13 @@ void
quantum_phase_scale(int target, float gamma, quantum_reg *reg)
{
int i;
COMPLEX_FLOAT z;
z = quantum_cexp(gamma);
for(i=0; i<reg->size; i++)
{
reg->node[i].amplitude *= quantum_cexp(gamma);
reg->node[i].amplitude *= z;
}
quantum_decohere(reg);
@@ -511,11 +555,14 @@ void
quantum_phase_kick(int target, float gamma, quantum_reg *reg)
{
int i;
COMPLEX_FLOAT z;
z = quantum_cexp(gamma);
for(i=0; i<reg->size; i++)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << target))
reg->node[i].amplitude *= quantum_cexp(gamma);
reg->node[i].amplitude *= z;
}
quantum_decohere(reg);
@@ -527,14 +574,16 @@ void
quantum_cond_phase(int control, int target, quantum_reg *reg)
{
int i;
COMPLEX_FLOAT z;
z = quantum_cexp(pi / ((MAX_UNSIGNED) 1 << (control - target)));
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)));
reg->node[i].amplitude *= z;
}
}
@@ -546,14 +595,16 @@ void
quantum_cond_phase_inv(int control, int target, quantum_reg *reg)
{
int i;
COMPLEX_FLOAT z;
z = quantum_cexp(-pi / ((MAX_UNSIGNED) 1 << (control - target)));
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)));
reg->node[i].amplitude *= z;
}
}
@@ -566,13 +617,16 @@ void
quantum_cond_phase_kick(int control, int target, float gamma, quantum_reg *reg)
{
int i;
COMPLEX_FLOAT z;
z = quantum_cexp(gamma);
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(gamma);
reg->node[i].amplitude *= z;
}
}
quantum_decohere(reg);

View File

@@ -31,6 +31,8 @@
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_unbounded_toffoli(int controlling, 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);
@@ -46,7 +48,7 @@ extern void quantum_r_y(int target, float gamma, quantum_reg *reg);
extern void quantum_r_z(int target, float gamma, quantum_reg *reg);
extern void quantum_hadamard(int target, quantum_reg *reg);
extern void quantum_walsh(int target, quantum_reg *reg);
extern void quantum_walsh(int width, quantum_reg *reg);
extern void quantum_phase_scale(int target, float gamma, quantum_reg *reg);
extern void quantum_phase_kick(int target, float gamma, quantum_reg *reg);

View File

@@ -120,14 +120,6 @@ void grover(int target, quantum_reg *reg)
}
void print_grover(quantum_reg *reg)
{
int i;
for(i=0;i<reg->size;i++)
printf("%llu %f\n", reg->node[i].state, __real__ reg->node[i].amplitude);
}
int main(int argc, char **argv)
{
quantum_reg reg;

102
measure.c
View File

@@ -59,8 +59,8 @@ quantum_measure(quantum_reg reg)
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)
r -= quantum_prob_inline(reg.node[i].amplitude);
if(quantum_prob_inline(reg.node[i].amplitude) >= r)
return reg.node[i].state;
}
@@ -86,14 +86,14 @@ quantum_bmeasure(int pos, quantum_reg *reg)
MAX_UNSIGNED lpat=0, rpat=0, pos2;
quantum_reg out;
pos2 = 1 << pos;
pos2 = (MAX_UNSIGNED) 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);
pa += quantum_prob_inline(reg->node[i].amplitude);
}
/* Compare the probability for 0 with a random number and determine
@@ -115,7 +115,7 @@ quantum_bmeasure(int pos, quantum_reg *reg)
reg->node[i].amplitude = 0;
else
{
d += quantum_prob(reg->node[i].amplitude);
d += quantum_prob_inline(reg->node[i].amplitude);
size++;
}
}
@@ -125,7 +125,7 @@ quantum_bmeasure(int pos, quantum_reg *reg)
reg->node[i].amplitude = 0;
else
{
d += quantum_prob(reg->node[i].amplitude);
d += quantum_prob_inline(reg->node[i].amplitude);
size++;
}
}
@@ -173,3 +173,93 @@ quantum_bmeasure(int pos, quantum_reg *reg)
*reg = out;
return result;
}
/* Measure a single bit, but do not remove it from the quantum
register */
int
quantum_bmeasure_bitpreserve(int pos, quantum_reg *reg)
{
int i, j;
int size=0, result=0;
double d=0, pa=0, r;
MAX_UNSIGNED pos2;
quantum_reg out;
pos2 = (MAX_UNSIGNED) 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_inline(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_inline(reg->node[i].amplitude);
size++;
}
}
else
{
if(result)
reg->node[i].amplitude = 0;
else
{
d += quantum_prob_inline(reg->node[i].amplitude);
size++;
}
}
}
/* Build the new quantum register */
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;
out.width = reg->width;
/* 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)
{
out.node[j].state = reg->node[i].state;
out.node[j].amplitude = reg->node[i].amplitude * 1 / (float) sqrt(d);
j++;
}
}
quantum_delete_qureg_hashpreserve(reg);
*reg = out;
return result;
}

View File

@@ -33,5 +33,6 @@ extern double quantum_frand();
extern MAX_UNSIGNED quantum_measure(quantum_reg reg);
extern int quantum_bmeasure(int pos, quantum_reg *reg);
extern int quantum_bmeasure_bitpreserve(int pos, quantum_reg *reg);
#endif

1
qec.c
View File

@@ -27,6 +27,7 @@
#include "gates.h"
#include "config.h"
#include "decoherence.h"
#include "measure.h"
/* Type of the QEC. Currently implemented versions are:

22
qft.c
View File

@@ -40,10 +40,20 @@ void quantum_qft(int width, quantum_reg *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);
}
}
void quantum_qft_inv(int width, quantum_reg *reg)
{
int i, j;
for(i=0; i<width; i++)
{
quantum_hadamard(i, reg);
for(j=i+1; j<width; j++)
quantum_cond_phase_inv(j, i, reg);
}
}

4
qft.h
View File

@@ -1,4 +1,4 @@
/* qft.c: Declarations for qft.c
/* qft.h: Declarations for qft.c
Copyright 2003 Bjoern Butscher, Hendrik Weimer
@@ -27,4 +27,6 @@
extern void quantum_qft(int width, quantum_reg *reg);
extern void quantum_qft_inv(int width, quantum_reg *reg);
#endif

View File

@@ -46,16 +46,6 @@ struct quantum_reg_node_struct
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
@@ -64,7 +54,7 @@ struct quantum_reg_struct
int size; /* number of non-zero vectors */
int hashw; /* width of the hash array */
quantum_reg_node *node;
quantum_reg_hash **hash;
int *hash;
};
typedef struct quantum_reg_struct quantum_reg;
@@ -77,6 +67,7 @@ extern void quantum_addscratch(int bits, quantum_reg *reg);
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_unbounded_toffoli(int controlling, 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);
@@ -87,7 +78,7 @@ extern void quantum_r_z(int target, float gamma, quantum_reg *reg);
extern void quantum_phase_scale(int target, float gamma, quantum_reg *reg);
extern void quantum_phase_kick(int target, float gamma, quantum_reg *reg);
extern void quantum_hadamard(int target, quantum_reg *reg);
extern void quantum_walsh(int target, quantum_reg *reg);
extern void quantum_walsh(int width, quantum_reg *reg);
extern void quantum_cond_phase(int control, int target, quantum_reg *reg);
extern void quantum_cond_phase_inv(int control, int target, quantum_reg *reg);
extern void quantum_cond_phase_kick(int control, int target, float gamma,
@@ -95,12 +86,14 @@ extern void quantum_cond_phase_kick(int control, int target, float gamma,
extern int quantum_gate_counter(int inc);
extern void quantum_qft(int width, quantum_reg *reg);
extern void quantum_qft_inv(int width, quantum_reg *reg);
extern void quantum_exp_mod_n(int N, int x, int width_input, int width,
quantum_reg *reg);
extern MAX_UNSIGNED quantum_measure(quantum_reg reg);
extern int quantum_bmeasure(int pos, quantum_reg *reg);
extern int quantum_bmeasure_bitpreserve(int pos, quantum_reg *reg);
extern quantum_matrix quantum_new_matrix(int cols, int rows);
extern void quantum_delete_matrix(quantum_matrix *m);
@@ -123,4 +116,6 @@ extern quantum_matrix quantum_qureg2matrix(quantum_reg reg);
extern void quantum_qec_encode(int type, int width, quantum_reg *reg);
extern void quantum_qec_decode(int type, int width, quantum_reg *reg);
extern const char * quantum_get_version();
#endif

145
qureg.c
View File

@@ -69,13 +69,13 @@ quantum_matrix2qureg(quantum_matrix *m, int width)
/* Allocate the hash table */
reg.hash = calloc(1 << reg.hashw, sizeof(quantum_reg_hash *));
reg.hash = calloc(1 << reg.hashw, sizeof(int));
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 *));
quantum_memman((1 << reg.hashw) * sizeof(int));
/* Copy the nonzero amplitudes of the vector into the quantum
register */
@@ -120,13 +120,13 @@ quantum_new_qureg(MAX_UNSIGNED initval, int width)
/* Allocate the hash table */
reg.hash = calloc(1 << reg.hashw, sizeof(quantum_reg_hash *));
reg.hash = calloc(1 << reg.hashw, sizeof(int));
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 *));
quantum_memman((1 << reg.hashw) * sizeof(int));
/* Initialize the quantum register */
@@ -161,22 +161,8 @@ quantum_qureg2matrix(quantum_reg reg)
void
quantum_destroy_hash(quantum_reg *reg)
{
int i;
quantum_reg_hash *p;
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;
}
}
free(reg->hash);
quantum_memman(-(1 << reg->hashw) * sizeof(quantum_reg_hash *));
quantum_memman(-(1 << reg->hashw) * sizeof(int));
}
/* Delete a quantum register */
@@ -205,12 +191,16 @@ quantum_delete_qureg_hashpreserve(quantum_reg *reg)
void
quantum_print_qureg(quantum_reg reg)
{
int i;
int i,j;
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("%f %+fi|%lli> (%e) (|", quantum_real(reg.node[i].amplitude),
quantum_imag(reg.node[i].amplitude), reg.node[i].state,
quantum_prob_inline(reg.node[i].amplitude));
for(j=reg.width-1;j>=0;j--)
printf("%i", ((((MAX_UNSIGNED) 1 << j) & reg.node[i].state) > 0));
printf(">)\n");
}
printf("\n");
@@ -249,122 +239,19 @@ quantum_addscratch(int bits, quantum_reg *reg)
}
}
/* 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)
quantum_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");
if(i)
printf("%i: %i %llu\n", i, reg.hash[i]-1,
reg.node[reg.hash[i]-1].state);
}
/* 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);
}

66
qureg.h
View File

@@ -40,16 +40,6 @@ struct quantum_reg_node_struct
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
@@ -58,7 +48,7 @@ struct quantum_reg_struct
int size; /* number of non-zero vectors */
int hashw; /* width of the hash array */
quantum_reg_node *node;
quantum_reg_hash **hash;
int *hash;
};
typedef struct quantum_reg_struct quantum_reg;
@@ -75,8 +65,6 @@ 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 */
@@ -100,56 +88,40 @@ 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])
while(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;
if(reg.node[reg.hash[i]-1].state == a)
return reg.hash[i]-1;
i++;
if(i == (1 << reg.hashw))
i = 0;
}
return -1;
}
/* Update an element of the hash table */
/* Add an element to the hash table */
static inline void
quantum_change_hash(MAX_UNSIGNED a, int oldpos, MAX_UNSIGNED b, int pos,
quantum_reg *reg)
quantum_add_hash(MAX_UNSIGNED a, int pos, quantum_reg *reg)
{
int i, j;
quantum_reg_hash *p, *q=0;
int i;
i = quantum_hash64(a, reg->hashw);
p = reg->hash[i];
q = reg->hash[i];
j = p->i;
while(reg->hash[i])
{
i++;
if(i == (1 << reg->hashw))
i = 0;
}
while(p->i != oldpos)
p = p->next;
reg->hash[i] = pos+1;
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

9
shor.c
View File

@@ -80,7 +80,14 @@ int main(int argc, char **argv) {
}
quantum_qft(width, &qr);
for(i=0; i<width/2; i++)
{
quantum_cnot(i, width-i-1, &qr);
quantum_cnot(width-i-1, i, &qr);
quantum_cnot(i, width-i-1, &qr);
}
// quantum_print_qureg(qr);
c=quantum_measure(qr);

30
version.c Normal file
View File

@@ -0,0 +1,30 @@
/* version.c: libquantum version information
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 "config.h"
const char *
quantum_get_version()
{
return PACKAGE_VERSION;
}

30
version.h Normal file
View File

@@ -0,0 +1,30 @@
/* version.h: Declarations for version.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 __VERSION_H
#define __VERSION_H
extern const char * quantum_get_version();
#endif