diff --git a/exercises/ex05_skeleton/qsimulator_skeleton.cpp b/exercises/ex05_skeleton/qsimulator_skeleton.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5161440a98731a01aa31c31e1bb534de267911a6 --- /dev/null +++ b/exercises/ex05_skeleton/qsimulator_skeleton.cpp @@ -0,0 +1,145 @@ +#include <vector> +#include <iostream> +#include <complex> +#include <string> +#include <random> + + +class QSimulator +{ +public: + typedef unsigned state_type; + typedef double scalar_type; + typedef std::complex<scalar_type> complex_type; + typedef std::vector<complex_type> wf_type; + typedef std::pair<scalar_type,scalar_type> dmatr_type; + QSimulator(unsigned n, bool v); + + void H(const wf_type& iwf, wf_type& owf, unsigned qubitId) const; + void CNOT(const wf_type& iwf, wf_type& owf, unsigned cqid, unsigned qid) const; + void Z(wf_type& wf, unsigned qid) const; + void X(const wf_type& iwf, wf_type& owf, unsigned qid) const; + void Uf(const wf_type& iwf, wf_type& owf, state_type(*f)(state_type st, unsigned hqid)) const; + + bool measureQubit(wf_type& wf, unsigned qid) const; // physical measurement + dmatr_type tomography(const wf_type& iwf, unsigned qid) const; // state of the qubit qid + void printWF(wf_type wf) const; + state_type maxState() const { return maxState_; } + +private: + const unsigned n_; + const state_type maxState_; + const bool verbose_; + + mutable std::mt19937 rndEngine_; + mutable std::uniform_real_distribution<scalar_type> probDist_; + mutable std::uniform_int_distribution<unsigned> qidDist_; +}; + +QSimulator::QSimulator(unsigned n, bool v) +: verbose_(v), n_(n), maxState_( (1<<n)-1 ), probDist_(0.0,1.0), qidDist_(1,n-1), rndEngine_(time(NULL)) +{ +} + + +void QSimulator::CNOT(const wf_type& iwf, wf_type& owf, unsigned cqid, unsigned qid) const{ + owf = iwf; + for(state_type st=0; st<=maxState(); st++){ + if(std::abs(iwf[st])!=0.0){ + if (st & (1<<cqid)){ // control qubit set + state_type flippedSt = st ^ (1<<qid); // flip the other qubit + owf[flippedSt] = iwf[st]; + owf[st] = iwf[flippedSt]; + } + } + } + if(verbose_){ + std::cout << "wavefunction after the CNOT gate:" << std::endl; + printWF(owf); + } +} + + +bool QSimulator::measureQubit(wf_type& wf, unsigned qid) const{ + dmatr_type dmatr = // calculate probabilities to measure 0 or 1 + + scalar_type randNum = probDist_(rndEngine_); + bool measured1 = (randNum<dmatr.second)? 1: 0; + if(verbose_){ + std::cout << "probability to measure |0>: " << dmatr.first << ", for |1>: " << dmatr.second << std::endl; + std::cout << "randNum = " << randNum << ",measured1 = " << measured1 << std::endl; + } + +// ====== drop projected out components, renormalize the rest +//.............. +// ====== drop projected out components, renormalize the rest + + if(verbose_){ + std::cout << "wavefunction after the measurement:" << std::endl; + printWF(wf); + } + + if(measured1){ + return true; + }else{ + return false; + } +} + +void QSimulator::printWF(wf_type wf) const{ + for(state_type st=0; st<=maxState(); st++){ + std::cout << wf[st] << "\t"; + } + std::cout << std::endl; +} + +std::string usage(const std::string& prog) +{ + return "usage: " + prog + " nQubitsForDeutschJosza"; +} +int main(int argc, const char** argv) +{ + if( argc != 2 ){ + std::cerr << usage(argv[0]) << std::endl; + return -1; + } + unsigned DJN = stoi(argv[1],nullptr,10); + if(DJN<2){ + std::cerr << "At least 2 qubits will be needed for the Deutsch-Josza algorithm" << std::endl; + return -1; + + } +// ============== Teleportation begin + // qubit index convention: unknown id=0, Alice Bell id=1, Bob Bell id=2 + bool verbose = false; + int n = 3; + std::cout << "Teleportation:" << std::endl; + QSimulator teleport(n, verbose); + QSimulator::wf_type iwf(teleport.maxState()+1,0); + QSimulator::wf_type owf(teleport.maxState()+1,0); + + iwf[1] = 1/3.0; + iwf[0] = 2*std::sqrt(2)/3; // 1/3 |001> + 2sqrt(2)/3 |000> "unknown" state to teleport + + std::cout << "initial wavefunction:" << std::endl; + teleport.printWF(iwf); + + QSimulator::dmatr_type dmatr = teleport.tomography(iwf, 0); + std::cout << "State of the Alice's |psi> qubit (id=0) is " << std::sqrt(dmatr.first) << "|0> + " << std::sqrt(dmatr.second) << "|1>" << std::endl; + +// ====== generate Bell00 state + teleport.H(iwf,owf,1); + iwf.swap(owf); + teleport.CNOT(iwf,owf,1,2); + iwf.swap(owf); +// ====== generate Bell00 state + +// ........... + +// ============== Teleportation end + +// ============== DJ begin + //......... +// ============== DJ end + +} diff --git a/exercises/exercise05.pdf b/exercises/exercise05.pdf new file mode 100644 index 0000000000000000000000000000000000000000..544f8b2952a685fa73805c162f0bb48d001b25ae Binary files /dev/null and b/exercises/exercise05.pdf differ