qgprog.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 "qgprog.h"
00026 #include "qggates.h"
00027 #include "qgtypes.h"
00028 #include "qgerror.h"
00029 
00030 #include <iostream>
00031 #include <fstream>
00032 #include <sstream>
00033 #include <vector>
00034 #include <string>
00035 #include <cmath>
00036 
00037 using namespace std;
00038 using namespace qgame;
00039 
00040 ostream & qgame::operator<<(ostream &o, const QInstr &i) {
00041   o << "(";
00042   if(i.gate) o << *i.gate << " ";
00043   else {
00044     switch(i.type) {
00045       case ORACLE: o << "ORACLE [tt=<UNKNOWN>]"; break;
00046       case LIMITED_ORACLE: o << "LIMITED-ORACLE [l=" << i.extra << " tt=<UNKNOWN>]"; break;
00047       case END: o << "END"; break;
00048       case HALT: o << "HALT"; break;
00049       case MEASURE: o << "MEASURE"; break;
00050     
00051       default: o << "<UNKNOWN> "; break;
00052     }
00053   }
00054   o << i.qubits << ")";
00055   return o;
00056 }
00057 
00058 QProgram::QProgram() {
00059   instrPnt = 0;
00060 }
00061 
00062 QProgram::~QProgram() {
00063   for(int i = 0; i<instr.size(); i++) {
00064     delete instr[i];
00065   }
00066 }
00067 
00068 ostream & qgame::operator<<(ostream &o, const QProgram &p) {
00069   if(p.instr.size()==0) {
00070     o << "<EMPTY>" << endl;
00071     return o;
00072   }
00073   for(int i=0; i<p.instr.size(); i++) {
00074     o << "***";
00075     o << *p.instr[i] << endl;
00076   }
00077   return o;
00078 }
00079 
00080 QInstr * QProgram::operator[](unsigned int index) throw(Error) {
00081   if(index>=instr.size()) throw E_OUTOFBOUNDS;
00082   return instr[index];
00083 }
00084 
00085 unsigned int QProgram::length() const {
00086   return instr.size();
00087 }
00088 
00089 QProgramSettings QProgram::read(istream &is) throw(Error) {
00090   const int bufsize = 2048;
00091   char buf[bufsize];
00092   QProgramSettings settings;
00093   //ifstream fin;
00094   //fin.open(fname.c_str(),ios::in);
00095   //if(!fin) throw(Error(E_IO));
00096   //while(is.getline(buf,bufsize)) {
00097   //  if(buf[0] == ':') parseSetting(settings, buf);
00098   //  else addInstruction(buf);
00099   //}
00100   //fin.close();
00101   char c;
00102   string instr;
00103   bool issetting = false;
00104   int depth = 0;
00105   while((c = is.get())!=EOF) {
00106     if(c != '\n') instr+=c;
00107     else if(is.peek() == '#') {
00108       while(is.peek() != '\n') is.get();
00109     } 
00110     if(c == ':') {
00111       issetting = true;
00112     } else {
00113       if(!issetting) {
00114         if(c == '(') {
00115           if(depth == 0) instr = "(";  // ignore whitespace
00116           depth++;
00117         } else if(c == ')') {
00118           depth--;
00119           if(depth < 0) throw Error(E_SYNTAX);
00120           if(depth == 0) {
00121             addInstruction(instr);
00122             instr = "";
00123           } else {
00124             while(is.peek() == ' ' || is.peek() == '\n') is.get();
00125           }
00126         }
00127       } else {
00128         if(c == '\n') {
00129           parseSetting(settings, instr);
00130           instr = "";
00131           issetting = false;
00132         }
00133       }
00134     }
00135   }
00136   return settings;
00137 }
00138 
00139 void QProgram::parseSetting(QProgramSettings &set, const string &line) throw(Error) {
00140   istringstream ss(line);
00141   char c = ss.get();
00142   if(c != ':') throw Error(E_SYNTAX);
00143   string param;
00144   ss >> param;
00145   if(param == "num-qubits") {
00146     ss >> set.numQb;
00147   } else if(param == "threshold") {
00148     ss >> set.threshold;
00149   } else if(param == "cases") {
00150     string str;
00151     while(ss >> str) {
00152       TestCase tc(str);
00153       if(tc.desiredRes<0) throw Error(E_SYNTAX);
00154       set.cases.push_back(tc);
00155       if(ss.peek() == EOF) break;
00156     }
00157   } else if(param == "final-measurement-qubits") {
00158     set.finalQb = getQubits(0, ss);
00159   }
00160   
00161   if(ss.get() != EOF) throw Error(E_SYNTAX);
00162 }
00163 
00164 // this method parses the QGAME syntax as defined in Lee's book.
00165 QInstr * QProgram::parseLine(const string &line) throw(Error) {
00166   QInstr *inst = new QInstr;
00167   istringstream ss(line);
00168   char c = ss.get();
00169   if(c == '#' || c == ':' || c == EOF) {
00170     inst->gate = NULL;
00171     inst->type = COMMENT;
00172     return inst;
00173   }
00174   if(c !='(') throw Error(E_SYNTAX);
00175   string cmd;
00176   ss >> cmd;
00177   if(cmd == "CNOT") {
00178     inst->qubits = getQubits(2,ss);
00179     inst->type = CNOT;
00180     inst->gate = new QGateCNOT;
00181   } else if(cmd == "QNOT") {
00182     inst->qubits = getQubits(1,ss);
00183     inst->type = QNOT;
00184     inst->gate = new QGateQNOT;
00185   } else if(cmd == "SRN") {
00186     inst->qubits = getQubits(1,ss);
00187     inst->type = SRN;
00188     inst->gate = new QGateSRN;
00189   } else if(cmd == "NAND") {
00190     inst->qubits = getQubits(3,ss);
00191     inst->type = NAND;
00192     inst->gate = new QGateNAND;
00193   } else if(cmd == "HADAMARD") {
00194     inst->qubits = getQubits(1,ss);
00195     inst->type = HADAMARD;
00196     inst->gate = new QGateH2;
00197   } else if(cmd == "U-THETA") {
00198     inst->qubits = getQubits(1,ss);
00199     double theta;
00200     ss >> theta;
00201     inst->type = U_THETA;
00202     inst->gate = new QGateUTHETA(theta);
00203   } else if(cmd == "CPHASE-OLD") {
00204     inst->qubits = getQubits(2,ss);
00205     double alpha;
00206     ss >> alpha;
00207     inst->type = CPHASE_OLD;
00208     inst->gate = new QGateCPHASEOLD(alpha);
00209   } else if(cmd == "CPHASE") {
00210     inst->qubits = getQubits(2,ss);
00211     double alpha;
00212     ss >> alpha;
00213     inst->type = CPHASE;
00214     inst->gate = new QGateCPHASE(alpha);
00215   } else if(cmd == "U2") {
00216     inst->qubits = getQubits(1,ss);
00217     double phi,theta,psi,alpha;
00218     ss >> phi >> theta >> psi >> alpha;
00219     inst->type = U2;
00220     inst->gate = new QGateU2(phi,theta,psi,alpha);
00221   } else if(cmd == "SWAP") {
00222     inst->qubits = getQubits(2,ss);
00223     inst->type = SWAP;
00224     inst->gate = new QGateSWAP;
00225   } else if(cmd == "ORACLE") {
00226     while(ss.peek() == ' ') ss.get();
00227     if(ss.peek() == '(') {  // oracle-tt given
00228       ss.get();
00229       string tt; char c;
00230       while((c = ss.get()) != ')') {
00231         if(c == ' ') continue;
00232         if(c!='0' && c!='1') throw Error(E_SYNTAX);
00233         tt+=c;
00234       }
00235       cerr << tt;
00236       inst->gate = new QOracle(tt);
00237       inst->flag = false;
00238     } else { 
00239       string dum;
00240       ss >> dum; // "ORACLE-TT"
00241       if(dum == "ORACLE-TT") inst->flag = true;
00242       else throw Error(E_SYNTAX);
00243     }
00244     inst->qubits = getQubits(-1,ss);
00245     inst->type = ORACLE;
00246   } else if(cmd == "LIMITED-ORACLE") {
00247     ss >> inst->extra;  // limit
00248     while(ss.peek() == ' ') ss.get();
00249     if(ss.peek() == '(') {  // oracle-tt given
00250       ss.get();
00251       string tt; char c;
00252       while((c = ss.get()) != ')') {
00253         if(c == ' ') continue;
00254         if(c!='0' && c!='1') throw Error(E_SYNTAX);
00255         tt+=c;
00256       }
00257       cerr << tt;
00258       inst->gate = new QOracle(tt);
00259       inst->flag = false;
00260     } else { 
00261       string dum;
00262       ss >> dum; // "ORACLE-TT"
00263       if(dum == "ORACLE-TT") inst->flag = true;
00264       else throw Error(E_SYNTAX);
00265     }
00266     inst->qubits = getQubits(-1,ss);
00267     inst->type = LIMITED_ORACLE;
00268   } else if(cmd == "MATRIX-GATE") {
00269     while(ss.peek() == ' ') ss.get();
00270     vector<vector<Complex> > m;
00271     int n = 0; int rows = 0;
00272     if(ss.get() != '#' || ss.get() != '2' || ss.get() != 'A' || ss.get() != '(')
00273       throw Error(E_SYNTAX);
00274     // read a matrix line
00275     for(;;rows++) {
00276       if(ss.peek() == ')') break;
00277       if(ss.get() != '(') throw Error(E_SYNTAX);
00278       vector<Complex> r;
00279       int cols = 0;
00280       for(;;cols++) {
00281         if(ss.peek() == ')' || ss.peek() == EOF) break;
00282         double entry;  // we don't support reading complex numbers at the moment!
00283         ss >> entry;
00284         r.push_back(entry);
00285       }
00286       ss.get();
00287       if(!n) n = cols;
00288       if(cols != n) { throw Error(E_SYNTAX); }
00289       m.push_back(r);
00290     }
00291     ss.get();
00292     if(rows != n) throw Error(E_SYNTAX);
00293     QubitList q;
00294     int numqb = (int)(log((double)n)/log(2.)+.5);
00295     for(int i=0; i<numqb; i++) q.append(i);
00296     inst->qubits = q;
00297     inst->type = MATRIX_GATE;
00298     inst->gate = new QMatrixGate(m);
00299     return inst;
00300   } else if(cmd == "MEASURE") {
00301     inst->qubits = getQubits(1,ss);
00302     inst->type = MEASURE;
00303   } else if(cmd == "END)") {
00304     inst->type = END;
00305     return inst;
00306   } else if(cmd == "HALT)") {
00307     inst->type = HALT;
00308     return inst;
00309   } else if(cmd == "PRINTAMPS)") {
00310     inst->type = PRINTAMPS;
00311     return inst;
00312   }   
00313   
00314   if(ss.get()!=')') throw Error(E_SYNTAX);
00315   return inst;
00316 }
00317 
00318 /* Read the specified number of qubits from the given stream. */
00319 QubitList QProgram::getQubits(int num, istringstream &ss) throw(Error) {
00320   vector<int> l;
00321   QubitList res;
00322   int n;
00323   if(num>0) {
00324     for(int i=0; i<num; i++) {
00325       ss >> n;
00326       l.push_back(n);
00327     }
00328   } else {
00329     while(ss.peek() != ')' && ss.peek() != EOF && ss >> n) l.push_back(n);
00330   }
00331   for(int i=l.size()-1; i>=0; i--) {
00332     res.append(l[i]);
00333   }
00334   return res;  
00335 }
00336 
00337 bool QProgram::addInstruction(const string &line) throw(Error) {
00338   QInstr *i = parseLine(line);
00339   return addInstruction(i);
00340 }
00341 
00342 bool QProgram::addInstruction(QInstr *i) throw(Error) {
00343   if(i->type != COMMENT) instr.push_back(i);
00344   return true;
00345 }
00346 
00347 void QProgram::installOracle(const string &tt) {
00348   if(tt == "") return;
00349   for(int i=0; i<instr.size(); i++) {
00350     if(instr[i]->type != ORACLE && instr[i]->type != LIMITED_ORACLE) continue;
00351     if(!instr[i]->flag) continue;  // fixed TT
00352     delete instr[i]->gate;
00353     instr[i]->gate = new QOracle(tt);
00354   }
00355 }

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