From e32e0b2d3a50c1dcb7d966754e975f5780074d1c Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Mon, 15 Jun 2020 21:48:38 -0400 Subject: [PATCH 01/12] Initial wfn permute changes --- src/Simulation/Native/CMakeSettings.json | 28 +++++++++++ .../Native/src/simulator/wavefunction.hpp | 48 ++++++++++++++++++- 2 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 src/Simulation/Native/CMakeSettings.json diff --git a/src/Simulation/Native/CMakeSettings.json b/src/Simulation/Native/CMakeSettings.json new file mode 100644 index 00000000000..ee45e8257c1 --- /dev/null +++ b/src/Simulation/Native/CMakeSettings.json @@ -0,0 +1,28 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "variables": [] + }, + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [] + } + ] +} \ No newline at end of file diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index 1d3a390642c..c129060ac36 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -116,6 +116,8 @@ class Wavefunction /// allocate a qubit and grow the wave function void allocateQubit(unsigned id) { + + assert(usage_ != 1); usage_ = 2; flush(); @@ -128,13 +130,16 @@ class Wavefunction qubitmap_.push_back(num_qubits_++); } assert((wfn_.size() >> num_qubits_) == 1); + //std::copy(qubitmap_.begin(), qubitmap_.end(), std::ostream_iterator(std::cout, " ")); + //std::cout << qubitmap_.back() << "\n"; + //std::cout << wfn_.back() << "\n"; } /// release the specified qubit /// \pre the qubit has to be in a classical state in the computational basis void release(qubit_t q) { - unsigned p = qubit(q); + unsigned p = qubit(q); //returns qubitmap_[q] flush(); kernels::collapse(wfn_, p, getvalue(q), true); for (int i = 0; i < qubitmap_.size(); ++i) @@ -238,18 +243,57 @@ class Wavefunction rng_.seed(s); } + void reorderWFN(unsigned qubitLoc, unsigned newPos) + { + //qubitmap_[qid]; //get location of qubit in wfn + //0,1,2 ->H(1)->1,0,2->X(2)_>2,0,1 + //get id of qubit located at newPos - getting index from the element + std::vector::iterator itr1 = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); + unsigned newPosId = std::distance(qubitmap_.begin(), itr1); + std::vector::iterator itr2 = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); + unsigned qid = std::distance(qubitmap_.begin(), itr2); + //swap qubits in wfn between qubitLoc and newPos + if (newPos != qubitLoc) + { + for (unsigned i = 0; i < wfn_.size(); i++) + { + unsigned int bit1 = (i >> qubitLoc) & 1; + unsigned int bit2 = (i >> newPos) & 1; + unsigned int x = (bit1 ^ bit2); + x = (x << qubitLoc) | (x << newPos); + unsigned new_i = i ^ x; + if (new_i > i) + { + std::iter_swap(wfn_.begin() + i, wfn_.begin() + new_i); + } + } + //swap elemnts in qubitmap located at qid and newPosId + std::iter_swap(qubitmap_.begin() + qid, qubitmap_.begin() + newPosId); + } + + } /// generic application of a gate template void apply(Gate const& g) { + //std::cout << *this << "\n"; + //std::copy(qubitmap_.begin(), qubitmap_.end(), std::ostream_iterator(std::cout, "\n")); + //std::cout << wfn_[0] << " " << qubitmap_[0]; + auto qid = qubit(g); + reorderWFN(qubit(g), 0); fused_.apply(wfn_, g.matrix(), qubit(g)); } - + /// generic application of a multiply controlled gate template void apply_controlled(std::vector cs, Gate const& g) { std::vector pcs = qubits(cs); + for (unsigned i = 0; i < pcs.size(); i++) + { + reorderWFN(qubit(pcs[i]), i); + } + reorderWFN(qubit(g), pcs.size()); fused_.apply_controlled(wfn_, g.matrix(), pcs, qubit(g)); } From f48134ed7934dac13fa7339d2007c01a6952aa00 Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Tue, 16 Jun 2020 19:13:00 -0400 Subject: [PATCH 02/12] changes to reorder to fix minor bugs --- src/Simulation/Native/src/external/fused.hpp | 3 ++- .../Native/src/simulator/capi_test.cpp | 18 ++++++++++-------- .../Native/src/simulator/wavefunction.hpp | 7 ++++--- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/Simulation/Native/src/external/fused.hpp b/src/Simulation/Native/src/external/fused.hpp index 235cf8ed15c..816da46d587 100644 --- a/src/Simulation/Native/src/external/fused.hpp +++ b/src/Simulation/Native/src/external/fused.hpp @@ -134,7 +134,8 @@ class Fused // New rules of when to stop fusing Fusion::IndexVector qs = std::vector(1, q); - if (fusedgates.predict(qs, cs) > maxFusedSpan || fusedgates.size() >= maxFusedDepth) flush(wfn); + if (fusedgates.predict(qs, cs) > maxFusedSpan || fusedgates.size() >= maxFusedDepth) flush(wfn); + fusedgates.insert(convertMatrix(mat), qs, cs); } diff --git a/src/Simulation/Native/src/simulator/capi_test.cpp b/src/Simulation/Native/src/simulator/capi_test.cpp index feb725db2fa..6cca1a6bcd0 100644 --- a/src/Simulation/Native/src/simulator/capi_test.cpp +++ b/src/Simulation/Native/src/simulator/capi_test.cpp @@ -106,23 +106,27 @@ void test_gates() allocateQubit(sim_id, 0); allocateQubit(sim_id, 1); + ////simpler test + //X(sim_id, 0); + //X(sim_id, 1); + //CX(sim_id, 0, 1); + //X(sim_id, 0); + CRx(sim_id, 1.0, 0, 1); - CRx(sim_id, 1.0, 0, 1); - - assert(M(sim_id, 1)==false); + assert(M(sim_id, 1) == false); X(sim_id, 0); - CRx(sim_id, 1.0, 0, 1); + CRx(sim_id, 1.0, 0, 1); H(sim_id, 1); CRx(sim_id, -1.0, 0, 1); H(sim_id, 1); - assert(M(sim_id, 1)==false); + assert(M(sim_id, 1) == false); X(sim_id, 1); - assert(M(sim_id, 1)==true); + assert(M(sim_id, 1) == true); X(sim_id, 1); @@ -131,8 +135,6 @@ void test_gates() destroy(sim_id); } - - void test_allocate() { auto sim_id = init(); diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index c129060ac36..0a15f18d6ef 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -279,7 +279,7 @@ class Wavefunction //std::cout << *this << "\n"; //std::copy(qubitmap_.begin(), qubitmap_.end(), std::ostream_iterator(std::cout, "\n")); //std::cout << wfn_[0] << " " << qubitmap_[0]; - auto qid = qubit(g); + //auto qid = qubit(g); reorderWFN(qubit(g), 0); fused_.apply(wfn_, g.matrix(), qubit(g)); } @@ -291,10 +291,11 @@ class Wavefunction std::vector pcs = qubits(cs); for (unsigned i = 0; i < pcs.size(); i++) { - reorderWFN(qubit(pcs[i]), i); + reorderWFN(pcs[i], i); } reorderWFN(qubit(g), pcs.size()); - fused_.apply_controlled(wfn_, g.matrix(), pcs, qubit(g)); + pcs = qubits(cs); + fused_.apply_controlled(wfn_, g.matrix(), pcs, qubit(g)); } /// generic application of a controlled gate From 32810757895bf7503b267371d4724b8a4ac4255c Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Wed, 17 Jun 2020 12:10:44 -0400 Subject: [PATCH 03/12] rebase with clean sim branch --- src/Simulation/Native/src/external/fused.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Simulation/Native/src/external/fused.hpp b/src/Simulation/Native/src/external/fused.hpp index 816da46d587..da2435e65d6 100644 --- a/src/Simulation/Native/src/external/fused.hpp +++ b/src/Simulation/Native/src/external/fused.hpp @@ -135,7 +135,6 @@ class Fused // New rules of when to stop fusing Fusion::IndexVector qs = std::vector(1, q); if (fusedgates.predict(qs, cs) > maxFusedSpan || fusedgates.size() >= maxFusedDepth) flush(wfn); - fusedgates.insert(convertMatrix(mat), qs, cs); } From c3189fbe94ce848605daa65793f67ef2252cb52a Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Thu, 25 Jun 2020 11:56:47 -0400 Subject: [PATCH 04/12] Reordering wfn to work with existing flush/fuse logic --- src/Simulation/Native/src/external/fused.hpp | 39 ++++++---- src/Simulation/Native/src/external/fusion.hpp | 43 +++++++++++ .../Native/src/simulator/capi_test.cpp | 19 +++++ .../Native/src/simulator/wavefunction.hpp | 75 ++++++++++++++++--- 4 files changed, 151 insertions(+), 25 deletions(-) diff --git a/src/Simulation/Native/src/external/fused.hpp b/src/Simulation/Native/src/external/fused.hpp index da2435e65d6..22dd21423a7 100644 --- a/src/Simulation/Native/src/external/fused.hpp +++ b/src/Simulation/Native/src/external/fused.hpp @@ -41,7 +41,14 @@ class Fused fusedgates = Fusion(); } + Fusion getFusedGates() const { + return fusedgates; + } + void setFusedGates(Fusion newFG) const { + fusedgates = newFG; + } + template void flush(std::vector& wfn) const { @@ -85,7 +92,6 @@ class Fused std::vector& qubitswfn, double tolerance) { - flush(wfn); // we have to flush before we can extract the state return kernels::subsytemwavefunction(wfn, qs, qubitswfn, tolerance); } @@ -102,11 +108,25 @@ class Fused template void apply_controlled(std::vector& wfn, M const& mat, std::vector const& cs, unsigned q) { - // Major runtime logic change here + Fusion::IndexVector qs = std::vector(1, q); + fusedgates.insert(convertMatrix(mat), qs, cs); + } + + template + void apply(std::vector& wfn, M const& mat, unsigned q) + { + std::vector cs; + apply_controlled(wfn, mat, cs, q); + } + + template + bool shouldFlush(std::vector& wfn, M const& mat, std::vector const& cs, unsigned q) + { + // Major runtime logic change here - // Have to update capacity as the WFN grows + // Have to update capacity as the WFN grows if (wfnCapacity != wfn.capacity()) { - wfnCapacity = wfn.capacity(); + wfnCapacity = wfn.capacity(); char* envNT = NULL; size_t len; #ifdef _MSC_VER @@ -133,16 +153,9 @@ class Fused } // New rules of when to stop fusing - Fusion::IndexVector qs = std::vector(1, q); - if (fusedgates.predict(qs, cs) > maxFusedSpan || fusedgates.size() >= maxFusedDepth) flush(wfn); - fusedgates.insert(convertMatrix(mat), qs, cs); - } + Fusion::IndexVector qs = std::vector(1, q); - template - void apply(std::vector& wfn, M const& mat, unsigned q) - { - std::vector cs; - apply_controlled(wfn, mat, cs, q); + return (fusedgates.predict(qs, cs) > maxFusedSpan || fusedgates.size() >= maxFusedDepth); } private: mutable Fusion fusedgates; diff --git a/src/Simulation/Native/src/external/fusion.hpp b/src/Simulation/Native/src/external/fusion.hpp index f3224f79212..00b21b0b990 100644 --- a/src/Simulation/Native/src/external/fusion.hpp +++ b/src/Simulation/Native/src/external/fusion.hpp @@ -10,6 +10,7 @@ #include #include #include "util/alignedalloc.hpp" +#include class Item{ public: @@ -20,6 +21,11 @@ class Item{ Item(Matrix mat, IndexVector idx) : mat_(mat), idx_(idx) {} Matrix& get_matrix() { return mat_; } IndexVector& get_indices() { return idx_; } + void setIdx(std::map elemDict) { + for (unsigned i = 0; i < idx_.size(); i++) { + idx_[i] = elemDict[idx_[i]]; + } + } private: Matrix mat_; IndexVector idx_; @@ -58,7 +64,44 @@ class Fusion{ handle_controls(empty_matrix, empty_vec, {}); // remove all current control qubits (this is a GLOBAL factor) } + IndexSet getSet() const { + return set_; + } + + ItemVector getItems() const { + return items_; + } + + IndexSet getCtrlSet() const { + return ctrl_set_; + } + + Complex getGlobalFactor() const { + return global_factor_; + } + + void setSet(std::map elemDict) { + std::set tempSet; + for (unsigned elem : set_) { + tempSet.insert(elemDict[elem]); + } + set_.clear(); + set_.insert(tempSet.begin(), tempSet.end()); //look into using swap instead + } + void setCtrlSet(std::map elemDict) { + std::set tempSet; + for (unsigned elem : ctrl_set_) { + tempSet.insert(elemDict[elem]); + } + ctrl_set_.clear(); + ctrl_set_.insert(tempSet.begin(), tempSet.end()); + } + + void setItems(ItemVector newItems) { + items_.clear(); + items_.insert(items_.begin(), newItems.begin(), newItems.end()); + } // This saves a class instance create/destroy on every gate insert // Need a quick way to decide if we're going to grow too wide int predict(IndexVector index_list, IndexVector const& ctrl_list = {}) { diff --git a/src/Simulation/Native/src/simulator/capi_test.cpp b/src/Simulation/Native/src/simulator/capi_test.cpp index 6cca1a6bcd0..e255109594b 100644 --- a/src/Simulation/Native/src/simulator/capi_test.cpp +++ b/src/Simulation/Native/src/simulator/capi_test.cpp @@ -106,15 +106,23 @@ void test_gates() allocateQubit(sim_id, 0); allocateQubit(sim_id, 1); + /*allocateQubit(sim_id, 2); + allocateQubit(sim_id, 3);*/ ////simpler test //X(sim_id, 0); //X(sim_id, 1); //CX(sim_id, 0, 1); //X(sim_id, 0); + //assert(M(sim_id, 1) == false); CRx(sim_id, 1.0, 0, 1); assert(M(sim_id, 1) == false); + //R(sim_id, 1, 3.14159265358979323846, 1); + //R(sim_id,1, 3.14159265358979323846, 0); + //CRx(sim_id, 3.14159265358979323846, 0, 1); + // + //assert(M(sim_id, 1) == false); X(sim_id, 0); CRx(sim_id, 1.0, 0, 1); @@ -128,7 +136,18 @@ void test_gates() assert(M(sim_id, 1) == true); + /*X(sim_id, 2); + X(sim_id, 0); + X(sim_id, 3); X(sim_id, 1); + CX(sim_id, 1, 2); + + assert(M(sim_id, 2) == false); + + X(sim_id, 2); + X(sim_id, 0); + X(sim_id, 3); + X(sim_id, 1);*/ release(sim_id, 0); release(sim_id, 1); diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index 0a15f18d6ef..b016d573092 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -90,6 +90,49 @@ class Wavefunction void flush() const { + Fusion fg = fused_.getFusedGates(); + auto items = fg.getItems(); + auto sets = fg.getSet(); + auto ctrlSets = fg.getCtrlSet(); + if (items.size() > 0) { + std::vector indices; + std::set indicesSet; //make optimal + for (int i = 0; i < items.size(); i++) { + auto tempIndices = items[i].get_indices(); + for (unsigned j = 0; j < tempIndices.size(); j++) { + if (indicesSet.count(tempIndices[j]) == 0) { + indices.push_back(tempIndices[j]); + indicesSet.insert(tempIndices[j]); + } + } + } + for (auto it = ctrlSets.begin(); it != ctrlSets.end(); ++it) { + if (indicesSet.count(*it) == 0) { + indices.push_back(*it); + indicesSet.insert(*it); + } + } + std::vector indexLocs = qubits(indices); + for (unsigned i = 0; i < indexLocs.size(); i++) + { + auto currLoc = indexLocs[i]; + reorderWFN(currLoc, i); + indexLocs = qubits(indices); + } + std::map old2newDict; + for (unsigned i = 0; i < indices.size(); i++) { + old2newDict[indices[i]] = indexLocs[i]; + } + + for (int i = 0; i < items.size(); i++) { + items[i].setIdx(old2newDict); + } + fg.setItems(items); + fg.setSet(old2newDict); + fg.setCtrlSet(old2newDict); + fused_.setFusedGates(fg); + } + fused_.flush(wfn_); } @@ -243,15 +286,15 @@ class Wavefunction rng_.seed(s); } - void reorderWFN(unsigned qubitLoc, unsigned newPos) + void reorderWFN(unsigned qubitLoc, unsigned newPos) const { //qubitmap_[qid]; //get location of qubit in wfn //0,1,2 ->H(1)->1,0,2->X(2)_>2,0,1 //get id of qubit located at newPos - getting index from the element - std::vector::iterator itr1 = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); - unsigned newPosId = std::distance(qubitmap_.begin(), itr1); - std::vector::iterator itr2 = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); - unsigned qid = std::distance(qubitmap_.begin(), itr2); + auto itr1 = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); + auto newPosId = std::distance(qubitmap_.begin(), itr1); + auto itr2 = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); + auto qid = std::distance(qubitmap_.begin(), itr2); //swap qubits in wfn between qubitLoc and newPos if (newPos != qubitLoc) { @@ -280,8 +323,12 @@ class Wavefunction //std::copy(qubitmap_.begin(), qubitmap_.end(), std::ostream_iterator(std::cout, "\n")); //std::cout << wfn_[0] << " " << qubitmap_[0]; //auto qid = qubit(g); - reorderWFN(qubit(g), 0); - fused_.apply(wfn_, g.matrix(), qubit(g)); + //reorderWFN(qubit(g), 0); + std::vector cs; + if (fused_.shouldFlush(wfn_, g.matrix(), cs, g.qubit())) { + flush(); + } + fused_.apply(wfn_, g.matrix(), g.qubit()); } /// generic application of a multiply controlled gate @@ -289,13 +336,16 @@ class Wavefunction void apply_controlled(std::vector cs, Gate const& g) { std::vector pcs = qubits(cs); - for (unsigned i = 0; i < pcs.size(); i++) + /*for (unsigned i = 0; i < pcs.size(); i++) { reorderWFN(pcs[i], i); } reorderWFN(qubit(g), pcs.size()); - pcs = qubits(cs); - fused_.apply_controlled(wfn_, g.matrix(), pcs, qubit(g)); + pcs = qubits(cs);*/ + if (fused_.shouldFlush(wfn_, g.matrix(), cs, g.qubit())) { + flush(); + } + fused_.apply_controlled(wfn_, g.matrix(), cs, g.qubit()); } /// generic application of a controlled gate @@ -319,7 +369,8 @@ class Wavefunction template bool subsytemwavefunction(std::vector const& qs, std::vector& qubitswfn, double tolerance) { - return fused_.subsytemwavefunction(wfn_, qubits(qs), qubitswfn, tolerance); + flush(); // we have to flush before we can extract the state + return kernels::subsytemwavefunction(wfn_, qubits(qs), qubitswfn, tolerance); } @@ -383,7 +434,7 @@ class Wavefunction private: unsigned num_qubits_; // for convenience mutable WavefunctionStorage wfn_; // storing the wave function - std::vector qubitmap_; // mapping of logical to physical qubits + mutable std::vector qubitmap_; // mapping of logical to physical qubits int usage_; // randomness support From d6b2ca28cd6eff8d16ec0822d6b757a74c54bda6 Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Wed, 1 Jul 2020 13:12:55 -0400 Subject: [PATCH 05/12] Added some comments --- src/Simulation/Native/src/external/fusion.hpp | 8 +++++-- .../Native/src/simulator/wavefunction.hpp | 23 +++++++------------ 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/Simulation/Native/src/external/fusion.hpp b/src/Simulation/Native/src/external/fusion.hpp index 00b21b0b990..b8f6f936acc 100644 --- a/src/Simulation/Native/src/external/fusion.hpp +++ b/src/Simulation/Native/src/external/fusion.hpp @@ -83,7 +83,9 @@ class Fusion{ void setSet(std::map elemDict) { std::set tempSet; for (unsigned elem : set_) { - tempSet.insert(elemDict[elem]); + if (elemDict.find(elem) != elemDict.end()) { + tempSet.insert(elemDict[elem]); + } } set_.clear(); set_.insert(tempSet.begin(), tempSet.end()); //look into using swap instead @@ -92,7 +94,9 @@ class Fusion{ void setCtrlSet(std::map elemDict) { std::set tempSet; for (unsigned elem : ctrl_set_) { - tempSet.insert(elemDict[elem]); + if (elemDict.find(elem) != elemDict.end()) { + tempSet.insert(elemDict[elem]); + } } ctrl_set_.clear(); ctrl_set_.insert(tempSet.begin(), tempSet.end()); diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index b016d573092..ca98a829c60 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -90,13 +90,15 @@ class Wavefunction void flush() const { + //logic to reorder Fusion fg = fused_.getFusedGates(); auto items = fg.getItems(); auto sets = fg.getSet(); auto ctrlSets = fg.getCtrlSet(); + //getting all qubits to move to lower end of the wfn if (items.size() > 0) { std::vector indices; - std::set indicesSet; //make optimal + std::set indicesSet; for (int i = 0; i < items.size(); i++) { auto tempIndices = items[i].get_indices(); for (unsigned j = 0; j < tempIndices.size(); j++) { @@ -112,6 +114,7 @@ class Wavefunction indicesSet.insert(*it); } } + //performing reorder std::vector indexLocs = qubits(indices); for (unsigned i = 0; i < indexLocs.size(); i++) { @@ -119,6 +122,7 @@ class Wavefunction reorderWFN(currLoc, i); indexLocs = qubits(indices); } + //keeping old and new location in order to set it appropriately std::map old2newDict; for (unsigned i = 0; i < indices.size(); i++) { old2newDict[indices[i]] = indexLocs[i]; @@ -288,9 +292,7 @@ class Wavefunction void reorderWFN(unsigned qubitLoc, unsigned newPos) const { - //qubitmap_[qid]; //get location of qubit in wfn - //0,1,2 ->H(1)->1,0,2->X(2)_>2,0,1 - //get id of qubit located at newPos - getting index from the element + //get id of qubit located at newPos and qubitLoc - getting index from the element auto itr1 = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); auto newPosId = std::distance(qubitmap_.begin(), itr1); auto itr2 = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); @@ -319,11 +321,7 @@ class Wavefunction template void apply(Gate const& g) { - //std::cout << *this << "\n"; - //std::copy(qubitmap_.begin(), qubitmap_.end(), std::ostream_iterator(std::cout, "\n")); - //std::cout << wfn_[0] << " " << qubitmap_[0]; - //auto qid = qubit(g); - //reorderWFN(qubit(g), 0); + //check flush condition std::vector cs; if (fused_.shouldFlush(wfn_, g.matrix(), cs, g.qubit())) { flush(); @@ -336,12 +334,7 @@ class Wavefunction void apply_controlled(std::vector cs, Gate const& g) { std::vector pcs = qubits(cs); - /*for (unsigned i = 0; i < pcs.size(); i++) - { - reorderWFN(pcs[i], i); - } - reorderWFN(qubit(g), pcs.size()); - pcs = qubits(cs);*/ + //check flush condition if (fused_.shouldFlush(wfn_, g.matrix(), cs, g.qubit())) { flush(); } From 1c4b9775e7c9ababb6caad07419102038d7f89ce Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Thu, 2 Jul 2020 21:19:57 -0400 Subject: [PATCH 06/12] Combining Dave's scheduling logic with reordering --- .../Native/src/external/nointrin/kernel1.hpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Simulation/Native/src/external/nointrin/kernel1.hpp b/src/Simulation/Native/src/external/nointrin/kernel1.hpp index 015e7e9d227..27be3912432 100644 --- a/src/Simulation/Native/src/external/nointrin/kernel1.hpp +++ b/src/Simulation/Native/src/external/nointrin/kernel1.hpp @@ -1,4 +1,4 @@ -// (C) 2018 ETH Zurich, ITP, Thomas Häner and Damian Steiger +// (C) 2018 ETH Zurich, ITP, Thomas HΣner and Damian Steiger template inline void kernel_core(V& psi, std::size_t I, std::size_t d0, M const& m) @@ -60,20 +60,20 @@ void kernel(V& psi, unsigned id0, M const& matrix, std::size_t ctrlmask) } } #else - std::intptr_t zero = 0; - std::intptr_t dmask = dsorted[0]; + std::intptr_t zero = 0; + std::intptr_t dmask = dsorted[0]; - if (ctrlmask == 0){ - #pragma omp parallel for schedule(static) - for (std::intptr_t i = 0; i < static_cast(n); ++i) - if ((i & dmask) == zero) - kernel_core(psi, i, dsorted[0], mm); - } else { - #pragma omp parallel for schedule(static) - for (std::intptr_t i = 0; i < static_cast(n); ++i) - if ((i & ctrlmask) == ctrlmask && (i & dmask) == zero) - kernel_core(psi, i, dsorted[0], mm); - } + if (ctrlmask == 0){ + #pragma omp parallel for schedule(static) + for (std::intptr_t i = 0; i < static_cast(n); ++i) + if ((i & dmask) == zero) + kernel_core(psi, i, dsorted[0], mm); + } else { + #pragma omp parallel for schedule(static) + for (std::intptr_t i = 0; i < static_cast(n); ++i) + if ((i & ctrlmask) == ctrlmask && (i & dmask) == zero) + kernel_core(psi, i, dsorted[0], mm); + } #endif } From 97bd17cf0ef1e87f0ff0f3c8295b7b99ef8ea3b7 Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Tue, 21 Jul 2020 20:06:20 -0400 Subject: [PATCH 07/12] PR changes --- src/Simulation/Native/src/external/fused.hpp | 19 ++-- src/Simulation/Native/src/external/fusion.hpp | 65 +++++++------- .../Native/src/simulator/capi_test.cpp | 28 +----- .../Native/src/simulator/wavefunction.hpp | 87 +++++++++---------- 4 files changed, 81 insertions(+), 118 deletions(-) diff --git a/src/Simulation/Native/src/external/fused.hpp b/src/Simulation/Native/src/external/fused.hpp index 22dd21423a7..b123facc83e 100644 --- a/src/Simulation/Native/src/external/fused.hpp +++ b/src/Simulation/Native/src/external/fused.hpp @@ -45,8 +45,8 @@ class Fused return fusedgates; } - void setFusedGates(Fusion newFG) const { - fusedgates = newFG; + void setFusedGates(Fusion newFusedGates) const { + fusedgates = newFusedGates; } template @@ -86,15 +86,6 @@ class Fused fusedgates = Fusion(); } - template - bool subsytemwavefunction(std::vector& wfn, - std::vector const& qs, - std::vector& qubitswfn, - double tolerance) - { - return kernels::subsytemwavefunction(wfn, qs, qubitswfn, tolerance); - } - template Fusion::Matrix convertMatrix(M const& m) { @@ -108,7 +99,7 @@ class Fused template void apply_controlled(std::vector& wfn, M const& mat, std::vector const& cs, unsigned q) { - Fusion::IndexVector qs = std::vector(1, q); + Fusion::IndexVector qs = std::vector(1, q); fusedgates.insert(convertMatrix(mat), qs, cs); } @@ -119,8 +110,8 @@ class Fused apply_controlled(wfn, mat, cs, q); } - template - bool shouldFlush(std::vector& wfn, M const& mat, std::vector const& cs, unsigned q) + template + bool shouldFlush(std::vector& wfn, std::vector const& cs, unsigned q) { // Major runtime logic change here diff --git a/src/Simulation/Native/src/external/fusion.hpp b/src/Simulation/Native/src/external/fusion.hpp index b8f6f936acc..d8626ab93af 100644 --- a/src/Simulation/Native/src/external/fusion.hpp +++ b/src/Simulation/Native/src/external/fusion.hpp @@ -10,7 +10,7 @@ #include #include #include "util/alignedalloc.hpp" -#include +#include class Item{ public: @@ -21,8 +21,8 @@ class Item{ Item(Matrix mat, IndexVector idx) : mat_(mat), idx_(idx) {} Matrix& get_matrix() { return mat_; } IndexVector& get_indices() { return idx_; } - void setIdx(std::map elemDict) { - for (unsigned i = 0; i < idx_.size(); i++) { + void setIdx(std::unordered_map elemDict) { + for (size_t i = 0; i < idx_.size(); i++) { idx_[i] = elemDict[idx_[i]]; } } @@ -31,6 +31,7 @@ class Item{ IndexVector idx_; }; +// Class handling the fusion of gates class Fusion{ public: using Index = unsigned; @@ -43,7 +44,7 @@ class Fusion{ Fusion() : global_factor_(1.) {} Index num_qubits() const { - return static_cast(set_.size()); + return static_cast(target_set_.size()); } Index num_controls() const { @@ -64,8 +65,8 @@ class Fusion{ handle_controls(empty_matrix, empty_vec, {}); // remove all current control qubits (this is a GLOBAL factor) } - IndexSet getSet() const { - return set_; + IndexSet getTargetSet() const { + return target_set_; } ItemVector getItems() const { @@ -80,46 +81,42 @@ class Fusion{ return global_factor_; } - void setSet(std::map elemDict) { + static void remapQubits(std::set& qubits, const std::unordered_map& mapFromOldLocToNewLoc) { std::set tempSet; - for (unsigned elem : set_) { - if (elemDict.find(elem) != elemDict.end()) { - tempSet.insert(elemDict[elem]); + for (unsigned elem : qubits) { + if (mapFromOldLocToNewLoc.find(elem) != mapFromOldLocToNewLoc.end()) { + tempSet.insert(mapFromOldLocToNewLoc.at(elem)); } } - set_.clear(); - set_.insert(tempSet.begin(), tempSet.end()); //look into using swap instead + qubits.swap(tempSet); } - void setCtrlSet(std::map elemDict) { - std::set tempSet; - for (unsigned elem : ctrl_set_) { - if (elemDict.find(elem) != elemDict.end()) { - tempSet.insert(elemDict[elem]); - } - } - ctrl_set_.clear(); - ctrl_set_.insert(tempSet.begin(), tempSet.end()); + void updateTargetSet(std::unordered_map mapFromOldLocToNewLoc) { + remapQubits(target_set_, mapFromOldLocToNewLoc); + } + + void setCtrlSet(std::unordered_map mapFromOldLocToNewLoc) { + remapQubits(ctrl_set_, mapFromOldLocToNewLoc); } - void setItems(ItemVector newItems) { - items_.clear(); - items_.insert(items_.begin(), newItems.begin(), newItems.end()); + void setItems(ItemVector&& newItems) { + items_.swap(newItems); } + // This saves a class instance create/destroy on every gate insert // Need a quick way to decide if we're going to grow too wide int predict(IndexVector index_list, IndexVector const& ctrl_list = {}) { int cnt = num_qubits() + num_controls(); for (auto idx : index_list) - if (set_.count(idx) == 0 && ctrl_set_.count(idx) == 0) cnt++; + if (target_set_.count(idx) == 0 && ctrl_set_.count(idx) == 0) cnt++; for (auto idx : ctrl_list) - if (set_.count(idx) == 0 && ctrl_set_.count(idx) == 0) cnt++; + if (target_set_.count(idx) == 0 && ctrl_set_.count(idx) == 0) cnt++; return cnt; } void insert(Matrix matrix, IndexVector index_list, IndexVector const& ctrl_list = {}){ for (auto idx : index_list) - set_.emplace(idx); + target_set_.emplace(idx); if (global_factor_ != 1. && ctrl_list.size() > 0){ assert(ctrl_set_.size() == 0); @@ -132,7 +129,7 @@ class Fusion{ } void get_indices(IndexVector &indices) const{ - for (auto idx : set_) + for (auto idx : target_set_) indices.push_back(idx); } @@ -140,7 +137,7 @@ class Fusion{ if (global_factor_ != 1.) assert(ctrl_set_.size() == 0); - for (auto idx : set_) + for (auto idx : target_set_) index_list.push_back(idx); unsigned N = num_qubits(); @@ -214,7 +211,7 @@ class Fusion{ if (ctrl_set_.count(ctrlIdx) == 0){ // need to either add it to the list or to the command if (items_.size() > 0){ // add it to the command add_controls(matrix, indexList, {ctrlIdx}); - set_.insert(ctrlIdx); + target_set_.insert(ctrlIdx); } else // add it to the list ctrl_set_.emplace(ctrlIdx); @@ -230,16 +227,16 @@ class Fusion{ for (auto idx : unhandled_ctrl){ new_ctrls.push_back(idx); ctrl_set_.erase(idx); - set_.insert(idx); + target_set_.insert(idx); } for (auto &item : items_) add_controls(item.get_matrix(), item.get_indices(), new_ctrls); } } - IndexSet set_; - ItemVector items_; - IndexSet ctrl_set_; + IndexSet target_set_; //set of qubits being acted on + ItemVector items_; //queue if gates to be fused + IndexSet ctrl_set_; //set of controls Complex global_factor_; }; diff --git a/src/Simulation/Native/src/simulator/capi_test.cpp b/src/Simulation/Native/src/simulator/capi_test.cpp index e255109594b..4a686291619 100644 --- a/src/Simulation/Native/src/simulator/capi_test.cpp +++ b/src/Simulation/Native/src/simulator/capi_test.cpp @@ -106,23 +106,11 @@ void test_gates() allocateQubit(sim_id, 0); allocateQubit(sim_id, 1); - /*allocateQubit(sim_id, 2); - allocateQubit(sim_id, 3);*/ - ////simpler test - //X(sim_id, 0); - //X(sim_id, 1); - //CX(sim_id, 0, 1); - //X(sim_id, 0); - //assert(M(sim_id, 1) == false); + CRx(sim_id, 1.0, 0, 1); assert(M(sim_id, 1) == false); - //R(sim_id, 1, 3.14159265358979323846, 1); - //R(sim_id,1, 3.14159265358979323846, 0); - //CRx(sim_id, 3.14159265358979323846, 0, 1); - // - //assert(M(sim_id, 1) == false); X(sim_id, 0); CRx(sim_id, 1.0, 0, 1); @@ -136,24 +124,12 @@ void test_gates() assert(M(sim_id, 1) == true); - /*X(sim_id, 2); - X(sim_id, 0); - X(sim_id, 3); - X(sim_id, 1); - CX(sim_id, 1, 2); - - assert(M(sim_id, 2) == false); - - X(sim_id, 2); - X(sim_id, 0); - X(sim_id, 3); - X(sim_id, 1);*/ - release(sim_id, 0); release(sim_id, 1); destroy(sim_id); } + void test_allocate() { auto sim_id = init(); diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index ca98a829c60..c313548e147 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -92,47 +92,46 @@ class Wavefunction { //logic to reorder Fusion fg = fused_.getFusedGates(); - auto items = fg.getItems(); - auto sets = fg.getSet(); - auto ctrlSets = fg.getCtrlSet(); + auto itemsToFuse = fg.getItems(); + auto ctrlSet = fg.getCtrlSet(); //getting all qubits to move to lower end of the wfn - if (items.size() > 0) { - std::vector indices; - std::set indicesSet; - for (int i = 0; i < items.size(); i++) { - auto tempIndices = items[i].get_indices(); + if (itemsToFuse.size() > 0) { + std::vector unionOfAllQubitsInUse; + std::set indicesSet; //set is introduced to guard against duplicate insertion and maintianing original order + for (int i = 0; i < itemsToFuse.size(); i++) { + auto tempIndices = itemsToFuse[i].get_indices(); for (unsigned j = 0; j < tempIndices.size(); j++) { if (indicesSet.count(tempIndices[j]) == 0) { - indices.push_back(tempIndices[j]); + unionOfAllQubitsInUse.push_back(tempIndices[j]); indicesSet.insert(tempIndices[j]); } } } - for (auto it = ctrlSets.begin(); it != ctrlSets.end(); ++it) { + for (auto it = ctrlSet.begin(); it != ctrlSet.end(); ++it) { if (indicesSet.count(*it) == 0) { - indices.push_back(*it); + unionOfAllQubitsInUse.push_back(*it); indicesSet.insert(*it); } } //performing reorder - std::vector indexLocs = qubits(indices); + std::vector indexLocs = qubits(unionOfAllQubitsInUse); for (unsigned i = 0; i < indexLocs.size(); i++) { auto currLoc = indexLocs[i]; - reorderWFN(currLoc, i); - indexLocs = qubits(indices); + reorderWavefunction(currLoc, i); + indexLocs = qubits(unionOfAllQubitsInUse); } //keeping old and new location in order to set it appropriately - std::map old2newDict; - for (unsigned i = 0; i < indices.size(); i++) { - old2newDict[indices[i]] = indexLocs[i]; + std::unordered_map old2newDict; + for (unsigned i = 0; i < unionOfAllQubitsInUse.size(); i++) { + old2newDict[unionOfAllQubitsInUse[i]] = indexLocs[i]; } - for (int i = 0; i < items.size(); i++) { - items[i].setIdx(old2newDict); + for (int i = 0; i < itemsToFuse.size(); i++) { + itemsToFuse[i].setIdx(old2newDict); } - fg.setItems(items); - fg.setSet(old2newDict); + fg.setItems(std::move(itemsToFuse)); + fg.updateTargetSet(old2newDict); fg.setCtrlSet(old2newDict); fused_.setFusedGates(fg); } @@ -163,8 +162,6 @@ class Wavefunction /// allocate a qubit and grow the wave function void allocateQubit(unsigned id) { - - assert(usage_ != 1); usage_ = 2; flush(); @@ -177,9 +174,6 @@ class Wavefunction qubitmap_.push_back(num_qubits_++); } assert((wfn_.size() >> num_qubits_) == 1); - //std::copy(qubitmap_.begin(), qubitmap_.end(), std::ostream_iterator(std::cout, " ")); - //std::cout << qubitmap_.back() << "\n"; - //std::cout << wfn_.back() << "\n"; } /// release the specified qubit @@ -290,30 +284,33 @@ class Wavefunction rng_.seed(s); } - void reorderWFN(unsigned qubitLoc, unsigned newPos) const + void reorderWavefunction(unsigned qubitLoc, unsigned newPos) const { - //get id of qubit located at newPos and qubitLoc - getting index from the element - auto itr1 = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); - auto newPosId = std::distance(qubitmap_.begin(), itr1); - auto itr2 = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); - auto qid = std::distance(qubitmap_.begin(), itr2); - //swap qubits in wfn between qubitLoc and newPos + + // swap qubits in wfn between qubitLoc and newPos if (newPos != qubitLoc) { - for (unsigned i = 0; i < wfn_.size(); i++) + // get id of qubit located at newPos and qubitLoc - getting index from the element + auto newQubitLocItr = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); + assert(newQubitLocItr != qubitmap_.end()); + auto newPosId = std::distance(qubitmap_.begin(), newQubitLocItr); + auto origQubitLocItr = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); + assert(origQubitLocItr != qubitmap_.end()); + auto qid = std::distance(qubitmap_.begin(), origQubitLocItr); + for (std::size_t i = 0ull; i < wfn_.size(); i++) { - unsigned int bit1 = (i >> qubitLoc) & 1; - unsigned int bit2 = (i >> newPos) & 1; - unsigned int x = (bit1 ^ bit2); + std::size_t bit1 = (i >> qubitLoc) & 1ull; + std::size_t bit2 = (i >> newPos) & 1ull; + std::size_t x = (bit1 ^ bit2); x = (x << qubitLoc) | (x << newPos); - unsigned new_i = i ^ x; + std::size_t new_i = i ^ x; if (new_i > i) { std::iter_swap(wfn_.begin() + i, wfn_.begin() + new_i); } } - //swap elemnts in qubitmap located at qid and newPosId - std::iter_swap(qubitmap_.begin() + qid, qubitmap_.begin() + newPosId); + // swap elements in qubitmap located at qid and newPosId + std::iter_swap(origQubitLocItr, newQubitLocItr); } } @@ -323,10 +320,11 @@ class Wavefunction { //check flush condition std::vector cs; - if (fused_.shouldFlush(wfn_, g.matrix(), cs, g.qubit())) { + auto mat = g.matrix(); + if (fused_.shouldFlush(wfn_, cs, g.qubit())) { flush(); } - fused_.apply(wfn_, g.matrix(), g.qubit()); + fused_.apply(wfn_, mat, g.qubit()); } /// generic application of a multiply controlled gate @@ -334,11 +332,12 @@ class Wavefunction void apply_controlled(std::vector cs, Gate const& g) { std::vector pcs = qubits(cs); + auto mat = g.matrix(); //check flush condition - if (fused_.shouldFlush(wfn_, g.matrix(), cs, g.qubit())) { + if (fused_.shouldFlush(wfn_, cs, g.qubit())) { flush(); } - fused_.apply_controlled(wfn_, g.matrix(), cs, g.qubit()); + fused_.apply_controlled(wfn_, mat, cs, g.qubit()); } /// generic application of a controlled gate From 1c4b04fb226310b13b7c0e270573c04097a184b2 Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Tue, 21 Jul 2020 21:12:02 -0400 Subject: [PATCH 08/12] PR changes --- src/Simulation/Native/src/external/fused.hpp | 4 ++-- src/Simulation/Native/src/external/fusion.hpp | 24 +++++++++---------- .../Native/src/simulator/wavefunction.hpp | 24 ++++++++++--------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/Simulation/Native/src/external/fused.hpp b/src/Simulation/Native/src/external/fused.hpp index b123facc83e..3c8463fee09 100644 --- a/src/Simulation/Native/src/external/fused.hpp +++ b/src/Simulation/Native/src/external/fused.hpp @@ -41,11 +41,11 @@ class Fused fusedgates = Fusion(); } - Fusion getFusedGates() const { + Fusion get_fusedgates() const& { return fusedgates; } - void setFusedGates(Fusion newFusedGates) const { + void set_fusedgates(Fusion newFusedGates) const { fusedgates = newFusedGates; } diff --git a/src/Simulation/Native/src/external/fusion.hpp b/src/Simulation/Native/src/external/fusion.hpp index d8626ab93af..58d510c1edc 100644 --- a/src/Simulation/Native/src/external/fusion.hpp +++ b/src/Simulation/Native/src/external/fusion.hpp @@ -18,10 +18,10 @@ class Item{ using IndexVector = std::vector; using Complex = std::complex; using Matrix = std::vector>>; - Item(Matrix mat, IndexVector idx) : mat_(mat), idx_(idx) {} + Item(Matrix mat, IndexVector idx) : mat_(std::move(mat)), idx_(idx) {} Matrix& get_matrix() { return mat_; } IndexVector& get_indices() { return idx_; } - void setIdx(std::unordered_map elemDict) { + void set_idx(std::unordered_map elemDict) { for (size_t i = 0; i < idx_.size(); i++) { idx_[i] = elemDict[idx_[i]]; } @@ -65,23 +65,23 @@ class Fusion{ handle_controls(empty_matrix, empty_vec, {}); // remove all current control qubits (this is a GLOBAL factor) } - IndexSet getTargetSet() const { + IndexSet get_target_set() const& { return target_set_; } - ItemVector getItems() const { + ItemVector get_items() const& { return items_; } - IndexSet getCtrlSet() const { + IndexSet get_ctrl_set() const& { return ctrl_set_; } - Complex getGlobalFactor() const { + Complex get_global_factor() const& { return global_factor_; } - static void remapQubits(std::set& qubits, const std::unordered_map& mapFromOldLocToNewLoc) { + static void remap_qubits(std::set& qubits, const std::unordered_map& mapFromOldLocToNewLoc) { std::set tempSet; for (unsigned elem : qubits) { if (mapFromOldLocToNewLoc.find(elem) != mapFromOldLocToNewLoc.end()) { @@ -91,15 +91,15 @@ class Fusion{ qubits.swap(tempSet); } - void updateTargetSet(std::unordered_map mapFromOldLocToNewLoc) { - remapQubits(target_set_, mapFromOldLocToNewLoc); + void update_target_set(std::unordered_map mapFromOldLocToNewLoc) { + remap_qubits(target_set_, mapFromOldLocToNewLoc); } - void setCtrlSet(std::unordered_map mapFromOldLocToNewLoc) { - remapQubits(ctrl_set_, mapFromOldLocToNewLoc); + void set_ctrl_set(std::unordered_map mapFromOldLocToNewLoc) { + remap_qubits(ctrl_set_, mapFromOldLocToNewLoc); } - void setItems(ItemVector&& newItems) { + void set_items(ItemVector&& newItems) { items_.swap(newItems); } diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index c313548e147..194efd2f94c 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "types.hpp" #include "gates.hpp" @@ -91,13 +92,13 @@ class Wavefunction void flush() const { //logic to reorder - Fusion fg = fused_.getFusedGates(); - auto itemsToFuse = fg.getItems(); - auto ctrlSet = fg.getCtrlSet(); + Fusion fg = fused_.get_fusedgates(); + auto itemsToFuse = fg.get_items(); + auto ctrlSet = fg.get_ctrl_set(); //getting all qubits to move to lower end of the wfn if (itemsToFuse.size() > 0) { std::vector unionOfAllQubitsInUse; - std::set indicesSet; //set is introduced to guard against duplicate insertion and maintianing original order + std::unordered_set indicesSet; //set is introduced to guard against duplicate insertion and maintianing original order for (int i = 0; i < itemsToFuse.size(); i++) { auto tempIndices = itemsToFuse[i].get_indices(); for (unsigned j = 0; j < tempIndices.size(); j++) { @@ -118,7 +119,7 @@ class Wavefunction for (unsigned i = 0; i < indexLocs.size(); i++) { auto currLoc = indexLocs[i]; - reorderWavefunction(currLoc, i); + reorder_wavefunction(currLoc, i); indexLocs = qubits(unionOfAllQubitsInUse); } //keeping old and new location in order to set it appropriately @@ -128,12 +129,12 @@ class Wavefunction } for (int i = 0; i < itemsToFuse.size(); i++) { - itemsToFuse[i].setIdx(old2newDict); + itemsToFuse[i].set_idx(old2newDict); } - fg.setItems(std::move(itemsToFuse)); - fg.updateTargetSet(old2newDict); - fg.setCtrlSet(old2newDict); - fused_.setFusedGates(fg); + fg.set_items(std::move(itemsToFuse)); + fg.update_target_set(old2newDict); + fg.set_ctrl_set(old2newDict); + fused_.set_fusedgates(fg); } fused_.flush(wfn_); @@ -284,7 +285,7 @@ class Wavefunction rng_.seed(s); } - void reorderWavefunction(unsigned qubitLoc, unsigned newPos) const + void reorder_wavefunction(unsigned qubitLoc, unsigned newPos) const { // swap qubits in wfn between qubitLoc and newPos @@ -314,6 +315,7 @@ class Wavefunction } } + /// generic application of a gate template void apply(Gate const& g) From 07bbb872ca67c47e2c0d48efae3e6111344177c2 Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Sat, 25 Jul 2020 19:26:06 -0400 Subject: [PATCH 09/12] PR changes --- src/Simulation/Native/src/external/fused.hpp | 2 +- src/Simulation/Native/src/external/fusion.hpp | 14 +++---- .../Native/src/simulator/wavefunction.hpp | 42 ++++++++----------- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/Simulation/Native/src/external/fused.hpp b/src/Simulation/Native/src/external/fused.hpp index 3c8463fee09..f1c7ac49e68 100644 --- a/src/Simulation/Native/src/external/fused.hpp +++ b/src/Simulation/Native/src/external/fused.hpp @@ -41,7 +41,7 @@ class Fused fusedgates = Fusion(); } - Fusion get_fusedgates() const& { + const Fusion& get_fusedgates() const { return fusedgates; } diff --git a/src/Simulation/Native/src/external/fusion.hpp b/src/Simulation/Native/src/external/fusion.hpp index 58d510c1edc..72f5f52a9d9 100644 --- a/src/Simulation/Native/src/external/fusion.hpp +++ b/src/Simulation/Native/src/external/fusion.hpp @@ -21,7 +21,7 @@ class Item{ Item(Matrix mat, IndexVector idx) : mat_(std::move(mat)), idx_(idx) {} Matrix& get_matrix() { return mat_; } IndexVector& get_indices() { return idx_; } - void set_idx(std::unordered_map elemDict) { + void remap_idx(std::unordered_map elemDict) { for (size_t i = 0; i < idx_.size(); i++) { idx_[i] = elemDict[idx_[i]]; } @@ -65,19 +65,19 @@ class Fusion{ handle_controls(empty_matrix, empty_vec, {}); // remove all current control qubits (this is a GLOBAL factor) } - IndexSet get_target_set() const& { + const IndexSet& get_target_set() const { return target_set_; } - ItemVector get_items() const& { + const ItemVector& get_items() const { return items_; } - IndexSet get_ctrl_set() const& { + const IndexSet& get_ctrl_set() const { return ctrl_set_; } - Complex get_global_factor() const& { + const Complex& get_global_factor() const { return global_factor_; } @@ -91,11 +91,11 @@ class Fusion{ qubits.swap(tempSet); } - void update_target_set(std::unordered_map mapFromOldLocToNewLoc) { + void remap_target_set(const std::unordered_map& mapFromOldLocToNewLoc) { remap_qubits(target_set_, mapFromOldLocToNewLoc); } - void set_ctrl_set(std::unordered_map mapFromOldLocToNewLoc) { + void remap_ctrl_set(const std::unordered_map& mapFromOldLocToNewLoc) { remap_qubits(ctrl_set_, mapFromOldLocToNewLoc); } diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index 194efd2f94c..85d67ed704d 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -91,12 +91,12 @@ class Wavefunction void flush() const { - //logic to reorder + // logic to reorder Fusion fg = fused_.get_fusedgates(); auto itemsToFuse = fg.get_items(); auto ctrlSet = fg.get_ctrl_set(); - //getting all qubits to move to lower end of the wfn - if (itemsToFuse.size() > 0) { + // getting all qubits to move to lower end of the wfn + if (!itemsToFuse.empty()) { std::vector unionOfAllQubitsInUse; std::unordered_set indicesSet; //set is introduced to guard against duplicate insertion and maintianing original order for (int i = 0; i < itemsToFuse.size(); i++) { @@ -114,7 +114,7 @@ class Wavefunction indicesSet.insert(*it); } } - //performing reorder + // performing reorder std::vector indexLocs = qubits(unionOfAllQubitsInUse); for (unsigned i = 0; i < indexLocs.size(); i++) { @@ -122,18 +122,18 @@ class Wavefunction reorder_wavefunction(currLoc, i); indexLocs = qubits(unionOfAllQubitsInUse); } - //keeping old and new location in order to set it appropriately + // keeping old and new location in order to set it appropriately std::unordered_map old2newDict; for (unsigned i = 0; i < unionOfAllQubitsInUse.size(); i++) { old2newDict[unionOfAllQubitsInUse[i]] = indexLocs[i]; } for (int i = 0; i < itemsToFuse.size(); i++) { - itemsToFuse[i].set_idx(old2newDict); + itemsToFuse[i].remap_idx(old2newDict); } fg.set_items(std::move(itemsToFuse)); - fg.update_target_set(old2newDict); - fg.set_ctrl_set(old2newDict); + fg.remap_target_set(old2newDict); + fg.remap_ctrl_set(old2newDict); fused_.set_fusedgates(fg); } @@ -287,17 +287,9 @@ class Wavefunction void reorder_wavefunction(unsigned qubitLoc, unsigned newPos) const { - // swap qubits in wfn between qubitLoc and newPos if (newPos != qubitLoc) { - // get id of qubit located at newPos and qubitLoc - getting index from the element - auto newQubitLocItr = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); - assert(newQubitLocItr != qubitmap_.end()); - auto newPosId = std::distance(qubitmap_.begin(), newQubitLocItr); - auto origQubitLocItr = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); - assert(origQubitLocItr != qubitmap_.end()); - auto qid = std::distance(qubitmap_.begin(), origQubitLocItr); for (std::size_t i = 0ull; i < wfn_.size(); i++) { std::size_t bit1 = (i >> qubitLoc) & 1ull; @@ -310,10 +302,14 @@ class Wavefunction std::iter_swap(wfn_.begin() + i, wfn_.begin() + new_i); } } - // swap elements in qubitmap located at qid and newPosId + // get id of qubit located at newPos and qubitLoc - getting index from the element + auto newQubitLocItr = std::find(qubitmap_.begin(), qubitmap_.end(), newPos); + assert(newQubitLocItr != qubitmap_.end()); + auto origQubitLocItr = std::find(qubitmap_.begin(), qubitmap_.end(), qubitLoc); + assert(origQubitLocItr != qubitmap_.end()); + // swap elements in qubitmap located at iterators std::iter_swap(origQubitLocItr, newQubitLocItr); } - } /// generic application of a gate @@ -321,12 +317,10 @@ class Wavefunction void apply(Gate const& g) { //check flush condition - std::vector cs; - auto mat = g.matrix(); - if (fused_.shouldFlush(wfn_, cs, g.qubit())) { + if (fused_.shouldFlush(wfn_, std::vector{}, g.qubit())) { flush(); } - fused_.apply(wfn_, mat, g.qubit()); + fused_.apply(wfn_, g.matrix(), g.qubit()); } /// generic application of a multiply controlled gate @@ -334,12 +328,10 @@ class Wavefunction void apply_controlled(std::vector cs, Gate const& g) { std::vector pcs = qubits(cs); - auto mat = g.matrix(); - //check flush condition if (fused_.shouldFlush(wfn_, cs, g.qubit())) { flush(); } - fused_.apply_controlled(wfn_, mat, cs, g.qubit()); + fused_.apply_controlled(wfn_, g.matrix(), cs, g.qubit()); } /// generic application of a controlled gate From d91fab36b863be567a91bc94707a2a85f92fc5ec Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Mon, 27 Jul 2020 20:38:41 -0400 Subject: [PATCH 10/12] PR change to avoid copying --- src/Simulation/Native/src/external/fusion.hpp | 16 ++++++++-------- .../Native/src/simulator/wavefunction.hpp | 10 ++++------ 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Simulation/Native/src/external/fusion.hpp b/src/Simulation/Native/src/external/fusion.hpp index 72f5f52a9d9..2c100f16400 100644 --- a/src/Simulation/Native/src/external/fusion.hpp +++ b/src/Simulation/Native/src/external/fusion.hpp @@ -20,15 +20,15 @@ class Item{ using Matrix = std::vector>>; Item(Matrix mat, IndexVector idx) : mat_(std::move(mat)), idx_(idx) {} Matrix& get_matrix() { return mat_; } - IndexVector& get_indices() { return idx_; } - void remap_idx(std::unordered_map elemDict) { + IndexVector& get_indices() const { return idx_; } + void remap_idx(std::unordered_map elemDict) const { for (size_t i = 0; i < idx_.size(); i++) { idx_[i] = elemDict[idx_[i]]; } } private: Matrix mat_; - IndexVector idx_; + mutable IndexVector idx_; }; // Class handling the fusion of gates @@ -91,11 +91,11 @@ class Fusion{ qubits.swap(tempSet); } - void remap_target_set(const std::unordered_map& mapFromOldLocToNewLoc) { + void remap_target_set(const std::unordered_map& mapFromOldLocToNewLoc) const { remap_qubits(target_set_, mapFromOldLocToNewLoc); } - void remap_ctrl_set(const std::unordered_map& mapFromOldLocToNewLoc) { + void remap_ctrl_set(const std::unordered_map& mapFromOldLocToNewLoc) const { remap_qubits(ctrl_set_, mapFromOldLocToNewLoc); } @@ -234,9 +234,9 @@ class Fusion{ } } - IndexSet target_set_; //set of qubits being acted on - ItemVector items_; //queue if gates to be fused - IndexSet ctrl_set_; //set of controls + mutable IndexSet target_set_; //set of qubits being acted on + mutable ItemVector items_; //queue if gates to be fused + mutable IndexSet ctrl_set_; //set of controls Complex global_factor_; }; diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index 85d67ed704d..0f73e79103f 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -92,15 +92,15 @@ class Wavefunction void flush() const { // logic to reorder - Fusion fg = fused_.get_fusedgates(); - auto itemsToFuse = fg.get_items(); - auto ctrlSet = fg.get_ctrl_set(); + const Fusion& fg = fused_.get_fusedgates(); + const auto& itemsToFuse = fg.get_items(); + const auto& ctrlSet = fg.get_ctrl_set(); // getting all qubits to move to lower end of the wfn if (!itemsToFuse.empty()) { std::vector unionOfAllQubitsInUse; std::unordered_set indicesSet; //set is introduced to guard against duplicate insertion and maintianing original order for (int i = 0; i < itemsToFuse.size(); i++) { - auto tempIndices = itemsToFuse[i].get_indices(); + const auto& tempIndices = itemsToFuse[i].get_indices(); for (unsigned j = 0; j < tempIndices.size(); j++) { if (indicesSet.count(tempIndices[j]) == 0) { unionOfAllQubitsInUse.push_back(tempIndices[j]); @@ -131,10 +131,8 @@ class Wavefunction for (int i = 0; i < itemsToFuse.size(); i++) { itemsToFuse[i].remap_idx(old2newDict); } - fg.set_items(std::move(itemsToFuse)); fg.remap_target_set(old2newDict); fg.remap_ctrl_set(old2newDict); - fused_.set_fusedgates(fg); } fused_.flush(wfn_); From 8f3c9636762e6ee522448402d51e1ca326335960 Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Mon, 27 Jul 2020 22:05:15 -0400 Subject: [PATCH 11/12] PR changes --- src/Simulation/Native/src/external/fusion.hpp | 2 +- src/Simulation/Native/src/simulator/wavefunction.hpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Simulation/Native/src/external/fusion.hpp b/src/Simulation/Native/src/external/fusion.hpp index 2c100f16400..f89471a1e88 100644 --- a/src/Simulation/Native/src/external/fusion.hpp +++ b/src/Simulation/Native/src/external/fusion.hpp @@ -237,7 +237,7 @@ class Fusion{ mutable IndexSet target_set_; //set of qubits being acted on mutable ItemVector items_; //queue if gates to be fused mutable IndexSet ctrl_set_; //set of controls - Complex global_factor_; + mutable Complex global_factor_; }; #endif diff --git a/src/Simulation/Native/src/simulator/wavefunction.hpp b/src/Simulation/Native/src/simulator/wavefunction.hpp index 0f73e79103f..bb9fdae21bf 100644 --- a/src/Simulation/Native/src/simulator/wavefunction.hpp +++ b/src/Simulation/Native/src/simulator/wavefunction.hpp @@ -108,10 +108,10 @@ class Wavefunction } } } - for (auto it = ctrlSet.begin(); it != ctrlSet.end(); ++it) { - if (indicesSet.count(*it) == 0) { - unionOfAllQubitsInUse.push_back(*it); - indicesSet.insert(*it); + for (unsigned index : ctrlSet) { + if (indicesSet.count(index) == 0) { + unionOfAllQubitsInUse.push_back(index); + indicesSet.insert(index); } } // performing reorder From bcb37db8bb5146f0a2c923aed766be180da6c480 Mon Sep 17 00:00:00 2001 From: Aniket Dalvi Date: Tue, 28 Jul 2020 13:17:05 -0400 Subject: [PATCH 12/12] PR changes to undo character change in Haner --- src/Simulation/Native/src/external/nointrin/kernel1.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Simulation/Native/src/external/nointrin/kernel1.hpp b/src/Simulation/Native/src/external/nointrin/kernel1.hpp index 27be3912432..5173b58d8a8 100644 --- a/src/Simulation/Native/src/external/nointrin/kernel1.hpp +++ b/src/Simulation/Native/src/external/nointrin/kernel1.hpp @@ -1,4 +1,4 @@ -// (C) 2018 ETH Zurich, ITP, Thomas HΣner and Damian Steiger +// (C) 2018 ETH Zurich, ITP, Thomas Häner and Damian Steiger template inline void kernel_core(V& psi, std::size_t I, std::size_t d0, M const& m)