Loading tnqvm/visitors/exatn-gen/ExatnGenVisitor.cpp +45 −15 Original line number Diff line number Diff line Loading @@ -252,7 +252,8 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::initialize( // Default number of layers m_layersReconstruct = 4; m_countByGates = false; m_layerTracker.clear(); // m_layerTracker.clear(); m_qubitToGateCount.clear(); if (options.keyExists<int>("reconstruct-gates")) { m_layersReconstruct = options.get<int>("reconstruct-gates"); xacc::info("Reconstruct tensor network every " + Loading Loading @@ -385,6 +386,9 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::initialize( template <typename TNQVM_COMPLEX_TYPE> void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::finalize() { m_buffer->addExtraInfo("reconstruction-fidelity", m_reconstructionFidelity); if (m_layerCounter > 0) { reconstructCircuitTensor(true); } // This is a single-circuit execution. // Do the evaluation now. if (!m_obsTensorOperator && !m_measuredBits.empty()) { Loading Loading @@ -681,12 +685,15 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::appendGateTensor( } template <typename TNQVM_COMPLEX_TYPE> void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::reconstructCircuitTensor() { void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::reconstructCircuitTensor(bool forced) { if (m_layersReconstruct <= 0) { return; } if (m_layerCounter >= m_layersReconstruct) { if (m_layerCounter > m_layersReconstruct || forced) { xacc::info("Reconstruct Tensor Expansion"); // Flush the count every reconstruct: m_qubitToGateCount.clear(); // m_tensorExpansion.printIt(); auto target = std::make_shared<exatn::TensorExpansion>(m_tensorExpansion); // List of Approximate tensors to delete: static std::vector<std::string> TENSORS_TO_DESTROY; Loading Loading @@ -1042,23 +1049,46 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::updateLayerCounter( if (m_countByGates) { ++m_layerCounter; } else { bool canCombine = true; const auto q1 = gate.bits()[0]; const auto q2 = gate.bits()[1]; if (m_qubitToGateCount.find(q1) != m_qubitToGateCount.end()) { m_qubitToGateCount[q1] = m_qubitToGateCount[q1] + 1; } else { m_qubitToGateCount[q1] = 1; } for (const auto& [bit1, bit2]: m_layerTracker) { if ((q1 == bit1 || q1 == bit2) || (q2 == bit1 || q2 == bit2)) { canCombine = false; break; if (m_qubitToGateCount.find(q2) != m_qubitToGateCount.end()) { m_qubitToGateCount[q2] = m_qubitToGateCount[q2] + 1; } else { m_qubitToGateCount[q2] = 1; } // Update layer counter = max qubit counter across all qubits. for (const auto &[qId, counter] : m_qubitToGateCount) { if (counter > m_layerCounter) { m_layerCounter = counter; } if (canCombine) { m_layerTracker.emplace(std::make_pair(q1, q2)); } else { ++m_layerCounter; m_layerTracker.clear(); m_layerTracker.emplace(std::make_pair(q1, q2)); } { std::stringstream ss; ss << "Processing " << gate.toString() << " : " << m_layerCounter; xacc::info(ss.str()); } // for (const auto& [bit1, bit2]: m_layerTracker) { // if ((q1 == bit1 || q1 == bit2) || (q2 == bit1 || q2 == bit2)) { // canCombine = false; // break; // } // } // if (canCombine) { // m_layerTracker.emplace(std::make_pair(q1, q2)); // } else { // ++m_layerCounter; // m_layerTracker.clear(); // m_layerTracker.emplace(std::make_pair(q1, q2)); // } } } } // end namespace tnqvm Loading tnqvm/visitors/exatn-gen/ExatnGenVisitor.hpp +3 −2 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ private: analyzeObsSubCircuit(std::shared_ptr<CompositeInstruction> in_function) const; exatn::TensorOperator constructObsTensorOperator(const std::vector<ObsOpType> &in_obsOps) const; void reconstructCircuitTensor(); void reconstructCircuitTensor(bool forced = false); // Compute the wave-function slice or amplitude (if all bits are set): std::vector<TNQVM_COMPLEX_TYPE> computeWaveFuncSlice(const exatn::TensorNetwork &in_tensorNetwork, Loading @@ -142,7 +142,8 @@ private: private: void updateLayerCounter(const xacc::Instruction &in_gateInstruction); std::set<std::pair<size_t, size_t>> m_layerTracker; // std::set<std::pair<size_t, size_t>> m_layerTracker; std::unordered_map<size_t, size_t> m_qubitToGateCount; std::shared_ptr<exatn::TensorNetwork> m_qubitNetwork; exatn::TensorExpansion m_tensorExpansion; std::shared_ptr<exatn::TensorExpansion> m_previousOptExpansion; Loading tnqvm/visitors/exatn-gen/tests/ExaTnGenTester.cpp +77 −3 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ TEST(ExaTnGenTester, checkExpVal) { { // Check exp-val by tensor expansion auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}}); xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-gates", -1}}); auto xasmCompiler = xacc::getCompiler("xasm"); auto program = xasmCompiler ->compile(R"(__qpu__ void testRY(qbit q, double t) { Loading @@ -46,7 +46,7 @@ TEST(ExaTnGenTester, checkExpVal) { } { auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}}); xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-gates", -1}}); auto xasmCompiler = xacc::getCompiler("xasm"); auto ir = xasmCompiler->compile(R"(__qpu__ void ansatz(qbit q, double t) { Loading Loading @@ -84,7 +84,7 @@ TEST(ExaTnGenTester, checkExpVal) { TEST(ExaTnGenTester, checkVqeH2) { auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}}); xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-gates", -1}}); // Create the N=2 deuteron Hamiltonian auto H_N_2 = xacc::quantum::getObservable( "pauli", std::string("5.907 - 2.1433 X0X1 " Loading Loading @@ -253,6 +253,80 @@ TEST(ExaTnGenTester, checkVqeH3Approx) { EXPECT_NEAR(energies[0], -2.04482, 0.25); } TEST(ExaTnGenTester, checkNewLayerCount) { // Use very high tolerance to save test time auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-layers", 4}, {"reconstruct-tolerance", 0.1}}); xacc::set_verbose(true); xacc::qasm(R"( .compiler xasm .circuit test_layers .qbit q X(q[0]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); )"); auto qreg = xacc::qalloc(8); auto program = xacc::getCompiled("test_layers"); accelerator->execute(qreg, program); } int main(int argc, char **argv) { xacc::Initialize(argc, argv); ::testing::InitGoogleTest(&argc, argv); Loading Loading
tnqvm/visitors/exatn-gen/ExatnGenVisitor.cpp +45 −15 Original line number Diff line number Diff line Loading @@ -252,7 +252,8 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::initialize( // Default number of layers m_layersReconstruct = 4; m_countByGates = false; m_layerTracker.clear(); // m_layerTracker.clear(); m_qubitToGateCount.clear(); if (options.keyExists<int>("reconstruct-gates")) { m_layersReconstruct = options.get<int>("reconstruct-gates"); xacc::info("Reconstruct tensor network every " + Loading Loading @@ -385,6 +386,9 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::initialize( template <typename TNQVM_COMPLEX_TYPE> void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::finalize() { m_buffer->addExtraInfo("reconstruction-fidelity", m_reconstructionFidelity); if (m_layerCounter > 0) { reconstructCircuitTensor(true); } // This is a single-circuit execution. // Do the evaluation now. if (!m_obsTensorOperator && !m_measuredBits.empty()) { Loading Loading @@ -681,12 +685,15 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::appendGateTensor( } template <typename TNQVM_COMPLEX_TYPE> void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::reconstructCircuitTensor() { void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::reconstructCircuitTensor(bool forced) { if (m_layersReconstruct <= 0) { return; } if (m_layerCounter >= m_layersReconstruct) { if (m_layerCounter > m_layersReconstruct || forced) { xacc::info("Reconstruct Tensor Expansion"); // Flush the count every reconstruct: m_qubitToGateCount.clear(); // m_tensorExpansion.printIt(); auto target = std::make_shared<exatn::TensorExpansion>(m_tensorExpansion); // List of Approximate tensors to delete: static std::vector<std::string> TENSORS_TO_DESTROY; Loading Loading @@ -1042,23 +1049,46 @@ void ExatnGenVisitor<TNQVM_COMPLEX_TYPE>::updateLayerCounter( if (m_countByGates) { ++m_layerCounter; } else { bool canCombine = true; const auto q1 = gate.bits()[0]; const auto q2 = gate.bits()[1]; if (m_qubitToGateCount.find(q1) != m_qubitToGateCount.end()) { m_qubitToGateCount[q1] = m_qubitToGateCount[q1] + 1; } else { m_qubitToGateCount[q1] = 1; } for (const auto& [bit1, bit2]: m_layerTracker) { if ((q1 == bit1 || q1 == bit2) || (q2 == bit1 || q2 == bit2)) { canCombine = false; break; if (m_qubitToGateCount.find(q2) != m_qubitToGateCount.end()) { m_qubitToGateCount[q2] = m_qubitToGateCount[q2] + 1; } else { m_qubitToGateCount[q2] = 1; } // Update layer counter = max qubit counter across all qubits. for (const auto &[qId, counter] : m_qubitToGateCount) { if (counter > m_layerCounter) { m_layerCounter = counter; } if (canCombine) { m_layerTracker.emplace(std::make_pair(q1, q2)); } else { ++m_layerCounter; m_layerTracker.clear(); m_layerTracker.emplace(std::make_pair(q1, q2)); } { std::stringstream ss; ss << "Processing " << gate.toString() << " : " << m_layerCounter; xacc::info(ss.str()); } // for (const auto& [bit1, bit2]: m_layerTracker) { // if ((q1 == bit1 || q1 == bit2) || (q2 == bit1 || q2 == bit2)) { // canCombine = false; // break; // } // } // if (canCombine) { // m_layerTracker.emplace(std::make_pair(q1, q2)); // } else { // ++m_layerCounter; // m_layerTracker.clear(); // m_layerTracker.emplace(std::make_pair(q1, q2)); // } } } } // end namespace tnqvm Loading
tnqvm/visitors/exatn-gen/ExatnGenVisitor.hpp +3 −2 Original line number Diff line number Diff line Loading @@ -133,7 +133,7 @@ private: analyzeObsSubCircuit(std::shared_ptr<CompositeInstruction> in_function) const; exatn::TensorOperator constructObsTensorOperator(const std::vector<ObsOpType> &in_obsOps) const; void reconstructCircuitTensor(); void reconstructCircuitTensor(bool forced = false); // Compute the wave-function slice or amplitude (if all bits are set): std::vector<TNQVM_COMPLEX_TYPE> computeWaveFuncSlice(const exatn::TensorNetwork &in_tensorNetwork, Loading @@ -142,7 +142,8 @@ private: private: void updateLayerCounter(const xacc::Instruction &in_gateInstruction); std::set<std::pair<size_t, size_t>> m_layerTracker; // std::set<std::pair<size_t, size_t>> m_layerTracker; std::unordered_map<size_t, size_t> m_qubitToGateCount; std::shared_ptr<exatn::TensorNetwork> m_qubitNetwork; exatn::TensorExpansion m_tensorExpansion; std::shared_ptr<exatn::TensorExpansion> m_previousOptExpansion; Loading
tnqvm/visitors/exatn-gen/tests/ExaTnGenTester.cpp +77 −3 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ TEST(ExaTnGenTester, checkExpVal) { { // Check exp-val by tensor expansion auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}}); xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-gates", -1}}); auto xasmCompiler = xacc::getCompiler("xasm"); auto program = xasmCompiler ->compile(R"(__qpu__ void testRY(qbit q, double t) { Loading @@ -46,7 +46,7 @@ TEST(ExaTnGenTester, checkExpVal) { } { auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}}); xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-gates", -1}}); auto xasmCompiler = xacc::getCompiler("xasm"); auto ir = xasmCompiler->compile(R"(__qpu__ void ansatz(qbit q, double t) { Loading Loading @@ -84,7 +84,7 @@ TEST(ExaTnGenTester, checkExpVal) { TEST(ExaTnGenTester, checkVqeH2) { auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}}); xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-gates", -1}}); // Create the N=2 deuteron Hamiltonian auto H_N_2 = xacc::quantum::getObservable( "pauli", std::string("5.907 - 2.1433 X0X1 " Loading Loading @@ -253,6 +253,80 @@ TEST(ExaTnGenTester, checkVqeH3Approx) { EXPECT_NEAR(energies[0], -2.04482, 0.25); } TEST(ExaTnGenTester, checkNewLayerCount) { // Use very high tolerance to save test time auto accelerator = xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-gen"}, {"reconstruct-layers", 4}, {"reconstruct-tolerance", 0.1}}); xacc::set_verbose(true); xacc::qasm(R"( .compiler xasm .circuit test_layers .qbit q X(q[0]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); CX(q[0], q[1]); CX(q[0], q[1]); CX(q[2], q[3]); CX(q[2], q[3]); CX(q[4], q[5]); CX(q[4], q[5]); CX(q[6], q[7]); CX(q[6], q[7]); CX(q[1], q[2]); CX(q[1], q[2]); CX(q[3], q[4]); CX(q[3], q[4]); CX(q[5], q[6]); CX(q[5], q[6]); )"); auto qreg = xacc::qalloc(8); auto program = xacc::getCompiled("test_layers"); accelerator->execute(qreg, program); } int main(int argc, char **argv) { xacc::Initialize(argc, argv); ::testing::InitGoogleTest(&argc, argv); Loading