From dc03271227757ed9360e1230c8dcd8406af6b935 Mon Sep 17 00:00:00 2001 From: libquantum Date: Thu, 27 Oct 2016 04:12:28 +0900 Subject: [PATCH] updated libquantum 0.2.0 source files --- CHANGES | 10 ++ INSTALL | 25 +++-- Makefile.in | 33 +++--- README | 12 +-- config.h.in | 3 + configure | 21 ++-- configure.in | 79 ++++++++++++++ decoherence.c | 49 +++++++-- decoherence.h | 2 + gates.c | 185 +++++++++++++++++++++++++-------- gates.h | 6 ++ grover.c | 183 +++++++++++++++++++++++++++++++++ matrix.c | 2 +- measure.c | 2 +- qec.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++ qec.h | 41 ++++++++ quantum.h.in | 8 ++ qureg.c | 39 ++++++- qureg.h | 2 + shor.c | 25 ++++- 20 files changed, 908 insertions(+), 99 deletions(-) create mode 100644 configure.in create mode 100644 grover.c create mode 100644 qec.c create mode 100644 qec.h diff --git a/CHANGES b/CHANGES index 8559544..08733b4 100644 --- a/CHANGES +++ b/CHANGES @@ -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 diff --git a/INSTALL b/INSTALL index a3e824c..92b5581 100644 --- a/INSTALL +++ b/INSTALL @@ -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 ---------------------------- diff --git a/Makefile.in b/Makefile.in index e4f51aa..cae79a1 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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) diff --git a/README b/README index 7aee583..300ca1f 100644 --- a/README +++ b/README @@ -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 \ No newline at end of file +See also the libquantum website: +http://www.enyo.de/libquantum diff --git a/config.h.in b/config.h.in index fd2fa05..9ffbcc3 100644 --- a/config.h.in +++ b/config.h.in @@ -3,6 +3,9 @@ /* Complex data type */ #undef COMPLEX_FLOAT +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H diff --git a/configure b/configure index a318d65..737b78f 100755 --- a/configure +++ b/configure @@ -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 . # @@ -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 - diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..d5ed163 --- /dev/null +++ b/configure.in @@ -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 \ No newline at end of file diff --git a/decoherence.c b/decoherence.c index a6509f2..3d60dda 100644 --- a/decoherence.c +++ b/decoherence.c @@ -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; jwidth; 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; iwidth; 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; isize; i++) + + /* Apply the phase shifts for decoherence simulation */ + + for(i=0; isize; i++) + { + angle = 0; + + for(j=0; jwidth; 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)); + } } diff --git a/decoherence.h b/decoherence.h index 31437d2..996697f 100644 --- a/decoherence.h +++ b/decoherence.h @@ -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); diff --git a/gates.c b/gates.c index 57c5762..52ac528 100644 --- a/gates.c +++ b/gates.c @@ -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; isize; 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; isize; 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; isize; 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; isize; 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; isize; 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; isize; 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; isize; 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; isize; 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; jnode[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; jnode[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; isize; 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; isize; 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; isize; 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; } diff --git a/gates.h b/gates.h index b2cb5c9..68e04d1 100644 --- a/gates.h +++ b/gates.h @@ -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); diff --git a/grover.c b/grover.c new file mode 100644 index 0000000..a63c6cc --- /dev/null +++ b/grover.c @@ -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 +#include +#include +#include + +#define pi 3.141592654 + +void oracle(int state, quantum_reg *reg) +{ + int i; + + for(i=0;iwidth;i++) + { + if(!(state & (1 << i))) + { + quantum_sigma_x(i, reg); + } + } + + quantum_toffoli(0, 1, reg->width+1, reg); + + for(i=1;iwidth;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;iwidth;i++) + { + if(!(state & (1 << i))) + quantum_sigma_x(i, reg); + } + +} + +void inversion(quantum_reg *reg) +{ + int i; + + for(i=0;iwidth;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;iwidth-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;iwidth;i++) + quantum_sigma_x(i, reg); +} + + +void grover(int target, quantum_reg *reg) +{ + int i; + + oracle(target, reg); + + for(i=0;iwidth;i++) + quantum_hadamard(i, reg); + + inversion(reg); + + for(i=0;iwidth;i++) + quantum_hadamard(i, reg); + +} + +void print_grover(quantum_reg *reg) +{ + int i; + + for(i=0;isize;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, ®); + + for(i=0;i max) max = mem; - return max; + return mem; } /* Create a new COLS x ROWS matrix */ diff --git a/measure.c b/measure.c index 39a6ba8..c09fc86 100644 --- a/measure.c +++ b/measure.c @@ -169,7 +169,7 @@ quantum_bmeasure(int pos, quantum_reg *reg) } } - quantum_delete_qureg(reg); + quantum_delete_qureg_hashpreserve(reg); *reg = out; return result; } diff --git a/qec.c b/qec.c new file mode 100644 index 0000000..c56b474 --- /dev/null +++ b/qec.c @@ -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 + +#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;iwidth;i++) + { + if(i==reg->width-1) + quantum_set_decoherence(lambda); + + if(iwidth+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 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;isize;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); + +} diff --git a/qec.h b/qec.h new file mode 100644 index 0000000..3cd1357 --- /dev/null +++ b/qec.h @@ -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 diff --git a/quantum.h.in b/quantum.h.in index edc9ab5..47ba7c4 100644 --- a/quantum.h.in +++ b/quantum.h.in @@ -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 diff --git a/qureg.c b/qureg.c index 6f51760..5310a2e 100644 --- a/qureg.c +++ b/qureg.c @@ -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 diff --git a/qureg.h b/qureg.h index e937f4f..ef312e2 100644 --- a/qureg.h +++ b/qureg.h @@ -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); diff --git a/shor.c b/shor.c index d662ba9..280ead8 100644 --- a/shor.c +++ b/shor.c @@ -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 #include #include @@ -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; }