00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00094
00095
00096
00097
00098
00099
00100
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 = "(";
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
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() == '(') {
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;
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;
00248 while(ss.peek() == ' ') ss.get();
00249 if(ss.peek() == '(') {
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;
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
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;
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
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;
00352 delete instr[i]->gate;
00353 instr[i]->gate = new QOracle(tt);
00354 }
00355 }