Files
libquantum/qureg.c
2016-10-27 04:14:06 +09:00

258 lines
5.2 KiB
C

/* qureg.c: Quantum register management
Copyright 2003 Bjoern Butscher, Hendrik Weimer
This file is part of libquantum
libquantum is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
libquantum is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with libquantum; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "matrix.h"
#include "qureg.h"
#include "config.h"
#include "complex.h"
/* Convert a vector to a quantum register */
quantum_reg
quantum_matrix2qureg(quantum_matrix *m, int width)
{
quantum_reg reg;
int i, j, size=0;
if(m->cols != 1)
{
printf("Error! Cannot convert a multi-column-matrix (%i)!\n", m->cols);
exit(1);
}
reg.width = width;
/* Determine the size of the quantum register */
for(i=0; i<m->rows; i++)
{
if(m->t[i])
size++;
}
/* Allocate the required memory */
reg.size = size;
reg.hashw = width + 2;
reg.node = calloc(size, sizeof(quantum_reg_node));
if(!reg.node)
{
printf("Not enough memory for %i-sized qubit!\n", size);
exit(1);
}
quantum_memman(size * sizeof(quantum_reg_node));
/* Allocate the hash table */
reg.hash = calloc(1 << reg.hashw, sizeof(int));
if(!reg.hash)
{
printf("Not enough memory for %i-sized hash!\n", 1 << reg.hashw);
exit(1);
}
quantum_memman((1 << reg.hashw) * sizeof(int));
/* Copy the nonzero amplitudes of the vector into the quantum
register */
for(i=0, j=0; i<m->rows; i++)
{
if(m->t[i])
{
reg.node[j].state = i;
reg.node[j].amplitude = m->t[i];
j++;
}
}
/* Initialize the PRNG */
srandom(time(0));
return reg;
}
/* Create a new quantum register from scratch */
quantum_reg
quantum_new_qureg(MAX_UNSIGNED initval, int width)
{
quantum_reg reg;
reg.width = width;
reg.size = 1;
reg.hashw = width + 2;
/* Allocate memory for 1 base state */
reg.node = calloc(1, sizeof(quantum_reg_node));
if(!reg.node)
{
printf("Not enough memory for %i-sized qubit!\n", 1);
exit(1);
}
quantum_memman(sizeof(quantum_reg_node));
/* Allocate the hash table */
reg.hash = calloc(1 << reg.hashw, sizeof(int));
if(!reg.hash)
{
printf("Not enough memory for %i-sized hash!\n", 1 << reg.hashw);
exit(1);
}
quantum_memman((1 << reg.hashw) * sizeof(int));
/* Initialize the quantum register */
reg.node[0].state = initval;
reg.node[0].amplitude = 1;
/* Initialize the PRNG */
srandom(time(0));
return reg;
}
/* Convert a quantum register to a vector */
quantum_matrix
quantum_qureg2matrix(quantum_reg reg)
{
quantum_matrix m;
int i;
m = quantum_new_matrix(1, 1 << reg.width);
for(i=0; i<reg.size; i++)
m.t[reg.node[i].state] = reg.node[i].amplitude;
return m;
}
/* Destroys the entire hash table of a quantum register */
void
quantum_destroy_hash(quantum_reg *reg)
{
free(reg->hash);
quantum_memman(-(1 << reg->hashw) * sizeof(int));
}
/* 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
quantum_print_qureg(quantum_reg reg)
{
int i,j;
for(i=0; i<reg.size; i++)
{
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");
}
/* Print the output of the modular exponentation algorithm */
void
quantum_print_expn(quantum_reg reg)
{
int i;
for(i=0; i<reg.size; i++)
{
printf("%i: %lli\n", i, reg.node[i].state - i * (1 << (reg.width / 2)));
}
}
/* Add additional space to a qureg. It is initialized to zero and can
be used as scratch space. Note that the space gets added at the LSB */
void
quantum_addscratch(int bits, quantum_reg *reg)
{
int i, oldwidth;
MAX_UNSIGNED l;
oldwidth = reg->width;
reg->width += bits;
for(i=0; i<reg->size; i++)
{
l = reg->node[i].state << bits;
reg->node[i].state = l;
}
}
/* Print the hash table to stdout and test if the hash table is
corrupted */
void
quantum_print_hash(quantum_reg reg)
{
int i;
for(i=0; i < (1 << reg.hashw); i++)
{
if(i)
printf("%i: %i %llu\n", i, reg.hash[i]-1,
reg.node[reg.hash[i]-1].state);
}
}