From 1af160667e9395bc7b2d2d005eb6b44a2085c85a Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 21 Jan 2021 09:33:56 -0500 Subject: [PATCH 01/20] Boilerplate for the full DM contraction visitor Signed-off-by: Thien Nguyen --- tnqvm/visitors/CMakeLists.txt | 3 +- tnqvm/visitors/exatn-dm/CMakeLists.txt | 79 +++++++++ tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 150 ++++++++++++++++++ tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp | 97 +++++++++++ tnqvm/visitors/exatn-dm/manifest.json | 6 + tnqvm/visitors/exatn-dm/tests/CMakeLists.txt | 6 + .../exatn-dm/tests/JsonNoiseModelTester.cpp | 131 +++++++++++++++ 7 files changed, 471 insertions(+), 1 deletion(-) create mode 100644 tnqvm/visitors/exatn-dm/CMakeLists.txt create mode 100644 tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp create mode 100644 tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp create mode 100644 tnqvm/visitors/exatn-dm/manifest.json create mode 100644 tnqvm/visitors/exatn-dm/tests/CMakeLists.txt create mode 100644 tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp diff --git a/tnqvm/visitors/CMakeLists.txt b/tnqvm/visitors/CMakeLists.txt index 9d763f0..17f6c2f 100644 --- a/tnqvm/visitors/CMakeLists.txt +++ b/tnqvm/visitors/CMakeLists.txt @@ -32,4 +32,5 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(itensor) add_subdirectory(exatn) add_subdirectory(exatn-mps) -add_subdirectory(exatn-mpo) \ No newline at end of file +add_subdirectory(exatn-mpo) +add_subdirectory(exatn-dm) \ No newline at end of file diff --git a/tnqvm/visitors/exatn-dm/CMakeLists.txt b/tnqvm/visitors/exatn-dm/CMakeLists.txt new file mode 100644 index 0000000..42be8f5 --- /dev/null +++ b/tnqvm/visitors/exatn-dm/CMakeLists.txt @@ -0,0 +1,79 @@ +find_package(ExaTN QUIET) + +if (ExaTN_FOUND) + message(STATUS "Found ExaTN at ${EXATN_ROOT}") + set (PACKAGE_NAME "TNQVM ExaTN Density Matrix Visitor") + set (PACKAGE_DESCIPTION "TNQVM ExaTN Density Matrix backend") + set (LIBRARY_NAME tnqvm-exatn-dm) + + if (TNQVM_MPI_ENABLED) + find_package(MPI REQUIRED) + message(STATUS "Found a suitable MPI compiler ${MPI_CXX_COMPILER}.") + message(STATUS "Compiler vendor is [${CMAKE_CXX_COMPILER_ID}]") + message(STATUS "Include path: ${MPI_CXX_INCLUDE_DIRS}") + message(STATUS "Compile flags: ${MPI_CXX_COMPILE_FLAGS}") + message(STATUS "Link flags: ${MPI_CXX_LINK_FLAGS}") + message(STATUS "Libraries: ${MPI_CXX_LIBRARIES}") + include_directories(${MPI_CXX_INCLUDE_DIRS}) + link_libraries(${MPI_CXX_LIBRARIES}) + add_definitions(-DTNQVM_MPI_ENABLED) + endif() + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTNQVM_HAS_EXATN") + set(CMAKE_INSTALL_RPATH "${EXATN_ROOT}/lib") + set(EXATN_VISITOR_CPP_FILE ExaTnDmVisitor.cpp) + + if (EXATN_BLAS_LIB MATCHES MKL) + # Fix for bug #30 + message(STATUS "Exatn built with MKL, updating our build: ${EXATN_MKL_PATH}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTNQVM_EXATN_USES_MKL_BLAS") + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ExaTnDmVisitor.cpp" + "${CMAKE_BINARY_DIR}/tnqvm/visitors/exatn-mpo/ExaTnDmVisitor.cpp" @ONLY) + set(EXATN_VISITOR_CPP_FILE ${CMAKE_BINARY_DIR}/tnqvm/visitors/exatn-mpo/ExaTnDmVisitor.cpp) + endif() + + file (GLOB HEADERS *.hpp) + file (GLOB SRC ${EXATN_VISITOR_CPP_FILE}) + + usFunctionGetResourceSource(TARGET ${LIBRARY_NAME} OUT SRC) + usFunctionGenerateBundleInit(TARGET ${LIBRARY_NAME} OUT SRC) + + add_library(${LIBRARY_NAME} SHARED ${SRC}) + + set(_bundle_name tnqvm_exatn_dm) + set_target_properties(${LIBRARY_NAME} PROPERTIES + # This is required for every bundle + COMPILE_DEFINITIONS US_BUNDLE_NAME=${_bundle_name} + # This is for convenience, used by other CMake functions + US_BUNDLE_NAME ${_bundle_name} + ) + + # Embed meta-data from a manifest.json file + usFunctionEmbedResources(TARGET ${LIBRARY_NAME} + WORKING_DIRECTORY + ${CMAKE_CURRENT_SOURCE_DIR} + FILES + manifest.json + ) + + target_include_directories(${LIBRARY_NAME} PUBLIC . .. ${XACC_DIR}/include/xacc/) + + # Links to ExaTN using its linker config flags. + target_link_libraries(${LIBRARY_NAME} PUBLIC xacc::xacc exatn::exatn xacc::quantum_gate) + + if(APPLE) + set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "@loader_path/../lib") + set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + else() + set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN/../lib;${EXATN_ROOT}/lib;${BLAS_PATH}") + set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared") + endif() + + install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins) + + if(TNQVM_BUILD_TESTS) + add_subdirectory(tests) + endif() +else() + message(STATUS "ExaTN not found, skipping ExaTNVisitor build") +endif() \ No newline at end of file diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp new file mode 100644 index 0000000..d3bfaf6 --- /dev/null +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -0,0 +1,150 @@ +#include "ExaTnDmVisitor.hpp" +#include "tensor_basic.hpp" +#include "talshxx.hpp" +#include "utils/GateMatrixAlgebra.hpp" +#include "base/Gates.hpp" +#include "NoiseModel.hpp" +#include "xacc_service.hpp" +#include "xacc_plugin.hpp" +#ifdef TNQVM_EXATN_USES_MKL_BLAS +#include +#endif + +namespace tnqvm { +ExaTnDmVisitor::ExaTnDmVisitor() { + // TODO +} + +void ExaTnDmVisitor::initialize(std::shared_ptr buffer, + int nbShots) { + // Initialize ExaTN (if not already initialized) + if (!exatn::isInitialized()) { +#ifdef TNQVM_EXATN_USES_MKL_BLAS + // Fix for TNQVM bug #30 + void *core_handle = + dlopen("@EXATN_MKL_PATH@/libmkl_core@CMAKE_SHARED_LIBRARY_SUFFIX@", + RTLD_LAZY | RTLD_GLOBAL); + if (core_handle == nullptr) { + std::string err = std::string(dlerror()); + xacc::error("Could not load mkl_core - " + err); + } + + void *thread_handle = dlopen( + "@EXATN_MKL_PATH@/libmkl_gnu_thread@CMAKE_SHARED_LIBRARY_SUFFIX@", + RTLD_LAZY | RTLD_GLOBAL); + if (thread_handle == nullptr) { + std::string err = std::string(dlerror()); + xacc::error("Could not load mkl_gnu_thread - " + err); + } +#endif + // If exaTN has not been initialized, do it now. + exatn::initialize(); + // ExaTN and XACC logging levels are always in-synced. + exatn::resetRuntimeLoggingLevel(xacc::verbose ? xacc::getLoggingLevel() + : 0); + xacc::subscribeLoggingLevel([](int level) { + exatn::resetRuntimeLoggingLevel(xacc::verbose ? level : 0); + }); + } + + // TODO +} + +exatn::TensorNetwork +ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits, + bool in_createQubitTensors) const { + // TODO +} + +void ExaTnDmVisitor::finalize() { + // TODO +} + +void ExaTnDmVisitor::applySingleQubitGate( + xacc::quantum::Gate &in_gateInstruction) { + // TODO +} + +void ExaTnDmVisitor::applyTwoQubitGate( + xacc::quantum::Gate &in_gateInstruction) { + // TODO +} +void ExaTnDmVisitor::applyKrausOp(const KrausOp &in_op) { + // TODO +} + +void ExaTnDmVisitor::visit(Identity &in_IdentityGate) { + applySingleQubitGate(in_IdentityGate); +} + +void ExaTnDmVisitor::visit(Hadamard &in_HadamardGate) { + applySingleQubitGate(in_HadamardGate); + // DEBUG: + // std::cout << "Apply: " << in_HadamardGate.toString() << "\n"; + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); +} + +void ExaTnDmVisitor::visit(X &in_XGate) { + applySingleQubitGate(in_XGate); + // DEBUG: + // std::cout << "Apply: " << in_XGate.toString() << "\n"; + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); +} + +void ExaTnDmVisitor::visit(Y &in_YGate) { applySingleQubitGate(in_YGate); } + +void ExaTnDmVisitor::visit(Z &in_ZGate) { applySingleQubitGate(in_ZGate); } + +void ExaTnDmVisitor::visit(Rx &in_RxGate) { applySingleQubitGate(in_RxGate); } + +void ExaTnDmVisitor::visit(Ry &in_RyGate) { applySingleQubitGate(in_RyGate); } + +void ExaTnDmVisitor::visit(Rz &in_RzGate) { applySingleQubitGate(in_RzGate); } + +void ExaTnDmVisitor::visit(T &in_TGate) { applySingleQubitGate(in_TGate); } + +void ExaTnDmVisitor::visit(Tdg &in_TdgGate) { + applySingleQubitGate(in_TdgGate); +} + +// others +void ExaTnDmVisitor::visit(Measure &in_MeasureGate) { + m_measuredBits.emplace_back(in_MeasureGate.bits()[0]); +} + +void ExaTnDmVisitor::visit(U &in_UGate) { applySingleQubitGate(in_UGate); } + +// two-qubit gates: +void ExaTnDmVisitor::visit(CNOT &in_CNOTGate) { + applyTwoQubitGate(in_CNOTGate); + // DEBUG: + // std::cout << "Apply: " << in_CNOTGate.toString() << "\n"; + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); +} + +void ExaTnDmVisitor::visit(Swap &in_SwapGate) { + applySingleQubitGate(in_SwapGate); +} + +void ExaTnDmVisitor::visit(CZ &in_CZGate) { applySingleQubitGate(in_CZGate); } + +void ExaTnDmVisitor::visit(CPhase &in_CPhaseGate) { + applySingleQubitGate(in_CPhaseGate); +} + +void ExaTnDmVisitor::visit(iSwap &in_iSwapGate) { + applySingleQubitGate(in_iSwapGate); +} + +void ExaTnDmVisitor::visit(fSim &in_fsimGate) { + applySingleQubitGate(in_fsimGate); +} + +const double ExaTnDmVisitor::getExpectationValueZ( + std::shared_ptr in_function) { + return 0.0; +} +} // namespace tnqvm + +// Register with CppMicroservices +REGISTER_PLUGIN(tnqvm::ExaTnDmVisitor, tnqvm::TNQVMVisitor) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp new file mode 100644 index 0000000..46251dc --- /dev/null +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp @@ -0,0 +1,97 @@ +#pragma once + +#include "TNQVMVisitor.hpp" +#include "tensor_network.hpp" +#include "exatn.hpp" + +// Full density matrix noisy visitor: +// Name: "exatn-dm" +// Supported initialization keys: +// +-----------------------------+------------------------------------------------------------------------+-------------+--------------------------+ +// | Initialization Parameter | Parameter Description | type | default | +// +=============================+========================================================================+=============+==========================+ +// | backend-json | Backend configuration JSON to estimate the noise model from. | string | None | +// +-----------------------------+------------------------------------------------------------------------+-------------+--------------------------+ +// | backend | Name of the IBMQ backend to query the backend configuration. | string | None | +// +-----------------------------+------------------------------------------------------------------------+-------------+--------------------------+ +// If either `backend-json` or `backend` is provided, the `exatn-dm` simulator will simulate the backend noise associated with each quantum gate. + +namespace xacc { +// Forward declaration +class NoiseModel; +struct NoiseChannelKraus; +} // namespace xacc +namespace tnqvm { +// Single-site Kraus Op (this Accelerator can only model this) +struct KrausOp { + size_t qubit; + // Choi matrix + std::vector>> mats; +}; + +class ExaTnDmVisitor : public TNQVMVisitor +{ +public: + // Constructor + ExaTnDmVisitor(); + + // Virtual function impls: + virtual void initialize(std::shared_ptr buffer, int nbShots) override; + virtual void finalize() override; + + // Service name as defined in manifest.json + virtual const std::string name() const override { return "exatn-dm"; } + virtual const std::string description() const override { return "ExaTN Density Matrix Visitor"; } + virtual std::shared_ptr clone() override { return std::make_shared(); } + + // one-qubit gates + virtual void visit(Identity& in_IdentityGate) override; + virtual void visit(Hadamard& in_HadamardGate) override; + virtual void visit(X& in_XGate) override; + virtual void visit(Y& in_YGate) override; + virtual void visit(Z& in_ZGate) override; + virtual void visit(Rx& in_RxGate) override; + virtual void visit(Ry& in_RyGate) override; + virtual void visit(Rz& in_RzGate) override; + virtual void visit(T& in_TGate) override; + virtual void visit(Tdg& in_TdgGate) override; + virtual void visit(CPhase& in_CPhaseGate) override; + virtual void visit(U& in_UGate) override; + // two-qubit gates + virtual void visit(CNOT& in_CNOTGate) override; + virtual void visit(Swap& in_SwapGate) override; + virtual void visit(CZ& in_CZGate) override; + virtual void visit(iSwap& in_iSwapGate) override; + virtual void visit(fSim& in_fsimGate) override; + // others + virtual void visit(Measure& in_MeasureGate) override; + + virtual const double getExpectationValueZ(std::shared_ptr in_function) override; + class ExaTnTensorFunctor : public talsh::TensorFunctor + { + public: + ExaTnTensorFunctor(const std::function& in_func) : + m_func(in_func) + {} + + const std::string name() const override { return "default"; } + const std::string description() const override { return ""; } + virtual void pack(BytePacket& packet) override {}; + virtual void unpack(BytePacket& packet) override {}; + virtual int apply(talsh::Tensor& local_tensor) override { return m_func(local_tensor); } + private: + std::function m_func; + }; + + [[nodiscard]] exatn::TensorNetwork buildInitialNetwork(size_t in_nbQubits, bool in_createQubitTensors) const; + void applySingleQubitGate(xacc::quantum::Gate& in_gateInstruction); + void applyTwoQubitGate(xacc::quantum::Gate& in_gateInstruction); + void applyKrausOp(const KrausOp& in_op); +private: + exatn::TensorNetwork m_tensorNetwork; + std::shared_ptr m_buffer; + std::shared_ptr m_noiseConfig; + std::vector m_measuredBits; + int m_nbShots; +}; +} // namespace tnqvm \ No newline at end of file diff --git a/tnqvm/visitors/exatn-dm/manifest.json b/tnqvm/visitors/exatn-dm/manifest.json new file mode 100644 index 0000000..4379f7b --- /dev/null +++ b/tnqvm/visitors/exatn-dm/manifest.json @@ -0,0 +1,6 @@ +{ + "bundle.symbolic_name" : "tnqvm_exatn_dm", + "bundle.activator" : true, + "bundle.name" : "XACC ExaTN Density Matrix Contract backend", + "bundle.description" : "This bundle provides a full density matrix tensor network Accelerator for Gate Model QC." +} \ No newline at end of file diff --git a/tnqvm/visitors/exatn-dm/tests/CMakeLists.txt b/tnqvm/visitors/exatn-dm/tests/CMakeLists.txt new file mode 100644 index 0000000..c2a154e --- /dev/null +++ b/tnqvm/visitors/exatn-dm/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +# Forcing use of XACC gtest install... :/ +include_directories(${XACC_ROOT}/include/gtest) + +add_executable(DensityMatrixSimTester JsonNoiseModelTester.cpp) +target_link_libraries(DensityMatrixSimTester PRIVATE ${XACC_ROOT}/lib/libgtest.so ${XACC_ROOT}/lib/libgtest_main.so tnqvm-exatn) +add_test(NAME DensityMatrixSimTester COMMAND DensityMatrixSimTester) diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp new file mode 100644 index 0000000..358b5a4 --- /dev/null +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -0,0 +1,131 @@ +#include +#include "xacc.hpp" +#include "xacc_service.hpp" +#include "NoiseModel.hpp" + +namespace { +// A sample Json for testing +// Single-qubit depolarizing: +const std::string depol_json = + R"({"gate_noise": [{"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; +// Single-qubit amplitude damping (25% rate): +const std::string ad_json = + R"({"gate_noise": [{"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[1.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.8660254037844386, 0.0]]], [[[0.0, 0.0], [0.5, 0.0]], [[0.0, 0.0], [0.0, 0.0]]]]}]}], "bit_order": "MSB"})"; +// Two-qubit noise channel (on a CNOT gate) in MSB and LSB order convention +// (matrix representation) +const std::string msb_noise_model = + R"({"gate_noise": [{"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.05773502691896258], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [-0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; +const std::string lsb_noise_model = + R"({"gate_noise": [{"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, -0.05773502691896258], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.05773502691896258], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [-0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}], "bit_order": "LSB"})"; +// Noise model that only has readout errors for validation: +// P(1|0) = 0.1; P(0|1) = 0.2 +const std::string ro_error_noise_model = + R"({"gate_noise": [], "bit_order": "MSB", "readout_errors": [{"register_location": "0", "prob_meas0_prep1": 0.2, "prob_meas1_prep0": 0.1}]})"; +} // namespace + +TEST(JsonNoiseModelTester, checkSimple) { + // Check depolarizing channels + { + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", depol_json}}); + auto accelerator = + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}, + {"noise-model", noiseModel}}); + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testX(qbit q) { + X(q[0]); + Measure(q[0]); + })", + accelerator) + ->getComposite("testX"); + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, program); + buffer->print(); + auto densityMatrix = (*buffer)["density_matrix"] + .as>>(); + EXPECT_EQ(densityMatrix.size(), 4); + // Check trace + EXPECT_NEAR(densityMatrix[0].first + densityMatrix[3].first, 1.0, 1e-6); + // Expected result: + // 0.00666667+0.j 0. +0.j + // 0. +0.j 0.99333333+0.j + // Check real part + EXPECT_NEAR(densityMatrix[0].first, 0.00666667, 1e-6); + EXPECT_NEAR(densityMatrix[1].first, 0.0, 1e-6); + EXPECT_NEAR(densityMatrix[2].first, 0.0, 1e-6); + EXPECT_NEAR(densityMatrix[3].first, 0.99333333, 1e-6); + // Check imag part + for (const auto &[real, imag] : densityMatrix) { + EXPECT_NEAR(imag, 0.0, 1e-6); + } + } + + // Check amplitude damping channels + { + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", ad_json}}); + auto accelerator = + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}, + {"noise-model", noiseModel}}); + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testX_ad(qbit q) { + X(q[0]); + Measure(q[0]); + })", + accelerator) + ->getComposites()[0]; + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, program); + buffer->print(); + // Verify the distribution (25% amplitude damping) + EXPECT_NEAR(buffer->computeMeasurementProbability("0"), 0.25, 0.1); + EXPECT_NEAR(buffer->computeMeasurementProbability("1"), 0.75, 0.1); + } +} + +TEST(JsonNoiseModelTester, checkRoError) { + auto xasmCompiler = xacc::getCompiler("xasm"); + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", ro_error_noise_model}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + { + auto program = xasmCompiler + ->compile(R"(__qpu__ void testId(qbit q) { + Measure(q[0]); + })", + nullptr) + ->getComposites()[0]; + + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, program); + buffer->print(); + // P(1|0) = 0.1 + EXPECT_NEAR(buffer->computeMeasurementProbability("1"), 0.1, 0.05); + } + { + auto program = xasmCompiler + ->compile(R"(__qpu__ void testFlip(qbit q) { + X(q[0]); + Measure(q[0]); + })", + nullptr) + ->getComposites()[0]; + + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, program); + buffer->print(); + // P(0|1) = 0.2 + EXPECT_NEAR(buffer->computeMeasurementProbability("0"), 0.2, 0.05); + } +} + +int main(int argc, char **argv) { + xacc::Initialize(argc, argv); + ::testing::InitGoogleTest(&argc, argv); + auto ret = RUN_ALL_TESTS(); + xacc::Finalize(); + return ret; +} \ No newline at end of file From 2df0419f45ef808da11aad1b81bf00ce8a204ace Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 21 Jan 2021 11:50:32 -0500 Subject: [PATCH 02/20] Append single-qubit gates Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 290 ++++++++++++++++++++- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp | 4 +- 2 files changed, 283 insertions(+), 11 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index d3bfaf6..6b73d2b 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -10,6 +10,120 @@ #include #endif +#define INITIAL_BOND_DIM 1 +#define INITIAL_KRAUS_DIM 1 +#define QUBIT_DIM 2 + +namespace { +std::vector> Q_ZERO_TENSOR_BODY(size_t in_volume) { + std::vector> body(in_volume, {0.0, 0.0}); + body[0] = std::complex(1.0, 0.0); + return body; +} + +const std::string ROOT_TENSOR_NAME = "Root"; + +void printDensityMatrix(const exatn::TensorNetwork &in_tensorNet, + size_t in_nbQubit) { + exatn::TensorNetwork tempNetwork(in_tensorNet); + tempNetwork.rename("__TEMP__" + in_tensorNet.getName()); + const bool evaledOk = exatn::evaluateSync(tempNetwork); + assert(evaledOk); + auto talsh_tensor = + exatn::getLocalTensor(tempNetwork.getTensor(0)->getName()); + const auto expectedDensityMatrixVolume = + (1ULL << in_nbQubit) * (1ULL << in_nbQubit); + const auto nbRows = 1ULL << in_nbQubit; + if (talsh_tensor) { + const std::complex *body_ptr; + const bool access_granted = talsh_tensor->getDataAccessHostConst(&body_ptr); + if (!access_granted) { + std::cout << "Failed to retrieve tensor data!!!\n"; + } else { + assert(expectedDensityMatrixVolume == talsh_tensor->getVolume()); + std::complex traceVal{0.0, 0.0}; + int rowId = -1; + for (int i = 0; i < talsh_tensor->getVolume(); ++i) { + if (i % nbRows == 0) { + std::cout << "\n"; + rowId++; + } + if (i == (rowId + rowId * nbRows)) { + traceVal += body_ptr[i]; + } + const auto &elem = body_ptr[i]; + std::cout << elem << " "; + } + std::cout << "\n"; + // Verify trace(density matrix) == 1.0 + assert(std::abs(traceVal.real() - 1.0) < 1e-12); + assert(std::abs(traceVal.imag()) < 1e-12); + } + } else { + std::cout << "Failed to retrieve tensor data!!!\n"; + } +} +std::vector> +getGateMatrix(const xacc::Instruction &in_gate) { + using namespace tnqvm; + const auto gateEnum = GetGateType(in_gate.name()); + const auto getMatrix = [&]() { + switch (gateEnum) { + case CommonGates::Rx: + return GetGateMatrix( + in_gate.getParameter(0).as()); + case CommonGates::Ry: + return GetGateMatrix( + in_gate.getParameter(0).as()); + case CommonGates::Rz: + return GetGateMatrix( + in_gate.getParameter(0).as()); + case CommonGates::I: + return GetGateMatrix(); + case CommonGates::H: + return GetGateMatrix(); + case CommonGates::X: + return GetGateMatrix(); + case CommonGates::Y: + return GetGateMatrix(); + case CommonGates::Z: + return GetGateMatrix(); + case CommonGates::T: + return GetGateMatrix(); + case CommonGates::Tdg: + return GetGateMatrix(); + case CommonGates::CNOT: + return GetGateMatrix(); + case CommonGates::Swap: + return GetGateMatrix(); + case CommonGates::iSwap: + return GetGateMatrix(); + case CommonGates::fSim: + return GetGateMatrix( + in_gate.getParameter(0).as(), + in_gate.getParameter(1).as()); + default: + return GetGateMatrix(); + } + }; + + const auto flattenGateMatrix = + [](const std::vector>> &in_gateMatrix) { + std::vector> resultVector; + resultVector.reserve(in_gateMatrix.size() * in_gateMatrix.size()); + for (const auto &row : in_gateMatrix) { + for (const auto &entry : row) { + resultVector.emplace_back(entry); + } + } + + return resultVector; + }; + + return flattenGateMatrix(getMatrix()); +} +} // namespace + namespace tnqvm { ExaTnDmVisitor::ExaTnDmVisitor() { // TODO @@ -46,14 +160,127 @@ void ExaTnDmVisitor::initialize(std::shared_ptr buffer, exatn::resetRuntimeLoggingLevel(xacc::verbose ? level : 0); }); } - - // TODO + m_buffer = buffer; + m_tensorNetwork = buildInitialNetwork(buffer->size()); + m_tensorIdCounter = m_tensorNetwork.getMaxTensorId(); } exatn::TensorNetwork -ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits, - bool in_createQubitTensors) const { - // TODO +ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits) const { + for (int i = 0; i < in_nbQubits; ++i) { + const std::string tensorName = "Q" + std::to_string(i); + auto tensor = [&]() { + if (in_nbQubits == 1) { + assert(tensorName == "Q0"); + return std::make_shared( + tensorName, exatn::TensorShape{QUBIT_DIM, INITIAL_BOND_DIM}); + } + if ((i == 0) || (i == (in_nbQubits - 1))) { + return std::make_shared( + tensorName, + exatn::TensorShape{QUBIT_DIM, INITIAL_BOND_DIM, INITIAL_KRAUS_DIM}); + } + + return std::make_shared( + tensorName, exatn::TensorShape{QUBIT_DIM, INITIAL_BOND_DIM, + INITIAL_KRAUS_DIM, INITIAL_BOND_DIM}); + }(); + + const bool created = + exatn::createTensorSync(tensor, exatn::TensorElementType::COMPLEX64); + assert(created); + const bool initialized = exatn::initTensorDataSync( + tensorName, Q_ZERO_TENSOR_BODY(tensor->getVolume())); + assert(initialized); + } + + const auto buildTensorMap = [](size_t in_nbQubits) { + const std::vector qubitTensorDim(in_nbQubits, QUBIT_DIM); + const std::vector ancTensorDim(in_nbQubits, INITIAL_KRAUS_DIM); + // Root tensor dimension: 2 .. 2 (upper legs/system dimensions) 1 ... 1 + // (lower legs/anc dimension) + std::vector rootTensorDim; + rootTensorDim.insert(rootTensorDim.end(), qubitTensorDim.begin(), + qubitTensorDim.end()); + rootTensorDim.insert(rootTensorDim.end(), ancTensorDim.begin(), + ancTensorDim.end()); + auto rootTensor = + std::make_shared(ROOT_TENSOR_NAME, rootTensorDim); + std::map> tensorMap; + tensorMap.emplace(ROOT_TENSOR_NAME, rootTensor); + for (int i = 0; i < in_nbQubits; ++i) { + const std::string qTensorName = "Q" + std::to_string(i); + tensorMap.emplace(qTensorName, exatn::getTensor(qTensorName)); + } + return tensorMap; + }; + + const std::string rootVarNameList = [](size_t in_nbQubits) { + std::string result = "("; + // Primary qubit legs + for (int i = 0; i < in_nbQubits; ++i) { + result += ("i" + std::to_string(i) + ","); + } + + // Anc legs: + for (int i = 0; i < in_nbQubits; ++i) { + result += ("k" + std::to_string(i) + ","); + } + assert(result.back() == ','); + result.back() = ')'; + return result; + }(in_nbQubits); + + const auto qubitTensorVarNameList = [](int in_qIdx, + int in_nbQubits) -> std::string { + if (in_nbQubits == 1) { + assert(in_qIdx == 0); + return "(i0,k0)"; + } + if (in_qIdx == 0) { + return "(i0,j0,k0)"; + } + if (in_qIdx == in_nbQubits - 1) { + return "(i" + std::to_string(in_nbQubits - 1) + ",j" + + std::to_string(in_nbQubits - 2) + ",k" + + std::to_string(in_nbQubits - 1) + ")"; + } + + return "(i" + std::to_string(in_qIdx) + ",j" + std::to_string(in_qIdx - 1) + + ",k" + std::to_string(in_qIdx) + ",j" + std::to_string(in_qIdx) + + ")"; + }; + + const std::string tensorNetworkString = [&]() { + std::string result = ROOT_TENSOR_NAME + rootVarNameList + "="; + for (int i = 0; i < in_nbQubits - 1; ++i) { + result += ("Q" + std::to_string(i) + + qubitTensorVarNameList(i, in_nbQubits) + "*"); + } + result += ("Q" + std::to_string(m_buffer->size() - 1) + + qubitTensorVarNameList(in_nbQubits - 1, in_nbQubits)); + return result; + }(); + + exatn::TensorNetwork qubitTensorNet("Tensor_Network", tensorNetworkString, + buildTensorMap(in_nbQubits)); + // qubitTensorNet.printIt(); + + // Conjugate of the network: + exatn::TensorNetwork conjugate(qubitTensorNet); + conjugate.rename("Conjugate"); + conjugate.conjugate(); + // conjugate.printIt(); + // Pair all ancilla legs + std::vector> pairings; + for (size_t i = 0; i < in_nbQubits; ++i) { + pairings.emplace_back(std::make_pair(i + in_nbQubits, i + in_nbQubits)); + } + + qubitTensorNet.appendTensorNetwork(std::move(conjugate), pairings); + std::cout << "Qubit Tensor network:\n"; + qubitTensorNet.printIt(); + return qubitTensorNet; } void ExaTnDmVisitor::finalize() { @@ -62,7 +289,45 @@ void ExaTnDmVisitor::finalize() { void ExaTnDmVisitor::applySingleQubitGate( xacc::quantum::Gate &in_gateInstruction) { - // TODO + m_tensorIdCounter++; + assert(in_gateInstruction.bits().size() == 1); + const auto gateMatrix = getGateMatrix(in_gateInstruction); + assert(gateMatrix.size() == 4); + const std::string uniqueGateName = + in_gateInstruction.name() + std::to_string(m_tensorIdCounter); + // Create the tensor + const bool created = exatn::createTensorSync( + uniqueGateName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(uniqueGateName, gateMatrix); + assert(initialized); + + const std::vector gatePairing{ + static_cast(in_gateInstruction.bits()[0])}; + // Append the tensor for this gate to the network + const bool appended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairing); + assert(appended); + + m_tensorIdCounter++; + const std::vector gatePairingConj{static_cast( + m_buffer->size() + in_gateInstruction.bits()[0])}; + const bool conjAppended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairingConj, + // conjugate + true); + assert(conjAppended); } void ExaTnDmVisitor::applyTwoQubitGate( @@ -87,8 +352,9 @@ void ExaTnDmVisitor::visit(Hadamard &in_HadamardGate) { void ExaTnDmVisitor::visit(X &in_XGate) { applySingleQubitGate(in_XGate); // DEBUG: - // std::cout << "Apply: " << in_XGate.toString() << "\n"; - // printDensityMatrix(m_tensorNetwork, m_buffer->size()); + std::cout << "Apply: " << in_XGate.toString() << "\n"; + m_tensorNetwork.printIt(); + printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Y &in_YGate) { applySingleQubitGate(in_YGate); } @@ -101,7 +367,13 @@ void ExaTnDmVisitor::visit(Ry &in_RyGate) { applySingleQubitGate(in_RyGate); } void ExaTnDmVisitor::visit(Rz &in_RzGate) { applySingleQubitGate(in_RzGate); } -void ExaTnDmVisitor::visit(T &in_TGate) { applySingleQubitGate(in_TGate); } +void ExaTnDmVisitor::visit(T &in_TGate) { + applySingleQubitGate(in_TGate); + // DEBUG: + std::cout << "Apply: " << in_TGate.toString() << "\n"; + m_tensorNetwork.printIt(); + printDensityMatrix(m_tensorNetwork, m_buffer->size()); +} void ExaTnDmVisitor::visit(Tdg &in_TdgGate) { applySingleQubitGate(in_TdgGate); diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp index 46251dc..414ca1f 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp @@ -83,15 +83,15 @@ class ExaTnDmVisitor : public TNQVMVisitor std::function m_func; }; - [[nodiscard]] exatn::TensorNetwork buildInitialNetwork(size_t in_nbQubits, bool in_createQubitTensors) const; + [[nodiscard]] exatn::TensorNetwork buildInitialNetwork(size_t in_nbQubits) const; void applySingleQubitGate(xacc::quantum::Gate& in_gateInstruction); void applyTwoQubitGate(xacc::quantum::Gate& in_gateInstruction); void applyKrausOp(const KrausOp& in_op); private: exatn::TensorNetwork m_tensorNetwork; std::shared_ptr m_buffer; - std::shared_ptr m_noiseConfig; std::vector m_measuredBits; int m_nbShots; + int m_tensorIdCounter; }; } // namespace tnqvm \ No newline at end of file From a2482faa927268c1fcd965f2e771b14d315e1afa Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 21 Jan 2021 12:15:50 -0500 Subject: [PATCH 03/20] Add two-qubit tensor append Also, expose ExecutionInfo to return density matrix for testing. Signed-off-by: Thien Nguyen --- tnqvm/TNQVM.hpp | 8 ++- tnqvm/visitors/TNQVMVisitor.hpp | 5 ++ tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 75 +++++++++++++++++++--- 3 files changed, 79 insertions(+), 9 deletions(-) diff --git a/tnqvm/TNQVM.hpp b/tnqvm/TNQVM.hpp index a6f41d8..d63aa24 100644 --- a/tnqvm/TNQVM.hpp +++ b/tnqvm/TNQVM.hpp @@ -133,7 +133,13 @@ class TNQVM : public Accelerator { const std::string& getVisitorName() const { return backendName; } virtual ~TNQVM() {} - + + virtual HeterogeneousMap getExecutionInfo() const override { + auto result = visitor->getExecutionInfo(); + result.insert("visitor", visitor->name()); + return result; + } + int verbose() const { return __verbose; } void verbose(int level) { __verbose = level; } void set_verbose(int level) { __verbose = level; } diff --git a/tnqvm/visitors/TNQVMVisitor.hpp b/tnqvm/visitors/TNQVMVisitor.hpp index 9e40cca..1c50b6a 100644 --- a/tnqvm/visitors/TNQVMVisitor.hpp +++ b/tnqvm/visitors/TNQVMVisitor.hpp @@ -71,9 +71,14 @@ class TNQVMVisitor : public AllGateVisitor, public OptionsProvider, // Does this visitor implementation support VQE mode execution? // i.e. ability to cache the state vector after simulating the ansatz. virtual bool supportVqeMode() const { return false; } + // Execution information that visitor wants to persist. + HeterogeneousMap getExecutionInfo() const { return executionInfo; } + protected: std::shared_ptr buffer; HeterogeneousMap options; + // Visitor impl to set if need be. + HeterogeneousMap executionInfo; }; } // namespace tnqvm diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 6b73d2b..71c7481 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -284,7 +284,22 @@ ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits) const { } void ExaTnDmVisitor::finalize() { - // TODO + std::unordered_set tensorList; + for (auto iter = m_tensorNetwork.cbegin(); iter != m_tensorNetwork.cend(); + ++iter) { + const auto &tensorName = iter->second.getTensor()->getName(); + // Not a root tensor + if (!tensorName.empty() && tensorName[0] != '_') { + tensorList.emplace(iter->second.getTensor()->getName()); + } + } + + for (const auto &tensorName : tensorList) { + const bool destroyed = exatn::destroyTensor(tensorName); + assert(destroyed); + } + + m_buffer.reset(); } void ExaTnDmVisitor::applySingleQubitGate( @@ -332,8 +347,51 @@ void ExaTnDmVisitor::applySingleQubitGate( void ExaTnDmVisitor::applyTwoQubitGate( xacc::quantum::Gate &in_gateInstruction) { - // TODO + m_tensorIdCounter++; + assert(in_gateInstruction.bits().size() == 2); + const auto gateMatrix = getGateMatrix(in_gateInstruction); + assert(gateMatrix.size() == 16); + const std::string uniqueGateName = + in_gateInstruction.name() + std::to_string(m_tensorIdCounter); + // Create the tensor + const bool created = exatn::createTensorSync( + uniqueGateName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2, 2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(uniqueGateName, gateMatrix); + assert(initialized); + + const std::vector gatePairing{ + static_cast(in_gateInstruction.bits()[1]), + static_cast(in_gateInstruction.bits()[0])}; + // Append the tensor for this gate to the network + const bool appended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairing); + assert(appended); + + m_tensorIdCounter++; + const std::vector gatePairingConj{ + static_cast(m_buffer->size() + + in_gateInstruction.bits()[1]), + static_cast(m_buffer->size() + + in_gateInstruction.bits()[0])}; + const bool conjAppended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairingConj, + // conjugate + true); + assert(conjAppended); } + void ExaTnDmVisitor::applyKrausOp(const KrausOp &in_op) { // TODO } @@ -391,25 +449,26 @@ void ExaTnDmVisitor::visit(CNOT &in_CNOTGate) { applyTwoQubitGate(in_CNOTGate); // DEBUG: // std::cout << "Apply: " << in_CNOTGate.toString() << "\n"; - // printDensityMatrix(m_tensorNetwork, m_buffer->size()); + m_tensorNetwork.printIt(); + printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Swap &in_SwapGate) { - applySingleQubitGate(in_SwapGate); + applyTwoQubitGate(in_SwapGate); } -void ExaTnDmVisitor::visit(CZ &in_CZGate) { applySingleQubitGate(in_CZGate); } +void ExaTnDmVisitor::visit(CZ &in_CZGate) { applyTwoQubitGate(in_CZGate); } void ExaTnDmVisitor::visit(CPhase &in_CPhaseGate) { - applySingleQubitGate(in_CPhaseGate); + applyTwoQubitGate(in_CPhaseGate); } void ExaTnDmVisitor::visit(iSwap &in_iSwapGate) { - applySingleQubitGate(in_iSwapGate); + applyTwoQubitGate(in_iSwapGate); } void ExaTnDmVisitor::visit(fSim &in_fsimGate) { - applySingleQubitGate(in_fsimGate); + applyTwoQubitGate(in_fsimGate); } const double ExaTnDmVisitor::getExpectationValueZ( From fafa84e004aed8fe90340d0b48fcc256ee463c22 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 21 Jan 2021 12:44:47 -0500 Subject: [PATCH 04/20] Added Density Matrix after full contraction to ExecutionInfo Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 71c7481..57792dc 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -284,6 +284,51 @@ ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits) const { } void ExaTnDmVisitor::finalize() { + executionInfo.clear(); + // Max number of qubits that we allow for a full density matrix retrieval. + // For more qubits, only expectation contraction is supported. + constexpr size_t MAX_SIZE_TO_COLLAPSE_DM = 10; + + if (m_buffer->size() <= MAX_SIZE_TO_COLLAPSE_DM) { + xacc::ExecutionInfo::DensityMatrixType densityMatrix; + const auto nbRows = 1ULL << m_buffer->size(); + densityMatrix.reserve(1 << m_buffer->size()); + exatn::TensorNetwork tempNetwork(m_tensorNetwork); + tempNetwork.rename("__TEMP__" + m_tensorNetwork.getName()); + const bool evaledOk = exatn::evaluateSync(tempNetwork); + assert(evaledOk); + auto talsh_tensor = + exatn::getLocalTensor(tempNetwork.getTensor(0)->getName()); + const auto expectedDensityMatrixVolume = nbRows * nbRows; + if (talsh_tensor) { + const std::complex *body_ptr; + const bool access_granted = + talsh_tensor->getDataAccessHostConst(&body_ptr); + if (!access_granted) { + std::cout << "Failed to retrieve tensor data!!!\n"; + } else { + assert(expectedDensityMatrixVolume == talsh_tensor->getVolume()); + xacc::ExecutionInfo::WaveFuncType dmRow; + dmRow.reserve(nbRows); + for (int i = 0; i < talsh_tensor->getVolume(); ++i) { + if ((i != 0) && (i % nbRows == 0)) { + assert(dmRow.size() == nbRows); + densityMatrix.emplace_back(std::move(dmRow)); + dmRow.clear(); + dmRow.reserve(nbRows); + } + const auto &elem = body_ptr[i]; + dmRow.emplace_back(elem); + } + assert(dmRow.size() == nbRows); + densityMatrix.emplace_back(std::move(dmRow)); + assert(densityMatrix.size() == nbRows); + } + } + + executionInfo.insert(ExecutionInfo::DmKey, std::make_shared(std::move(densityMatrix))); + } + std::unordered_set tensorList; for (auto iter = m_tensorNetwork.cbegin(); iter != m_tensorNetwork.cend(); ++iter) { From b86adc6532f8dd88b0da82952b9d60678c286c32 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 21 Jan 2021 12:49:34 -0500 Subject: [PATCH 05/20] Clean-up the test case First, test w/ no noise, just looking at the final density matrix Signed-off-by: Thien Nguyen --- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 103 ++++++------------ 1 file changed, 31 insertions(+), 72 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index 358b5a4..50ff6bd 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -23,14 +23,10 @@ const std::string ro_error_noise_model = R"({"gate_noise": [], "bit_order": "MSB", "readout_errors": [{"register_location": "0", "prob_meas0_prep1": 0.2, "prob_meas1_prep0": 0.1}]})"; } // namespace -TEST(JsonNoiseModelTester, checkSimple) { - // Check depolarizing channels +TEST(JsonNoiseModelTester, checkNoNoise) { { - auto noiseModel = xacc::getService("json"); - noiseModel->initialize({{"noise-model", depol_json}}); auto accelerator = - xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}, - {"noise-model", noiseModel}}); + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); auto xasmCompiler = xacc::getCompiler("xasm"); auto program = xasmCompiler ->compile(R"(__qpu__ void testX(qbit q) { @@ -41,84 +37,47 @@ TEST(JsonNoiseModelTester, checkSimple) { ->getComposite("testX"); auto buffer = xacc::qalloc(1); accelerator->execute(buffer, program); - buffer->print(); - auto densityMatrix = (*buffer)["density_matrix"] - .as>>(); - EXPECT_EQ(densityMatrix.size(), 4); - // Check trace - EXPECT_NEAR(densityMatrix[0].first + densityMatrix[3].first, 1.0, 1e-6); - // Expected result: - // 0.00666667+0.j 0. +0.j - // 0. +0.j 0.99333333+0.j - // Check real part - EXPECT_NEAR(densityMatrix[0].first, 0.00666667, 1e-6); - EXPECT_NEAR(densityMatrix[1].first, 0.0, 1e-6); - EXPECT_NEAR(densityMatrix[2].first, 0.0, 1e-6); - EXPECT_NEAR(densityMatrix[3].first, 0.99333333, 1e-6); - // Check imag part - for (const auto &[real, imag] : densityMatrix) { - EXPECT_NEAR(imag, 0.0, 1e-6); + auto exeInfo = accelerator->getExecutionInfo(); + auto dm = accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + std::cout << "Density matrix\n"; + for (const auto &row : *dm) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; } + EXPECT_EQ(dm->size(), 2); } - // Check amplitude damping channels { - auto noiseModel = xacc::getService("json"); - noiseModel->initialize({{"noise-model", ad_json}}); auto accelerator = - xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}, - {"noise-model", noiseModel}}); + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); auto xasmCompiler = xacc::getCompiler("xasm"); auto program = xasmCompiler - ->compile(R"(__qpu__ void testX_ad(qbit q) { - X(q[0]); + ->compile(R"(__qpu__ void testT(qbit q) { + H(q[0]); + CX(q[0], q[1]); Measure(q[0]); })", accelerator) - ->getComposites()[0]; - auto buffer = xacc::qalloc(1); + ->getComposite("testT"); + auto buffer = xacc::qalloc(2); accelerator->execute(buffer, program); buffer->print(); - // Verify the distribution (25% amplitude damping) - EXPECT_NEAR(buffer->computeMeasurementProbability("0"), 0.25, 0.1); - EXPECT_NEAR(buffer->computeMeasurementProbability("1"), 0.75, 0.1); - } -} - -TEST(JsonNoiseModelTester, checkRoError) { - auto xasmCompiler = xacc::getCompiler("xasm"); - auto noiseModel = xacc::getService("json"); - noiseModel->initialize({{"noise-model", ro_error_noise_model}}); - auto accelerator = xacc::getAccelerator( - "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); - { - auto program = xasmCompiler - ->compile(R"(__qpu__ void testId(qbit q) { - Measure(q[0]); - })", - nullptr) - ->getComposites()[0]; - - auto buffer = xacc::qalloc(1); - accelerator->execute(buffer, program); - buffer->print(); - // P(1|0) = 0.1 - EXPECT_NEAR(buffer->computeMeasurementProbability("1"), 0.1, 0.05); - } - { - auto program = xasmCompiler - ->compile(R"(__qpu__ void testFlip(qbit q) { - X(q[0]); - Measure(q[0]); - })", - nullptr) - ->getComposites()[0]; - - auto buffer = xacc::qalloc(1); - accelerator->execute(buffer, program); - buffer->print(); - // P(0|1) = 0.2 - EXPECT_NEAR(buffer->computeMeasurementProbability("0"), 0.2, 0.05); + auto exeInfo = accelerator->getExecutionInfo(); + auto dm = accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + std::cout << "Density matrix\n"; + for (const auto &row : *dm) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; + } + EXPECT_EQ(dm->size(), 4); } } From aa81e2c2045acfe54459e99d914a86a5dca0835f Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 21 Jan 2021 13:55:26 -0500 Subject: [PATCH 06/20] Appended noise tensors Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 75 +++++++++++++++++----- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp | 3 +- 2 files changed, 62 insertions(+), 16 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 57792dc..951cca8 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -63,6 +63,20 @@ void printDensityMatrix(const exatn::TensorNetwork &in_tensorNet, std::cout << "Failed to retrieve tensor data!!!\n"; } } + +std::vector> flattenGateMatrix( + const std::vector>> &in_gateMatrix) { + std::vector> resultVector; + resultVector.reserve(in_gateMatrix.size() * in_gateMatrix.size()); + for (const auto &row : in_gateMatrix) { + for (const auto &entry : row) { + resultVector.emplace_back(entry); + } + } + + return resultVector; +} + std::vector> getGateMatrix(const xacc::Instruction &in_gate) { using namespace tnqvm; @@ -107,19 +121,6 @@ getGateMatrix(const xacc::Instruction &in_gate) { } }; - const auto flattenGateMatrix = - [](const std::vector>> &in_gateMatrix) { - std::vector> resultVector; - resultVector.reserve(in_gateMatrix.size() * in_gateMatrix.size()); - for (const auto &row : in_gateMatrix) { - for (const auto &entry : row) { - resultVector.emplace_back(entry); - } - } - - return resultVector; - }; - return flattenGateMatrix(getMatrix()); } } // namespace @@ -163,6 +164,10 @@ void ExaTnDmVisitor::initialize(std::shared_ptr buffer, m_buffer = buffer; m_tensorNetwork = buildInitialNetwork(buffer->size()); m_tensorIdCounter = m_tensorNetwork.getMaxTensorId(); + if (options.pointerLikeExists("noise-model")) { + m_noiseConfig = xacc::as_shared_ptr( + options.getPointerLike("noise-model")); + } } exatn::TensorNetwork @@ -345,6 +350,7 @@ void ExaTnDmVisitor::finalize() { } m_buffer.reset(); + m_noiseConfig.reset(); } void ExaTnDmVisitor::applySingleQubitGate( @@ -388,6 +394,8 @@ void ExaTnDmVisitor::applySingleQubitGate( // conjugate true); assert(conjAppended); + // Adding noise tensors. + applyNoise(in_gateInstruction); } void ExaTnDmVisitor::applyTwoQubitGate( @@ -437,8 +445,45 @@ void ExaTnDmVisitor::applyTwoQubitGate( assert(conjAppended); } -void ExaTnDmVisitor::applyKrausOp(const KrausOp &in_op) { - // TODO +void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { + if (!m_noiseConfig) { + return; + } + + const auto noiseChannels = + m_noiseConfig->getNoiseChannels(in_gateInstruction); + auto noiseUtils = xacc::getService("default"); + + for (auto &channel : noiseChannels) { + auto noiseMat = noiseUtils->krausToChoi(channel.mats); + m_tensorIdCounter++; + const std::string noiseTensorName = in_gateInstruction.name() + "_Noise_" + + std::to_string(m_tensorIdCounter); + // Create the tensor + const bool created = exatn::createTensorSync( + noiseTensorName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2, 2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(noiseTensorName, flattenGateMatrix(noiseMat)); + assert(initialized); + + const std::vector noisePairing{ + static_cast(channel.noise_qubits[0]), + static_cast(channel.noise_qubits[0] + m_buffer->size())}; + // Append the tensor for this gate to the network + const bool appended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, exatn::getTensor(noiseTensorName), + // which qubits that the gate is acting on + noisePairing); + assert(appended); + } + + // DEBUG: + std::cout << "Apply Noise: " << in_gateInstruction.toString() << "\n"; + m_tensorNetwork.printIt(); + printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Identity &in_IdentityGate) { diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp index 414ca1f..c6d2d9a 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp @@ -86,12 +86,13 @@ class ExaTnDmVisitor : public TNQVMVisitor [[nodiscard]] exatn::TensorNetwork buildInitialNetwork(size_t in_nbQubits) const; void applySingleQubitGate(xacc::quantum::Gate& in_gateInstruction); void applyTwoQubitGate(xacc::quantum::Gate& in_gateInstruction); - void applyKrausOp(const KrausOp& in_op); + void applyNoise(xacc::quantum::Gate &in_gateInstruction); private: exatn::TensorNetwork m_tensorNetwork; std::shared_ptr m_buffer; std::vector m_measuredBits; int m_nbShots; int m_tensorIdCounter; + std::shared_ptr m_noiseConfig; }; } // namespace tnqvm \ No newline at end of file From 1c65b46657d167131d84d07255c6c1b6adce5d49 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 21 Jan 2021 14:49:29 -0500 Subject: [PATCH 07/20] Fixed appending noise tensors (changing connecting legs) Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 80 ++++++++++--- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp | 3 +- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 110 +++++++++++++++++- 3 files changed, 171 insertions(+), 22 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 951cca8..aae6d10 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -449,6 +449,8 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { if (!m_noiseConfig) { return; } + std::cout << "Before noise:\n"; + printDensityMatrix(m_tensorNetwork, m_buffer->size()); const auto noiseChannels = m_noiseConfig->getNoiseChannels(in_gateInstruction); @@ -456,28 +458,68 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { for (auto &channel : noiseChannels) { auto noiseMat = noiseUtils->krausToChoi(channel.mats); + + for (const auto &row : noiseMat) { + for (const auto &el : row) { + std::cout << el << " "; + } + std::cout << "\n"; + } + m_tensorIdCounter++; const std::string noiseTensorName = in_gateInstruction.name() + "_Noise_" + std::to_string(m_tensorIdCounter); - // Create the tensor - const bool created = exatn::createTensorSync( - noiseTensorName, exatn::TensorElementType::COMPLEX64, - exatn::TensorShape{2, 2, 2, 2}); - assert(created); - // Init tensor body data - const bool initialized = - exatn::initTensorDataSync(noiseTensorName, flattenGateMatrix(noiseMat)); - assert(initialized); - - const std::vector noisePairing{ - static_cast(channel.noise_qubits[0]), - static_cast(channel.noise_qubits[0] + m_buffer->size())}; - // Append the tensor for this gate to the network - const bool appended = m_tensorNetwork.appendTensorGate( - m_tensorIdCounter, exatn::getTensor(noiseTensorName), - // which qubits that the gate is acting on - noisePairing); - assert(appended); + if (channel.noise_qubits.size() == 1) { + // Create the tensor + const bool created = exatn::createTensorSync( + noiseTensorName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2, 2, 2}); + assert(created); + // Init tensor body data + const bool initialized = exatn::initTensorDataSync( + noiseTensorName, flattenGateMatrix(noiseMat)); + assert(initialized); + + const std::vector> noisePairing{ + {static_cast(channel.noise_qubits[0]), 1}, + {static_cast(channel.noise_qubits[0] + + m_buffer->size()), + 3}}; + // Append the tensor for this gate to the network + const bool appended = m_tensorNetwork.appendTensor( + m_tensorIdCounter, exatn::getTensor(noiseTensorName), + // which qubits that the gate is acting on + noisePairing); + assert(appended); + } else if (channel.noise_qubits.size() == 2) { + // Create the tensor + const bool created = exatn::createTensorSync( + noiseTensorName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2, 2, 2, 2, 2, 2, 2}); + assert(created); + // Init tensor body data + const bool initialized = exatn::initTensorDataSync( + noiseTensorName, flattenGateMatrix(noiseMat)); + assert(initialized); + + const std::vector> noisePairing{ + {static_cast(channel.noise_qubits[0]), 0}, + {static_cast(channel.noise_qubits[0] + + m_buffer->size()), + 2}, + {static_cast(channel.noise_qubits[1]), 4}, + {static_cast(channel.noise_qubits[1] + + m_buffer->size()), + 6}}; + // Append the tensor for this gate to the network + const bool appended = m_tensorNetwork.appendTensor( + m_tensorIdCounter, exatn::getTensor(noiseTensorName), + // which qubits that the gate is acting on + noisePairing); + assert(appended); + } else { + xacc::error("Unsupported noise data."); + } } // DEBUG: diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp index c6d2d9a..e8f1cda 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.hpp @@ -87,7 +87,8 @@ class ExaTnDmVisitor : public TNQVMVisitor void applySingleQubitGate(xacc::quantum::Gate& in_gateInstruction); void applyTwoQubitGate(xacc::quantum::Gate& in_gateInstruction); void applyNoise(xacc::quantum::Gate &in_gateInstruction); -private: + + private: exatn::TensorNetwork m_tensorNetwork; std::shared_ptr m_buffer; std::vector m_measuredBits; diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index 50ff6bd..8b3c1b6 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -56,13 +56,13 @@ TEST(JsonNoiseModelTester, checkNoNoise) { xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); auto xasmCompiler = xacc::getCompiler("xasm"); auto program = xasmCompiler - ->compile(R"(__qpu__ void testT(qbit q) { + ->compile(R"(__qpu__ void testBell(qbit q) { H(q[0]); CX(q[0], q[1]); Measure(q[0]); })", accelerator) - ->getComposite("testT"); + ->getComposite("testBell"); auto buffer = xacc::qalloc(2); accelerator->execute(buffer, program); buffer->print(); @@ -81,6 +81,112 @@ TEST(JsonNoiseModelTester, checkNoNoise) { } } +TEST(JsonNoiseModelTester, checkSimple) { + // Check depolarizing channels + { + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", depol_json}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testX(qbit q) { + X(q[0]); + Measure(q[0]); + })", + accelerator) + ->getComposite("testX"); + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, program); + buffer->print(); + auto dmPtr = + accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + auto densityMatrix = *dmPtr; + EXPECT_EQ(densityMatrix.size(), 2); + // Check trace + EXPECT_NEAR(densityMatrix[0][0].real() + densityMatrix[1][1].real(), 1.0, 1e-6); + // Expected result: + // 0.00666667+0.j 0. +0.j + // 0. +0.j 0.99333333+0.j + // Check real part + EXPECT_NEAR(densityMatrix[0][0].real(), 0.00666667, 1e-6); + EXPECT_NEAR(densityMatrix[1][0].real(), 0.0, 1e-6); + EXPECT_NEAR(densityMatrix[0][1].real(), 0.0, 1e-6); + EXPECT_NEAR(densityMatrix[1][1].real(), 0.99333333, 1e-6); + } + + // Check amplitude damping channels + { + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", ad_json}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testX_ad(qbit q) { + X(q[0]); + Measure(q[0]); + })", + accelerator) + ->getComposites()[0]; + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, program); + auto dmPtr = accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + auto densityMatrix = *dmPtr; + // Verify the distribution (25% amplitude damping) + EXPECT_NEAR(densityMatrix[0][0].real(), 0.25, 1e-6); + EXPECT_NEAR(densityMatrix[1][1].real(), 0.75, 1e-6); + } +} + +TEST(JsonNoiseModelTester, checkBitOrdering) { + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testCX(qbit q) { + CX(q[0], q[1]); + Measure(q[0]); + Measure(q[1]); + })", + nullptr) + ->getComposites()[0]; + + std::vector>> densityMatrix_msb, densityMatrix_lsb; + // Check MSB: + { + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", msb_noise_model}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + + auto buffer = xacc::qalloc(2); + accelerator->execute(buffer, program); + auto dmPtr = + accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + densityMatrix_msb = *dmPtr; + } + + // Check LSB: + { + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", lsb_noise_model}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + auto buffer = xacc::qalloc(2); + accelerator->execute(buffer, program); + auto dmPtr = + accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + densityMatrix_lsb = *dmPtr; + } +} + int main(int argc, char **argv) { xacc::Initialize(argc, argv); ::testing::InitGoogleTest(&argc, argv); From 28a7f699860545c0794d41d622264397e2437d63 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Fri, 22 Jan 2021 13:50:39 -0500 Subject: [PATCH 08/20] Append two-qubit Kraus tensors according to the LSB-MSB convention Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 21 ++++++++++++++--- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 23 +++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index aae6d10..0e146bb 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -443,6 +443,8 @@ void ExaTnDmVisitor::applyTwoQubitGate( // conjugate true); assert(conjAppended); + // Adding noise tensors. + applyNoise(in_gateInstruction); } void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { @@ -502,15 +504,28 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { noiseTensorName, flattenGateMatrix(noiseMat)); assert(initialized); - const std::vector> noisePairing{ + const std::vector> noisePairingMsb{ {static_cast(channel.noise_qubits[0]), 0}, {static_cast(channel.noise_qubits[0] + m_buffer->size()), - 2}, + 1}, {static_cast(channel.noise_qubits[1]), 4}, {static_cast(channel.noise_qubits[1] + m_buffer->size()), - 6}}; + 5}}; + + const std::vector> noisePairingLsb{ + {static_cast(channel.noise_qubits[1]), 0}, + {static_cast(channel.noise_qubits[1] + + m_buffer->size()), + 3}, + {static_cast(channel.noise_qubits[0]), 4}, + {static_cast(channel.noise_qubits[0] + + m_buffer->size()), + 7}}; + const std::vector> noisePairing = + (channel.bit_order == KrausMatBitOrder::MSB) ? noisePairingMsb + : noisePairingLsb; // Append the tensor for this gate to the network const bool appended = m_tensorNetwork.appendTensor( m_tensorIdCounter, exatn::getTensor(noiseTensorName), diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index 8b3c1b6..cfdf8d7 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -169,6 +169,13 @@ TEST(JsonNoiseModelTester, checkBitOrdering) { ->getExecutionInfo( xacc::ExecutionInfo::DmKey); densityMatrix_msb = *dmPtr; + std::cout << "Density matrix MSB\n"; + for (const auto &row : densityMatrix_msb) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; + } } // Check LSB: @@ -184,6 +191,22 @@ TEST(JsonNoiseModelTester, checkBitOrdering) { ->getExecutionInfo( xacc::ExecutionInfo::DmKey); densityMatrix_lsb = *dmPtr; + std::cout << "Density matrix LSB\n"; + for (const auto &row : densityMatrix_lsb) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; + } + } + + for (int row = 0; row < 4; ++row) { + for (int col = 0; col < 4; ++col) { + EXPECT_NEAR(densityMatrix_msb[row][col].real(), + densityMatrix_lsb[row][col].real(), 1e-9); + EXPECT_NEAR(densityMatrix_msb[row][col].imag(), + densityMatrix_lsb[row][col].imag(), 1e-9); + } } } From de27781484aeed91ca0a2b3cb4b5a933bf4baf3a Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Fri, 22 Jan 2021 15:44:28 -0500 Subject: [PATCH 09/20] Adding more validation tests for full density matrix contraction results Signed-off-by: Thien Nguyen --- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 73 +++++++++++++++++-- 1 file changed, 66 insertions(+), 7 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index cfdf8d7..aa51a25 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -21,6 +21,27 @@ const std::string lsb_noise_model = // P(1|0) = 0.1; P(0|1) = 0.2 const std::string ro_error_noise_model = R"({"gate_noise": [], "bit_order": "MSB", "readout_errors": [{"register_location": "0", "prob_meas0_prep1": 0.2, "prob_meas1_prep0": 0.1}]})"; + +// Multiple qubit depolarizing: +const std::string noise_model_multi_depol = R"({"gate_noise": [{"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; + +bool validateDensityMatrix( + const std::vector>> &in_dm) { + double sum_diag = 0.0; + const auto nbRows = in_dm.size(); + for (size_t i = 0; i < nbRows; ++i) { + if (in_dm[i].size() != nbRows) { + return false; + } + const auto diag_elem = in_dm[i][i]; + if (std::abs(diag_elem.imag()) > 1e-3) { + return false; + } + sum_diag += diag_elem.real(); + } + return std::abs(1.0 - sum_diag) < 1e-3; +} + } // namespace TEST(JsonNoiseModelTester, checkNoNoise) { @@ -49,6 +70,7 @@ TEST(JsonNoiseModelTester, checkNoNoise) { std::cout << "\n"; } EXPECT_EQ(dm->size(), 2); + EXPECT_TRUE(validateDensityMatrix(*dm)); } { @@ -70,14 +92,15 @@ TEST(JsonNoiseModelTester, checkNoNoise) { auto dm = accelerator ->getExecutionInfo( xacc::ExecutionInfo::DmKey); - std::cout << "Density matrix\n"; - for (const auto &row : *dm) { - for (const auto &elem : row) { - std::cout << elem << " "; - } - std::cout << "\n"; - } + // std::cout << "Density matrix\n"; + // for (const auto &row : *dm) { + // for (const auto &elem : row) { + // std::cout << elem << " "; + // } + // std::cout << "\n"; + // } EXPECT_EQ(dm->size(), 4); + EXPECT_TRUE(validateDensityMatrix(*dm)); } } @@ -104,6 +127,7 @@ TEST(JsonNoiseModelTester, checkSimple) { ->getExecutionInfo( xacc::ExecutionInfo::DmKey); auto densityMatrix = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix)); EXPECT_EQ(densityMatrix.size(), 2); // Check trace EXPECT_NEAR(densityMatrix[0][0].real() + densityMatrix[1][1].real(), 1.0, 1e-6); @@ -137,6 +161,7 @@ TEST(JsonNoiseModelTester, checkSimple) { ->getExecutionInfo( xacc::ExecutionInfo::DmKey); auto densityMatrix = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix)); // Verify the distribution (25% amplitude damping) EXPECT_NEAR(densityMatrix[0][0].real(), 0.25, 1e-6); EXPECT_NEAR(densityMatrix[1][1].real(), 0.75, 1e-6); @@ -169,6 +194,7 @@ TEST(JsonNoiseModelTester, checkBitOrdering) { ->getExecutionInfo( xacc::ExecutionInfo::DmKey); densityMatrix_msb = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix_msb)); std::cout << "Density matrix MSB\n"; for (const auto &row : densityMatrix_msb) { for (const auto &elem : row) { @@ -191,6 +217,7 @@ TEST(JsonNoiseModelTester, checkBitOrdering) { ->getExecutionInfo( xacc::ExecutionInfo::DmKey); densityMatrix_lsb = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix_lsb)); std::cout << "Density matrix LSB\n"; for (const auto &row : densityMatrix_lsb) { for (const auto &elem : row) { @@ -210,6 +237,38 @@ TEST(JsonNoiseModelTester, checkBitOrdering) { } } +TEST(JsonNoiseModelTester, checkMultiDepol) { + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testCX2(qbit q) { + CX(q[0], q[1]); + Measure(q[0]); + Measure(q[1]); + })", + nullptr) + ->getComposites()[0]; + + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", noise_model_multi_depol}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + + auto buffer = xacc::qalloc(2); + accelerator->execute(buffer, program); + auto dmPtr = + accelerator->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + auto densityMatrix = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix)); + std::cout << "Density matrix:\n"; + // for (const auto &row : densityMatrix) { + // for (const auto &elem : row) { + // std::cout << elem << " "; + // } + // std::cout << "\n"; + // } +} + int main(int argc, char **argv) { xacc::Initialize(argc, argv); ::testing::InitGoogleTest(&argc, argv); From 6b4cee6b343c3b2fd750c773f906e4f7210bacb0 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Fri, 22 Jan 2021 15:58:09 -0500 Subject: [PATCH 10/20] Adding a multi-qubit test for validation Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 12 +++--- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 40 +++++++++++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 0e146bb..0a9d238 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -461,12 +461,12 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { for (auto &channel : noiseChannels) { auto noiseMat = noiseUtils->krausToChoi(channel.mats); - for (const auto &row : noiseMat) { - for (const auto &el : row) { - std::cout << el << " "; - } - std::cout << "\n"; - } + // for (const auto &row : noiseMat) { + // for (const auto &el : row) { + // std::cout << el << " "; + // } + // std::cout << "\n"; + // } m_tensorIdCounter++; const std::string noiseTensorName = in_gateInstruction.name() + "_Noise_" + diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index aa51a25..9d623c6 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -25,6 +25,9 @@ const std::string ro_error_noise_model = // Multiple qubit depolarizing: const std::string noise_model_multi_depol = R"({"gate_noise": [{"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; +// Complex noise model: 4 qubits, X and H and CNOT +const std::string noise_model_4q = R"({"gate_noise": [{"gate_name": "H", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; + bool validateDensityMatrix( const std::vector>> &in_dm) { double sum_diag = 0.0; @@ -269,6 +272,43 @@ TEST(JsonNoiseModelTester, checkMultiDepol) { // } } +TEST(JsonNoiseModelTester, checkGHZ) { + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testGHZ(qbit q) { + H(q[0]); + CX(q[0], q[1]); + CX(q[1], q[2]); + CX(q[2], q[3]); + Measure(q[0]); + Measure(q[1]); + Measure(q[2]); + Measure(q[3]); + })", + nullptr) + ->getComposites()[0]; + + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", noise_model_4q}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + + auto buffer = xacc::qalloc(4); + accelerator->execute(buffer, program); + auto dmPtr = + accelerator->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + auto densityMatrix = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix)); + std::cout << "Density matrix:\n"; + for (const auto &row : densityMatrix) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; + } +} + int main(int argc, char **argv) { xacc::Initialize(argc, argv); ::testing::InitGoogleTest(&argc, argv); From aab4ac5ee524067eebbc153c120bbdc03b36ab7d Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Mon, 25 Jan 2021 09:48:01 -0500 Subject: [PATCH 11/20] Adding a test to check the output tensor leg ordering issue Legs of output tensor are re-shuffled after Kraus tensor connection. Affecting multi-qubit cases. Waiting for a new ExaTN API to handle this use case... Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 4 + .../exatn-dm/tests/JsonNoiseModelTester.cpp | 124 ++++++++++++++---- 2 files changed, 103 insertions(+), 25 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 0a9d238..a50d1e0 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -394,6 +394,10 @@ void ExaTnDmVisitor::applySingleQubitGate( // conjugate true); assert(conjAppended); + // DEBUG + std::cout << "Before noise:\n"; + m_tensorNetwork.printIt(); + // Adding noise tensors. applyNoise(in_gateInstruction); } diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index 9d623c6..9f439f0 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -25,6 +25,9 @@ const std::string ro_error_noise_model = // Multiple qubit depolarizing: const std::string noise_model_multi_depol = R"({"gate_noise": [{"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; +// Extremely-weak noise, just to check DM tensor network contraction. +const std::string noise_model_weak_noise = R"({"gate_noise": [{"gate_name": "H", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}], "bit_order": "MSB"})"; + // Complex noise model: 4 qubits, X and H and CNOT const std::string noise_model_4q = R"({"gate_noise": [{"gate_name": "H", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; @@ -272,43 +275,114 @@ TEST(JsonNoiseModelTester, checkMultiDepol) { // } } -TEST(JsonNoiseModelTester, checkGHZ) { +// Test the ordering of root tensor legs after contraction. +TEST(JsonNoiseModelTester, checkOutputLegOrder) { + std::vector>> densityMatrix_no_noise, densityMatrix_weak_noise; auto xasmCompiler = xacc::getCompiler("xasm"); auto program = xasmCompiler - ->compile(R"(__qpu__ void testGHZ(qbit q) { + ->compile(R"(__qpu__ void testLegOrdering(qbit q) { H(q[0]); - CX(q[0], q[1]); - CX(q[1], q[2]); - CX(q[2], q[3]); - Measure(q[0]); - Measure(q[1]); - Measure(q[2]); - Measure(q[3]); })", nullptr) ->getComposites()[0]; - auto noiseModel = xacc::getService("json"); - noiseModel->initialize({{"noise-model", noise_model_4q}}); - auto accelerator = xacc::getAccelerator( - "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + { + // No noise + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); - auto buffer = xacc::qalloc(4); - accelerator->execute(buffer, program); - auto dmPtr = - accelerator->getExecutionInfo( - xacc::ExecutionInfo::DmKey); - auto densityMatrix = *dmPtr; - EXPECT_TRUE(validateDensityMatrix(densityMatrix)); - std::cout << "Density matrix:\n"; - for (const auto &row : densityMatrix) { - for (const auto &elem : row) { - std::cout << elem << " "; + auto buffer = xacc::qalloc(4); + accelerator->execute(buffer, program); + auto dmPtr = + accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + densityMatrix_no_noise = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix_no_noise)); + std::cout << "Density matrix:\n"; + for (const auto &row : densityMatrix_no_noise) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; } - std::cout << "\n"; } + { + // Extremely weak noise: + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", noise_model_weak_noise}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + + auto buffer = xacc::qalloc(4); + accelerator->execute(buffer, program); + auto dmPtr = + accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + densityMatrix_weak_noise = *dmPtr; + // This is failing atm b/c of leg ordering issue. + // EXPECT_TRUE(validateDensityMatrix(densityMatrix_weak_noise)); + std::cout << "Density matrix:\n"; + for (const auto &row : densityMatrix_weak_noise) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; + } + } + + // 4 qubits + // TODO: enable this once ExaTN fix is added... + // const auto nbRows = 1ULL << 4; + // for (int row = 0; row < nbRows; ++row) { + // for (int col = 0; col < nbRows; ++col) { + // EXPECT_NEAR(densityMatrix_no_noise[row][col].real(), + // densityMatrix_weak_noise[row][col].real(), 1e-3); + // EXPECT_NEAR(densityMatrix_no_noise[row][col].imag(), + // densityMatrix_weak_noise[row][col].imag(), 1e-3); + // } + // } } +// This test doesn't work, pending ExaTN updates. +// TEST(JsonNoiseModelTester, checkGHZ) { +// auto xasmCompiler = xacc::getCompiler("xasm"); +// auto program = xasmCompiler +// ->compile(R"(__qpu__ void testGHZ(qbit q) { +// H(q[0]); +// CX(q[0], q[1]); +// CX(q[1], q[2]); +// CX(q[2], q[3]); +// Measure(q[0]); +// Measure(q[1]); +// Measure(q[2]); +// Measure(q[3]); +// })", +// nullptr) +// ->getComposites()[0]; + +// auto noiseModel = xacc::getService("json"); +// noiseModel->initialize({{"noise-model", noise_model_4q}}); +// auto accelerator = xacc::getAccelerator( +// "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + +// auto buffer = xacc::qalloc(4); +// accelerator->execute(buffer, program); +// auto dmPtr = +// accelerator->getExecutionInfo( +// xacc::ExecutionInfo::DmKey); +// auto densityMatrix = *dmPtr; +// EXPECT_TRUE(validateDensityMatrix(densityMatrix)); +// std::cout << "Density matrix:\n"; +// for (const auto &row : densityMatrix) { +// for (const auto &elem : row) { +// std::cout << elem << " "; +// } +// std::cout << "\n"; +// } +// } + int main(int argc, char **argv) { xacc::Initialize(argc, argv); ::testing::InitGoogleTest(&argc, argv); From c4e4be1163ced4e8aeb746af45c0e6455c6f3ada Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Mon, 25 Jan 2021 12:18:16 -0500 Subject: [PATCH 12/20] Adding exp-val calc by contracting the tracing tensor network Appending Z tensors at measure locations then closing the bra and ket legs to compute the trace. Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 100 +++++++++++++++++- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 24 +++++ 2 files changed, 120 insertions(+), 4 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index a50d1e0..c732532 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -24,7 +24,7 @@ std::vector> Q_ZERO_TENSOR_BODY(size_t in_volume) { const std::string ROOT_TENSOR_NAME = "Root"; void printDensityMatrix(const exatn::TensorNetwork &in_tensorNet, - size_t in_nbQubit) { + size_t in_nbQubit, bool in_checkTrace = true) { exatn::TensorNetwork tempNetwork(in_tensorNet); tempNetwork.rename("__TEMP__" + in_tensorNet.getName()); const bool evaledOk = exatn::evaluateSync(tempNetwork); @@ -55,9 +55,11 @@ void printDensityMatrix(const exatn::TensorNetwork &in_tensorNet, std::cout << elem << " "; } std::cout << "\n"; - // Verify trace(density matrix) == 1.0 - assert(std::abs(traceVal.real() - 1.0) < 1e-12); - assert(std::abs(traceVal.imag()) < 1e-12); + if (in_checkTrace) { + // Verify trace(density matrix) == 1.0 + assert(std::abs(traceVal.real() - 1.0) < 1e-12); + assert(std::abs(traceVal.imag()) < 1e-12); + } } } else { std::cout << "Failed to retrieve tensor data!!!\n"; @@ -334,6 +336,96 @@ void ExaTnDmVisitor::finalize() { executionInfo.insert(ExecutionInfo::DmKey, std::make_shared(std::move(densityMatrix))); } + // Expectation value calculation: + // Exp = Trace(rho * Op) + if (!m_measuredBits.empty()) { + auto tensorIdCounter = m_tensorIdCounter; + auto expValTensorNet = m_tensorNetwork; + const std::string measZTensorName = "MEAS_Z"; + { + xacc::quantum::Z zGate(0); + const auto gateMatrix = getGateMatrix(zGate); + assert(gateMatrix.size() == 4); + // Create the tensor + const bool created = exatn::createTensorSync( + measZTensorName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(measZTensorName, gateMatrix); + assert(initialized); + } + // Add Z tensors for measurement + for (const auto &measBit : m_measuredBits) { + tensorIdCounter++; + const std::vector gatePairing{ + static_cast(measBit)}; + // Append the tensor for this gate to the network + const bool appended = expValTensorNet.appendTensorGate( + tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(measZTensorName), + // which qubits that the gate is acting on + gatePairing); + assert(appended); + } + // DEBUG: + std::cout << "TENSOR NETWORK TO COMPUTE THE TRACE:\n"; + printDensityMatrix(expValTensorNet, m_buffer->size(), false); + // Compute the trace, closing the tensor network: + const std::string idTensor = "ID_TRACE"; + { + xacc::quantum::Identity idGate(0); + const auto idGateMatrix = getGateMatrix(idGate); + // Create the tensor + const bool created = + exatn::createTensorSync(idTensor, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(idTensor, idGateMatrix); + assert(initialized); + } + + for (size_t qId = 0; qId < m_buffer->size(); ++qId) { + tensorIdCounter++; + const std::vector> tracePairing{ + {static_cast(qId), 0}, + {static_cast(qId + m_buffer->size()), 1}}; + const bool appended = expValTensorNet.appendTensor( + tensorIdCounter, exatn::getTensor(idTensor), tracePairing); + assert(appended); + } + + // Evaluate the trace by contraction: + const bool evaledOk = exatn::evaluateSync(expValTensorNet); + assert(evaledOk); + auto talsh_tensor = + exatn::getLocalTensor(expValTensorNet.getTensor(0)->getName()); + if (talsh_tensor) { + const std::complex *body_ptr; + const bool access_granted = + talsh_tensor->getDataAccessHostConst(&body_ptr); + if (!access_granted) { + xacc::error("Failed to retrieve tensor data!"); + } else { + // Should only have 1 element: + assert(talsh_tensor->getVolume() == 1); + const std::complex traceVal = *body_ptr; + assert(traceVal.imag() < 1e-3); + const double expValZ = traceVal.real(); + std::cout << "Exp-val Z = " << expValZ << "\n"; + m_buffer->addExtraInfo("exp-val-z", expValZ); + } + } + bool destroyed = exatn::destroyTensor(measZTensorName); + assert(destroyed); + destroyed = exatn::destroyTensor(idTensor); + assert(destroyed); + } + std::unordered_set tensorList; for (auto iter = m_tensorNetwork.cbegin(); iter != m_tensorNetwork.cend(); ++iter) { diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index 9f439f0..e6c2df1 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -108,6 +108,30 @@ TEST(JsonNoiseModelTester, checkNoNoise) { EXPECT_EQ(dm->size(), 4); EXPECT_TRUE(validateDensityMatrix(*dm)); } + + { + // Check exp-val by trace (direct tensor network contraction) + auto accelerator = + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testRX(qbit q, double t) { + Rx(q[0], t); + Measure(q[0]); + })", + accelerator) + ->getComposite("testRX"); + const auto angles = xacc::linspace(-M_PI, M_PI, 20); + for (const auto& angle: angles) { + auto evaled = program->operator()({angle}); + const double expResult = -1.0 + 2.0*std::cos(angle/2.0)*std::cos(angle/2.0); + std::cout << "Angle = " << angle << ": " << expResult << "\n"; + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, evaled); + buffer->print(); + EXPECT_NEAR(buffer->getExpectationValueZ(), expResult, 1e-3); + } + } } TEST(JsonNoiseModelTester, checkSimple) { From e6186c1ccb8500d1447525eed641e127035217e0 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Mon, 25 Jan 2021 14:51:00 -0500 Subject: [PATCH 13/20] Added a test to debug negative density matrix diag elems Signed-off-by: Thien Nguyen --- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index e6c2df1..8b54c50 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -128,10 +128,71 @@ TEST(JsonNoiseModelTester, checkNoNoise) { std::cout << "Angle = " << angle << ": " << expResult << "\n"; auto buffer = xacc::qalloc(1); accelerator->execute(buffer, evaled); - buffer->print(); + // buffer->print(); EXPECT_NEAR(buffer->getExpectationValueZ(), expResult, 1e-3); } } + + { + // Check exp-val by trace (direct tensor network contraction) + auto accelerator = + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testRY(qbit q, double t) { + Ry(q[0], t); + Measure(q[0]); + })", + accelerator) + ->getComposite("testRY"); + const auto angles = xacc::linspace(-M_PI, M_PI, 20); + for (const auto& angle: angles) { + auto evaled = program->operator()({angle}); + const double expResult = -1.0 + 2.0*std::cos(angle/2.0)*std::cos(angle/2.0); + std::cout << "Angle = " << angle << ": " << expResult << "\n"; + auto buffer = xacc::qalloc(1); + accelerator->execute(buffer, evaled); + // buffer->print(); + EXPECT_NEAR(buffer->getExpectationValueZ(), expResult, 1e-3); + } + } + + // Two-qubit expectation calculation by tracing DM tensor network + { + auto accelerator = + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); + auto xasmCompiler = xacc::getCompiler("xasm"); + auto ir = xasmCompiler->compile(R"(__qpu__ void ansatz(qbit q, double t) { + X(q[0]); + Ry(q[1], t); + CX(q[1], q[0]); + H(q[0]); + H(q[1]); + Measure(q[0]); + Measure(q[1]); + })", + accelerator); + + auto program = ir->getComposite("ansatz"); + // Expected results from deuteron_2qbit_xasm_X0X1 + const std::vector expectedResults{ + 0.0, -0.324699, -0.614213, -0.837166, -0.9694, + -0.996584, -0.915773, -0.735724, -0.475947, -0.164595, + 0.164595, 0.475947, 0.735724, 0.915773, 0.996584, + 0.9694, 0.837166, 0.614213, 0.324699, 0.0}; + + const auto angles = + xacc::linspace(-xacc::constants::pi, xacc::constants::pi, 20); + for (size_t i = 0; i < angles.size(); ++i) { + auto buffer = xacc::qalloc(2); + auto evaled = program->operator()({angles[i]}); + accelerator->execute(buffer, evaled); + std::cout << "Angle = " << angles[i] + << ": Expected = " << expectedResults[i] + << "; ExaTN = " << buffer->getExpectationValueZ() << "\n"; + EXPECT_NEAR(buffer->getExpectationValueZ(), expectedResults[i], 1e-6); + } + } } TEST(JsonNoiseModelTester, checkSimple) { From 5c0d180a9805594c4c5b9f6a5a0a35c76726e1fa Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Mon, 25 Jan 2021 15:37:07 -0500 Subject: [PATCH 14/20] Fixes dagger side gate append Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 356 ++++++++++----------- 1 file changed, 164 insertions(+), 192 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index c732532..4029490 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -10,8 +10,6 @@ #include #endif -#define INITIAL_BOND_DIM 1 -#define INITIAL_KRAUS_DIM 1 #define QUBIT_DIM 2 namespace { @@ -79,8 +77,20 @@ std::vector> flattenGateMatrix( return resultVector; } +std::vector>> conjugateMatrix( + const std::vector>> &in_mat) { + auto result = in_mat; + const auto dim = in_mat.size(); + for (size_t rowId = 0; rowId < dim; ++rowId) { + for (size_t colId = 0; colId < dim; ++colId) { + result[colId][rowId] = std::conj(in_mat[colId][rowId]); + } + } + return result; +} + std::vector> -getGateMatrix(const xacc::Instruction &in_gate) { +getGateMatrix(const xacc::Instruction &in_gate, bool in_dagger = false) { using namespace tnqvm; const auto gateEnum = GetGateType(in_gate.name()); const auto getMatrix = [&]() { @@ -121,9 +131,11 @@ getGateMatrix(const xacc::Instruction &in_gate) { default: return GetGateMatrix(); } - }; + }; - return flattenGateMatrix(getMatrix()); + const auto gateMatrix = getMatrix(); + return in_dagger ? flattenGateMatrix(conjugateMatrix(gateMatrix)) + : flattenGateMatrix(gateMatrix); } } // namespace @@ -176,23 +188,8 @@ exatn::TensorNetwork ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits) const { for (int i = 0; i < in_nbQubits; ++i) { const std::string tensorName = "Q" + std::to_string(i); - auto tensor = [&]() { - if (in_nbQubits == 1) { - assert(tensorName == "Q0"); - return std::make_shared( - tensorName, exatn::TensorShape{QUBIT_DIM, INITIAL_BOND_DIM}); - } - if ((i == 0) || (i == (in_nbQubits - 1))) { - return std::make_shared( - tensorName, - exatn::TensorShape{QUBIT_DIM, INITIAL_BOND_DIM, INITIAL_KRAUS_DIM}); - } - - return std::make_shared( - tensorName, exatn::TensorShape{QUBIT_DIM, INITIAL_BOND_DIM, - INITIAL_KRAUS_DIM, INITIAL_BOND_DIM}); - }(); - + auto tensor = std::make_shared( + tensorName, exatn::TensorShape{QUBIT_DIM, QUBIT_DIM}); const bool created = exatn::createTensorSync(tensor, exatn::TensorElementType::COMPLEX64); assert(created); @@ -200,91 +197,16 @@ ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits) const { tensorName, Q_ZERO_TENSOR_BODY(tensor->getVolume())); assert(initialized); } - - const auto buildTensorMap = [](size_t in_nbQubits) { - const std::vector qubitTensorDim(in_nbQubits, QUBIT_DIM); - const std::vector ancTensorDim(in_nbQubits, INITIAL_KRAUS_DIM); - // Root tensor dimension: 2 .. 2 (upper legs/system dimensions) 1 ... 1 - // (lower legs/anc dimension) - std::vector rootTensorDim; - rootTensorDim.insert(rootTensorDim.end(), qubitTensorDim.begin(), - qubitTensorDim.end()); - rootTensorDim.insert(rootTensorDim.end(), ancTensorDim.begin(), - ancTensorDim.end()); - auto rootTensor = - std::make_shared(ROOT_TENSOR_NAME, rootTensorDim); - std::map> tensorMap; - tensorMap.emplace(ROOT_TENSOR_NAME, rootTensor); - for (int i = 0; i < in_nbQubits; ++i) { - const std::string qTensorName = "Q" + std::to_string(i); - tensorMap.emplace(qTensorName, exatn::getTensor(qTensorName)); - } - return tensorMap; - }; - - const std::string rootVarNameList = [](size_t in_nbQubits) { - std::string result = "("; - // Primary qubit legs - for (int i = 0; i < in_nbQubits; ++i) { - result += ("i" + std::to_string(i) + ","); - } - - // Anc legs: - for (int i = 0; i < in_nbQubits; ++i) { - result += ("k" + std::to_string(i) + ","); - } - assert(result.back() == ','); - result.back() = ')'; - return result; - }(in_nbQubits); - - const auto qubitTensorVarNameList = [](int in_qIdx, - int in_nbQubits) -> std::string { - if (in_nbQubits == 1) { - assert(in_qIdx == 0); - return "(i0,k0)"; - } - if (in_qIdx == 0) { - return "(i0,j0,k0)"; - } - if (in_qIdx == in_nbQubits - 1) { - return "(i" + std::to_string(in_nbQubits - 1) + ",j" + - std::to_string(in_nbQubits - 2) + ",k" + - std::to_string(in_nbQubits - 1) + ")"; - } - - return "(i" + std::to_string(in_qIdx) + ",j" + std::to_string(in_qIdx - 1) + - ",k" + std::to_string(in_qIdx) + ",j" + std::to_string(in_qIdx) + - ")"; - }; - - const std::string tensorNetworkString = [&]() { - std::string result = ROOT_TENSOR_NAME + rootVarNameList + "="; - for (int i = 0; i < in_nbQubits - 1; ++i) { - result += ("Q" + std::to_string(i) + - qubitTensorVarNameList(i, in_nbQubits) + "*"); - } - result += ("Q" + std::to_string(m_buffer->size() - 1) + - qubitTensorVarNameList(in_nbQubits - 1, in_nbQubits)); - return result; - }(); - - exatn::TensorNetwork qubitTensorNet("Tensor_Network", tensorNetworkString, - buildTensorMap(in_nbQubits)); - // qubitTensorNet.printIt(); - - // Conjugate of the network: - exatn::TensorNetwork conjugate(qubitTensorNet); - conjugate.rename("Conjugate"); - conjugate.conjugate(); - // conjugate.printIt(); - // Pair all ancilla legs - std::vector> pairings; - for (size_t i = 0; i < in_nbQubits; ++i) { - pairings.emplace_back(std::make_pair(i + in_nbQubits, i + in_nbQubits)); + exatn::TensorNetwork qubitTensorNet("Tensor_Network"); + // Append the qubit tensors to the tensor network + size_t tensorIdCounter = 0; + for (int i = 0; i < in_nbQubits; ++i) { + tensorIdCounter++; + const std::string tensorName = "Q" + std::to_string(i); + qubitTensorNet.appendTensor( + tensorIdCounter, exatn::getTensor(tensorName), + std::vector>{}); } - - qubitTensorNet.appendTensorNetwork(std::move(conjugate), pairings); std::cout << "Qubit Tensor network:\n"; qubitTensorNet.printIt(); return qubitTensorNet; @@ -392,8 +314,8 @@ void ExaTnDmVisitor::finalize() { for (size_t qId = 0; qId < m_buffer->size(); ++qId) { tensorIdCounter++; const std::vector> tracePairing{ - {static_cast(qId), 0}, - {static_cast(qId + m_buffer->size()), 1}}; + {static_cast(0), 0}, + {static_cast(m_buffer->size() - qId), 1}}; const bool appended = expValTensorNet.appendTensor( tensorIdCounter, exatn::getTensor(idTensor), tracePairing); assert(appended); @@ -447,45 +369,70 @@ void ExaTnDmVisitor::finalize() { void ExaTnDmVisitor::applySingleQubitGate( xacc::quantum::Gate &in_gateInstruction) { - m_tensorIdCounter++; - assert(in_gateInstruction.bits().size() == 1); - const auto gateMatrix = getGateMatrix(in_gateInstruction); - assert(gateMatrix.size() == 4); - const std::string uniqueGateName = - in_gateInstruction.name() + std::to_string(m_tensorIdCounter); - // Create the tensor - const bool created = exatn::createTensorSync( - uniqueGateName, exatn::TensorElementType::COMPLEX64, - exatn::TensorShape{2, 2}); - assert(created); - // Init tensor body data - const bool initialized = - exatn::initTensorDataSync(uniqueGateName, gateMatrix); - assert(initialized); - - const std::vector gatePairing{ - static_cast(in_gateInstruction.bits()[0])}; - // Append the tensor for this gate to the network - const bool appended = m_tensorNetwork.appendTensorGate( - m_tensorIdCounter, - // Get the gate tensor data which must have been initialized. - exatn::getTensor(uniqueGateName), - // which qubits that the gate is acting on - gatePairing); - assert(appended); - - m_tensorIdCounter++; - const std::vector gatePairingConj{static_cast( - m_buffer->size() + in_gateInstruction.bits()[0])}; - const bool conjAppended = m_tensorNetwork.appendTensorGate( - m_tensorIdCounter, - // Get the gate tensor data which must have been initialized. - exatn::getTensor(uniqueGateName), - // which qubits that the gate is acting on - gatePairingConj, - // conjugate - true); - assert(conjAppended); + { + m_tensorIdCounter++; + assert(in_gateInstruction.bits().size() == 1); + const auto gateMatrix = getGateMatrix(in_gateInstruction); + // std::cout << "Gate mattrix:\n"; + // for (const auto &el : gateMatrix) { + // std::cout << el << "\n"; + // } + assert(gateMatrix.size() == 4); + const std::string uniqueGateName = + in_gateInstruction.name() + std::to_string(m_tensorIdCounter); + // Create the tensor + const bool created = exatn::createTensorSync( + uniqueGateName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(uniqueGateName, gateMatrix); + assert(initialized); + + const std::vector gatePairing{ + static_cast(in_gateInstruction.bits()[0])}; + // Append the tensor for this gate to the network + const bool appended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairing); + assert(appended); + } + + { + // Append the dagger gate + m_tensorIdCounter++; + const auto gateMatrix = getGateMatrix(in_gateInstruction, true); + // std::cout << "Gate mattrix dagger:\n"; + // for (const auto &el : gateMatrix) { + // std::cout << el << "\n"; + // } + assert(gateMatrix.size() == 4); + const std::string uniqueGateName = + in_gateInstruction.name() + "_CONJ_" + std::to_string(m_tensorIdCounter); + // Create the tensor + const bool created = exatn::createTensorSync( + uniqueGateName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(uniqueGateName, gateMatrix); + assert(initialized); + const std::vector gatePairingConj{static_cast( + m_buffer->size() + in_gateInstruction.bits()[0])}; + const bool conjAppended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairingConj); + assert(conjAppended); + } + // DEBUG std::cout << "Before noise:\n"; m_tensorNetwork.printIt(); @@ -496,49 +443,64 @@ void ExaTnDmVisitor::applySingleQubitGate( void ExaTnDmVisitor::applyTwoQubitGate( xacc::quantum::Gate &in_gateInstruction) { - m_tensorIdCounter++; - assert(in_gateInstruction.bits().size() == 2); - const auto gateMatrix = getGateMatrix(in_gateInstruction); - assert(gateMatrix.size() == 16); - const std::string uniqueGateName = - in_gateInstruction.name() + std::to_string(m_tensorIdCounter); - // Create the tensor - const bool created = exatn::createTensorSync( - uniqueGateName, exatn::TensorElementType::COMPLEX64, - exatn::TensorShape{2, 2, 2, 2}); - assert(created); - // Init tensor body data - const bool initialized = - exatn::initTensorDataSync(uniqueGateName, gateMatrix); - assert(initialized); - - const std::vector gatePairing{ - static_cast(in_gateInstruction.bits()[1]), - static_cast(in_gateInstruction.bits()[0])}; - // Append the tensor for this gate to the network - const bool appended = m_tensorNetwork.appendTensorGate( - m_tensorIdCounter, - // Get the gate tensor data which must have been initialized. - exatn::getTensor(uniqueGateName), - // which qubits that the gate is acting on - gatePairing); - assert(appended); - - m_tensorIdCounter++; - const std::vector gatePairingConj{ - static_cast(m_buffer->size() + - in_gateInstruction.bits()[1]), - static_cast(m_buffer->size() + - in_gateInstruction.bits()[0])}; - const bool conjAppended = m_tensorNetwork.appendTensorGate( - m_tensorIdCounter, - // Get the gate tensor data which must have been initialized. - exatn::getTensor(uniqueGateName), - // which qubits that the gate is acting on - gatePairingConj, - // conjugate - true); - assert(conjAppended); + { + m_tensorIdCounter++; + assert(in_gateInstruction.bits().size() == 2); + const auto gateMatrix = getGateMatrix(in_gateInstruction); + assert(gateMatrix.size() == 16); + const std::string uniqueGateName = + in_gateInstruction.name() + std::to_string(m_tensorIdCounter); + // Create the tensor + const bool created = exatn::createTensorSync( + uniqueGateName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2, 2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(uniqueGateName, gateMatrix); + assert(initialized); + + const std::vector gatePairing{ + static_cast(in_gateInstruction.bits()[1]), + static_cast(in_gateInstruction.bits()[0])}; + // Append the tensor for this gate to the network + const bool appended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairing); + assert(appended); + } + { + m_tensorIdCounter++; + const auto gateMatrix = getGateMatrix(in_gateInstruction, true); + assert(gateMatrix.size() == 16); + const std::string uniqueGateName = + in_gateInstruction.name() + "_CONJ_" + std::to_string(m_tensorIdCounter); + // Create the tensor + const bool created = exatn::createTensorSync( + uniqueGateName, exatn::TensorElementType::COMPLEX64, + exatn::TensorShape{2, 2, 2, 2}); + assert(created); + // Init tensor body data + const bool initialized = + exatn::initTensorDataSync(uniqueGateName, gateMatrix); + assert(initialized); + const std::vector gatePairingConj{ + static_cast(m_buffer->size() + + in_gateInstruction.bits()[1]), + static_cast(m_buffer->size() + + in_gateInstruction.bits()[0])}; + const bool conjAppended = m_tensorNetwork.appendTensorGate( + m_tensorIdCounter, + // Get the gate tensor data which must have been initialized. + exatn::getTensor(uniqueGateName), + // which qubits that the gate is acting on + gatePairingConj); + assert(conjAppended); + } + // Adding noise tensors. applyNoise(in_gateInstruction); } @@ -662,9 +624,19 @@ void ExaTnDmVisitor::visit(Y &in_YGate) { applySingleQubitGate(in_YGate); } void ExaTnDmVisitor::visit(Z &in_ZGate) { applySingleQubitGate(in_ZGate); } -void ExaTnDmVisitor::visit(Rx &in_RxGate) { applySingleQubitGate(in_RxGate); } +void ExaTnDmVisitor::visit(Rx &in_RxGate) { + applySingleQubitGate(in_RxGate); + std::cout << "Apply: " << in_RxGate.toString() << "\n"; + m_tensorNetwork.printIt(); + printDensityMatrix(m_tensorNetwork, m_buffer->size()); +} -void ExaTnDmVisitor::visit(Ry &in_RyGate) { applySingleQubitGate(in_RyGate); } +void ExaTnDmVisitor::visit(Ry &in_RyGate) { + applySingleQubitGate(in_RyGate); + std::cout << "Apply: " << in_RyGate.toString() << "\n"; + m_tensorNetwork.printIt(); + printDensityMatrix(m_tensorNetwork, m_buffer->size()); +} void ExaTnDmVisitor::visit(Rz &in_RzGate) { applySingleQubitGate(in_RzGate); } From 110e391c772dae698a37b97f245bd674ff1fd655 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Mon, 25 Jan 2021 15:57:08 -0500 Subject: [PATCH 15/20] Using newly-added ExaTN appendTensorGateGeneral API to add Kraus tensor Fixing the output leg ordering issue. Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 64 ++++++++++--------- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 22 +++---- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 4029490..5835b2c 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -540,13 +540,15 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { noiseTensorName, flattenGateMatrix(noiseMat)); assert(initialized); - const std::vector> noisePairing{ - {static_cast(channel.noise_qubits[0]), 1}, - {static_cast(channel.noise_qubits[0] + - m_buffer->size()), - 3}}; + const std::vector< + std::pair>> + noisePairing{ + {static_cast(channel.noise_qubits[0]), {1, 0}}, + {static_cast(channel.noise_qubits[0] + + m_buffer->size()), + {3, 2}}}; // Append the tensor for this gate to the network - const bool appended = m_tensorNetwork.appendTensor( + const bool appended = m_tensorNetwork.appendTensorGateGeneral( m_tensorIdCounter, exatn::getTensor(noiseTensorName), // which qubits that the gate is acting on noisePairing); @@ -562,30 +564,34 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { noiseTensorName, flattenGateMatrix(noiseMat)); assert(initialized); - const std::vector> noisePairingMsb{ - {static_cast(channel.noise_qubits[0]), 0}, - {static_cast(channel.noise_qubits[0] + - m_buffer->size()), - 1}, - {static_cast(channel.noise_qubits[1]), 4}, - {static_cast(channel.noise_qubits[1] + - m_buffer->size()), - 5}}; - - const std::vector> noisePairingLsb{ - {static_cast(channel.noise_qubits[1]), 0}, - {static_cast(channel.noise_qubits[1] + - m_buffer->size()), - 3}, - {static_cast(channel.noise_qubits[0]), 4}, - {static_cast(channel.noise_qubits[0] + - m_buffer->size()), - 7}}; - const std::vector> noisePairing = - (channel.bit_order == KrausMatBitOrder::MSB) ? noisePairingMsb - : noisePairingLsb; + const std::vector< + std::pair>> + noisePairingMsb{ + {static_cast(channel.noise_qubits[0]), {0, 2}}, + {static_cast(channel.noise_qubits[0] + + m_buffer->size()), + {1, 6}}, + {static_cast(channel.noise_qubits[1]), {4, 3}}, + {static_cast(channel.noise_qubits[1] + + m_buffer->size()), + {5, 7}}}; + + const std::vector< + std::pair>> + noisePairingLsb{ + {static_cast(channel.noise_qubits[1]), {0, 2}}, + {static_cast(channel.noise_qubits[1] + + m_buffer->size()), + {1, 6}}, + {static_cast(channel.noise_qubits[0]), {4, 3}}, + {static_cast(channel.noise_qubits[0] + + m_buffer->size()), + {5, 7}}}; + const auto noisePairing = (channel.bit_order == KrausMatBitOrder::MSB) + ? noisePairingMsb + : noisePairingLsb; // Append the tensor for this gate to the network - const bool appended = m_tensorNetwork.appendTensor( + const bool appended = m_tensorNetwork.appendTensorGateGeneral( m_tensorIdCounter, exatn::getTensor(noiseTensorName), // which qubits that the gate is acting on noisePairing); diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index 8b54c50..8292482 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -406,8 +406,7 @@ TEST(JsonNoiseModelTester, checkOutputLegOrder) { ->getExecutionInfo( xacc::ExecutionInfo::DmKey); densityMatrix_weak_noise = *dmPtr; - // This is failing atm b/c of leg ordering issue. - // EXPECT_TRUE(validateDensityMatrix(densityMatrix_weak_noise)); + EXPECT_TRUE(validateDensityMatrix(densityMatrix_weak_noise)); std::cout << "Density matrix:\n"; for (const auto &row : densityMatrix_weak_noise) { for (const auto &elem : row) { @@ -418,16 +417,15 @@ TEST(JsonNoiseModelTester, checkOutputLegOrder) { } // 4 qubits - // TODO: enable this once ExaTN fix is added... - // const auto nbRows = 1ULL << 4; - // for (int row = 0; row < nbRows; ++row) { - // for (int col = 0; col < nbRows; ++col) { - // EXPECT_NEAR(densityMatrix_no_noise[row][col].real(), - // densityMatrix_weak_noise[row][col].real(), 1e-3); - // EXPECT_NEAR(densityMatrix_no_noise[row][col].imag(), - // densityMatrix_weak_noise[row][col].imag(), 1e-3); - // } - // } + const auto nbRows = 1ULL << 4; + for (int row = 0; row < nbRows; ++row) { + for (int col = 0; col < nbRows; ++col) { + EXPECT_NEAR(densityMatrix_no_noise[row][col].real(), + densityMatrix_weak_noise[row][col].real(), 1e-3); + EXPECT_NEAR(densityMatrix_no_noise[row][col].imag(), + densityMatrix_weak_noise[row][col].imag(), 1e-3); + } + } } // This test doesn't work, pending ExaTN updates. From 553904f1efe6fa84abb51728b0a9a2d36e2e63d3 Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 28 Jan 2021 10:40:00 -0500 Subject: [PATCH 16/20] Formalize a set of helpers to support debugging Kraus tensor leg ordering Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 81 ++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 5835b2c..c1fa714 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -9,6 +9,7 @@ #ifdef TNQVM_EXATN_USES_MKL_BLAS #include #endif +#include #define QUBIT_DIM 2 @@ -137,6 +138,86 @@ getGateMatrix(const xacc::Instruction &in_gate, bool in_dagger = false) { return in_dagger ? flattenGateMatrix(conjugateMatrix(gateMatrix)) : flattenGateMatrix(gateMatrix); } + +void recursiveFindAllCombinations(std::vector>& io_result, +const std::vector &arr, + std::vector &data, int start, int end, int index, + int r) { + // Current combination is ready + if (index == r) { + std::vector combination; + for (int j = 0; j < r; j++) { + combination.emplace_back(data[j]); + } + io_result.emplace_back(combination); + return; + } + for (int i = start; i <= end && end - i + 1 >= r - index; i++) { + data[index] = arr[i]; + recursiveFindAllCombinations(io_result, arr, data, i + 1, end, index + 1, r); + } +} + +std::vector> +findAllPermutations(const std::vector &in_elements) { + auto a = in_elements; + std::sort(a.begin(), a.end()); + std::vector> result; + do { + result.emplace_back(a); + + } while (std::next_permutation(a.begin(), a.end())); + return result; +} + +std::vector +filterList(const std::vector &in_totalList, + const std::vector &in_filter) { + std::vector result; + for (const auto &el : in_totalList) { + if (!xacc::container::contains(in_filter, el)) { + result.emplace_back(el); + } + } + return result; +} + +// Helper to find all input->output leg connection permutation. +// This is *only* used for development purposes to figure out the +// correct connection configs to preseve the order of the root density matrix +// tensor. +std::vector>> +findAllGateTensorPairings(int in_tensorRank) { + assert(in_tensorRank % 2 == 0); + std::vector legIds; + std::vector tempVec(in_tensorRank / 2); + for (unsigned int i = 0; i < in_tensorRank; ++i) { + legIds.emplace_back(i); + } + // Find all possible input leg combination: + std::vector> inputCombinations; + recursiveFindAllCombinations(inputCombinations, legIds, tempVec, 0, + in_tensorRank - 1, 0, in_tensorRank / 2); + + std::vector>> result; + for (const auto &inputLegs : inputCombinations) { + const auto inputLegPerm = findAllPermutations(inputLegs); + const auto outputLegPerm = + findAllPermutations(filterList(legIds, inputLegs)); + for (const auto &inputPerm : inputLegPerm) { + for (const auto &outputPerm : outputLegPerm) { + assert(inputPerm.size() == outputPerm.size()); + std::vector> combo; + for (size_t i = 0; i < inputPerm.size(); ++i) { + combo.emplace_back(std::make_pair(inputPerm[i], outputPerm[i])); + } + result.emplace_back(combo); + } + } + } + + return result; +} } // namespace namespace tnqvm { From 830ecd5ff54bf39cac800ad0d14eb8d972f8bfdd Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 28 Jan 2021 11:35:20 -0500 Subject: [PATCH 17/20] Support visitor selection via the "backend" key (i.e. support the tnqvm:visitor format) Signed-off-by: Thien Nguyen --- tnqvm/TNQVM.hpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tnqvm/TNQVM.hpp b/tnqvm/TNQVM.hpp index d63aa24..18b962d 100644 --- a/tnqvm/TNQVM.hpp +++ b/tnqvm/TNQVM.hpp @@ -65,9 +65,16 @@ class TNQVM : public Accelerator { vqeMode = config.get("vqe-mode"); } - if (config.stringExists("tnqvm-visitor")) { - const auto requestedBackend = config.getString("tnqvm-visitor"); - const auto& allVisitorServices = xacc::getServices(); + if (config.stringExists("tnqvm-visitor") || + config.stringExists("backend")) { + // Get the specific TNQVM visitor, either using the `tnqvm-visitor` key + // or the `backend` key. + // e.g., when users use the convention "tnqvm::exatn", "exatn" will be + // parsed and passed in the "backend" field. + const auto requestedBackend = config.stringExists("tnqvm-visitor") + ? config.getString("tnqvm-visitor") + : config.getString("backend"); + const auto &allVisitorServices = xacc::getServices(); // We must have at least one TNQVM service registered. assert(!allVisitorServices.empty()); bool foundRequestedBackend = false; From 08c57d30e33edc4b11fc23511efa9d211fa20faf Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 28 Jan 2021 14:16:33 -0500 Subject: [PATCH 18/20] Added the helper to iteratively search the tensor connection pattern and update the one found Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 91 ++++++++++++++++++++-- 1 file changed, 83 insertions(+), 8 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index c1fa714..02ef80c 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -65,6 +65,44 @@ void printDensityMatrix(const exatn::TensorNetwork &in_tensorNet, } } +bool checkDmTensorNetwork(const exatn::TensorNetwork &in_tensorNet, + size_t in_nbQubit) { + exatn::TensorNetwork tempNetwork(in_tensorNet); + tempNetwork.rename("__TEMP__" + in_tensorNet.getName()); + const bool evaledOk = exatn::evaluateSync(tempNetwork); + assert(evaledOk); + auto talsh_tensor = + exatn::getLocalTensor(tempNetwork.getTensor(0)->getName()); + const auto expectedDensityMatrixVolume = + (1ULL << in_nbQubit) * (1ULL << in_nbQubit); + const auto nbRows = 1ULL << in_nbQubit; + if (talsh_tensor) { + const std::complex *body_ptr; + const bool access_granted = talsh_tensor->getDataAccessHostConst(&body_ptr); + if (!access_granted) { + std::cout << "Failed to retrieve tensor data!!!\n"; + } else { + assert(expectedDensityMatrixVolume == talsh_tensor->getVolume()); + std::complex traceVal{0.0, 0.0}; + int rowId = -1; + for (int i = 0; i < talsh_tensor->getVolume(); ++i) { + if (i % nbRows == 0) { + rowId++; + } + if (i == (rowId + rowId * nbRows)) { + traceVal += body_ptr[i]; + } + const auto &elem = body_ptr[i]; + } + return (std::abs(traceVal.real() - 1.0) < 1e-12) && + (std::abs(traceVal.imag()) < 1e-12); + } + } else { + std::cout << "Failed to retrieve tensor data!!!\n"; + } + return false; +} + std::vector> flattenGateMatrix( const std::vector>> &in_gateMatrix) { std::vector> resultVector; @@ -218,6 +256,38 @@ findAllGateTensorPairings(int in_tensorRank) { return result; } + +void checkKrausTensorConfig(const exatn::TensorNetwork &in_tensorNet, + unsigned int in_q0, unsigned int in_q1, + unsigned int in_numQubits, + const std::string &in_krausTensorName) { + auto noiseTensor = exatn::getTensor(in_krausTensorName); + std::cout << "Checking Kraus tensor connections:\n"; + auto test = findAllGateTensorPairings(noiseTensor->getDimExtents().size()); + for (const auto &config : test) { + const std::vector< + std::pair>> + noisePairing{{in_q0, config[0]}, + {in_q0 + in_numQubits, config[1]}, + {in_q1, config[2]}, + {in_q1 + in_numQubits, config[3]}}; + + // Append the tensor for this gate to the network + auto temp = in_tensorNet; + const auto tensorIdCounter = temp.getMaxTensorId() + 1; + const bool appended = temp.appendTensorGateGeneral( + tensorIdCounter, noiseTensor, noisePairing); + assert(appended); + if (checkDmTensorNetwork(temp, in_numQubits)) { + std::cout << "============================== \n Valid: "; + for (const auto &[iLeg, oLeg] : config) { + std::cout << "(" << iLeg << "-->" << oLeg << ")"; + } + printDensityMatrix(temp, in_numQubits); + std::cout << "==============================\n"; + } + } +} } // namespace namespace tnqvm { @@ -645,29 +715,34 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { noiseTensorName, flattenGateMatrix(noiseMat)); assert(initialized); + // DEBUG: Using this to check all possible permutations. + // checkKrausTensorConfig(m_tensorNetwork, channel.noise_qubits[0], + // channel.noise_qubits[1], m_buffer->size(), + // noiseTensorName); + const std::vector< std::pair>> noisePairingMsb{ - {static_cast(channel.noise_qubits[0]), {0, 2}}, + {static_cast(channel.noise_qubits[0]), {5, 6}}, {static_cast(channel.noise_qubits[0] + m_buffer->size()), - {1, 6}}, - {static_cast(channel.noise_qubits[1]), {4, 3}}, + {1, 2}}, + {static_cast(channel.noise_qubits[1]), {4, 7}}, {static_cast(channel.noise_qubits[1] + m_buffer->size()), - {5, 7}}}; + {0, 3}}}; const std::vector< std::pair>> noisePairingLsb{ - {static_cast(channel.noise_qubits[1]), {0, 2}}, + {static_cast(channel.noise_qubits[1]), {5, 6}}, {static_cast(channel.noise_qubits[1] + m_buffer->size()), - {1, 6}}, - {static_cast(channel.noise_qubits[0]), {4, 3}}, + {1, 2}}, + {static_cast(channel.noise_qubits[0]), {4, 7}}, {static_cast(channel.noise_qubits[0] + m_buffer->size()), - {5, 7}}}; + {0, 3}}}; const auto noisePairing = (channel.bit_order == KrausMatBitOrder::MSB) ? noisePairingMsb : noisePairingLsb; From be4806e85e697c43fd95e4a0744a60f99d48634f Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 28 Jan 2021 14:30:22 -0500 Subject: [PATCH 19/20] All tests are passing now added an integration test with VQE. Signed-off-by: Thien Nguyen --- .../exatn-dm/tests/JsonNoiseModelTester.cpp | 164 ++++++++++++------ 1 file changed, 112 insertions(+), 52 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp index 8292482..812e7e5 100644 --- a/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp +++ b/tnqvm/visitors/exatn-dm/tests/JsonNoiseModelTester.cpp @@ -2,6 +2,9 @@ #include "xacc.hpp" #include "xacc_service.hpp" #include "NoiseModel.hpp" +#include "Optimizer.hpp" +#include "xacc_observable.hpp" +#include "Algorithm.hpp" namespace { // A sample Json for testing @@ -23,13 +26,16 @@ const std::string ro_error_noise_model = R"({"gate_noise": [], "bit_order": "MSB", "readout_errors": [{"register_location": "0", "prob_meas0_prep1": 0.2, "prob_meas1_prep0": 0.1}]})"; // Multiple qubit depolarizing: -const std::string noise_model_multi_depol = R"({"gate_noise": [{"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; +const std::string noise_model_multi_depol = + R"({"gate_noise": [{"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; // Extremely-weak noise, just to check DM tensor network contraction. -const std::string noise_model_weak_noise = R"({"gate_noise": [{"gate_name": "H", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}], "bit_order": "MSB"})"; +const std::string noise_model_weak_noise = + R"({"gate_noise": [{"gate_name": "H", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.9999999999995, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.9999999999995, 0.0]]], [[[0.0, 0.0], [5.773502691896258e-07, 0.0]], [[5.773502691896258e-07, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -5.773502691896258e-07]], [[0.0, 5.773502691896258e-07], [0.0, 0.0]]], [[[5.773502691896258e-07, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-5.773502691896258e-07, 0.0]]]]}]}], "bit_order": "MSB"})"; // Complex noise model: 4 qubits, X and H and CNOT -const std::string noise_model_4q = R"({"gate_noise": [{"gate_name": "H", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; +const std::string noise_model_4q = + R"({"gate_noise": [{"gate_name": "H", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "H", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "X", "register_location": ["3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.05773502691896258, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, -0.05773502691896258]], [[0.0, 0.05773502691896258], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["0", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["1", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["2", "3"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "0"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "1"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}, {"gate_name": "CNOT", "register_location": ["3", "2"], "noise_channels": [{"matrix": [[[[0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.99498743710662, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]], [[[0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [-0.05773502691896258, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.05773502691896258, 0.0]]]]}]}], "bit_order": "MSB"})"; bool validateDensityMatrix( const std::vector>> &in_dm) { @@ -122,9 +128,10 @@ TEST(JsonNoiseModelTester, checkNoNoise) { accelerator) ->getComposite("testRX"); const auto angles = xacc::linspace(-M_PI, M_PI, 20); - for (const auto& angle: angles) { + for (const auto &angle : angles) { auto evaled = program->operator()({angle}); - const double expResult = -1.0 + 2.0*std::cos(angle/2.0)*std::cos(angle/2.0); + const double expResult = + -1.0 + 2.0 * std::cos(angle / 2.0) * std::cos(angle / 2.0); std::cout << "Angle = " << angle << ": " << expResult << "\n"; auto buffer = xacc::qalloc(1); accelerator->execute(buffer, evaled); @@ -146,9 +153,10 @@ TEST(JsonNoiseModelTester, checkNoNoise) { accelerator) ->getComposite("testRY"); const auto angles = xacc::linspace(-M_PI, M_PI, 20); - for (const auto& angle: angles) { + for (const auto &angle : angles) { auto evaled = program->operator()({angle}); - const double expResult = -1.0 + 2.0*std::cos(angle/2.0)*std::cos(angle/2.0); + const double expResult = + -1.0 + 2.0 * std::cos(angle / 2.0) * std::cos(angle / 2.0); std::cout << "Angle = " << angle << ": " << expResult << "\n"; auto buffer = xacc::qalloc(1); accelerator->execute(buffer, evaled); @@ -221,7 +229,8 @@ TEST(JsonNoiseModelTester, checkSimple) { EXPECT_TRUE(validateDensityMatrix(densityMatrix)); EXPECT_EQ(densityMatrix.size(), 2); // Check trace - EXPECT_NEAR(densityMatrix[0][0].real() + densityMatrix[1][1].real(), 1.0, 1e-6); + EXPECT_NEAR(densityMatrix[0][0].real() + densityMatrix[1][1].real(), 1.0, + 1e-6); // Expected result: // 0.00666667+0.j 0. +0.j // 0. +0.j 0.99333333+0.j @@ -248,9 +257,10 @@ TEST(JsonNoiseModelTester, checkSimple) { ->getComposites()[0]; auto buffer = xacc::qalloc(1); accelerator->execute(buffer, program); - auto dmPtr = accelerator - ->getExecutionInfo( - xacc::ExecutionInfo::DmKey); + auto dmPtr = + accelerator + ->getExecutionInfo( + xacc::ExecutionInfo::DmKey); auto densityMatrix = *dmPtr; EXPECT_TRUE(validateDensityMatrix(densityMatrix)); // Verify the distribution (25% amplitude damping) @@ -270,7 +280,8 @@ TEST(JsonNoiseModelTester, checkBitOrdering) { nullptr) ->getComposites()[0]; - std::vector>> densityMatrix_msb, densityMatrix_lsb; + std::vector>> densityMatrix_msb, + densityMatrix_lsb; // Check MSB: { auto noiseModel = xacc::getService("json"); @@ -362,7 +373,8 @@ TEST(JsonNoiseModelTester, checkMultiDepol) { // Test the ordering of root tensor legs after contraction. TEST(JsonNoiseModelTester, checkOutputLegOrder) { - std::vector>> densityMatrix_no_noise, densityMatrix_weak_noise; + std::vector>> densityMatrix_no_noise, + densityMatrix_weak_noise; auto xasmCompiler = xacc::getCompiler("xasm"); auto program = xasmCompiler ->compile(R"(__qpu__ void testLegOrdering(qbit q) { @@ -373,8 +385,8 @@ TEST(JsonNoiseModelTester, checkOutputLegOrder) { { // No noise - auto accelerator = xacc::getAccelerator( - "tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); + auto accelerator = + xacc::getAccelerator("tnqvm", {{"tnqvm-visitor", "exatn-dm"}}); auto buffer = xacc::qalloc(4); accelerator->execute(buffer, program); @@ -428,43 +440,91 @@ TEST(JsonNoiseModelTester, checkOutputLegOrder) { } } -// This test doesn't work, pending ExaTN updates. -// TEST(JsonNoiseModelTester, checkGHZ) { -// auto xasmCompiler = xacc::getCompiler("xasm"); -// auto program = xasmCompiler -// ->compile(R"(__qpu__ void testGHZ(qbit q) { -// H(q[0]); -// CX(q[0], q[1]); -// CX(q[1], q[2]); -// CX(q[2], q[3]); -// Measure(q[0]); -// Measure(q[1]); -// Measure(q[2]); -// Measure(q[3]); -// })", -// nullptr) -// ->getComposites()[0]; - -// auto noiseModel = xacc::getService("json"); -// noiseModel->initialize({{"noise-model", noise_model_4q}}); -// auto accelerator = xacc::getAccelerator( -// "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); - -// auto buffer = xacc::qalloc(4); -// accelerator->execute(buffer, program); -// auto dmPtr = -// accelerator->getExecutionInfo( -// xacc::ExecutionInfo::DmKey); -// auto densityMatrix = *dmPtr; -// EXPECT_TRUE(validateDensityMatrix(densityMatrix)); -// std::cout << "Density matrix:\n"; -// for (const auto &row : densityMatrix) { -// for (const auto &elem : row) { -// std::cout << elem << " "; -// } -// std::cout << "\n"; -// } -// } +TEST(JsonNoiseModelTester, checkGHZ) { + auto xasmCompiler = xacc::getCompiler("xasm"); + auto program = xasmCompiler + ->compile(R"(__qpu__ void testGHZ(qbit q) { + H(q[0]); + CX(q[0], q[1]); + CX(q[1], q[2]); + CX(q[2], q[3]); + Measure(q[0]); + Measure(q[1]); + Measure(q[2]); + Measure(q[3]); + })", + nullptr) + ->getComposites()[0]; + + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", noise_model_4q}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + + auto buffer = xacc::qalloc(4); + accelerator->execute(buffer, program); + auto dmPtr = + accelerator->getExecutionInfo( + xacc::ExecutionInfo::DmKey); + auto densityMatrix = *dmPtr; + EXPECT_TRUE(validateDensityMatrix(densityMatrix)); + std::cout << "Density matrix:\n"; + for (const auto &row : densityMatrix) { + for (const auto &elem : row) { + std::cout << elem << " "; + } + std::cout << "\n"; + } + + // Expect the first and last element of the matrix are near 0.5 (GHZ state) + const auto dmDimension = 1ULL << buffer->size(); + EXPECT_NEAR(densityMatrix[0][0].real(), 0.5, 0.1); + EXPECT_NEAR(densityMatrix[dmDimension - 1][dmDimension - 1].real(), 0.5, 0.1); + EXPECT_NEAR(densityMatrix[0][0].imag(), 0.0, 1e-6); + EXPECT_NEAR(densityMatrix[dmDimension - 1][dmDimension - 1].imag(), 0.0, + 1e-6); +} + +// Test VQE with noise +TEST(JsonNoiseModelTester, testDeuteronVqeH2) { + auto noiseModel = xacc::getService("json"); + noiseModel->initialize({{"noise-model", noise_model_4q}}); + auto accelerator = xacc::getAccelerator( + "tnqvm", {{"tnqvm-visitor", "exatn-dm"}, {"noise-model", noiseModel}}); + + // Create the N=2 deuteron Hamiltonian + auto H_N_2 = xacc::quantum::getObservable( + "pauli", std::string("5.907 - 2.1433 X0X1 " + "- 2.1433 Y0Y1" + "+ .21829 Z0 - 6.125 Z1")); + + auto optimizer = xacc::getOptimizer("nlopt"); + xacc::qasm(R"( + .compiler xasm + .circuit deuteron_ansatz1 + .parameters theta + .qbit q + X(q[0]); + Ry(q[1], theta); + CNOT(q[1],q[0]); + )"); + auto ansatz = xacc::getCompiled("deuteron_ansatz1"); + + // Get the VQE Algorithm and initialize it + auto vqe = xacc::getAlgorithm("vqe"); + vqe->initialize({std::make_pair("ansatz", ansatz), + std::make_pair("observable", H_N_2), + std::make_pair("accelerator", accelerator), + std::make_pair("optimizer", optimizer)}); + + // Allocate some qubits and execute + auto buffer = xacc::qalloc(2); + vqe->execute(buffer); + std::cout << "Energy = " << (*buffer)["opt-val"].as() << "\n"; + // Expected result: -1.74886 + // Relax the limit due to noise. + EXPECT_NEAR((*buffer)["opt-val"].as(), -1.74886, 0.5); +} int main(int argc, char **argv) { xacc::Initialize(argc, argv); From bbe41a78c09ee2ea39c721c8963bb77411d635dc Mon Sep 17 00:00:00 2001 From: Thien Nguyen Date: Thu, 28 Jan 2021 14:39:08 -0500 Subject: [PATCH 20/20] Comment out a bunch of debug print out Signed-off-by: Thien Nguyen --- tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp | 52 +++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp index 02ef80c..60ce905 100644 --- a/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp +++ b/tnqvm/visitors/exatn-dm/ExaTnDmVisitor.cpp @@ -358,8 +358,8 @@ ExaTnDmVisitor::buildInitialNetwork(size_t in_nbQubits) const { tensorIdCounter, exatn::getTensor(tensorName), std::vector>{}); } - std::cout << "Qubit Tensor network:\n"; - qubitTensorNet.printIt(); + // std::cout << "Qubit Tensor network:\n"; + // qubitTensorNet.printIt(); return qubitTensorNet; } @@ -444,8 +444,8 @@ void ExaTnDmVisitor::finalize() { assert(appended); } // DEBUG: - std::cout << "TENSOR NETWORK TO COMPUTE THE TRACE:\n"; - printDensityMatrix(expValTensorNet, m_buffer->size(), false); + // std::cout << "TENSOR NETWORK TO COMPUTE THE TRACE:\n"; + // printDensityMatrix(expValTensorNet, m_buffer->size(), false); // Compute the trace, closing the tensor network: const std::string idTensor = "ID_TRACE"; { @@ -489,7 +489,7 @@ void ExaTnDmVisitor::finalize() { const std::complex traceVal = *body_ptr; assert(traceVal.imag() < 1e-3); const double expValZ = traceVal.real(); - std::cout << "Exp-val Z = " << expValZ << "\n"; + // std::cout << "Exp-val Z = " << expValZ << "\n"; m_buffer->addExtraInfo("exp-val-z", expValZ); } } @@ -585,8 +585,8 @@ void ExaTnDmVisitor::applySingleQubitGate( } // DEBUG - std::cout << "Before noise:\n"; - m_tensorNetwork.printIt(); + // std::cout << "Before noise:\n"; + // m_tensorNetwork.printIt(); // Adding noise tensors. applyNoise(in_gateInstruction); @@ -660,8 +660,8 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { if (!m_noiseConfig) { return; } - std::cout << "Before noise:\n"; - printDensityMatrix(m_tensorNetwork, m_buffer->size()); + // std::cout << "Before noise:\n"; + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); const auto noiseChannels = m_noiseConfig->getNoiseChannels(in_gateInstruction); @@ -758,9 +758,9 @@ void ExaTnDmVisitor::applyNoise(xacc::quantum::Gate &in_gateInstruction) { } // DEBUG: - std::cout << "Apply Noise: " << in_gateInstruction.toString() << "\n"; - m_tensorNetwork.printIt(); - printDensityMatrix(m_tensorNetwork, m_buffer->size()); + // std::cout << "Apply Noise: " << in_gateInstruction.toString() << "\n"; + // m_tensorNetwork.printIt(); + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Identity &in_IdentityGate) { @@ -777,9 +777,9 @@ void ExaTnDmVisitor::visit(Hadamard &in_HadamardGate) { void ExaTnDmVisitor::visit(X &in_XGate) { applySingleQubitGate(in_XGate); // DEBUG: - std::cout << "Apply: " << in_XGate.toString() << "\n"; - m_tensorNetwork.printIt(); - printDensityMatrix(m_tensorNetwork, m_buffer->size()); + // std::cout << "Apply: " << in_XGate.toString() << "\n"; + // m_tensorNetwork.printIt(); + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Y &in_YGate) { applySingleQubitGate(in_YGate); } @@ -788,16 +788,16 @@ void ExaTnDmVisitor::visit(Z &in_ZGate) { applySingleQubitGate(in_ZGate); } void ExaTnDmVisitor::visit(Rx &in_RxGate) { applySingleQubitGate(in_RxGate); - std::cout << "Apply: " << in_RxGate.toString() << "\n"; - m_tensorNetwork.printIt(); - printDensityMatrix(m_tensorNetwork, m_buffer->size()); + // std::cout << "Apply: " << in_RxGate.toString() << "\n"; + // m_tensorNetwork.printIt(); + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Ry &in_RyGate) { applySingleQubitGate(in_RyGate); - std::cout << "Apply: " << in_RyGate.toString() << "\n"; - m_tensorNetwork.printIt(); - printDensityMatrix(m_tensorNetwork, m_buffer->size()); + // std::cout << "Apply: " << in_RyGate.toString() << "\n"; + // m_tensorNetwork.printIt(); + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Rz &in_RzGate) { applySingleQubitGate(in_RzGate); } @@ -805,9 +805,9 @@ void ExaTnDmVisitor::visit(Rz &in_RzGate) { applySingleQubitGate(in_RzGate); } void ExaTnDmVisitor::visit(T &in_TGate) { applySingleQubitGate(in_TGate); // DEBUG: - std::cout << "Apply: " << in_TGate.toString() << "\n"; - m_tensorNetwork.printIt(); - printDensityMatrix(m_tensorNetwork, m_buffer->size()); + // std::cout << "Apply: " << in_TGate.toString() << "\n"; + // m_tensorNetwork.printIt(); + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Tdg &in_TdgGate) { @@ -826,8 +826,8 @@ void ExaTnDmVisitor::visit(CNOT &in_CNOTGate) { applyTwoQubitGate(in_CNOTGate); // DEBUG: // std::cout << "Apply: " << in_CNOTGate.toString() << "\n"; - m_tensorNetwork.printIt(); - printDensityMatrix(m_tensorNetwork, m_buffer->size()); + // m_tensorNetwork.printIt(); + // printDensityMatrix(m_tensorNetwork, m_buffer->size()); } void ExaTnDmVisitor::visit(Swap &in_SwapGate) {