updated libquantum 0.2.0 source files

This commit is contained in:
libquantum
2016-10-27 04:12:28 +09:00
parent 1da72aab81
commit dc03271227
20 changed files with 908 additions and 99 deletions

10
CHANGES
View File

@@ -1,3 +1,13 @@
libquantum 0.2.0:
- Added Quantum Error Correction
- Included an Implementation of Grover's algorithm
- Added some inverse functions and conditional phase kick
- Improved speed of the decoherence simulation
- Fixed a memory leak in the quantum register deletion routine
- Fixed a segfault in the sigma functions
- Fixed a typo in the configure script that could result in a build
failure
libquantum 0.1.1:
- Completed rotation gates (quantum_r_z)
- Fixed a build problem with the demo program

25
INSTALL
View File

@@ -1,4 +1,4 @@
libquantum 0.1.1 installation guide
libquantum 0.2.0 installation guide
-----------------------------------
Contents:
@@ -37,16 +37,24 @@ Now you can build the beast:
make
By now, you can create a sample program which implements Shor's
factoring algorithm:
By now, you can create two demo programs which show Shor's factoring
algorithm and Grover's search algorithm:
make shor
make demos
The number to be factored is given on the command line as the first
parameter. To factor 15, simply type:
For the Shor algorithm demo, the number to be factored is given on the
command line as the first parameter. To factor 15, simply type:
./shor 15
The demo for Grover's algorithm requires the number of the marked
element (i.e. the desired result of the search) as the first argument
on the command line. The number of qubits may be given as a second
arguments. To mark element No. 42 in a database of 10 qubits (which
means 2^10 = 1024 elements):
./grover 42 10
2. Installation of the library
------------------------------
@@ -57,8 +65,9 @@ For this step you will need to have superuser privileges. Just type
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.
not in the standard search path for libraries. 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
----------------------------

View File

@@ -36,29 +36,29 @@ top_builddir=.
# Release information
MAJOR=0
MINOR=1
RELEASE=1
MINOR=2
RELEASE=0
# Tools needed to build libquantum
CC=@CC@
CC=@CC@ -O2 -g -pg
INSTALL=@INSTALL@
LIBTOOL=@LIBTOOL@
# Flags passed to C compiler
CFLAGS=@CFLAGS@
LDFLAGS=-rpath $(LIBDIR) -version-info 1:1:1
LDFLAGS=-rpath $(LIBDIR) -version-info 2:0:2
# 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
qureg.lo decoherence.lo oaddn.lo omuln.lo expn.lo qec.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
qureg.lo decoherence.lo qec.lo -lm
complex.lo: complex.c complex.h Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -c complex.c
@@ -90,21 +90,30 @@ classic.lo: classic.c classic.h Makefile
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
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
$(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)
# Build a demo showing Shor's factoring algorithm
# Build demos of Shor's and Grover's algorithms
demos: shor grover
shor: libquantum.la shor.c Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -o shor shor.c -I./ -lquantum -static -lm
grover: libquantum.la grover.c Makefile
$(LIBTOOL) $(CC) $(CFLAGS) -o grover grover.c -I./ -lquantum -static\
-lm
# Make everything neat and tidy
clean:
@@ -119,9 +128,9 @@ distclean:
dist:
-rm quantum.h config.h
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 CHANGES\
libquantum-$(MAJOR).$(MINOR).$(RELEASE)
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)

12
README
View File

@@ -1,4 +1,4 @@
libquantum 0.1.1 README file
libquantum 0.2.0 README file
----------------------------
libquantum is a C library for quantum computing. It provides quantum
@@ -6,16 +6,16 @@ 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.
Implementations of Shor's factoring algorithm and Grover's search
algorithm are included with this release.
See the file INSTALL for help on the installation.
guardian is distributed under the terms of the GNU General Public
libquantum 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
See also the libquantum website:
http://www.enyo.de/libquantum

View File

@@ -3,6 +3,9 @@
/* Complex data type */
#undef COMPLEX_FLOAT
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define to 1 if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H

21
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.1.1.
# Generated by GNU Autoconf 2.57 for libquantum 0.2.0.
#
# 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.1.1'
PACKAGE_STRING='libquantum 0.1.1'
PACKAGE_VERSION='0.2.0'
PACKAGE_STRING='libquantum 0.2.0'
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.1.1 to adapt to many kinds of systems.
\`configure' configures libquantum 0.2.0 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.1.1:";;
short | recursive ) echo "Configuration of libquantum 0.2.0:";;
esac
cat <<\_ACEOF
@@ -1092,7 +1092,7 @@ fi
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
libquantum configure 0.1.1
libquantum configure 0.2.0
generated by GNU Autoconf 2.57
Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
@@ -1107,7 +1107,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.1.1, which was
It was created by libquantum $as_me 0.2.0, which was
generated by GNU Autoconf 2.57. Invocation command line was
$ $0 $@
@@ -7877,7 +7877,7 @@ if test $ac_cv_type_uint_64t = yes; then
#define MAX_UNSIGNED uint_64t
_ACEOF
MU_TYPE="unint_64t"
MU_TYPE="uint_64t"
fi
if test "$MU_TYPE" = "none"
@@ -8620,7 +8620,7 @@ _ASBOX
} >&5
cat >&5 <<_CSEOF
This file was extended by libquantum $as_me 0.1.1, which was
This file was extended by libquantum $as_me 0.2.0, which was
generated by GNU Autoconf 2.57. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -8680,7 +8680,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
libquantum config.status 0.1.1
libquantum config.status 0.2.0
configured by $0, generated by GNU Autoconf 2.57,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
@@ -9358,4 +9358,3 @@ if test "$no_create" != yes; then
# would make configure fail if this is the last instruction.
$ac_cs_success || { (exit 1); exit 1; }
fi

79
configure.in Normal file
View File

@@ -0,0 +1,79 @@
# Process this file with autoconf to produce a configure script.
AC_INIT([libquantum], [0.2.0], [libquantum@enyo.de])
AC_CONFIG_SRCDIR([classic.c])
AC_CONFIG_HEADER([config.h])
# The language of our choice
AC_LANG([C])
# Checks for programs.
AC_PROG_CC
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.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h stdlib.h unistd.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_INLINE
# Check for 64-bit integer
MU_TYPE="none"
AC_CHECK_TYPE([uint_64t], [AC_DEFINE([MAX_UNSIGNED], [uint_64t])
MU_TYPE="uint_64t"])
if test "$MU_TYPE" = "none"
then
AC_CHECK_TYPE([u_int_64t], [AC_DEFINE([MAX_UNSIGNED], [u_int_64t])
MU_TYPE="u_int_64t"])
fi
if test "$MU_TYPE" = "none"
then
AC_CHECK_TYPE([unsigned long long], [AC_DEFINE(MAX_UNSIGNED,
[unsigned long long], [Integer type for quantum registers])
MU_TYPE="unsigned long long"])
fi
if test "$MU_TYPE" = "none"
then
AC_MSG_ERROR([No 64-bit integer type!])
fi
# Check for complex number type
CF_TYPE="none"
AC_CHECK_TYPE([float _Complex], [AC_DEFINE([COMPLEX_FLOAT], [float _Complex])
CF_TYPE="float _Complex"])
if test "$CF_TYPE" = "none"
then
AC_CHECK_TYPE([__complex__ float], [AC_DEFINE([COMPLEX_FLOAT],
[__complex__ float], [Complex data type])
CF_TYPE="__complex__ float"])
fi
if test "$CF_TYPE" = "none"
then
AC_MSG_ERROR([No complex number type!])
fi
# Check for the imaginary unit
AC_MSG_CHECKING([for the imaginary unit])
I="none"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([COMPLEX_FLOAT z;], [z=I;])],
[AC_DEFINE([IMAGINARY], [I], [Imaginary unit]) I="I"])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([COMPLEX_FLOAT z;], [z=_Complex_I;])],
[AC_DEFINE([IMAGINARY], [_Complex_I]) I="_Complex_I"])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([COMPLEX_FLOAT z;], [z=1i;])],
[AC_DEFINE([IMAGINARY], [1i]) I="1i"])
if test $I = "none"
then
AC_MSG_ERROR([No imaginary unit!])
fi
AC_MSG_RESULT($I)
AC_SUBST(MU_TYPE)
AC_SUBST(CF_TYPE)
AC_CONFIG_FILES([Makefile quantum.h])
AC_OUTPUT

View File

@@ -40,6 +40,12 @@ int status = 0;
float lambda = 0;
float
quantum_get_decoherence()
{
return lambda;
}
/* Initialize the decoherence simulation and set the decoherence
parameter. */
@@ -63,7 +69,8 @@ void
quantum_decohere(quantum_reg *reg)
{
float u, v, s, x;
COMPLEX_FLOAT c0, c1;
float *nrands;
float angle;
int i, j;
/* Increase the gate counter */
@@ -72,9 +79,19 @@ quantum_decohere(quantum_reg *reg)
if(status)
{
for(j=0; j<reg->width; j++)
nrands = calloc(reg->width, sizeof(float));
if(!nrands)
{
/* Generate a normal distributed random number */
printf("Not enough memory for %i-sized array of float!\n",
reg->width);
exit(1);
}
quantum_memman(reg->width * sizeof(float));
for(i=0; i<reg->width; i++)
{
/* Generate normal distributed random numbers */
do {
u = 2 * quantum_frand() - 1;
@@ -85,20 +102,30 @@ quantum_decohere(quantum_reg *reg)
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);
nrands[i] = x/2;
}
for(i=0; i<reg->size; i++)
/* Apply the phase shifts for decoherence simulation */
for(i=0; i<reg->size; i++)
{
angle = 0;
for(j=0; j<reg->width; j++)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << j))
reg->node[i].amplitude *= c1;
angle += nrands[j];
else
reg->node[i].amplitude *= c0;
angle -= nrands[j];
}
reg->node[i].amplitude *= quantum_cexp(angle);
}
free(nrands);
quantum_memman(reg->width * sizeof(float));
}
}

View File

@@ -25,6 +25,8 @@
#define __DECOHERENCE_H
extern float quantum_get_decoherence();
extern void quantum_set_decoherence(float lambda);
extern void quantum_decohere(quantum_reg *reg);

185
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
@@ -30,6 +30,7 @@
#include "complex.h"
#include "qureg.h"
#include "decoherence.h"
#include "qec.h"
/* Apply a controlled-not gate */
@@ -37,15 +38,23 @@ void
quantum_cnot(int control, int target, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
int qec;
quantum_qec_get_status(&qec, NULL);
if(qec)
quantum_cnot_ft(control, target, reg);
else
{
/* Flip the target bit of a base state if the control bit is set */
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);
if((reg->node[i].state & ((MAX_UNSIGNED) 1 << control)))
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
quantum_decohere(reg);
}
quantum_decohere(reg);
}
/* Apply a toffoli (or controlled-controlled-not) gate */
@@ -54,21 +63,29 @@ void
quantum_toffoli(int control1, int control2, int target, quantum_reg *reg)
{
int i;
int qec;
for(i=0; i<reg->size; i++)
quantum_qec_get_status(&qec, NULL);
if(qec)
quantum_toffoli_ft(control1, control2, target, reg);
else
{
/* Flip the target bit of a base state if both control bits are
set */
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control1))
for(i=0; i<reg->size; i++)
{
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control2))
/* Flip the target bit of a base state if both control bits are
set */
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control1))
{
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control2))
{
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
}
}
}
quantum_decohere(reg);
}
quantum_decohere(reg);
}
/* Apply a sigma_x (or not) gate */
@@ -77,20 +94,28 @@ 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 */
int qec;
reg->node[i].state ^= ((MAX_UNSIGNED) 1 << target);
}
quantum_decohere(reg);
quantum_qec_get_status(&qec, NULL);
if(qec)
quantum_sigma_x_ft(target, reg);
else
{
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)
quantum_sigma_y(int target, quantum_reg *reg)
{
int i;
@@ -113,7 +138,7 @@ quantum_sigma_y(int target, int width, quantum_reg *reg)
/* Apply a sigma_y gate */
void
quantum_sigma_z(int target, int width, quantum_reg *reg)
quantum_sigma_z(int target, quantum_reg *reg)
{
int i;
@@ -128,34 +153,49 @@ quantum_sigma_z(int target, int width, quantum_reg *reg)
}
/* Swap the first WIDTH bits of the quantum register. This is done
classically by renaming the bits. */
classically by renaming the bits, unless QEC is enabled. */
void
quantum_swaptheleads(int width, quantum_reg *reg)
{
int i, j;
int pat1, pat2;
int qec;
MAX_UNSIGNED l;
for(i=0; i<reg->size; i++)
quantum_qec_get_status(&qec, NULL);
if(qec)
{
/* calculate left bit pattern */
pat1 = reg->node[i].state % ((MAX_UNSIGNED) 1 << width);
for(i=0; i<width; i++)
{
quantum_cnot(i, width+i, reg);
quantum_cnot(width+i, i, reg);
quantum_cnot(i, width+i, reg);
}
}
else
{
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;
/*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;
for(j=0; j<width; j++)
pat2 += reg->node[i].state & ((MAX_UNSIGNED) 1 << (width + j));
/* construct the new basis state */
l = reg->node[i].state - (pat1 + pat2);
l += (pat1 << width);
l += (pat2 >> width);
reg->node[i].state = l;
}
}
}
@@ -352,7 +392,7 @@ quantum_gate1(int target, quantum_matrix m, quantum_reg *reg)
}
}
quantum_delete_qureg(reg);
quantum_delete_qureg_hashpreserve(reg);
*reg = out;
}
@@ -449,6 +489,22 @@ quantum_r_z(int target, float gamma, quantum_reg *reg)
quantum_decohere(reg);
}
/* Scale the phase of qubit */
void
quantum_phase_scale(int target, float gamma, quantum_reg *reg)
{
int i;
for(i=0; i<reg->size; i++)
{
reg->node[i].amplitude *= quantum_cexp(gamma);
}
quantum_decohere(reg);
}
/* Apply a phase kick by the angle GAMMA */
void
@@ -485,6 +541,45 @@ quantum_cond_phase(int control, int target, quantum_reg *reg)
quantum_decohere(reg);
}
void
quantum_cond_phase_inv(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);
}
void
quantum_cond_phase_kick(int control, int target, float gamma, 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(gamma);
}
}
quantum_decohere(reg);
}
/* Increase the gate counter by INC steps or reset it if INC < 0. The
current value of the counter is returned. */
@@ -497,6 +592,6 @@ quantum_gate_counter(int inc)
counter += inc;
else if(inc < 0)
counter = 0;
return counter;
}

View File

@@ -48,8 +48,14 @@ 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_phase_scale(int target, float gamma, quantum_reg *reg);
extern void quantum_phase_kick(int target, float gamma, 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,
quantum_reg *reg);
extern int quantum_gate_counter(int inc);

183
grover.c Normal file
View File

@@ -0,0 +1,183 @@
/* grover.c: Implementation of Grover's search algorithm
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 <quantum.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define pi 3.141592654
void oracle(int state, quantum_reg *reg)
{
int i;
for(i=0;i<reg->width;i++)
{
if(!(state & (1 << i)))
{
quantum_sigma_x(i, reg);
}
}
quantum_toffoli(0, 1, reg->width+1, reg);
for(i=1;i<reg->width;i++)
{
quantum_toffoli(i, reg->width+i, reg->width+i+1, reg);
}
quantum_cnot(reg->width+i, reg->width, reg);
for(i=reg->width-1;i>0;i--)
{
quantum_toffoli(i, reg->width+i, reg->width+i+1, reg);
}
quantum_toffoli(0, 1, reg->width+1, reg);
for(i=0;i<reg->width;i++)
{
if(!(state & (1 << i)))
quantum_sigma_x(i, reg);
}
}
void inversion(quantum_reg *reg)
{
int i;
for(i=0;i<reg->width;i++)
quantum_sigma_x(i, reg);
quantum_phase_scale(0, pi/2, reg);
quantum_hadamard(reg->width-1, reg);
if(reg->width==3)
quantum_toffoli(0, 1, 2, reg);
else
{
quantum_toffoli(0, 1, reg->width+1, reg);
for(i=1;i<reg->width-1;i++)
{
quantum_toffoli(i, reg->width+i, reg->width+i+1, reg);
}
quantum_cnot(reg->width+i, reg->width-1, reg);
for(i=reg->width-2;i>0;i--)
{
quantum_toffoli(i, reg->width+i, reg->width+i+1, reg);
}
quantum_toffoli(0, 1, reg->width+1, reg);
}
quantum_hadamard(reg->width-1, reg);
quantum_phase_scale(0, pi/2, reg);
for(i=0;i<reg->width;i++)
quantum_sigma_x(i, reg);
}
void grover(int target, quantum_reg *reg)
{
int i;
oracle(target, reg);
for(i=0;i<reg->width;i++)
quantum_hadamard(i, reg);
inversion(reg);
for(i=0;i<reg->width;i++)
quantum_hadamard(i, 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;
int i, N, width=0;
if(argc==1)
{
printf("Usage: grover [number] [[qubits]]\n\n");
return 3;
}
N=atoi(argv[1]);
if(argc > 2)
width = atoi(argv[2]);
if(width < quantum_getwidth(N+1))
width = quantum_getwidth(N+1);
reg = quantum_new_qureg(0, width);
quantum_sigma_x(reg.width, &reg);
for(i=0;i<reg.width;i++)
quantum_hadamard(i, &reg);
quantum_hadamard(reg.width, &reg);
printf("Iterating %i times\n", (int) (pi/4*sqrt(1<<reg.width)));
for(i=1; i<=pi/4*sqrt(1 << reg.width); i++)
{
printf("Iteration #%i\n", i);
grover(N, &reg);
}
quantum_hadamard(reg.width, &reg);
reg.width++;
quantum_bmeasure(reg.width-1, &reg);
for(i=0; i<reg.size; i++)
{
if(reg.node[i].state == N)
printf("\nFound %i with a probability of %f\n\n", N,
quantum_prob(reg.node[i].amplitude));
}
quantum_delete_qureg(&reg);
return 0;
}

View File

@@ -39,7 +39,7 @@ unsigned long quantum_memman(long change)
if(mem > max)
max = mem;
return max;
return mem;
}
/* Create a new COLS x ROWS matrix */

View File

@@ -169,7 +169,7 @@ quantum_bmeasure(int pos, quantum_reg *reg)
}
}
quantum_delete_qureg(reg);
quantum_delete_qureg_hashpreserve(reg);
*reg = out;
return result;
}

280
qec.c Normal file
View File

@@ -0,0 +1,280 @@
/* qec.c: Quantum Error Correction
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 "qureg.h"
#include "gates.h"
#include "config.h"
#include "decoherence.h"
/* Type of the QEC. Currently implemented versions are:
0: no QEC (default)
1: Steane's 3-bit code */
int type = 0;
/* How many qubits are protected */
int width = 0;
/* Change the status of the QEC. */
void
quantum_qec_set_status(int stype, int swidth)
{
type = stype;
width = swidth;
}
/* Get the current QEC status */
void
quantum_qec_get_status(int *ptype, int *pwidth)
{
if(ptype)
*ptype = type;
if(pwidth)
*pwidth = width;
}
/* Encode a quantum register. All qubits up to SWIDTH are protected,
the rest is expanded with a repition code. */
void
quantum_qec_encode(int type, int width, quantum_reg *reg)
{
int i;
float lambda;
lambda = quantum_get_decoherence();
quantum_set_decoherence(0);
for(i=0;i<reg->width;i++)
{
if(i==reg->width-1)
quantum_set_decoherence(lambda);
if(i<width)
{
quantum_hadamard(reg->width+i, reg);
quantum_hadamard(2*reg->width+i, reg);
quantum_cnot(reg->width+i, i, reg);
quantum_cnot(2*reg->width+i, i, reg);
}
else
{
quantum_cnot(i, reg->width+i, reg);
quantum_cnot(i, 2*reg->width+i, reg);
}
}
quantum_qec_set_status(1, reg->width);
reg->width *= 3;
}
/* Decode a quantum register and perform Quantum Error Correction on
it */
void
quantum_qec_decode(int type, int width, quantum_reg *reg)
{
int i, a, b;
int swidth;
float lambda;
lambda = quantum_get_decoherence();
quantum_set_decoherence(0);
swidth=reg->width/3;
quantum_qec_set_status(0, 0);
for(i=reg->width/3-1;i>=0;i--)
{
if(i==0)
quantum_set_decoherence(lambda);
if(i<width)
{
quantum_cnot(2*swidth+i, i, reg);
quantum_cnot(swidth+i, i, reg);
quantum_hadamard(2*swidth+i, reg);
quantum_hadamard(swidth+i, reg);
}
else
{
quantum_cnot(i, 2*swidth+i, reg);
quantum_cnot(i, swidth+i, reg);
}
}
for(i=1;i<=swidth;i++)
{
a = quantum_bmeasure(swidth, reg);
b = quantum_bmeasure(2*swidth-i, reg);
if(a == 1 && b == 1 && i-1 < width)
quantum_sigma_z(i-1, reg); /* Z = HXH */
}
}
/* Counter which can be used to apply QEC periodically */
int
quantum_qec_counter(int inc, int frequency, quantum_reg *reg)
{
static int counter = 0;
static int freq = (1<<30);
if(inc > 0)
counter += inc;
else if(inc < 0)
counter = 0;
if(frequency > 0)
freq = frequency;
if(counter >= freq)
{
counter = 0;
quantum_qec_decode(type, width, reg);
quantum_qec_encode(type, width, reg);
}
return counter;
}
/* Fault-tolerant version of the NOT gate */
void
quantum_sigma_x_ft(int target, quantum_reg *reg)
{
int tmp;
float lambda;
tmp = type;
type = 0;
lambda = quantum_get_decoherence();
quantum_set_decoherence(0);
/* These operations can be performed simultaneously */
quantum_sigma_x(target, reg);
quantum_sigma_x(target+width, reg);
quantum_set_decoherence(lambda);
quantum_sigma_x(target+2*width, reg);
quantum_qec_counter(1, 0, reg);
type = tmp;
}
/* Fault-tolerant version of the Controlled NOT gate */
void
quantum_cnot_ft(int control, int target, quantum_reg *reg)
{
int tmp;
float lambda;
tmp = type;
type = 0;
/* These operations can be performed simultaneously */
lambda = quantum_get_decoherence();
quantum_set_decoherence(0);
quantum_cnot(control, target, reg);
quantum_cnot(control+width, target+width, reg);
quantum_set_decoherence(lambda);
quantum_cnot(control+2*width, target+2*width, reg);
quantum_qec_counter(1, 0, reg);
type = tmp;
}
/* Fault-tolerant version of the Toffoli gate */
void
quantum_toffoli_ft(int control1, int control2, int target, quantum_reg *reg)
{
int i;
int c1, c2;
MAX_UNSIGNED mask;
mask = ((MAX_UNSIGNED) 1 << target)
+ ((MAX_UNSIGNED) 1 << (target+width))
+ ((MAX_UNSIGNED) 1 << (target+2*width));
for(i=0;i<reg->size;i++)
{
c1 = 0;
c2 = 0;
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control1))
c1 = 1;
if(reg->node[i].state
& ((MAX_UNSIGNED) 1 << (control1+width)))
{
c1 ^= 1;
}
if(reg->node[i].state
& ((MAX_UNSIGNED) 1 << (control1+2*width)))
{
c1 ^= 1;
}
if(reg->node[i].state & ((MAX_UNSIGNED) 1 << control2))
c2 = 1;
if(reg->node[i].state
& ((MAX_UNSIGNED) 1 << (control2+width)))
{
c2 ^= 1;
}
if(reg->node[i].state
& ((MAX_UNSIGNED) 1 << (control2+2*width)))
{
c2 ^= 1;
}
if(c1 == 1 && c2 == 1)
reg->node[i].state = reg->node[i].state ^ mask;
}
quantum_decohere(reg);
quantum_qec_counter(1, 0, reg);
}

41
qec.h Normal file
View File

@@ -0,0 +1,41 @@
/* gates.h: Declarations for qec.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 __QEC_H
#define __QEC_H
#include "qureg.h"
extern void quantum_qec_set_status(int stype, int swidth);
extern void quantum_qec_get_status(int *ptype, int *pwidth);
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 void quantum_sigma_x_ft(int target, quantum_reg *reg);
extern void quantum_cnot_ft(int control, int target, quantum_reg *reg);
extern void quantum_toffoli_ft(int control1, int control2, int target,
quantum_reg *reg);
#endif

View File

@@ -84,10 +84,14 @@ extern void quantum_gate1(int target, quantum_matrix m, quantum_reg *reg);
extern void quantum_r_x(int target, float gamma, quantum_reg *reg);
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_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_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,
quantum_reg *reg);
extern int quantum_gate_counter(int inc);
extern void quantum_qft(int width, quantum_reg *reg);
@@ -109,10 +113,14 @@ extern int quantum_getwidth(int n);
extern float quantum_prob(COMPLEX_FLOAT a);
extern float quantum_get_decoherence();
extern void quantum_set_decoherence(float lambda);
extern void quantum_decohere(quantum_reg *reg);
extern quantum_reg quantum_matrix2qureg(quantum_matrix *m, int width);
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);
#endif

39
qureg.c
View File

@@ -156,17 +156,50 @@ quantum_qureg2matrix(quantum_reg reg)
return m;
}
/* Delete a quantum register. Note that the hash table is still
alive. */
/* Destroys the entire hash table of a quantum register */
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 *));
}
/* Delete a quantum register */
void
quantum_delete_qureg(quantum_reg *reg)
{
quantum_destroy_hash(reg);
free(reg->node);
quantum_memman(-reg->size * sizeof(quantum_reg_node));
reg->node = 0;
}
/* Delete a quantum register but leave the hash table alive */
void
quantum_delete_qureg_hashpreserve(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

View File

@@ -66,7 +66,9 @@ 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_destroy_hash(quantum_reg *reg);
extern void quantum_delete_qureg(quantum_reg *reg);
extern void quantum_delete_qureg_hashpreserve(quantum_reg *reg);
extern void quantum_print_qureg(quantum_reg reg);
extern void quantum_print_expn(quantum_reg reg);

25
shor.c
View File

@@ -1,3 +1,26 @@
/* shor.c: Implementation of Shor's factoring algorithm
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>
@@ -119,7 +142,7 @@ int main(int argc, char **argv) {
quantum_delete_qureg(&qr);
// printf("Memory usage: %i bytes\n", (int )memman(0));
// printf("Memory leak: %i bytes\n", (int) quantum_memman(0));
return 0;
}