qgtypes.cpp

00001 /***************************************************************************
00002  *   QGame++                                                               *
00003  *   =======                                                               *
00004  *   A Quantum Gate And Measurement Emulator.                              *
00005  *                                                                         *
00006  *   Copyright (C) 2003/04 by Manuel Nickschas                             *
00007  *   <qgame-devel@nickschas.de>                                            *
00008  *                                                                         *
00009  *   This program is free software; you can redistribute it and/or modify  *
00010  *   it under the terms of the GNU General Public License as published by  *
00011  *   the Free Software Foundation; either version 2 of the License, or     *
00012  *   (at your option) any later version.                                   *
00013  *                                                                         *
00014  *   This program is distributed in the hope that it will be useful,       *
00015  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017  *   GNU General Public License for more details.                          *
00018  *                                                                         *
00019  *   You should have received a copy of the GNU General Public License     *
00020  *   along with this program; if not, write to the                         *
00021  *   Free Software Foundation, Inc.,                                       *
00022  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00023  ***************************************************************************/
00024 
00025 #include "qgame++.h"
00026 #include "qgtypes.h"
00027 #include "qgerror.h"
00028 
00029 using namespace qgame;
00030 using namespace std;
00031 
00032 /***************************************************************************
00033  * Class Complex                                                           *
00034  ***************************************************************************/
00035 
00036 Complex::Complex(double r, double i) {
00037   re = r; im = i;
00038 }
00039 
00040 double Complex::Re() {
00041   return re;
00042 }
00043 
00044 double Complex::Im() {
00045   return im;
00046 }
00047 
00048 Complex Complex::operator+(const Complex &c) {
00049   double r = re + c.re;
00050   double i = im + c.im;
00051   return Complex(r,i);
00052 }
00053 
00054 Complex Complex::operator+=(const Complex &c) {
00055   re += c.re;
00056   im += c.im;
00057   return *this;
00058 }
00059 
00060 Complex Complex::operator-(const Complex &c) {
00061   double r = re - c.re;
00062   double i = im - c.im;
00063   return Complex(r,i);
00064 }
00065 
00066 Complex Complex::operator*(const Complex &c) {
00067   double r = re*c.re - im*c.im;
00068   double i = re*c.im + im*c.re;
00069   return Complex(r,i);
00070 }
00071 
00072 Complex Complex::operator*=(const Complex &c) {
00073   double r = re*c.re - im*c.im;
00074   double i = re*c.im + im*c.re;
00075   re = r; im = i;
00076   return *this;
00077 }
00078 
00079 std::ostream& qgame::operator<<(std::ostream &o, const Complex &c) {
00080   o << '(' << c.re << ',' << c.im << ')';
00081   return o;
00082 }
00083 
00084 double Complex::sqabs() {
00085   return re*re + im*im;
00086 }
00087 
00088 /* (namespace) global function for convenience */
00089 double qgame::sqabs(const Complex &c) {
00090   return c.re*c.re + c.im*c.im;
00091 }
00092 
00093 /***************************************************************************
00094  * Class QubitList                                                         *
00095  ***************************************************************************/
00096 
00097 unsigned int QubitList::size() const {
00098   return qbl.size();
00099 }
00100 
00101 void QubitList::append(int x) {
00102   qbl.push_back(x);
00103 }
00104 
00105 int QubitList::operator[](const unsigned int i) const throw(Error) {
00106   if(i>=qbl.size()) throw Error(E_OUTOFBOUNDS);
00107   return qbl[i];
00108 }
00109 
00110 ostream & qgame::operator<<(ostream &o, const QubitList &l) {
00111   o << "{ ";
00112   for(int i=l.size()-1; i>=0; i--) o << l[i] << " ";
00113   o << "}";
00114 }
00115 
00116 /***************************************************************************
00117  * Class QuSubReg                                                          *
00118  ***************************************************************************/
00119 
00120 QuSubReg::QuSubReg(int s) {
00121   num = s;
00122   sub = vector<Complex*>(1<<s, (Complex*)NULL);
00123   //for(int i=0; i<1<<s; i++) { sub.push_back(NULL); }
00124 }
00125 
00126 QuSubReg::~QuSubReg() {
00127 
00128 }
00129 
00130 unsigned int QuSubReg::numAmps() const {
00131   return 1<<num;
00132 }
00133 
00134 unsigned int QuSubReg::numQb() const {
00135   return num;
00136 }
00137 
00138 Complex & QuSubReg::operator[](const unsigned int i) throw(Error) {
00139   if(i>=sub.size()) throw Error(E_OUTOFBOUNDS);
00140   return *sub[i];
00141 }
00142 
00143 /***************************************************************************
00144  * Class Qureg                                                             *
00145  ***************************************************************************/
00146 
00147 Qureg::Qureg(int s) {
00148   num = s;
00149   amp = vector<Complex>(1<<s, Complex(0,0));
00150   amp[0] = Complex(1,0);  // |00...00>
00151 }
00152 
00153 vector<QuSubReg> Qureg::getSubRegs(const QubitList &qubits) {
00154   vector<QuSubReg> result;
00155   int numqb = qubits.size();
00156   int numot = num - numqb;
00157   QubitList otbits; // remaining qubits
00158   for(int i=0; i<num; i++) {
00159     bool flg = false;
00160     for(int j=0; j<numqb; j++) {
00161       if(qubits[j]==i) { flg = true; break; }
00162     }
00163     if(!flg) otbits.append(i);
00164   }
00165   for(int sr=0; sr<(1<<numot); sr++) {
00166     int index2 = 0; int dum = sr;
00167     for(int i = 0; i<numot; i++) {
00168       if(dum%2) index2 += (1<<otbits[i]);
00169       dum = dum>>1;
00170     }
00171     QuSubReg sreg(numqb);
00172     for(int sqb=0; sqb<(1<<numqb); sqb++) {
00173       int index = index2; dum = sqb;
00174       for(int i = 0; i<numqb; i++) {
00175         if(dum%2) index += (1<<qubits[i]);
00176         dum = dum>>1;
00177       }
00178       sreg.sub[sqb] = &amp[index];
00179     }
00180     result.push_back(sreg);
00181   }
00182   return result;
00183 }
00184 
00185 /* TODO: this needs some serious cleaning... */
00186 vector<double> Qureg::getProbabilities(const QubitList &qubits) {
00187   vector<double> result = vector<double>(1<<qubits.size(),0);
00188   vector<QuSubReg> subregs = getSubRegs(qubits);
00189   double t = 0; // DEBUG // 
00190   //cerr << "\nabs: ";
00191   for(int s = 0; s < subregs.size(); s++) {
00192     for(int a = 0; a < subregs[s].numAmps(); a++) {
00193       result[a] += sqabs(subregs[s][a]);
00194       //cerr << sqabs(subregs[s][a])<< " ";
00195       t += sqabs(subregs[s][a]); // DEBUG
00196     }
00197   }
00198   /* sanity check works only for normalized register! */
00199   if(fabs(1-t)>.0000001) cerr << "\n\nWARNING: Non-unitary transformation? p="<<t;
00200   //if(t>1.000000001) cerr << "\n\nWARNING: Something wrong with probs in register! (p="<<t<<")";
00201   //cerr << "\n probs: "; for(int i=0; i< result.size(); i++) cerr << result[i]<<" "; 
00202   return result;
00203 }
00204 
00205 /* return false if the system completely collapses! */
00206 void Qureg::collapse(const QubitList &qubits, int value) {
00207   vector<QuSubReg> subregs = getSubRegs(qubits);
00208   for(int s = 0; s < subregs.size(); s++) {
00209     for(int a = 0; a < subregs[s].numAmps(); a++) {
00210       if(a != value) subregs[s][a] = 0;
00211     }
00212   }
00213   normalize();
00214 }
00215 
00216 void Qureg::normalize() {
00217   double sum = 0;
00218   for(int i=0; i<amp.size(); i++) sum += sqabs(amp[i]);
00219   if(sum == 0) cerr << "\nWARNING: Cannot happen!"; 
00220   sum = 1.0/sqrt(sum);
00221   for(int i=0; i<amp.size(); i++) amp[i]*=sum; 
00222   //return true;
00223 }
00224 
00225 unsigned int Qureg::size() const {
00226   return num;
00227 }
00228 
00229 Complex & Qureg::operator[](const unsigned int i) throw(Error) {
00230   if(i>=amp.size()) throw Error(E_OUTOFBOUNDS);
00231   return amp[i];
00232 };
00233 
00234 #if 0
00235 /* old, more compact representation */
00236 std::ostream& qgame::operator<<(std::ostream &o, const Qureg &r) {
00237   o << "[ ";
00238   for(int i=0; i<r.amp.size();i++) o << r.amp[i] << ' ';
00239   o << "]";
00240   return o;
00241 }
00242 #else
00243 /* this prints everything */
00244 std::ostream& qgame::operator<<(std::ostream &o, Qureg r) {
00245   for(int i = 0; i<r.amp.size(); i++) {
00246     o << "\n   |";
00247     int dum = i;
00248     for(int j = r.num-1; j>=0; j--) {
00249       if(dum >= 1<<j) { dum -= 1<<j; o << "1"; }
00250       else o << "0";
00251     }
00252     o << ">: " << r[i] << " (p = " << sqabs(r.amp[i]) << ")";
00253   }
00254   return o;
00255 }
00256 
00257 #endif
00258 
00259 /***************************************************************************
00260  * TestCase                                                                *
00261  ***************************************************************************/
00262  
00263 /* parse case and set desiredRes to -1 if invalid */
00264 TestCase::TestCase(const string &casestr) {
00265   char buf[256];
00266   desiredRes = -1;
00267   if(casestr.length()<3) return;
00268   
00269   int k;
00270   for(k=0; k<casestr.length()-2; k++) {
00271     if(casestr[k]=='-') break;
00272     if(casestr[k]!='0' && casestr[k]!='1') return;
00273     buf[k] = casestr[k];
00274   }
00275   buf[k] = '\0';
00276   if(casestr[k]!='-') return;
00277   char *endpnt;
00278   desiredRes = strtol(casestr.c_str()+k+1,&endpnt,10);
00279   if(*endpnt != '\0') desiredRes = -1;
00280   oracleTT = buf; 
00281 }

Generated on Sat Apr 3 18:42:28 2004 for QGame++ by doxygen 1.3.5