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 "qgame++.h"
00026
00027 using namespace std;
00028 using namespace qgame;
00029
00030 ostream & qgame::operator<<(ostream &o, const Result &r) {
00031 o << "Misses: " << r.misses << endl;
00032 o << "Max error: " << r.maxError << endl;
00033 o << "Average error: " << r.avgError << endl;
00034 o << "Max expected oracles: " << r.maxExpOracles << endl;
00035 o << "Average expected oracles: " << r.avgExpOracles << endl;
00036 return o;
00037 }
00038
00039
00040 QSys::QSys() {
00041 prg = NULL;
00042 numQubits = 0;
00043 oracleTT = "";
00044 }
00045
00046 QSys::~QSys() {
00047 delete prg;
00048 }
00049
00050 void QSys::init (int numqb, QProgram *p, const string &tt) {
00051 prg = p;
00052 instrPnt = 0;
00053 oracleTT = tt;
00054 prob = 1;
00055 numQubits = numqb;
00056 reg = Qureg(numqb);
00057 prg->installOracle(tt);
00058 oracleCount = 0;
00059 execInstr.clear();
00060 measureHistory.clear();
00061 execInstr = vector<bool>(p->length(), true);
00062 };
00063
00064 void QSys::setReg(const Qureg &r) {
00065 reg = r;
00066 }
00067
00068 Qureg QSys::getReg() {
00069 return reg;
00070 }
00071
00072 double QSys::getProb() {
00073 return prob;
00074 }
00075
00076 void QSys::setProb(double p) {
00077 prob = p;
00078 }
00079
00080 int QSys::getOracleCount() {
00081 return oracleCount;
00082 }
00083
00084 void QSys::appendMeasurement(QubitList q, int outcome, double prob) {
00085 Measurement m;
00086 m.qubit = q[0];
00087 m.result = outcome;
00088 m.prob = prob;
00089 measureHistory.push_back(m);
00090 }
00091
00092 QSys *QSys::clone(double p) {
00093 QSys *res = new QSys;
00094 res->prob = p;
00095 res->instrPnt = instrPnt;
00096 res->prg = prg;
00097 res->oracleTT = oracleTT;
00098 res->numQubits = numQubits;
00099 res->reg = reg;
00100 res->oracleCount = oracleCount;
00101 res->execInstr = execInstr;
00102 res->measureHistory = measureHistory;
00103 return res;
00104 }
00105
00106 void QSys::apply(QGate *gate, const QubitList &qubits) throw(Error) {
00107 if(gate->numQb() != qubits.size()) throw(Error(E_MISMATCH));
00108 vector<QuSubReg> subregs = reg.getSubRegs(qubits);
00109 for(int sr = 0; sr < subregs.size(); sr++) {
00110 gate->apply(subregs[sr]);
00111 }
00112 }
00113
00114 void QSys::apply(const QInstr &instr) throw(Error) {
00115 if(!instr.gate) return;
00116 if(instr.type == ORACLE) oracleCount++;
00117 else if(instr.type == LIMITED_ORACLE) {
00118 if(oracleCount >= instr.extra) return;
00119 else oracleCount++;
00120 }
00121 apply(instr.gate, instr.qubits);
00122 }
00123
00124 vector<QSys*> QSys::execute(int numqb, QProgram *p, const string &tt) throw(Error) {
00125 QSys *sys = new QSys;
00126 sys->init(numqb, p, tt);
00127 return sys->exec();
00128 }
00129
00130 vector<QSys*> QSys::exec() throw(Error) {
00131 vector<QSys*> result;
00132 bool term = false;
00133 while(!term && instrPnt<prg->length()) {
00134 if(!execInstr[instrPnt]) { instrPnt++; continue; }
00135 QInstr *instr = (*prg)[instrPnt];
00136 if(instr->gate) {
00137
00138 apply(*instr);
00139 instrPnt++;
00140 } else {
00141 instrPnt++;
00142 switch(instr->type) {
00143 case MEASURE: {
00144 vector<double> probs = reg.getProbabilities(instr->qubits);
00145 QSys *ifsys = NULL;
00146 QSys *elsys = NULL;
00147 if(probs[0]>0) elsys = this;
00148 if(probs[1]>0) {
00149 if(elsys) ifsys = clone(prob);
00150 else ifsys = this;
00151 }
00152 if(ifsys) {
00153 ifsys->reg.collapse(instr->qubits, 1);
00154 ifsys->setProb(ifsys->getProb() * probs[1]);
00155 ifsys->appendMeasurement(instr->qubits, 1, probs[1]);
00156 }
00157 if(elsys) {
00158 elsys->reg.collapse(instr->qubits, 0);
00159 elsys->setProb(elsys->getProb() * probs[0]);
00160 elsys->appendMeasurement(instr->qubits, 0, probs[0]);
00161 }
00162
00163 int i = instrPnt;
00164 int d = 0;
00165 bool flg = false; bool branch = true;
00166 QSys *curSys = elsys;
00167 while(!flg && i<prg->length()) {
00168 if(curSys) curSys->execInstr[i] = false;
00169 switch((*prg)[i]->type) {
00170 case MEASURE:
00171 d+=2; break;
00172 case END:
00173 if(d>0) d--;
00174 else {
00175 if(branch) {
00176 if(elsys) elsys->instrPnt = i+1;
00177 if(!ifsys) flg = true;
00178 else { branch = false; curSys = ifsys; }
00179 } else flg = true;
00180 }
00181 break;
00182 }
00183 i++;
00184 }
00185 if(ifsys && elsys) {
00186 vector<QSys*> ifRes = ifsys->exec();
00187 for(int r = 0; r<ifRes.size(); r++) result.push_back(ifRes[r]);
00188 }
00189 break;
00190 }
00191 case HALT:
00192 term = true;
00193 break;
00194
00195 case ORACLE:
00196 throw(Error(E_NOORACLE));
00197 break;
00198
00199 case PRINTAMPS:
00200
00201
00202
00203
00204
00205
00206 cout << *this;
00207 break;
00208
00209
00210 }
00211 }
00212 }
00213 result.push_back(this);
00214 return result;
00215 }
00216
00217 Result QSys::testProgram(int numqb, QProgram *p, const std::vector<TestCase> &cases,
00218 const QubitList &finm, double thresh) throw(Error) {
00219 Result res;
00220 res.misses = 0;
00221 res.avgError = res.avgExpOracles = res.maxError = res.maxExpOracles = 0;
00222 double totalErr = 0;
00223 double totalExpOracles = 0;
00224 for(int c = 0; c < cases.size(); c++) {
00225 TestCase tcase = cases[c];
00226 vector<QSys*> systems = execute(numqb, p, tcase.oracleTT);
00227 double expOracles = 0;
00228 double rawerr = 1.0;
00229 for(int s=0; s<systems.size(); s++) {
00230 rawerr -= systems[s]->getReg().getProbabilities(finm)[tcase.desiredRes] * systems[s]->getProb();
00231 expOracles += systems[s]->getProb() * systems[s]->getOracleCount();
00232 }
00233 if(rawerr<-0.000000001) { cerr << "\nWARNING: rawerr = "<<rawerr; }
00234 if(rawerr>thresh) res.misses++;
00235 totalErr += rawerr;
00236 if(rawerr > res.maxError) res.maxError = rawerr;
00237 totalExpOracles += expOracles;
00238 if(expOracles > res.maxExpOracles) res.maxExpOracles = expOracles;
00239 }
00240 res.avgError = totalErr / cases.size();
00241 res.avgExpOracles = totalExpOracles / cases.size();
00242 return res;
00243 }
00244
00245 ostream& qgame::operator<<(std::ostream &o, const QSys &s) {
00246 o << "\n========================================================================";
00247 o << "\nQSys ("<<s.numQubits<<" qubits, prior prob = "<<s.prob<<")\n";
00248 o << "\nMeasurement History:";
00249
00250 for(int i = 0; i<s.measureHistory.size(); i++) {
00251 o << "\n q" <<s.measureHistory[i].qubit << " = " << s.measureHistory[i].result
00252 << " (p = " << s.measureHistory[i].prob << ")";
00253 }
00254 o << "\nRegister:" << s.reg << "\n";
00255
00256 return o;
00257
00258 }
00259
00260
00261
00262
00263
00264