diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..a1970e28 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "extern/mqt-core"] + path = extern/mqt-core + url = git@github.com:cda-tum/mqt-core.git diff --git a/cmake/ExternalDependencies.cmake b/cmake/ExternalDependencies.cmake index 2c1bcf34..33fcde48 100644 --- a/cmake/ExternalDependencies.cmake +++ b/cmake/ExternalDependencies.cmake @@ -65,6 +65,30 @@ if(BUILD_MQT_QCEC_TESTS) endif() endif() +set(TF_BUILD_TESTS + OFF + CACHE INTERNAL "") +set(TF_BUILD_EXAMPLES + OFF + CACHE INTERNAL "") +set(TF_BUILD_PROFILER + OFF + CACHE INTERNAL "") +set(TF_VERSION + 3.6.0 + CACHE STRING "Taskflow version") +set(TF_URL https://github.com/taskflow/taskflow/archive/refs/tags/v${TF_VERSION}.tar.gz) +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + FetchContent_Declare(taskflow URL ${TF_URL} FIND_PACKAGE_ARGS) + list(APPEND FETCH_PACKAGES taskflow) +else() + find_package(taskflow ${TF_VERSION} QUIET) + if(NOT taskflow_FOUND) + FetchContent_Declare(taskflow URL ${TF_URL}) + list(APPEND FETCH_PACKAGES taskflow) + endif() +endif() + if(BUILD_MQT_QCEC_BINDINGS) # add pybind11_json library if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) diff --git a/docs/source/ApproximateEquivalence.ipynb b/docs/source/ApproximateEquivalence.ipynb new file mode 100644 index 00000000..d83d90db --- /dev/null +++ b/docs/source/ApproximateEquivalence.ipynb @@ -0,0 +1,248 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "77a131e6", + "metadata": {}, + "source": [ + "# Approximate Equivalence Checking\n", + "\n", + "## Approximate Equivalence vs. Exact Equivalence\n", + "\n", + "Two circuits are considered exactly equivalent if their matrix representations, `U` and `V`, are identical. Thus, the problem of exact equivalence checking reduces to verifying whether $UV^\\dagger = I$, where `I` is the identity matrix.\n", + "\n", + "In practice, however, it is often sufficient to determine whether two circuits are equivalent up to a certain percentage, while permitting an error tolerance. For instance, when optimizing circuits, we may not require exact equivalence, but rather a circuit that is sufficiently close to the original, while being optimal with respect to a specific metric, such as minimizing gate counts.\n", + "\n", + "Here, approximate equivalence is quantified by the process distance between two circuits based on the Hilbert-Schmidt inner product, with n being the number of qubits: $$\\Delta(U, V) = 1 - |\\frac{Tr(U V^\\dagger)}{2^n}|$$ Specifically, we compute the magnitude of the normalized trace of $UV^\\dagger$ and assess its proximity to 1. Two circuits are considered approximately equivalent if their process distance is below a specified error threshold, $\\epsilon$.\n", + "\n", + "\n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "id": "b9be796e", + "metadata": {}, + "source": [ + "\n", + "## Checking Approximate Equivalence of Quantum Circuits\n", + "\n", + "To enable approximate equivalence checking, set the `check_approximate_equivalence` option to `True` in the configuration parameters. When activated, the equivalence checker will return `equivalent` if the process distance is below a specified threshold. Otherwise, it will return `not-equivalent`. The error threshold is controlled via the `approximate_checking_threshold` parameter, with a default value of `1e-8`. Moreover, it is recommended to disable the simulation checker by setting `run_simulation_checker` to `False`.\n", + "\n", + "The following is a summary of the behaviour of each type of equivalence checker when the `checkApproximateEquivalence` option is set to `True`.\n", + "\n", + "1. **Construction Equivalence Checker:** The construction checker supports approximate equivalence checking by using decision diagrams to compute $UV^\\dagger$. It then calculates the normalized trace and compares the process distance to the defined error threshold. \n", + "\n", + "1. **Alternating Equivalence Checker:** The alternating checker likewise computes the composition of one circuit with the inverse of the other. Again, when checking for approximate equivalence, it suffices to verify that the normalized trace is sufficiently close to 1. \n", + "\n", + "1. **Simulation Equivalence Checker:** Approximate equivalence checking is not directly supported by the Simulation checker. Although numerical instabilities can be mitigated through the configuration parameter `simulation.fidelityThreshold`, this parameter does not serve as an approximate equivalence threshold. For instance, consider $UV^\\dagger$ representing a 10-qubit multi-controlled X-gate with the first 9 qubits as control and the last qubit as the target. In this setup, the process distance would meet an error threshold of $1e^-2$. However, since the Simulation checker evaluates both circuits using random input states, the fidelity drops to zero whenever one of the two computational basis states, $|1111111110\\rangle$ or $|1111111111\\rangle$, is selected. In such cases, regardless of any threshold setting, the checker reports non-equivalence.\n", + "\n", + "1. **ZX-Calculus Equivalence Checker:** Approximate equivalence checking is not yet supported in the ZX-calculus checker, which is not a problem for the equivalence checking workflow, given that the ZX-calculus checker cannot demonstrate non-equivalence of circuits due to its incompleteness. \n", + "Therefore, it will simply output 'No Information' for circuits that are approximately but not totally equivalent.\n", + "\n", + "1. **Hybrid Schrödinger-Feynman (HSF) Equivalence Checker:** By default, the HSF checker is disabled. To enable it, both the `run_hsf_checker` flag and the `check_approximate_equivalence` option must be set to true. The HSF checker computes the process distance by dividing the circuit corresponding to $UV^\\dagger$ horizontally into two independent halves: a lower part and an upper part. This is achieved by decomposing controlled gates, acting across both halves, according to the Schmidt decomposition.\n", + "By leveraging key trace equalities - specifically,\n", + "\n", + " • $tr[L⊗U]=tr[L]⋅tr[U]$\n", + "\n", + " • $tr[P_1+P_2]=tr[P_1]+tr[P_2]$\n", + "\n", + " we can treat the lower and upper circuit parts, as well as the summands from the Schmidt decomposition, independently. This enables parallel trace computation, allowing to check the equivalence of larger, yet shallow circuits.\n", + " \n", + " Note: The following configurations are not currently supported, as they require the explicit computation of the Schmidt decomposition for the gates being cut (decisions):\n", + "\n", + " • Multiple targets spread across the cut through the circuit\n", + " • Multiple controls in the control part of the gate being cut \n", + " \n", + " Moreover, despite parallelization, the method is best suited for shallow circuits, as the number of paths to be computed grows exponentially with the number of decisions. " + ] + }, + { + "cell_type": "markdown", + "id": "977071d9", + "metadata": {}, + "source": [ + "## Using QCEC to Check for Approximate Equivalence\n", + "\n", + "Consider the following three-qubit circuit representing the Toffoli gate." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03b73b17", + "metadata": {}, + "outputs": [], + "source": [ + "from qiskit import QuantumCircuit\n", + "\n", + "qc_lhs = QuantumCircuit(3)\n", + "qc_lhs.mcx([0, 1], 2)\n", + "qc_lhs.measure_all()\n", + "qc_lhs.draw(output=\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "markdown", + "id": "10fff8c7-f36c-422e-8deb-796cc7637e45", + "metadata": {}, + "source": [ + "Additionally, consider the following simple circuit, which represents the Identity." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d167869e-e082-4a42-9eab-112931f5c697", + "metadata": {}, + "outputs": [], + "source": [ + "qc_rhs = QuantumCircuit(3)\n", + "qc_rhs.id(0)\n", + "qc_rhs.id(1)\n", + "qc_rhs.id(2)\n", + "qc_rhs.measure_all()\n", + "qc_rhs.draw(output=\"mpl\", style=\"iqp\")" + ] + }, + { + "cell_type": "markdown", + "id": "3b85338e", + "metadata": {}, + "source": [ + "We now aim to compute the process distance between these circuits. Since the second circuit represents the Identity, it follows that $UV^\\dagger$ simplifies to the Toffoli gate matrix. \n", + "\n", + "$$\n", + "\\text{Toffoli} = \\begin{bmatrix}\n", + "1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 1 & 0 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\\\\n", + "0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\\\\n", + "\\end{bmatrix}\n", + "$$\n", + "\n", + "The normalized trace of this matrix is `0.75`. \n", + "\n", + "Consequently, the process distance $\\Delta(U, V) = 1 - |\\frac{Tr(U V^\\dagger)}{2^n}|$ is equal to `0.25`.\n", + "\n", + "If we set the equivalence tolerance to `0.3`, the checker should output `equivalent`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36df44b7", + "metadata": {}, + "outputs": [], + "source": [ + "from mqt.qcec import Configuration, verify\n", + "\n", + "config = Configuration()\n", + "config.execution.run_simulation_checker = False\n", + "config.functionality.check_approximate_equivalence = True\n", + "config.functionality.approximate_checking_threshold = 0.3\n", + "verify(qc_lhs, qc_rhs, configuration=config)" + ] + }, + { + "cell_type": "markdown", + "id": "f2c4104d", + "metadata": {}, + "source": [ + "However, with an error tolerance below `0.25`, the checker should return `not_equivalent`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "da9fa188", + "metadata": {}, + "outputs": [], + "source": [ + "config = Configuration()\n", + "config.execution.run_simulation_checker = False\n", + "config.functionality.check_approximate_equivalence = True\n", + "config.functionality.approximate_checking_threshold = 0.2\n", + "verify(qc_lhs, qc_rhs, configuration=config)" + ] + }, + { + "cell_type": "markdown", + "id": "5d7f9c62", + "metadata": {}, + "source": [ + "To use the HSF checker, it must be explicitly enabled in the configuration. Below, we will use the HSF checker exclusively and disable the other checkers." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "494ef477", + "metadata": {}, + "outputs": [], + "source": [ + "config.execution.run_simulation_checker = False\n", + "config.execution.run_alternating_checker = False\n", + "config.execution.run_construction_checker = False\n", + "config.execution.run_zx_checker = False\n", + "config.execution.run_hsf_checker = True\n", + "config.functionality.check_approximate_equivalence = False\n", + "config.functionality.approximate_checking_threshold = 0.3\n", + "verify(qc_lhs, qc_rhs, configuration=config)" + ] + }, + { + "cell_type": "markdown", + "id": "b327ab4b", + "metadata": {}, + "source": [ + "However, we also need to explicitly enable the `check_approximate_equivalence` option." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "679291b7", + "metadata": {}, + "outputs": [], + "source": [ + "config.functionality.check_approximate_equivalence = True\n", + "config.functionality.approximate_checking_threshold = 0.3\n", + "verify(qc_lhs, qc_rhs, configuration=config)" + ] + }, + { + "cell_type": "markdown", + "id": "6af54b68", + "metadata": {}, + "source": [ + "Source: The concept of approximate equivalence used here is inspired by [Approximate Equivalence Checking of Noisy Quantum Circuits](https://arxiv.org/abs/2103.11595) by Xin Hong, Mingsheng Ying, Yuan Feng, Xiangzhen Zhou, Sanjiang Li, and [QUEST: systematically approximating Quantum circuits for higher output fidelity](https://dl.acm.org/doi/10.1145/3503222.3507739) by Tirthak Patel, Ed Younis, Costin Iancu, Wibe de Jong, and Devesh Tiwari." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/source/index.rst b/docs/source/index.rst index 5c09ecff..79bf4439 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -27,6 +27,7 @@ We appreciate any feedback and contributions to the project. If you want to cont CompilationFlowVerification ParameterizedCircuits PartialEquivalence + ApproximateEquivalence Publications .. toctree:: diff --git a/include/Configuration.hpp b/include/Configuration.hpp index 87ce7118..ff7156fb 100644 --- a/include/Configuration.hpp +++ b/include/Configuration.hpp @@ -33,6 +33,7 @@ class Configuration { bool runSimulationChecker = true; bool runAlternatingChecker = true; bool runZXChecker = true; + bool runHSFChecker = false; }; // configuration options for pre-check optimizations @@ -62,7 +63,9 @@ class Configuration { struct Functionality { double traceThreshold = 1e-8; + double approximateCheckingThreshold = 1e-8; bool checkPartialEquivalence = false; + bool checkApproximateEquivalence = false; }; // configuration options for the simulation scheme diff --git a/include/EquivalenceCheckingManager.hpp b/include/EquivalenceCheckingManager.hpp index 2ce213df..ca7bcad9 100644 --- a/include/EquivalenceCheckingManager.hpp +++ b/include/EquivalenceCheckingManager.hpp @@ -139,12 +139,14 @@ class EquivalenceCheckingManager { configuration.execution.runAlternatingChecker = run; } void setZXChecker(bool run) { configuration.execution.runZXChecker = run; } + void setHSFChecker(bool run) { configuration.execution.runHSFChecker = run; } void disableAllCheckers() { configuration.execution.runConstructionChecker = false; configuration.execution.runZXChecker = false; configuration.execution.runSimulationChecker = false; configuration.execution.runAlternatingChecker = false; + configuration.execution.runHSFChecker = false; } // Optimization: Optimizations are applied during initialization. Already @@ -219,10 +221,16 @@ class EquivalenceCheckingManager { void setTraceThreshold(double traceThreshold) { configuration.functionality.traceThreshold = traceThreshold; } + void setApproximateCheckingThreshold(double approximateCheckingThreshold) { + configuration.functionality.approximateCheckingThreshold = + approximateCheckingThreshold; + } void setCheckPartialEquivalence(bool checkPE) { configuration.functionality.checkPartialEquivalence = checkPE; } - + void setCheckApproximateEquivalence(bool checkAE) { + configuration.functionality.checkApproximateEquivalence = checkAE; + } // Simulation: These setting may be changed to adjust the kinds of simulations // that are performed void setFidelityThreshold(double fidelityThreshold) { diff --git a/include/checker/EquivalenceChecker.hpp b/include/checker/EquivalenceChecker.hpp index c164edb1..199e189f 100644 --- a/include/checker/EquivalenceChecker.hpp +++ b/include/checker/EquivalenceChecker.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,13 @@ class EquivalenceChecker { nqubits(std::max(qc1->getNqubits(), qc2->getNqubits())), configuration(std::move(config)) {}; + EquivalenceChecker(const qc::QuantumComputation& circ1, + std::unique_ptr circ2, + ec::Configuration config) noexcept + : qc1(&circ1), qc2(circ2.release()), + nqubits(std::max(qc1->getNqubits(), qc2->getNqubits())), + configuration(std::move(config)) {}; + virtual ~EquivalenceChecker() = default; virtual EquivalenceCriterion run() = 0; diff --git a/include/checker/dd/DDHybridSchrodingerFeynmanChecker.hpp b/include/checker/dd/DDHybridSchrodingerFeynmanChecker.hpp new file mode 100644 index 00000000..dca1c303 --- /dev/null +++ b/include/checker/dd/DDHybridSchrodingerFeynmanChecker.hpp @@ -0,0 +1,213 @@ +#pragma once + +#include "Configuration.hpp" +#include "Definitions.hpp" +#include "EquivalenceCriterion.hpp" +#include "checker/EquivalenceChecker.hpp" +#include "dd/ComplexValue.hpp" +#include "dd/DDpackageConfig.hpp" +#include "dd/Package.hpp" +#include "dd/Package_fwd.hpp" +#include "ir/QuantumComputation.hpp" +#include "memory" +#include "nlohmann/json_fwd.hpp" + +#include +#include +#include +#include +#include + +namespace ec { +/** + * @brief Approximate Equivalence Checking with the + * DDHybridSchrodingerFeynmanChecker This checker divides a circuit horizontally + * into two halves: a lower part and an upper part. This is achieved by + * decomposing controlled gates, acting across both halves, according to the + * Schmidt decomposition. By leveraging key trace equalities - specifically, + * + * tr[L ⊗ U] = tr[L] ⋅ tr[U] + * + * and + * + * tr[A + B] = tr[A] + tr[B], + * + * we can treat the lower and upper circuit parts, as well as the summands from + * the Schmidt decomposition, independently. This enables parallel trace + * computation, allowing to check the equivalence of larger, yet shallow + * circuits. + * @note Only suitable for shallow circuits with a maximum number of 63 + * controlled gates acting on both circuit parts (decisions). + */ +class DDHybridSchrodingerFeynmanChecker final : public EquivalenceChecker { +public: + DDHybridSchrodingerFeynmanChecker(const qc::QuantumComputation& circ1, + const qc::QuantumComputation& circ2, + ec::Configuration config) + : EquivalenceChecker(circ1, invertCircuit(circ2), std::move(config)) { + if (qc1->getNqubits() != qc2->getNqubits()) { + throw std::invalid_argument( + "The two circuits have a different number of qubits and cannot be " + "checked for equivalence."); + } + splitQubit = static_cast(qc1->getNqubits() / 2); + } + + EquivalenceCriterion run() override; + + void json(nlohmann::json& j) const noexcept override; + + /** + * @brief Get # of decisions for given split_qubit, so that lower slice: q0 < + * i < qubit; upper slice: qubit <= i < nqubits + * @details The number of decisions is determined by the number of controlled + * gates that operate across both halves. + * @param qc + * @return std::size_t + */ + [[nodiscard]] static std::size_t + getNDecisions(const qc::QuantumComputation& qc); + + /** + * @brief Check whether the HSF checker can handle the given circuits. + * + * The function returns `false` if any of the following conditions are met: + * - The circuits contain multi-qubit gates that are not supported by the HSF + * checker. + * - The total number of decisions exceeds the maximum allowable limit of 63. + * + * @param qc1 + * @param qc2 + * @return `true` if both circuits can be handled by the HSF checker, + * otherwise `false`. + */ + static bool canHandle(const qc::QuantumComputation& qc1, + const qc::QuantumComputation& qc2); + + /** + * @brief Creates a unique pointer to a copy of the given quantum circuit and + * returns an inverted version of it + * @param circ + * @return std::unique_ptr + */ + static std::unique_ptr + invertCircuit(const qc::QuantumComputation& circ) { + auto qcInverted = std::make_unique(circ); + qcInverted->invert(); + return qcInverted; + } + +private: + qc::Qubit splitQubit; + + using DDPackage = typename dd::Package; + + /** + * @brief Computing the Frobenius inner product trace(U * V^-1) and comparing + * it to the desired threshold. + * @return EquivalenceCriterion Returns `Equivalent` if the result is below + * the `traceThreshold`, `NotEquivalent´ otherwise. + */ + EquivalenceCriterion checkEquivalence(); + + /** + * @brief Computes the trace for the i-th summand after applying the Schmidt + * decomposition for all control decisions. + * + * @details The Schmidt decomposition allows decomposing a controlled gate + * into a sum of circuits, each consisting of only single-qubit gates. By + * recursively applying this decomposition to all decisions, we generate a + * total of 2^decisions circuits, which do not contain controlled operations + * acting on both halves. This enables independent investigation of the + * lower and upper circuit parts. + * + * This function computes the trace for the i-th summand, where the index 'i' + * determines, for each gate, whether the 0 or 1 projection is considered. See + * getNextControl() and apply() for more details on how these projections are + * managed. + * + * @param sliceDD1 Decision diagram for the lower circuit part. + * @param sliceDD2 Decision diagram for the upper circuit part. + * @param i Index of the summand for which the trace is computed. + * @return dd::ComplexValue Returns the trace value for the specified summand. + */ + dd::ComplexValue simulateSlicing(std::unique_ptr& sliceDD1, + std::unique_ptr& sliceDD2, + std::size_t i); + + class Slice; + + /** + * @brief Applies a single operation to the lower and upper circuit parts + * according to the Schmidt decomposition, for the summand specified by + * `controlIdx` from the class Slice. + * + * @param sliceDD1 Decision diagram for the lower circuit part. + * @param sliceDD2 Decision diagram for the upper circuit part. + * @param op Current operation to be applied + * @param lower + * @param upper + */ + static void applyLowerUpper(std::unique_ptr& sliceDD1, + std::unique_ptr& sliceDD2, + const std::unique_ptr& op, + Slice& lower, Slice& upper) { + if (op->isUnitary()) { + [[maybe_unused]] auto l = lower.apply(sliceDD1, op); + [[maybe_unused]] auto u = upper.apply(sliceDD2, op); + assert(l == u); + } + sliceDD1->garbageCollect(); + sliceDD2->garbageCollect(); + } + + class Slice { + protected: + std::uint64_t nextControlIdx = 0; + + /** + * @brief Determines how the current operation is decomposed for the summand + * at index `controlIdx`. + * @details nextControlIdx tracks the number of operations processed so far. + * By comparing the shifted value to the bits of `controlIdx`, we can + * determine how the current operation should be decomposed for the summand + * at index `controlIdx`. + * @return std::size_t + */ + std::size_t getNextControl() { + const std::size_t idx = 1UL << nextControlIdx; + nextControlIdx++; + return controlIdx & idx; + } + + public: + qc::Qubit start; + qc::Qubit end; + std::size_t controlIdx; + qc::Qubit nqubits; + std::size_t nDecisionsExecuted = 0; + qc::MatrixDD matrix{}; + + explicit Slice(std::unique_ptr& dd, const qc::Qubit startQ, + const qc::Qubit endQ, const std::size_t controlQ) + : start(startQ), end(endQ), controlIdx(controlQ), + nqubits(end - start + 1), matrix(dd->makeIdent()) { + dd->incRef(matrix); + } + + /** + * @brief Applies the decomposition of the current operation, based on the + * summand index `controlIdx`, to the decision diagram of the specified + * circuit slice. + * + * @param sliceDD Decision diagram for the lower or upper circuit part. + * @param op + * @return bool Returns true if the operation is a split operation, false + * otherwise. + */ + bool apply(std::unique_ptr& sliceDD, + const std::unique_ptr& op); + }; +}; + +} // namespace ec diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97560ca1..a69ae0aa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,9 +14,13 @@ if(NOT TARGET MQT::QCEC) # link to the MQT::Core libraries target_link_libraries( ${PROJECT_NAME} - PUBLIC MQT::CoreDD MQT::CoreZX + PUBLIC MQT::CoreDD MQT::CoreZX Taskflow PRIVATE MQT::CoreCircuitOptimizer MQT::CoreAlgorithms MQT::ProjectWarnings MQT::ProjectOptions) + set_target_properties( + Taskflow PROPERTIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES + $) + # add MQT alias add_library(MQT::QCEC ALIAS ${PROJECT_NAME}) endif() diff --git a/src/Configuration.cpp b/src/Configuration.cpp index 3a1d6dae..34ab432e 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -15,25 +15,28 @@ namespace ec { bool Configuration::anythingToExecute() const noexcept { return (execution.runSimulationChecker && simulation.maxSims > 0U) || execution.runAlternatingChecker || execution.runConstructionChecker || - execution.runZXChecker; + execution.runZXChecker || + (execution.runHSFChecker && functionality.checkApproximateEquivalence); } bool Configuration::onlySingleTask() const noexcept { // only a single simulation shall be performed if (execution.runSimulationChecker && (simulation.maxSims == 1U) && !execution.runAlternatingChecker && !execution.runConstructionChecker && - !execution.runZXChecker) { + !execution.runZXChecker && !execution.runHSFChecker) { return true; } // no simulations and only one of the other checks shall be performed if (!execution.runSimulationChecker && ((execution.runAlternatingChecker && !execution.runConstructionChecker && - !execution.runZXChecker) || + !execution.runZXChecker && !execution.runHSFChecker) || (!execution.runAlternatingChecker && execution.runConstructionChecker && - !execution.runZXChecker) || + !execution.runZXChecker && !execution.runHSFChecker) || (!execution.runAlternatingChecker && !execution.runConstructionChecker && - execution.runZXChecker))) { + execution.runZXChecker && !execution.runHSFChecker) || + (!execution.runAlternatingChecker && !execution.runConstructionChecker && + !execution.runZXChecker && execution.runHSFChecker))) { return true; } @@ -42,12 +45,14 @@ bool Configuration::onlySingleTask() const noexcept { bool Configuration::onlyZXCheckerConfigured() const noexcept { return !execution.runConstructionChecker && !execution.runSimulationChecker && - !execution.runAlternatingChecker && execution.runZXChecker; + !execution.runAlternatingChecker && execution.runZXChecker && + !execution.runHSFChecker; } bool Configuration::onlySimulationCheckerConfigured() const noexcept { return !execution.runConstructionChecker && execution.runSimulationChecker && - !execution.runAlternatingChecker && !execution.runZXChecker; + !execution.runAlternatingChecker && !execution.runZXChecker && + !execution.runHSFChecker; } nlohmann::basic_json<> Configuration::json() const { @@ -64,6 +69,7 @@ nlohmann::basic_json<> Configuration::json() const { exe["run_simulation_checker"] = execution.runSimulationChecker; exe["run_alternating_checker"] = execution.runAlternatingChecker; exe["run_zx_checker"] = execution.runZXChecker; + exe["run_hsf_checker"] = execution.runHSFChecker; if (execution.timeout > 0.) { exe["timeout"] = execution.timeout; } @@ -106,7 +112,11 @@ nlohmann::basic_json<> Configuration::json() const { if (execution.runConstructionChecker || execution.runAlternatingChecker) { auto& fun = config["functionality"]; fun["trace_threshold"] = functionality.traceThreshold; + fun["approximate_checking_threshold"] = + functionality.approximateCheckingThreshold; fun["check_partial_equivalence"] = functionality.checkPartialEquivalence; + fun["check_approximate_equivalence"] = + functionality.checkApproximateEquivalence; } if (execution.runSimulationChecker) { diff --git a/src/EquivalenceCheckingManager.cpp b/src/EquivalenceCheckingManager.cpp index dd4614c7..8badcb1f 100644 --- a/src/EquivalenceCheckingManager.cpp +++ b/src/EquivalenceCheckingManager.cpp @@ -10,6 +10,7 @@ #include "ThreadSafeQueue.hpp" #include "checker/dd/DDAlternatingChecker.hpp" #include "checker/dd/DDConstructionChecker.hpp" +#include "checker/dd/DDHybridSchrodingerFeynmanChecker.hpp" #include "checker/dd/DDSimulationChecker.hpp" #include "checker/dd/simulation/StateType.hpp" #include "checker/zx/ZXChecker.hpp" @@ -362,11 +363,21 @@ EquivalenceCheckingManager::EquivalenceCheckingManager( // set numeric tolerance used throughout the check setTolerance(configuration.execution.numericalTolerance); - if (qc1.isVariableFree() && qc2.isVariableFree()) { + if (qc1.isVariableFree() && qc2.isVariableFree() && + !configuration.execution.runHSFChecker) { // run all configured optimization passes runOptimizationPasses(); } + // If the HSF checker is enabled, flatten the operations in the circuits and + // remove the final measurements + if (configuration.execution.runHSFChecker) { + qc::CircuitOptimizer::flattenOperations(qc1); + qc::CircuitOptimizer::flattenOperations(qc2); + qc::CircuitOptimizer::removeFinalMeasurements(qc1); + qc::CircuitOptimizer::removeFinalMeasurements(qc2); + } + // strip away qubits that are not acted upon stripIdleQubits(); @@ -380,6 +391,24 @@ EquivalenceCheckingManager::EquivalenceCheckingManager( "inputs! Proceed with caution!\n"; } + if (!configuration.functionality.checkApproximateEquivalence && + configuration.execution.runHSFChecker) { + std::clog << "[QCEC] Warning: The HSF checker performs approximate " + "equivalence checking. The HSF checker has been disabled. Set " + "'checkApproximateEquivalence' to True to enable it.\n"; + this->configuration.execution.runHSFChecker = false; + } + + // Check whether the hsf checker is configured and can handle the circuits + if (configuration.execution.runHSFChecker && + !DDHybridSchrodingerFeynmanChecker::canHandle(this->qc1, this->qc2)) { + std::clog + << "[QCEC] Warning: Hsf checker cannot handle the " + "circuits. Falling back to alternating or construction checker.\n"; + this->configuration.execution.runHSFChecker = false; + this->configuration.execution.runAlternatingChecker = true; + } + // check whether the alternating checker is configured and can handle the // circuits if (configuration.execution.runAlternatingChecker && @@ -524,6 +553,24 @@ void EquivalenceCheckingManager::checkSequential() { } } + if (configuration.execution.runHSFChecker && !done) { + checkers.emplace_back(std::make_unique( + qc1, qc2, configuration)); + const auto& hsfChecker = checkers.back(); + if (!done) { + const auto result = hsfChecker->run(); + + // if the hsf check produces a result, this is final + if (result != EquivalenceCriterion::NoInformation) { + results.equivalence = result; + + // everything is done + done = true; + doneCond.notify_one(); + } + } + } + if (configuration.execution.runZXChecker && !done) { if (zx::FunctionalityConstruction::transformableToZX(&qc1) && zx::FunctionalityConstruction::transformableToZX(&qc2)) { @@ -609,6 +656,9 @@ void EquivalenceCheckingManager::checkParallel() { if (configuration.execution.runConstructionChecker) { ++tasksToExecute; } + if (configuration.execution.runHSFChecker) { + ++tasksToExecute; + } if (configuration.execution.runSimulationChecker) { if (configuration.simulation.maxSims > 0U) { tasksToExecute += configuration.simulation.maxSims; @@ -657,6 +707,13 @@ void EquivalenceCheckingManager::checkParallel() { ++id; } + if (configuration.execution.runHSFChecker && !done) { + // start a new thread that constructs and runs the HSF check + futures.emplace_back( + asyncRunChecker(id, queue)); + ++id; + } + if (configuration.execution.runZXChecker && !done) { // start a new thread that constructs and runs the ZX checker futures.emplace_back(asyncRunChecker(id, queue)); @@ -743,10 +800,12 @@ void EquivalenceCheckingManager::checkParallel() { break; } - // the alternating and the construction checker provide definitive answers - // once they finish + // the alternating, the construction and the HSF checker provide definitive + // answers once they finish if ((dynamic_cast(checker) != nullptr) || - (dynamic_cast(checker) != nullptr)) { + (dynamic_cast(checker) != nullptr) || + (dynamic_cast(checker) != + nullptr)) { setAndSignalDone(); results.equivalence = result; break; diff --git a/src/checker/dd/DDAlternatingChecker.cpp b/src/checker/dd/DDAlternatingChecker.cpp index 6ee0c313..20eb3197 100644 --- a/src/checker/dd/DDAlternatingChecker.cpp +++ b/src/checker/dd/DDAlternatingChecker.cpp @@ -11,6 +11,7 @@ #include "checker/dd/applicationscheme/ApplicationScheme.hpp" #include +#include #include #include #include @@ -102,21 +103,32 @@ EquivalenceCriterion DDAlternatingChecker::checkEquivalence() { garbage[static_cast(q)] = qc1->logicalQubitIsGarbage(q) && qc2->logicalQubitIsGarbage(q); } - const bool isClose = - configuration.functionality.checkPartialEquivalence - ? dd->isCloseToIdentity(functionality, - configuration.functionality.traceThreshold, - garbage, false) - : dd->isCloseToIdentity(functionality, - configuration.functionality.traceThreshold); - - if (isClose) { - // whenever the top edge weight is not one, both decision diagrams are only - // equivalent up to a global phase - if (!functionality.w.approximatelyEquals(dd::Complex::one())) { - return EquivalenceCriterion::EquivalentUpToGlobalPhase; + // For approximate equivalence checking, calculate the Frobenius inner + // product trace(U V^-1) and compare it to some threshold. + if (configuration.functionality.checkApproximateEquivalence) { + auto trace = dd->trace(functionality, nqubits).mag(); + if (std::abs(trace - 1.) < + configuration.functionality.approximateCheckingThreshold) { + return EquivalenceCriterion::Equivalent; + } + } else { + // Otherwise, we can simply compare U V^-1 with the identity + const bool isClose = + configuration.functionality.checkPartialEquivalence + ? dd->isCloseToIdentity(functionality, + configuration.functionality.traceThreshold, + garbage, false) + : dd->isCloseToIdentity(functionality, + configuration.functionality.traceThreshold); + + if (isClose) { + // whenever the top edge weight is not one, both decision diagrams are + // only equivalent up to a global phase + if (!functionality.w.approximatelyEquals(dd::Complex::one())) { + return EquivalenceCriterion::EquivalentUpToGlobalPhase; + } + return EquivalenceCriterion::Equivalent; } - return EquivalenceCriterion::Equivalent; } return EquivalenceCriterion::NotEquivalent; } diff --git a/src/checker/dd/DDEquivalenceChecker.cpp b/src/checker/dd/DDEquivalenceChecker.cpp index 3639a984..34927d44 100644 --- a/src/checker/dd/DDEquivalenceChecker.cpp +++ b/src/checker/dd/DDEquivalenceChecker.cpp @@ -5,6 +5,7 @@ #include "checker/dd/DDEquivalenceChecker.hpp" +#include "Configuration.hpp" #include "EquivalenceCriterion.hpp" #include "checker/EquivalenceChecker.hpp" #include "checker/dd/DDPackageConfigs.hpp" @@ -19,6 +20,7 @@ #include "dd/Package_fwd.hpp" #include +#include #include #include @@ -48,34 +50,42 @@ DDEquivalenceChecker::equals(const DDType& e, const DDType& f) { // decision diagrams being extremely close (for some definition of `close`). if constexpr (std::is_same_v) { // for matrices this can be resolved by calculating their Frobenius inner - // product trace(U V^-1) and comparing it to some threshold. in a similar - // fashion, we can simply compare U V^-1 with the identity, which results in - // a much simpler check that is not prone to overflow. - bool isClose{}; - const bool eIsClose = - dd->isCloseToIdentity(e, configuration.functionality.traceThreshold); - const bool fIsClose = - dd->isCloseToIdentity(f, configuration.functionality.traceThreshold); - if (eIsClose || fIsClose) { - // if any of the DDs is close to the identity (structure), the result can - // be decided by whether both DDs are close enough to the identity. - isClose = eIsClose && fIsClose; - } else { - // otherwise, one DD needs to be inverted before multiplying both of them - // together and checking whether the resulting DD is close enough to the - // identity. + // product trace(U V^-1) and comparing it to some threshold. + if (configuration.functionality.checkApproximateEquivalence) { auto g = dd->multiply(e, dd->conjugateTranspose(f)); - isClose = - dd->isCloseToIdentity(g, configuration.functionality.traceThreshold); - } - - if (isClose) { - // whenever the top edge weights differ, both decision diagrams are only - // equivalent up to a global phase - if (!e.w.approximatelyEquals(f.w)) { - return EquivalenceCriterion::EquivalentUpToGlobalPhase; + auto trace = dd->trace(g, nqubits).mag(); + if (std::abs(trace - 1.) < + configuration.functionality.approximateCheckingThreshold) { + return EquivalenceCriterion::Equivalent; + } + } else { + // in a similar fashion, we can simply compare U V^-1 with the identity, + // which results in a much simpler check that is not prone to overflow. + bool isClose{}; + const bool eIsClose = + dd->isCloseToIdentity(e, configuration.functionality.traceThreshold); + const bool fIsClose = + dd->isCloseToIdentity(f, configuration.functionality.traceThreshold); + if (eIsClose || fIsClose) { + // if any of the DDs is close to the identity (structure), the result + // can be decided by whether both DDs are close enough to the identity. + isClose = eIsClose && fIsClose; + } else { + // otherwise, one DD needs to be inverted before multiplying both of + // them together and checking whether the resulting DD is close enough + // to the identity. + auto g = dd->multiply(e, dd->conjugateTranspose(f)); + isClose = dd->isCloseToIdentity( + g, configuration.functionality.traceThreshold); + } + if (isClose) { + // whenever the top edge weights differ, both decision diagrams are only + // equivalent up to a global phase + if (!e.w.approximatelyEquals(f.w)) { + return EquivalenceCriterion::EquivalentUpToGlobalPhase; + } + return EquivalenceCriterion::Equivalent; } - return EquivalenceCriterion::Equivalent; } } else { // for vectors this is resolved by computing the inner product (or fidelity) diff --git a/src/checker/dd/DDHybridSchrodingerFeynmanChecker.cpp b/src/checker/dd/DDHybridSchrodingerFeynmanChecker.cpp new file mode 100644 index 00000000..d8547d66 --- /dev/null +++ b/src/checker/dd/DDHybridSchrodingerFeynmanChecker.cpp @@ -0,0 +1,255 @@ +#include "checker/dd/DDHybridSchrodingerFeynmanChecker.hpp" + +#include "Definitions.hpp" +#include "EquivalenceCriterion.hpp" +#include "checker/EquivalenceChecker.hpp" +#include "dd/ComplexValue.hpp" +#include "dd/GateMatrixDefinitions.hpp" +#include "dd/Operations.hpp" +#include "dd/Package.hpp" +#include "ir/QuantumComputation.hpp" +#include "ir/operations/Control.hpp" +#include "ir/operations/OpType.hpp" +#include "ir/operations/StandardOperation.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: keep +#include +#include + +namespace ec { +std::size_t DDHybridSchrodingerFeynmanChecker::getNDecisions( + const qc::QuantumComputation& qc) { + std::size_t ndecisions = 0; + // calculate number of decisions + for (const auto& op : qc) { + if (op->getType() == qc::Barrier) { + continue; + } + assert(op->isStandardOperation()); + + bool targetInLowerSlice = false; + bool targetInUpperSlice = false; + bool controlInLowerSlice = false; + size_t nControlsInLowerSlice = 0; + bool controlInUpperSlice = false; + size_t nControlsInUpperSlice = 0; + auto spQubit = static_cast(qc.getNqubits() / 2); + for (const auto& target : op->getTargets()) { + targetInLowerSlice = targetInLowerSlice || target < spQubit; + targetInUpperSlice = targetInUpperSlice || target >= spQubit; + } + for (const auto& control : op->getControls()) { + if (control.qubit < spQubit) { + controlInLowerSlice = true; + nControlsInLowerSlice++; + } else { + controlInUpperSlice = true; + nControlsInUpperSlice++; + } + } + + if (targetInLowerSlice && targetInUpperSlice) { + throw std::invalid_argument( + "Multiple targets spread across the cut through the circuit are not " + "supported at the moment as this would require actually computing " + "the Schmidt decomposition of the gate being cut."); + } + + if (targetInLowerSlice && controlInUpperSlice) { + if (nControlsInUpperSlice > 1) { + throw std::invalid_argument( + "Multiple controls in the control part of the gate being cut are " + "not supported at the moment as this would require actually " + "computing the Schmidt decomposition of the gate being cut."); + } + ++ndecisions; + } else if (targetInUpperSlice && controlInLowerSlice) { + if (nControlsInLowerSlice > 1) { + throw std::invalid_argument( + "Multiple controls in the control part of the gate being cut are " + "not supported at the moment as this would require actually " + "computing the Schmidt decomposition of the gate being cut."); + } + ++ndecisions; + } + } + return ndecisions; +} + +bool DDHybridSchrodingerFeynmanChecker::canHandle( + const qc::QuantumComputation& qc1, const qc::QuantumComputation& qc2) { + try { + const auto ndecisions = + getNDecisions(qc1) + getNDecisions(*invertCircuit(qc2)); + if (ndecisions > 63) { + std::clog << "[QCEC] Warning: Number of split operations exceeds the " + "maximum allowed number: " + << ndecisions << "\n"; + return false; + } + return true; + } catch (const std::invalid_argument& e) { + std::clog << "[QCEC] Warning: " << e.what() << "\n"; + return false; + } +} + +dd::ComplexValue DDHybridSchrodingerFeynmanChecker::simulateSlicing( + std::unique_ptr& sliceDD1, std::unique_ptr& sliceDD2, + size_t i) { + Slice lower(sliceDD1, 0, splitQubit - 1, i); + Slice upper(sliceDD2, splitQubit, + static_cast(this->qc1->getNqubits() - 1), i); + for (const auto& op : *qc1) { + applyLowerUpper(sliceDD1, sliceDD2, op, lower, upper); + } + for (const auto& op : *qc2) { + applyLowerUpper(sliceDD1, sliceDD2, op, lower, upper); + } + auto traceLower = sliceDD1->trace(lower.matrix, lower.nqubits); + auto traceUpper = sliceDD2->trace(upper.matrix, upper.nqubits); + auto result = traceLower * traceUpper; + return result; +} + +bool DDHybridSchrodingerFeynmanChecker::Slice::apply( + std::unique_ptr& sliceDD, + const std::unique_ptr& op) { + bool isSplitOp = false; + assert(op->isStandardOperation()); + qc::Targets opTargets{}; + qc::Controls opControls{}; + + // check targets + bool targetInSplit = false; + bool targetInOtherSplit = false; + for (const auto& target : op->getTargets()) { + if (start <= target && target <= end) { + opTargets.emplace_back(target - start); + targetInSplit = true; + } else { + targetInOtherSplit = true; + } + } + + // Ensured in the getNDecisions function + assert(!(targetInSplit && targetInOtherSplit)); + + // check controls + for (const auto& control : op->getControls()) { + if (start <= control.qubit && control.qubit <= end) { + opControls.emplace(control.qubit - start, control.type); + } else { // other controls are set to the corresponding value + if (targetInSplit) { + isSplitOp = true; + const bool nextControl = getNextControl() != 0U; + // break if control is not activated + if ((control.type == qc::Control::Type::Pos && !nextControl) || + (control.type == qc::Control::Type::Neg && nextControl)) { + nDecisionsExecuted++; + return true; + } + } + } + } + + if (targetInOtherSplit && !opControls.empty()) { // control slice for split + // Ensured in the getNDecisions function + assert(opControls.size() == 1); + + isSplitOp = true; + const bool control = getNextControl() != 0U; + for (const auto& c : opControls) { + auto tmp = matrix; + auto projMatrix = control == (c.type == qc::Control::Type::Neg) + ? sliceDD->makeGateDD(dd::MEAS_ZERO_MAT, c.qubit) + : sliceDD->makeGateDD(dd::MEAS_ONE_MAT, c.qubit); + matrix = sliceDD->multiply(projMatrix, matrix); + sliceDD->incRef(matrix); + sliceDD->decRef(tmp); + } + } else if (targetInSplit) { // target slice for split or operation in split + const auto& param = op->getParameter(); + qc::StandardOperation newOp(opControls, opTargets, op->getType(), param); + auto tmp = matrix; + matrix = sliceDD->multiply(dd::getDD(&newOp, *sliceDD), matrix); + sliceDD->incRef(matrix); + sliceDD->decRef(tmp); + } + if (isSplitOp) { + nDecisionsExecuted++; + } + return isSplitOp; +} + +EquivalenceCriterion DDHybridSchrodingerFeynmanChecker::run() { + const auto start = std::chrono::steady_clock::now(); + equivalence = checkEquivalence(); + const auto end = std::chrono::steady_clock::now(); + runtime += std::chrono::duration(end - start).count(); + return equivalence; +} + +EquivalenceCriterion DDHybridSchrodingerFeynmanChecker::checkEquivalence() { + const auto ndecisions = getNDecisions(*qc1) + getNDecisions(*qc2); + if (ndecisions > 63) { + throw std::overflow_error( + "Number of split operations exceeds the maximum allowed number of 63."); + } + const auto maxControl = 1ULL << ndecisions; + const std::size_t nthreads = + std::max(2U, std::thread::hardware_concurrency()); + const auto actuallyUsedThreads = std::min(maxControl, nthreads); + const auto chunkSize = static_cast( + std::ceil(static_cast(maxControl) / + static_cast(actuallyUsedThreads))); + const auto nslicesOnOneCpu = std::min(64, chunkSize); + dd::ComplexValue trace{0.0, 0.0}; + std::mutex traceMutex; + tf::Executor executor(actuallyUsedThreads); + for (std::size_t control = 0; control < maxControl; + control += nslicesOnOneCpu) { + executor.silent_async([this, &trace, nslicesOnOneCpu, control, maxControl, + &traceMutex]() { + for (std::size_t localControl = 0; localControl < nslicesOnOneCpu; + localControl++) { + const std::size_t totalControl = control + localControl; + if (totalControl >= maxControl) { + break; + } + std::unique_ptr sliceDD1 = + std::make_unique(splitQubit); + std::unique_ptr sliceDD2 = + std::make_unique(this->qc1->getNqubits() - splitQubit); + auto result = simulateSlicing(sliceDD1, sliceDD2, totalControl); + const std::lock_guard guard(traceMutex); + trace += result; + } + }); + } + executor.wait_for_all(); + if (std::abs(trace.mag() - 1.) < + configuration.functionality.approximateCheckingThreshold) { + return EquivalenceCriterion::Equivalent; + } + return EquivalenceCriterion::NotEquivalent; +} + +void DDHybridSchrodingerFeynmanChecker::json( + nlohmann::basic_json<>& j) const noexcept { + EquivalenceChecker::json(j); + j["checker"] = "hsf"; +} +} // namespace ec diff --git a/src/mqt/qcec/configuration.py b/src/mqt/qcec/configuration.py index 54884455..be66a872 100644 --- a/src/mqt/qcec/configuration.py +++ b/src/mqt/qcec/configuration.py @@ -29,10 +29,13 @@ class ConfigurationOptions(TypedDict, total=False): run_construction_checker: bool run_simulation_checker: bool run_zx_checker: bool + run_hsf_checker: bool timeout: float # Functionality trace_threshold: float + approximate_checking_threshold: float check_partial_equivalence: bool + check_approximate_equivalence: bool # Optimizations backpropagate_output_permutation: bool elide_permutations: bool diff --git a/src/mqt/qcec/pyqcec.pyi b/src/mqt/qcec/pyqcec.pyi index 46ff207d..7c9715a0 100644 --- a/src/mqt/qcec/pyqcec.pyi +++ b/src/mqt/qcec/pyqcec.pyi @@ -43,12 +43,15 @@ class Configuration: run_construction_checker: bool run_simulation_checker: bool run_zx_checker: bool + run_hsf_checker: bool timeout: float def __init__(self) -> None: ... class Functionality: trace_threshold: float + approximate_checking_threshold: float check_partial_equivalence: bool + check_approximate_equivalence: bool def __init__(self) -> None: ... class Optimizations: @@ -144,7 +147,9 @@ class EquivalenceCheckingManager: def set_timeout(self, timeout: float = ...) -> None: ... def set_tolerance(self, tolerance: float = ...) -> None: ... def set_trace_threshold(self, threshold: float = ...) -> None: ... + def set_approximate_checking_threshold(self, threshold: float = ...) -> None: ... def set_check_partial_equivalence(self, enable: bool = ...) -> None: ... + def set_check_approximate_equivalence(self, enable: bool = ...) -> None: ... def set_zx_checker(self, enable: bool = ...) -> None: ... def store_cex_input(self, enable: bool = ...) -> None: ... def store_cex_output(self, enable: bool = ...) -> None: ... diff --git a/src/python/bindings.cpp b/src/python/bindings.cpp index 3ede11df..92fb846d 100644 --- a/src/python/bindings.cpp +++ b/src/python/bindings.cpp @@ -322,6 +322,12 @@ PYBIND11_MODULE(pyqcec, m, py::mod_gil_not_used()) { "Set the :attr:`trace threshold " "<.Configuration.Functionality.trace_threshold>` used for comparing " "two unitaries or functionality matrices.") + .def("set_approximate_checking_threshold", + &EquivalenceCheckingManager::setApproximateCheckingThreshold, + "threshold"_a = 1e-8, + "Set the :attr:`approximate checking threshold " + "<.Configuration.Functionality.approximate_checking_threshold>` " + "used for approximate equivalence checking.") .def( "set_check_partial_equivalence", &EquivalenceCheckingManager::setCheckPartialEquivalence, @@ -331,6 +337,16 @@ PYBIND11_MODULE(pyqcec, m, py::mod_gil_not_used()) { "they have the same probability for each measurement outcome. " "If set to false, the checker will output 'not equivalent' for " "circuits that are partially equivalent but not totally equivalent. ") + .def("set_check_approximate_equivalence", + &EquivalenceCheckingManager::setCheckApproximateEquivalence, + "enable"_a = false, + "Set whether to check for approximate equivalence. Two circuits are " + "approximately equivalent if the Hilbert-Schmidt inner product " + "(process distance) of the two circuits is less than the " + "approximate_checking_threshold. " + "If set to false, the checker will output 'not equivalent' for " + "circuits that are approximately equivalent but not totally " + "equivalent. ") // Simulation .def("set_fidelity_threshold", &EquivalenceCheckingManager::setFidelityThreshold, @@ -546,6 +562,13 @@ PYBIND11_MODULE(pyqcec, m, py::mod_gil_not_used()) { "` should be " "executed. Defaults to :code:`True` but arbitrary multi-controlled " "operations are only partially supported.") + .def_readwrite( + "run_hsf_checker", &Configuration::Execution::runHSFChecker, + "Set whether the :ref:`hsf checker " + "` should be " + "executed. Defaults to :code:`False`. Arbitrary multi-controlled " + "operations are only partially supported.") .def_readwrite("numerical_tolerance", &Configuration::Execution::numericalTolerance, "Set the numerical tolerance of the underlying decision " @@ -668,6 +691,15 @@ PYBIND11_MODULE(pyqcec, m, py::mod_gil_not_used()) { "Whenever any decision diagram node differs from this structure by " "more than the configured threshold, the circuits are concluded to " "be non-equivalent. Defaults to :code:`1e-8`.") + .def_readwrite( + "approximate_checking_threshold", + &Configuration::Functionality::approximateCheckingThreshold, + "To determine approximate equivalence, the Hilbert-Schmidt inner " + "product (or process distance) between two circuit representations " + "is calculated and compared against the " + "approximate_checking_threshold. If the process distance falls below " + "this threshold, the circuits are considered approximately " + "equivalent. Defaults to :code:`1e-8`.") .def_readwrite( "check_partial_equivalence", &Configuration::Functionality::checkPartialEquivalence, @@ -679,6 +711,21 @@ PYBIND11_MODULE(pyqcec, m, py::mod_gil_not_used()) { "output 'not equivalent' for circuits that are partially equivalent " "but not totally equivalent. In particular, garbage qubits will be " "treated as if they were measured qubits. Defaults to " + ":code:`False`.") + .def_readwrite( + "check_approximate_equivalence", + &Configuration::Functionality::checkApproximateEquivalence, + "To determine approximate equivalence, the Hilbert-Schmidt inner " + "product (or process distance) between two circuit representations " + "is calculated and compared against the " + "approximate_checking_threshold. If the process distance falls below " + "this threshold, the circuits are considered approximately " + "equivalent. If set to :code:`True`, a check for approximate " + "equivalence " + "will be performed. If set to :code:`False`, the checker will " + "output 'not equivalent' for circuits that are approximately " + "equivalent " + "but not totally equivalent. Defaults to " ":code:`False`."); // simulation options @@ -752,5 +799,5 @@ PYBIND11_MODULE(pyqcec, m, py::mod_gil_not_used()) { "to simpler equivalence checking instances as the random " "instantiation. This option " "changes how many of those additional checks are performed."); -} +}; } // namespace ec diff --git a/test/circuits/approximateEquivalenceTest/bell.qasm b/test/circuits/approximateEquivalenceTest/bell.qasm new file mode 100644 index 00000000..c8b3cff4 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/bell.qasm @@ -0,0 +1,5 @@ +OPENQASM 2.0; +//include "qelib1.inc"; +qreg q[2]; +U(pi/2,0,pi) q[0]; +CX q[0],q[1]; diff --git a/test/circuits/approximateEquivalenceTest/bell_out_default_error.qasm b/test/circuits/approximateEquivalenceTest/bell_out_default_error.qasm new file mode 100644 index 00000000..aec426e1 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/bell_out_default_error.qasm @@ -0,0 +1,8 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +// This file was generated using the Berkeley Quantum Synthesis Toolkit (BQSKit) v1. (DOI: https://doi.org/10.11578/dc.20210603.2) + +qreg q[2]; +u3(1.5707963267948966, 0.0, 3.141592653589793) q[0]; +cx q[0], q[1]; diff --git a/test/circuits/approximateEquivalenceTest/bell_out_high_error.qasm b/test/circuits/approximateEquivalenceTest/bell_out_high_error.qasm new file mode 100644 index 00000000..a69afc4a --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/bell_out_high_error.qasm @@ -0,0 +1,11 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +// This file was generated using the Berkeley Quantum Synthesis Toolkit (BQSKit) v1. (DOI: https://doi.org/10.11578/dc.20210603.2) +// synthesis_epsilon = error_threshold = 0.5 + +qreg q[2]; +u3(1.4247154207173944, 3.2723216017380983, 3.9165877165474567) q[0]; +u3(7.0635798455555285, 6.030167955846771, 2.233142840253472) q[1]; +u3(7.068920866489056, 6.076579311743602, 1.5874947689660417) q[0]; +u3(2.1594592649028512, 7.307161171725773, 2.562695121614239) q[1]; diff --git a/test/circuits/approximateEquivalenceTest/check/out_qft_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/check/out_qft_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..afc005f9 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/check/out_qft_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,64 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(1.5967129094740669, 4.4928594494509095, 5.150343955654042) q[0]; +u3(1.571277808724709, 5.1704480804551975, 4.7058109396384875) q[1]; +u3(5.128870313530324, 0.5759784277474378, 1.6601677063880982) q[2]; +u3(1.5722330814941592, 4.105088953129066, 4.688047235568617) q[3]; +u3(3.93193673603767, -0.06344516396092184, 4.328585545862223) q[4]; +u3(0.9684081152538433, 1.9765746111715055, 6.039859904633682) q[5]; +u3(1.6823833182557422, 4.2901034146354355, 5.277396922771205) q[6]; +u3(2.654986350734364, 4.088274687300487, 1.7562956033571526) q[7]; +u3(1.0544434612965976, 5.267772989707272, 1.7291064653658261) q[8]; +u3(0.641113142627662, 7.192075069135769, 3.9320337459461436) q[9]; +u3(1.9538389810638437, 4.964291458272374, 1.3652070123363917) q[0]; +u3(2.3843449472209897, 2.2010808705856357, 4.624028765483452) q[2]; +u3(5.447960841549981, 1.59476939119586, 2.746429606300692) q[4]; +u3(1.913584541620204, 1.6694216592928375, 4.489068317383709) q[5]; +u3(5.3082742737570845, 1.198573480013265, 5.768780198427521) q[6]; +u3(6.286963354044012, 1.4075489721153083, 3.671699319313141) q[7]; +u3(1.047222376635397, 0.9837428793073856, 1.523916289256121) q[8]; +u3(2.6087754794578792, 4.470984440851894, 5.914200407443676) q[9]; +u3(1.6853232648142211, 2.5691404081457856, 2.2170605385634814) q[0]; +cx q[3], q[2]; +u3(3.112813579869372, -0.005086569009791922, -0.6763638429222424) q[4]; +u3(3.266449635193457, 4.601084620131254, 5.01183142575176) q[5]; +u3(3.0035259768116305, 5.061947949359225, 3.333639359639256) q[7]; +cx q[1], q[0]; +u3(3.952973997039404, 0.9112613682939704, 5.66152617167672) q[2]; +u3(0.29398837848108766, 7.86152792254003, 0.7606379491757174) q[3]; +u3(-1.3261785086518214, 5.2550398411032875, 5.253001858310459) q[4]; +u3(1.1752031415272242, 2.965173505694305, 1.123681484443717) q[5]; +u3(4.022623069545801, 3.828491477785868, 7.2429270171472) q[7]; +u3(2.278615777897216, -0.26399318536482214, 6.078401211465244) q[0]; +u3(5.069329884285512, 3.35546281749432, 4.775259602606341) q[1]; +u3(2.1459139280808905, 6.47170317472704, 1.2024028631933765) q[2]; +u3(0.0039782718676524016, 1.851693751459628, 3.9622323749301116) q[3]; +u3(1.5325389620514507, 3.424619717923357, 0.18833473836150086) q[4]; +u3(5.792343024981983, -0.23465679736477632, 0.5440041655486838) q[0]; +u3(1.7322308875276524, 2.6759349370464793, 4.196159843736261) q[1]; +u3(3.139240058485812, 2.1966495705789795, 0.4694639031581532) q[2]; +u3(4.9960152145609, 0.1363522117966733, 0.1887355912029966) q[4]; +cx q[6], q[3]; +u3(5.197900698519211, -1.2291296220147176, 0.40674806317965656) q[0]; +u3(3.4453389891381576, 0.8973100918033137, 1.4899145259464557) q[1]; +u3(5.3195261132415546, -0.5952332112374324, 2.886544063800346) q[2]; +u3(0.004061041683970168, 4.223134090645838, 1.359673086994882) q[3]; +cx q[4], q[5]; +u3(3.721836476047589, 4.712346102669534, 2.497146967238639) q[6]; +cx q[0], q[9]; +cx q[1], q[8]; +u3(3.754162453789071, 2.830561068297695, 5.012748524871331) q[2]; +cx q[3], q[6]; +u3(1.332090168808036, 4.449428556036081, 4.59829167453284) q[4]; +u3(4.31195170608881, 4.473955935282206, 7.4871683820525385) q[5]; +u3(5.961566416233183, 8.086738331005916, -1.898209816603531) q[0]; +u3(0.14054336948585064, 11.824967064822681, -1.8073352027371405) q[1]; +u3(1.787075040639769, 7.175403463682723, 5.34180083961384) q[2]; +u3(3.1171525601684484, 3.3375756505299274, 6.445500896033654) q[3]; +u3(2.3900682383066765, 3.560341979592746, 1.9587280583634472) q[6]; +u3(1.1362056519130377, 5.462532178393413, 4.131028245070759) q[8]; +u3(4.297707522791769, 2.7910302083068954, -0.46261426812485057) q[9]; +cx q[2], q[7]; +u3(0.38022358447733623, -2.292165449828588, 5.9899941160723165) q[2]; +u3(6.215356564545466, 4.422976717855075, -1.0003804239044725) q[7]; diff --git a/test/circuits/approximateEquivalenceTest/check/out_qpeexact_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/check/out_qpeexact_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..e5cc3808 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/check/out_qpeexact_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,59 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(3.1457786349355605, 5.421761263017323, 4.008638617346886) q[0]; +u3(0.904683427787509, 4.3264218857676555, 3.253105757391102) q[1]; +u3(2.6348176194625625, 0.4108423236862732, 1.377231261112393) q[2]; +u3(6.282282095155324, 5.063584798718981, 1.21920143227369) q[3]; +u3(5.226936913602318, 4.445702468765694, 5.361808570806572) q[4]; +u3(3.431712019481757, 4.957274061917898, 4.0270273723347625) q[5]; +u3(5.192066717956585, -0.5085951158058518, 4.543388762153159) q[6]; +u3(4.908833247103972, 1.8216770953807266, 5.5682134564044805) q[7]; +u3(4.151805472836474, 0.2843423392797228, 1.081391082813205) q[8]; +u3(1.5724221312411957, 4.1340786573218455, 0.23487666351889958) q[9]; +u3(5.491260804387185, 3.8309387045422487, 5.225483590762154) q[0]; +u3(4.371229839526961, 1.2167597848486305, 5.0334366897438905) q[1]; +u3(6.329609332149668, 6.033062629680499, 4.66899412692601) q[2]; +u3(4.322466240681685, 2.634873057109232, 4.364392429852933) q[4]; +u3(1.8067768600586394, 3.3592837461860436, 2.2239574039094863) q[5]; +u3(5.95989390963119, 5.112910082303549, 2.7802425097780286) q[6]; +u3(0.6154107606056808, 0.47160276105126897, 0.29684090570252764) q[7]; +u3(1.0064518035388261, 2.3114408993721463, 1.2922756230884562) q[8]; +u3(1.3403519090262621, 1.7537404082568262, 2.271127405631342) q[9]; +cx q[0], q[8]; +u3(1.896254279309141, -0.15427072812476778, 3.663050265862602) q[1]; +cx q[6], q[2]; +u3(0.2588655148457335, 5.433198666092998, 4.033382161129801) q[9]; +u3(6.66941058173718, 5.023040879713362, 1.673243318092424) q[0]; +u3(3.8491189151064433, 0.44403968171469715, 4.165607581234752) q[1]; +u3(6.282912371652363, 4.608606790035007, 6.1516123929947275) q[2]; +u3(3.143017743540702, 5.226307488194178, 3.97761252075505) q[6]; +u3(5.425557372496884, 2.693578870290858, 6.50263298923416) q[8]; +cx q[9], q[3]; +u3(2.7634758054344144, 1.571006182519934, 4.68681636643541) q[0]; +u3(0.5661698017180979, 0.4565939096693895, 5.412531813552105) q[1]; +cx q[2], q[6]; +u3(2.7700865414472555, 6.833953728382238, 4.675168215118555) q[3]; +u3(0.00015248532059705712, 2.5891929496533495, 1.8975540979327976) q[9]; +cx q[1], q[7]; +u3(3.7289735608965806, 1.1876869133936214, 1.0062657745415329) q[2]; +u3(3.6953713477279053, 3.2501549101241243, 3.601982124113901) q[3]; +u3(0.2295229542231854, -0.22720771134856393, 7.180672912549948) q[6]; +u3(1.0246599123687141, -0.10615620726433331, 3.921461203140884) q[1]; +u3(0.8804565635436522, 4.712441051413684, 4.712332233827866) q[2]; +u3(-0.6382114918549516, 3.944721784132758, 1.9748244362030691) q[3]; +u3(6.662689056448501, 5.321449748742438, 0.9696017817824325) q[7]; +cx q[1], q[0]; +cx q[3], q[5]; +u3(-0.37826666343853843, 7.069913364639215, 1.5697293053874528) q[0]; +u3(3.1412590229022124, 2.442120727035348, 0.39170308864252407) q[1]; +u3(1.1655877434441426, 0.9449424980081808, 0.024306147074296704) q[3]; +u3(5.744555252633346, 4.272761840428961, 1.3738580140907444) q[5]; +cx q[1], q[0]; +cx q[3], q[2]; +u3(1.6222434212025327, 5.352379970315436, 3.8211760065446008) q[5]; +u3(-0.0005558739554070201, 1.5075823444855694, 2.092870689641878) q[0]; +u3(4.712368434652736, 4.724734742770601, 4.843247673458674) q[1]; +u3(1.5706995647081978, 1.5836777799903987, 3.14131659126619) q[2]; +u3(4.712705956583802, 1.6198357664326943, 0.5021959835739244) q[3]; +u3(2.3353937622138026, 6.551762026177583, 5.693194723242856) q[5]; diff --git a/test/circuits/approximateEquivalenceTest/check/out_qpeinexact_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/check/out_qpeinexact_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..5c8c38ee --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/check/out_qpeinexact_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,69 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(4.686961865276838, 1.357046345610335, 3.6059379742589863) q[0]; +u3(2.7763007945083906, 4.874168232099246, 1.34389606222912) q[1]; +u3(1.074170682089161, 3.8754724145048454, 0.8599458997080227) q[2]; +u3(-0.6678330427275795, 6.135726206541356, 0.04871213149620333) q[3]; +u3(0.6412236318508795, 5.745358986659732, 2.211913162090944) q[4]; +u3(1.9429630160371687, 3.841707793175603, 3.1370799759773376) q[5]; +u3(0.12014767907268181, 4.386573451553275, 4.040587895725029) q[6]; +u3(3.127141902524777, 3.6438241676013123, 1.8284777423127205) q[7]; +u3(2.672549444309574, 6.19851250587084, 1.3951813093016705) q[8]; +u3(6.107199947787151, 0.5439235603794383, 1.8229586394855188) q[9]; +u3(3.905509221332195, 3.601428193000014, -0.22770460419531344) q[0]; +u3(1.870117194942164, 5.904545341629118, 1.7819512751714832) q[1]; +u3(4.799926791781231, 3.3407756322344637, 4.876679257405755) q[2]; +u3(1.1246278397487752, 0.6640502669749878, 4.174525788139747) q[3]; +u3(3.953893442300813, 1.0201793437786988, 6.003536159098982) q[5]; +u3(5.932426892537282, 3.7929253044356437, 2.6973946125665456) q[6]; +u3(5.838399304109481, 3.2542268544314434, 3.490373080216075) q[7]; +u3(2.110296125777016, 1.0886312117003818, 2.548664966467628) q[8]; +u3(1.8009778488643773, 2.334028773086897, 5.635879551967924) q[9]; +u3(2.5323208361839042, 3.4575599593292865, 4.470077674623373) q[1]; +cx q[2], q[6]; +cx q[3], q[5]; +u3(4.621382119661225, 4.394740982718423, 5.019927077591458) q[7]; +cx q[8], q[0]; +u3(4.2492831047970245, 1.5123247296571625, 4.958989236223148) q[9]; +u3(0.00017831793077354954, 3.8938923975898025, 6.915953679514266) q[0]; +u3(4.547164069892221, 0.7816895315461284, 2.4591992708875092) q[2]; +u3(1.6752722763666597, 1.732736022107561, 6.373084819044298) q[3]; +u3(5.029680804253102, 5.7442339350505245, 5.432700823102606) q[5]; +u3(1.4983648333153212, 4.918908321047535, 5.581725192639537) q[6]; +cx q[7], q[1]; +u3(5.910805374772858, 1.5707503838453503, 1.0703313773006158) q[8]; +u3(-1.0703146842309457, 3.382272862155488, 2.986386853004498) q[9]; +cx q[0], q[8]; +u3(4.497713688537638, 0.8385381577458554, 1.5710010780079438) q[1]; +u3(4.4206399777342105, 3.3982564172030645, 4.881911181175938) q[3]; +cx q[6], q[4]; +u3(0.4334902385698476, 1.569916302404894, 2.700378879563038) q[7]; +u3(3.1499523996255068, 2.033468882511722, 2.369338471133545) q[9]; +u3(7.340326258872505, 4.862620774859223, 3.5037014908936914) q[0]; +cx q[1], q[7]; +u3(3.4630749312836517, 3.45374430244687, 3.3286568137346295) q[3]; +u3(1.5695223320204397, 4.444334703404689, 3.1416498502526453) q[4]; +u3(6.281284569133057, 2.1424933442030127, 3.7969435713529274) q[6]; +u3(3.1529933261324756, 2.1703300473153884, 3.3500025245573943) q[8]; +u3(2.1165554283637533, 5.268124594621309, 0.46416419039101436) q[1]; +u3(3.1432898133639493, 3.3259154693965898, 4.959912477617047) q[3]; +u3(6.283167703381702, 0.6359863671367816, 2.158356885818126) q[6]; +u3(1.6041636869177707, 3.5924461888868766, -2.076006605998757) q[7]; +u3(5.452121167785458, 5.6743131817040355, 5.379184831251755) q[8]; +u3(1.5708061606267292, 2.445860726698459, 4.586272927132378) q[1]; +cx q[6], q[5]; +u3(4.864022583111293, 5.493838401359525, 0.08792325980658289) q[7]; +u3(3.9830546423229385, 5.841572669787988, 3.1328732288796726) q[8]; +cx q[1], q[0]; +u3(4.712715768864319, 1.8729143957482526, 3.1409258298654352) q[5]; +u3(4.712449472498667, 5.105679204852368, 1.1499386170077854) q[6]; +u3(3.3170876764172528, 0.895872060986512, 3.4054526477440423) q[7]; +u3(3.141621098536432, 2.369813173477838, 3.1552258411364824) q[0]; +u3(6.283175768200863, 2.0745578369894355, 3.4951717374175333) q[1]; +cx q[1], q[0]; +u3(-0.0006755683389837666, 3.440820444063311, 3.2550665958512925) q[0]; +u3(4.711590134358627, 1.5832541042569503, 4.55373362040219) q[1]; +u3(5.2123091349785735, 0.3224508630392817, 3.4248672896748085) q[0]; +u3(1.660516509853004, 1.4300323242496271, 5.600099709224268) q[0]; +u3(2.4580234168829036, 5.460416328980352, 4.340713718287529) q[0]; diff --git a/test/circuits/approximateEquivalenceTest/check/qft_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/check/qft_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..993bf7b2 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/check/qft_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,227 @@ +// Benchmark was created by MQT Bench on 2024-03-18 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[10]; +creg meas[10]; +rz(pi/2) q[9]; +sx q[9]; +rz(3.1385246920140215) q[9]; +cx q[9],q[8]; +rz(-pi/4) q[8]; +cx q[9],q[8]; +rz(3*pi/4) q[8]; +sx q[8]; +rz(3.1354567304382504) q[8]; +cx q[9],q[7]; +rz(-pi/8) q[7]; +cx q[9],q[7]; +rz(pi/8) q[7]; +cx q[8],q[7]; +rz(-pi/4) q[7]; +cx q[8],q[7]; +rz(3*pi/4) q[7]; +sx q[7]; +rz(3.1293208072867076) q[7]; +cx q[9],q[6]; +rz(-pi/16) q[6]; +cx q[9],q[6]; +rz(pi/16) q[6]; +cx q[8],q[6]; +rz(-pi/8) q[6]; +cx q[8],q[6]; +rz(pi/8) q[6]; +cx q[7],q[6]; +rz(-pi/4) q[6]; +cx q[7],q[6]; +rz(3*pi/4) q[6]; +sx q[6]; +rz(3.1170489609836225) q[6]; +cx q[9],q[5]; +rz(-pi/32) q[5]; +cx q[9],q[5]; +rz(pi/32) q[5]; +cx q[8],q[5]; +rz(-pi/16) q[5]; +cx q[8],q[5]; +rz(pi/16) q[5]; +cx q[7],q[5]; +rz(-pi/8) q[5]; +cx q[7],q[5]; +rz(pi/8) q[5]; +cx q[6],q[5]; +rz(-pi/4) q[5]; +cx q[6],q[5]; +rz(3*pi/4) q[5]; +sx q[5]; +rz(3.0925052683774523) q[5]; +cx q[9],q[4]; +rz(-pi/64) q[4]; +cx q[9],q[4]; +rz(pi/64) q[4]; +cx q[8],q[4]; +rz(-pi/32) q[4]; +cx q[8],q[4]; +rz(pi/32) q[4]; +cx q[7],q[4]; +rz(-pi/16) q[4]; +cx q[7],q[4]; +rz(pi/16) q[4]; +cx q[6],q[4]; +rz(-pi/8) q[4]; +cx q[6],q[4]; +rz(pi/8) q[4]; +cx q[5],q[4]; +rz(-pi/4) q[4]; +cx q[5],q[4]; +rz(3*pi/4) q[4]; +sx q[4]; +rz(3.043417883165112) q[4]; +cx q[9],q[3]; +rz(-pi/128) q[3]; +cx q[9],q[3]; +rz(pi/128) q[3]; +cx q[8],q[3]; +rz(-pi/64) q[3]; +cx q[8],q[3]; +rz(pi/64) q[3]; +cx q[7],q[3]; +rz(-pi/32) q[3]; +cx q[7],q[3]; +rz(pi/32) q[3]; +cx q[6],q[3]; +rz(-pi/16) q[3]; +cx q[6],q[3]; +rz(pi/16) q[3]; +cx q[5],q[3]; +rz(-pi/8) q[3]; +cx q[5],q[3]; +rz(pi/8) q[3]; +cx q[4],q[3]; +rz(-pi/4) q[3]; +cx q[4],q[3]; +rz(3*pi/4) q[3]; +sx q[3]; +rz(15*pi/16) q[3]; +cx q[9],q[2]; +rz(-pi/256) q[2]; +cx q[9],q[2]; +rz(pi/256) q[2]; +cx q[8],q[2]; +rz(-pi/128) q[2]; +cx q[8],q[2]; +rz(pi/128) q[2]; +cx q[7],q[2]; +rz(-pi/64) q[2]; +cx q[7],q[2]; +rz(pi/64) q[2]; +cx q[6],q[2]; +rz(-pi/32) q[2]; +cx q[6],q[2]; +rz(pi/32) q[2]; +cx q[5],q[2]; +rz(-pi/16) q[2]; +cx q[5],q[2]; +rz(pi/16) q[2]; +cx q[4],q[2]; +rz(-pi/8) q[2]; +cx q[4],q[2]; +rz(pi/8) q[2]; +cx q[3],q[2]; +rz(-pi/4) q[2]; +cx q[3],q[2]; +rz(3*pi/4) q[2]; +sx q[2]; +rz(7*pi/8) q[2]; +cx q[9],q[1]; +rz(-pi/512) q[1]; +cx q[9],q[1]; +rz(pi/512) q[1]; +cx q[8],q[1]; +rz(-pi/256) q[1]; +cx q[8],q[1]; +rz(pi/256) q[1]; +cx q[7],q[1]; +rz(-pi/128) q[1]; +cx q[7],q[1]; +rz(pi/128) q[1]; +cx q[6],q[1]; +rz(-pi/64) q[1]; +cx q[6],q[1]; +rz(pi/64) q[1]; +cx q[5],q[1]; +rz(-pi/32) q[1]; +cx q[5],q[1]; +rz(pi/32) q[1]; +cx q[4],q[1]; +rz(-pi/16) q[1]; +cx q[4],q[1]; +rz(pi/16) q[1]; +cx q[3],q[1]; +rz(-pi/8) q[1]; +cx q[3],q[1]; +rz(pi/8) q[1]; +cx q[2],q[1]; +rz(-pi/4) q[1]; +cx q[2],q[1]; +rz(3*pi/4) q[1]; +sx q[1]; +rz(3*pi/4) q[1]; +cx q[9],q[0]; +rz(-pi/1024) q[0]; +cx q[9],q[0]; +rz(pi/1024) q[0]; +cx q[8],q[0]; +rz(-pi/512) q[0]; +cx q[8],q[0]; +rz(pi/512) q[0]; +cx q[7],q[0]; +rz(-pi/256) q[0]; +cx q[7],q[0]; +rz(pi/256) q[0]; +cx q[6],q[0]; +rz(-pi/128) q[0]; +cx q[6],q[0]; +rz(pi/128) q[0]; +cx q[5],q[0]; +rz(-pi/64) q[0]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[4],q[0]; +rz(-pi/32) q[0]; +cx q[4],q[0]; +rz(pi/32) q[0]; +cx q[3],q[0]; +rz(-pi/16) q[0]; +cx q[3],q[0]; +rz(pi/16) q[0]; +cx q[2],q[0]; +rz(-pi/8) q[0]; +cx q[2],q[0]; +rz(pi/8) q[0]; +cx q[1],q[0]; +rz(-pi/4) q[0]; +cx q[1],q[0]; +rz(3*pi/4) q[0]; +sx q[0]; +rz(pi/2) q[0]; +cx q[0],q[9]; +cx q[1],q[8]; +cx q[2],q[7]; +cx q[3],q[6]; +cx q[4],q[5]; +cx q[5],q[4]; +cx q[4],q[5]; +cx q[6],q[3]; +cx q[3],q[6]; +cx q[7],q[2]; +cx q[2],q[7]; +cx q[8],q[1]; +cx q[1],q[8]; +cx q[9],q[0]; +cx q[0],q[9]; diff --git a/test/circuits/approximateEquivalenceTest/check/qpeexact_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/check/qpeexact_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..9a0b170a --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/check/qpeexact_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,254 @@ +// Benchmark was created by MQT Bench on 2024-03-18 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[9]; +qreg psi[1]; +creg c[9]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(-pi/2) q[6]; +sx q[6]; +rz(2.4881540023736894) q[6]; +rz(pi/2) q[7]; +sx q[7]; +rz(pi/2) q[7]; +rz(pi/2) q[8]; +sx q[8]; +rz(pi/2) q[8]; +x psi[0]; +rz(-1.0536092607691794) psi[0]; +cx psi[0],q[0]; +rz(1.3499030933393643) q[0]; +cx psi[0],q[0]; +rz(-1.3499030933393643) q[0]; +cx q[0],q[8]; +cx q[8],q[0]; +cx q[0],q[8]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(0.006135923151542544) q[8]; +cx psi[0],q[1]; +rz(-0.44178646691106466) q[1]; +cx psi[0],q[1]; +rz(0.44178646691106466) q[1]; +cx q[1],q[7]; +cx q[7],q[1]; +cx q[1],q[7]; +rz(pi/4) q[1]; +cx q[1],q[0]; +rz(pi/4) q[0]; +cx q[1],q[0]; +rz(-pi/4) q[0]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/256) q[7]; +cx psi[0],q[2]; +rz(-0.8835729338221293) q[2]; +cx psi[0],q[2]; +rz(0.8835729338221293) q[2]; +cx psi[0],q[3]; +rz(7*pi/16) q[3]; +cx psi[0],q[3]; +rz(-7*pi/16) q[3]; +cx psi[0],q[4]; +rz(-pi/8) q[4]; +cx psi[0],q[4]; +rz(0.49087385212340506) q[4]; +cx psi[0],q[5]; +rz(-pi/4) q[5]; +cx psi[0],q[5]; +rz(pi/4) q[5]; +cx q[3],q[5]; +cx q[5],q[3]; +cx q[3],q[5]; +rz(pi/16) q[3]; +rz(pi/64) q[5]; +sx psi[0]; +rz(-pi/2) psi[0]; +cx q[6],psi[0]; +x q[6]; +rz(-2.2242349780110002) q[6]; +cx q[2],q[6]; +cx q[6],q[2]; +cx q[2],q[6]; +rz(pi/8) q[2]; +cx q[2],q[0]; +rz(pi/8) q[0]; +cx q[2],q[0]; +rz(-pi/8) q[0]; +cx q[2],q[1]; +rz(pi/4) q[1]; +cx q[2],q[1]; +rz(-pi/4) q[1]; +sx q[2]; +rz(pi/2) q[2]; +cx q[3],q[0]; +rz(pi/16) q[0]; +cx q[3],q[0]; +rz(-pi/16) q[0]; +cx q[3],q[1]; +rz(pi/8) q[1]; +cx q[3],q[1]; +rz(-pi/8) q[1]; +cx q[3],q[2]; +rz(pi/4) q[2]; +cx q[3],q[2]; +rz(-pi/4) q[2]; +sx q[3]; +rz(pi/2) q[3]; +cx q[4],q[0]; +rz(pi/32) q[0]; +cx q[4],q[0]; +rz(-pi/32) q[0]; +cx q[4],q[1]; +rz(pi/16) q[1]; +cx q[4],q[1]; +rz(-pi/16) q[1]; +cx q[4],q[2]; +rz(pi/8) q[2]; +cx q[4],q[2]; +rz(-pi/8) q[2]; +cx q[4],q[3]; +rz(pi/4) q[3]; +cx q[4],q[3]; +rz(-pi/4) q[3]; +sx q[4]; +rz(pi/2) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[5],q[0]; +rz(-pi/64) q[0]; +cx q[5],q[1]; +rz(pi/32) q[1]; +cx q[5],q[1]; +rz(-pi/32) q[1]; +cx q[5],q[2]; +rz(pi/16) q[2]; +cx q[5],q[2]; +rz(-pi/16) q[2]; +cx q[5],q[3]; +rz(pi/8) q[3]; +cx q[5],q[3]; +rz(-pi/8) q[3]; +cx q[5],q[4]; +rz(pi/4) q[4]; +cx q[5],q[4]; +rz(-pi/4) q[4]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/128) q[6]; +cx q[6],q[0]; +rz(pi/128) q[0]; +cx q[6],q[0]; +rz(-pi/128) q[0]; +cx q[6],q[1]; +rz(pi/64) q[1]; +cx q[6],q[1]; +rz(-pi/64) q[1]; +cx q[6],q[2]; +rz(pi/32) q[2]; +cx q[6],q[2]; +rz(-pi/32) q[2]; +cx q[6],q[3]; +rz(pi/16) q[3]; +cx q[6],q[3]; +rz(-pi/16) q[3]; +cx q[6],q[4]; +rz(pi/8) q[4]; +cx q[6],q[4]; +rz(-pi/8) q[4]; +cx q[6],q[5]; +rz(pi/4) q[5]; +cx q[6],q[5]; +rz(-pi/4) q[5]; +sx q[6]; +rz(pi/2) q[6]; +cx q[7],q[0]; +rz(pi/256) q[0]; +cx q[7],q[0]; +rz(-pi/256) q[0]; +cx q[7],q[1]; +rz(pi/128) q[1]; +cx q[7],q[1]; +rz(-pi/128) q[1]; +cx q[7],q[2]; +rz(pi/64) q[2]; +cx q[7],q[2]; +rz(-pi/64) q[2]; +cx q[7],q[3]; +rz(pi/32) q[3]; +cx q[7],q[3]; +rz(-pi/32) q[3]; +cx q[7],q[4]; +rz(pi/16) q[4]; +cx q[7],q[4]; +rz(-pi/16) q[4]; +cx q[7],q[5]; +rz(pi/8) q[5]; +cx q[7],q[5]; +rz(-pi/8) q[5]; +cx q[7],q[6]; +rz(pi/4) q[6]; +cx q[7],q[6]; +rz(-pi/4) q[6]; +sx q[7]; +rz(pi/2) q[7]; +cx q[8],q[0]; +rz(pi/512) q[0]; +cx q[8],q[0]; +rz(-pi/512) q[0]; +cx q[8],q[1]; +rz(pi/256) q[1]; +cx q[8],q[1]; +rz(-pi/256) q[1]; +cx q[8],q[2]; +rz(pi/128) q[2]; +cx q[8],q[2]; +rz(-pi/128) q[2]; +cx q[8],q[3]; +rz(pi/64) q[3]; +cx q[8],q[3]; +rz(-pi/64) q[3]; +cx q[8],q[4]; +rz(pi/32) q[4]; +cx q[8],q[4]; +rz(-pi/32) q[4]; +cx q[8],q[5]; +rz(pi/16) q[5]; +cx q[8],q[5]; +rz(-pi/16) q[5]; +cx q[8],q[6]; +rz(pi/8) q[6]; +cx q[8],q[6]; +rz(-pi/8) q[6]; +cx q[8],q[7]; +rz(pi/4) q[7]; +cx q[8],q[7]; +rz(-pi/4) q[7]; +sx q[8]; +rz(pi/2) q[8]; +rz(-pi/2) psi[0]; +sx psi[0]; +rz(0.832716027313646) psi[0]; diff --git a/test/circuits/approximateEquivalenceTest/check/qpeinexact_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/check/qpeinexact_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..ecf55502 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/check/qpeinexact_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,258 @@ +// Benchmark was created by MQT Bench on 2024-03-18 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[9]; +qreg psi[1]; +creg c[9]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +rz(pi/2) q[6]; +sx q[6]; +rz(pi/2) q[6]; +rz(pi/2) q[7]; +sx q[7]; +rz(pi/2) q[7]; +rz(pi/2) q[8]; +sx q[8]; +rz(pi/2) q[8]; +x psi[0]; +rz(-0.22396119503130363) psi[0]; +cx psi[0],q[0]; +rz(1.346835131763593) q[0]; +cx psi[0],q[0]; +rz(-1.346835131763593) q[0]; +cx psi[0],q[1]; +rz(-0.4479223900626072) q[1]; +cx psi[0],q[1]; +rz(0.4479223900626072) q[1]; +cx psi[0],q[2]; +rz(-0.8958447801252144) q[2]; +cx psi[0],q[2]; +rz(0.8958447801252144) q[2]; +cx psi[0],q[3]; +rz(1.3499030933393643) q[3]; +cx psi[0],q[3]; +rz(-1.3499030933393643) q[3]; +cx psi[0],q[4]; +rz(-0.44178646691106466) q[4]; +cx psi[0],q[4]; +rz(0.5399612373357454) q[4]; +cx psi[0],q[5]; +rz(-0.8835729338221293) q[5]; +cx psi[0],q[5]; +rz(0.8835729338221293) q[5]; +cx q[3],q[5]; +cx q[5],q[3]; +cx q[3],q[5]; +rz(pi/16) q[3]; +rz(pi/64) q[5]; +cx psi[0],q[6]; +rz(7*pi/16) q[6]; +cx psi[0],q[6]; +rz(-7*pi/16) q[6]; +cx q[2],q[6]; +cx q[6],q[2]; +cx q[2],q[6]; +rz(pi/8) q[2]; +rz(pi/128) q[6]; +cx psi[0],q[7]; +rz(-pi/8) q[7]; +cx psi[0],q[7]; +rz(pi/8) q[7]; +cx q[1],q[7]; +cx q[7],q[1]; +cx q[1],q[7]; +rz(pi/4) q[1]; +rz(pi/256) q[7]; +cx psi[0],q[8]; +rz(-pi/4) q[8]; +cx psi[0],q[8]; +rz(pi/4) q[8]; +cx q[0],q[8]; +cx q[8],q[0]; +cx q[0],q[8]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +cx q[1],q[0]; +rz(pi/4) q[0]; +cx q[1],q[0]; +rz(-pi/4) q[0]; +sx q[1]; +rz(pi/2) q[1]; +cx q[2],q[0]; +rz(pi/8) q[0]; +cx q[2],q[0]; +rz(-pi/8) q[0]; +cx q[2],q[1]; +rz(pi/4) q[1]; +cx q[2],q[1]; +rz(-pi/4) q[1]; +sx q[2]; +rz(pi/2) q[2]; +cx q[3],q[0]; +rz(pi/16) q[0]; +cx q[3],q[0]; +rz(-pi/16) q[0]; +cx q[3],q[1]; +rz(pi/8) q[1]; +cx q[3],q[1]; +rz(-pi/8) q[1]; +cx q[3],q[2]; +rz(pi/4) q[2]; +cx q[3],q[2]; +rz(-pi/4) q[2]; +sx q[3]; +rz(pi/2) q[3]; +cx q[4],q[0]; +rz(pi/32) q[0]; +cx q[4],q[0]; +rz(-pi/32) q[0]; +cx q[4],q[1]; +rz(pi/16) q[1]; +cx q[4],q[1]; +rz(-pi/16) q[1]; +cx q[4],q[2]; +rz(pi/8) q[2]; +cx q[4],q[2]; +rz(-pi/8) q[2]; +cx q[4],q[3]; +rz(pi/4) q[3]; +cx q[4],q[3]; +rz(-pi/4) q[3]; +sx q[4]; +rz(pi/2) q[4]; +cx q[5],q[0]; +rz(pi/64) q[0]; +cx q[5],q[0]; +rz(-pi/64) q[0]; +cx q[5],q[1]; +rz(pi/32) q[1]; +cx q[5],q[1]; +rz(-pi/32) q[1]; +cx q[5],q[2]; +rz(pi/16) q[2]; +cx q[5],q[2]; +rz(-pi/16) q[2]; +cx q[5],q[3]; +rz(pi/8) q[3]; +cx q[5],q[3]; +rz(-pi/8) q[3]; +cx q[5],q[4]; +rz(pi/4) q[4]; +cx q[5],q[4]; +rz(-pi/4) q[4]; +sx q[5]; +rz(pi/2) q[5]; +cx q[6],q[0]; +rz(pi/128) q[0]; +cx q[6],q[0]; +rz(-pi/128) q[0]; +cx q[6],q[1]; +rz(pi/64) q[1]; +cx q[6],q[1]; +rz(-pi/64) q[1]; +cx q[6],q[2]; +rz(pi/32) q[2]; +cx q[6],q[2]; +rz(-pi/32) q[2]; +cx q[6],q[3]; +rz(pi/16) q[3]; +cx q[6],q[3]; +rz(-pi/16) q[3]; +cx q[6],q[4]; +rz(pi/8) q[4]; +cx q[6],q[4]; +rz(-pi/8) q[4]; +cx q[6],q[5]; +rz(pi/4) q[5]; +cx q[6],q[5]; +rz(-pi/4) q[5]; +sx q[6]; +rz(pi/2) q[6]; +cx q[7],q[0]; +rz(pi/256) q[0]; +cx q[7],q[0]; +rz(-pi/256) q[0]; +cx q[7],q[1]; +rz(pi/128) q[1]; +cx q[7],q[1]; +rz(-pi/128) q[1]; +cx q[7],q[2]; +rz(pi/64) q[2]; +cx q[7],q[2]; +rz(-pi/64) q[2]; +cx q[7],q[3]; +rz(pi/32) q[3]; +cx q[7],q[3]; +rz(-pi/32) q[3]; +cx q[7],q[4]; +rz(pi/16) q[4]; +cx q[7],q[4]; +rz(-pi/16) q[4]; +cx q[7],q[5]; +rz(pi/8) q[5]; +cx q[7],q[5]; +rz(-pi/8) q[5]; +cx q[7],q[6]; +rz(pi/4) q[6]; +cx q[7],q[6]; +rz(-pi/4) q[6]; +sx q[7]; +rz(pi/2) q[7]; +rz(0.006135923151542544) q[8]; +cx q[8],q[0]; +rz(pi/512) q[0]; +cx q[8],q[0]; +rz(-pi/512) q[0]; +cx q[8],q[1]; +rz(pi/256) q[1]; +cx q[8],q[1]; +rz(-pi/256) q[1]; +cx q[8],q[2]; +rz(pi/128) q[2]; +cx q[8],q[2]; +rz(-pi/128) q[2]; +cx q[8],q[3]; +rz(pi/64) q[3]; +cx q[8],q[3]; +rz(-pi/64) q[3]; +cx q[8],q[4]; +rz(pi/32) q[4]; +cx q[8],q[4]; +rz(-pi/32) q[4]; +cx q[8],q[5]; +rz(pi/16) q[5]; +cx q[8],q[5]; +rz(-pi/16) q[5]; +cx q[8],q[6]; +rz(pi/8) q[6]; +cx q[8],q[6]; +rz(-pi/8) q[6]; +cx q[8],q[7]; +rz(pi/4) q[7]; +cx q[8],q[7]; +rz(-pi/4) q[7]; +sx q[8]; +rz(pi/2) q[8]; diff --git a/test/circuits/approximateEquivalenceTest/dj_indep_qiskit_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/dj_indep_qiskit_10_no_measure.qasm new file mode 100644 index 00000000..ae21cc45 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/dj_indep_qiskit_10_no_measure.qasm @@ -0,0 +1,37 @@ +// Benchmark was created by MQT Bench on 2024-03-17 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[9]; +u2(0,0) q[0]; +u2(0,0) q[1]; +h q[2]; +u2(0,0) q[3]; +h q[4]; +u2(0,0) q[5]; +u2(0,0) q[6]; +h q[7]; +u2(0,0) q[8]; +u2(-pi,-pi) q[9]; +cx q[0],q[9]; +u2(-pi,-pi) q[0]; +cx q[1],q[9]; +u2(-pi,-pi) q[1]; +cx q[2],q[9]; +h q[2]; +cx q[3],q[9]; +u2(-pi,-pi) q[3]; +cx q[4],q[9]; +h q[4]; +cx q[5],q[9]; +u2(-pi,-pi) q[5]; +cx q[6],q[9]; +u2(-pi,-pi) q[6]; +cx q[7],q[9]; +h q[7]; +cx q[8],q[9]; +u2(-pi,-pi) q[8]; diff --git a/test/circuits/approximateEquivalenceTest/dj_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/dj_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..4eb30e82 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/dj_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,69 @@ +// Benchmark was created by MQT Bench on 2024-03-17 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg c[9]; +rz(-pi/2) q[0]; +sx q[0]; +rz(pi) q[0]; +rz(-pi/2) q[1]; +sx q[1]; +rz(pi/2) q[2]; +sx q[2]; +rz(-pi/2) q[3]; +sx q[3]; +rz(pi/2) q[4]; +sx q[4]; +rz(-pi/2) q[5]; +sx q[5]; +rz(-pi/2) q[6]; +sx q[6]; +rz(pi/2) q[7]; +sx q[7]; +rz(-pi/2) q[8]; +sx q[8]; +rz(pi/2) q[9]; +sx q[9]; +rz(-pi/2) q[9]; +cx q[0],q[9]; +sx q[0]; +rz(-pi/2) q[0]; +rz(-pi/2) q[9]; +sx q[9]; +rz(-2.308876626276157) q[9]; +sx q[9]; +rz(pi/2) q[9]; +cx q[1],q[9]; +sx q[1]; +rz(-pi/2) q[1]; +cx q[2],q[9]; +sx q[2]; +rz(pi/2) q[2]; +cx q[3],q[9]; +sx q[3]; +rz(-pi/2) q[3]; +cx q[4],q[9]; +sx q[4]; +rz(pi/2) q[4]; +cx q[5],q[9]; +sx q[5]; +rz(-pi/2) q[5]; +cx q[6],q[9]; +sx q[6]; +rz(-pi/2) q[6]; +cx q[7],q[9]; +sx q[7]; +rz(pi/2) q[7]; +cx q[8],q[9]; +sx q[8]; +rz(-pi/2) q[8]; +rz(-pi/2) q[9]; +sx q[9]; +rz(-2.3088766262761578) q[9]; +sx q[9]; +rz(pi/2) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/ghz_indep_qiskit_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/ghz_indep_qiskit_10_no_measure.qasm new file mode 100644 index 00000000..ff59370c --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/ghz_indep_qiskit_10_no_measure.qasm @@ -0,0 +1,19 @@ +// Benchmark was created by MQT Bench on 2024-03-17 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +h q[9]; +cx q[9],q[8]; +cx q[8],q[7]; +cx q[7],q[6]; +cx q[6],q[5]; +cx q[5],q[4]; +cx q[4],q[3]; +cx q[3],q[2]; +cx q[2],q[1]; +cx q[1],q[0]; diff --git a/test/circuits/approximateEquivalenceTest/ghz_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/ghz_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..da97a1ed --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/ghz_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,22 @@ +// Benchmark was created by MQT Bench on 2024-03-17 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +rz(pi/2) q[9]; +sx q[9]; +rz(pi/2) q[9]; +cx q[9],q[8]; +cx q[8],q[7]; +cx q[7],q[6]; +cx q[6],q[5]; +cx q[5],q[4]; +cx q[4],q[3]; +cx q[3],q[2]; +cx q[2],q[1]; +cx q[1],q[0]; diff --git a/test/circuits/approximateEquivalenceTest/graphstate_indep_qiskit_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/graphstate_indep_qiskit_10_no_measure.qasm new file mode 100644 index 00000000..38886fa0 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/graphstate_indep_qiskit_10_no_measure.qasm @@ -0,0 +1,29 @@ +// Benchmark was created by MQT Bench on 2024-03-17 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +h q[0]; +h q[1]; +cz q[0],q[1]; +h q[2]; +cz q[1],q[2]; +h q[3]; +h q[4]; +cz q[0],q[4]; +cz q[3],q[4]; +h q[5]; +cz q[2],q[5]; +h q[6]; +cz q[3],q[6]; +cz q[5],q[6]; +h q[7]; +h q[8]; +cz q[7],q[8]; +h q[9]; +cz q[7],q[9]; +cz q[8],q[9]; diff --git a/test/circuits/approximateEquivalenceTest/graphstate_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/graphstate_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..2c1273f3 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/graphstate_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,50 @@ +// Benchmark was created by MQT Bench on 2024-03-17 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi/2) q[0]; +cx q[0],q[1]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi/2) q[2]; +cx q[2],q[3]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[1],q[4]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +cx q[4],q[5]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi/2) q[5]; +cx q[5],q[6]; +rz(pi/2) q[6]; +sx q[6]; +rz(pi/2) q[6]; +cx q[6],q[7]; +rz(pi/2) q[7]; +sx q[7]; +rz(pi/2) q[7]; +cx q[3],q[8]; +cx q[7],q[8]; +rz(pi/2) q[8]; +sx q[8]; +rz(pi/2) q[8]; +cx q[0],q[9]; +cx q[2],q[9]; +rz(pi/2) q[9]; +sx q[9]; +rz(pi/2) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/out_dj_indep_qiskit_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_dj_indep_qiskit_10_high_error.qasm new file mode 100644 index 00000000..3818ab68 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_dj_indep_qiskit_10_high_error.qasm @@ -0,0 +1,29 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(6.06881057839052, 5.903628153049844, 3.0820752952692287) q[0]; +u3(3.774395453789126, 1.6709824825990403, 3.33882857475355) q[1]; +u3(3.604030233387013, 4.266213899121946, -1.1674700191224305) q[2]; +u3(4.713248404795393, 7.4791039259414465, 3.1412247596131837) q[3]; +u3(5.021591154847043, 6.323156730574956, 1.2475761402468823) q[4]; +u3(4.296274954505401, 5.483900759354059, 5.532252415758215) q[5]; +u3(4.419387891174763, 5.3075662498442675, 5.368882638058229) q[6]; +u3(1.5710974411468126, -0.021458163063248534, 0.00043099957982519485) q[7]; +u3(6.784915833152506, 1.634342226570327, 1.9940035867092534) q[8]; +u3(6.945900060636145, 4.666872104921736, 2.4346891426054214) q[9]; +u3(1.5576976507933171, 1.7847821116849119, 2.0083604068943974) q[0]; +u3(-1.6864541005637683, 7.230328119859851, 3.2019424679687423) q[1]; +u3(4.290132918908613, 1.7637434129664025, 2.4619306935322216) q[2]; +u3(6.727080321075377, 0.789023577116072, 3.9341430307926575) q[4]; +u3(4.039131641415167, 2.5981778523200796, 2.008974898274495) q[5]; +u3(0.709218017823603, 0.45864336957936336, 2.1883596097690146) q[6]; +u3(4.257859499816279, 4.4905468668280495, 4.1743999094930535) q[8]; +u3(2.0572393653210113, 3.6112303623305793, 5.5842279129491645) q[9]; +cx q[3], q[9]; +u3(4.711457784824099, -0.0003602263844019784, 1.9455853330529376) q[3]; +u3(6.283309547520465, 5.076237356837114, 1.2070912924807158) q[9]; +u3(-0.13031236669726765, 1.0887725661619272, 3.0091337433275984) q[9]; +u3(1.5884896468654224, 1.4403570173959617, 3.753325609696006) q[9]; +cx q[7], q[9]; +u3(4.712590063817558, 0.00045599593374527885, 3.1631252425729355) q[7]; +u3(-0.0005454370046024911, 6.047308379412852, 3.3770182885562674) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/out_dj_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_dj_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..18718f20 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_dj_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,29 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(2.335306671190346, 3.772812277566454, 2.108741442318727) q[0]; +u3(3.054177095786275, 6.521210169501422, 6.522692801382013) q[1]; +u3(4.445664880809077, 0.4644324719678442, 3.16053766876242) q[2]; +u3(1.57158482298804, 0.32124556615883415, 0.0009593828889625011) q[3]; +u3(5.1647481210818915, 1.9277822468147676, 0.9754987052319422) q[4]; +u3(0.47129463944587763, 2.214354530891446, 3.353365312561171) q[5]; +u3(1.4827897573470243, 0.9417618068009833, 4.883192724133633) q[6]; +u3(1.5717470287211532, 1.0167086547925923, 3.1415340377073235) q[7]; +u3(1.0825206639489946, 2.9280854271111387, 1.1710648430062278) q[8]; +u3(0.5989509836144578, 2.9500255284939136, 5.060035635525321) q[9]; +u3(4.044248376888316, 2.061304101973117, 6.363302885400944) q[0]; +u3(7.832734421282508, 1.6559427069124357, 1.571576574040885) q[1]; +u3(1.5525330152405294, 2.8747693099478377, 4.25320021652121) q[2]; +u3(0.7306917441894218, 0.7130792095915414, 2.212449755753419) q[4]; +u3(4.6160471153784055, 2.032971513123998, 5.4507154661344295) q[5]; +u3(2.949378041854789, 3.6230298276558384, 1.1029104388293516) q[6]; +u3(3.7620355295461785, 5.344854569453492, 4.088736678668232) q[8]; +u3(1.1253917784355454, 3.555964933239227, 2.538307206679658) q[9]; +cx q[3], q[9]; +u3(4.713671755883596, 6.282594625947213, -0.32179273662146896) q[3]; +u3(5.896603381333034, 1.5683833990255478, 4.7136291282296945) q[9]; +u3(1.3184907268778128, 5.325243607641265, 5.596125201988893) q[9]; +u3(2.035653819378473, 3.7197439670825867, 3.2019020544302967) q[9]; +cx q[7], q[9]; +u3(4.712405346456387, 3.141417733882747, -1.0166831735504562) q[7]; +u3(1.8666946080156421, 1.5707648288198446, 4.712613099350399) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/out_ghz_indep_qiskit_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_ghz_indep_qiskit_10_high_error.qasm new file mode 100644 index 00000000..ba4a9f9f --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_ghz_indep_qiskit_10_high_error.qasm @@ -0,0 +1,23 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(-0.6143483334225731, 1.4771257802030138, 4.714276007177734) q[0]; +u3(2.7948842906645646, 3.343488390415191, 4.037932886632076) q[1]; +u3(3.2697050896394253, 1.977487880204244, 1.3056428364533377) q[2]; +u3(2.59107044495318, 4.37444909579603, 4.62938494734676) q[3]; +u3(3.2051829241746397, 2.561893454996514, -0.40164581838041613) q[4]; +u3(4.399043818012508, 3.968692556542786, 1.7737197457170457) q[5]; +u3(1.5786792564859715, 6.455268469721191, 0.878122324232283) q[6]; +u3(1.956348923586676, 0.6548072080713027, 1.2007421173597088) q[7]; +u3(2.114476242182641, 1.2706805676028825, -0.4033711772867306) q[8]; +u3(5.1872033357024225, 6.352255117102099, 1.167531747505399) q[9]; +u3(2.1856597587244257, 1.5699777340044532, 4.804285563971735) q[0]; +u3(1.8398758060738734, -0.22207692020895373, 2.2348696290284455) q[1]; +u3(4.588824605317062, -0.03338686201523063, 4.038928794122309) q[2]; +u3(4.1617406479053, 6.232321334090658, 4.952556005909968) q[3]; +u3(1.5954108334862225, 0.059553849640958355, 1.7498206442004949) q[4]; +u3(3.512863675997405, 3.7000151496319607, 2.904494938284918) q[5]; +u3(3.8342365734957755, 1.5832106331352656, 1.4089831368148396) q[6]; +u3(3.669520405598157, 5.554875924077623, 1.6848740101058448) q[7]; +u3(4.36962904292202, 4.1302220839027886, 3.2243152385877636) q[8]; +u3(1.2141452647009583, 2.6324089754912143, 1.6943114768660263) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/out_ghz_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_ghz_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..72567c9b --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_ghz_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,23 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(5.047725273307948, 3.8997785650205583, 2.9653095910496408) q[0]; +u3(2.7662143649914155, 0.7760860320782041, 2.5885346725391973) q[1]; +u3(0.9532994313308205, 2.5497840063420103, 5.681138784560119) q[2]; +u3(4.1191491196917385, 4.772961085343913, 1.9019670713296728) q[3]; +u3(7.793867363553461, 3.3802242803407863, 1.367029880859521) q[4]; +u3(2.0651941103360945, 2.56711917204636, 1.8943324485150532) q[5]; +u3(2.493509453943615, 2.7880242937251296, 0.019422390046078486) q[6]; +u3(3.2831530558423676, 1.836557976116568, 3.2533726217462084) q[7]; +u3(2.31613457125066, 4.416467383381407, 2.10220415641265) q[8]; +u3(-1.6858200613731753, 2.934475344451984, 3.269300432973157) q[9]; +u3(1.404592390794163, 2.8013484127241095, 4.013053572044193) q[0]; +u3(1.3780194780009043, 5.960027157016272, 3.4140734461447066) q[1]; +u3(5.191821051498533, 0.858862855932312, 5.682601431803838) q[2]; +u3(5.6133478485960095, -0.44820307398048637, 5.202741182288472) q[3]; +u3(2.9285781360738965, 7.559560811966148, 1.0445926706466884) q[4]; +u3(5.698593781277909, 2.6092061719198334, 4.33152560692951) q[5]; +u3(4.723701529665525, 0.646968408218973, 1.939776323406654) q[6]; +u3(7.868130407571769, 6.142355452901236, 6.128274073444406) q[7]; +u3(4.025217475457678, 0.5012489867565808, 5.721434197772335) q[8]; +u3(2.9699255128667974, 2.4031714938907967, 1.0448040920303607) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/out_graphstate_indep_qiskit_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_graphstate_indep_qiskit_10_high_error.qasm new file mode 100644 index 00000000..05f711fb --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_graphstate_indep_qiskit_10_high_error.qasm @@ -0,0 +1,31 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(1.432594117296715, 6.523517503696879, 0.5307753009182036) q[0]; +u3(-1.563719864741981, 1.6385481762828487, 3.1501519987816677) q[1]; +u3(5.483925120679292, 4.711156244372728, 4.715245581747235) q[2]; +u3(1.2781788813956485, 4.7532819488974996, 5.42441697008978) q[3]; +u3(1.6964362215906845, 3.0078671870139804, -0.11799205682439023) q[4]; +u3(4.987464431507268, -0.8327076872866116, 0.7700929980801302) q[5]; +u3(0.9859716126901675, 1.5704600844018486, -1.5700489886406939) q[6]; +u3(3.5567369106682056, 1.882368621533429, 0.9899827707353679) q[7]; +u3(-1.570770647415144, -0.017951498822503034, 12.566494237899454) q[8]; +u3(7.155188828036308, 5.6203819882398935, 2.0329220364345195) q[9]; +u3(2.595136575126597, 1.8420136600638655, 1.561545713580413) q[0]; +u3(3.1309091894391763, 1.024288984562663, 3.7375026392585267) q[1]; +u3(2.246259998379157, 6.328344876664135, 5.997561262385133) q[3]; +u3(2.9692037765904344, 5.533117379115061, 2.517174437297823) q[4]; +u3(0.8080522118639935, 1.185700101199915, 2.6769405250075584) q[5]; +u3(4.93584042797918, -0.353042450902948, 2.2883462105038834) q[7]; +u3(1.2740591430973232, 1.9346335353727981, 6.524619047639296) q[9]; +cx q[1], q[2]; +cx q[3], q[6]; +cx q[8], q[9]; +u3(6.2829209455465245, 2.931758104031811, 2.9894621804657286) q[1]; +u3(7.852076600509691, 0.771223369207406, -0.00013106892522044152) q[2]; +u3(6.282504070663867, 6.8700130737682885, 5.271847193703128) q[3]; +u3(0.5512530500777284, 1.571186803497867, 4.712688323023295) q[6]; +u3(0.00025723443696661525, 7.770111440165413, -3.0394939501279237) q[8]; +u3(4.712635149491865, 2.64121679513578, 3.1413335394340307) q[9]; +u3(1.2006011499705118, 3.3624913612182477, 4.296737054801426) q[6]; +u3(5.098372970275851, 4.278452206099582, 4.649821004709238) q[6]; diff --git a/test/circuits/approximateEquivalenceTest/out_graphstate_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_graphstate_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..28088d97 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_graphstate_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,25 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(0.0, 0.0, 0.0) q[0]; +u3(1.5708004796822823, 0.0001122150979442349, -3.141686950159258) q[1]; +u3(4.7132469899784475, 10.693282422255491, -6.28339856365495) q[2]; +u3(1.5707796381087182, -3.1404984683866095, 3.1416335793283556) q[3]; +u3(4.644762724723176, 4.039696158282753, 3.2966197717561525) q[4]; +u3(4.752627214253485, 2.453114764693034, 0.6820669534381145) q[5]; +u3(2.7205332796241186, 2.0677343154903234, 3.9467562202461446) q[6]; +u3(2.3327963490034898, 6.365748929050915, 0.7786224790735101) q[7]; +u3(1.5708699366210679, -0.0005118302437518985, 3.142402850856444) q[8]; +u3(0.04837667378412253, 1.8095455087965278, -0.6573485325032415) q[9]; +u3(0.0, 0.0, 0.0) q[0]; +u3(3.3105311106953974, 1.1559008777490294, 3.4058026473017504) q[4]; +u3(-0.6832889689411028, 4.6493914227679705, 2.3093147747270963) q[5]; +u3(1.2828722620108934, 2.8301002008037655, 1.9234190291182376) q[6]; +u3(4.170071744080869, 3.7759623531347035, 4.019447028491128) q[7]; +u3(3.212498803717826, 1.0124702581344829, 3.003857242235134) q[9]; +u3(0.0, 0.0, 0.0) q[0]; +cx q[2], q[9]; +u3(4.570152680042814, 2.6444675785744884, 0.8530782413266593) q[0]; +u3(6.282303408208207, 1.9045396024277235, 7.822459782931171) q[2]; +u3(7.8541017243149, 4.801951116840429, 3.1423127524001635) q[9]; +u3(0.8620836184095643, 4.899796869847033, 5.086088148796226) q[0]; diff --git a/test/circuits/approximateEquivalenceTest/out_qaoa_indep_qiskit_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_qaoa_indep_qiskit_10_high_error.qasm new file mode 100644 index 00000000..3f6f60d9 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_qaoa_indep_qiskit_10_high_error.qasm @@ -0,0 +1,30 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(1.4624019839245497, -0.24343275343142734, -2.1452489713953007) q[0]; +u3(1.933343797495146, -0.6520681965631354, 4.250068817364644) q[1]; +u3(5.466578160237326, 1.944230971396738, 4.694000276279117) q[2]; +u3(3.0620761958611573, 4.086864345257192, 1.2743521026739149) q[3]; +u3(1.814227440579282, 6.4700374794611575, -1.6867419861657262) q[4]; +u3(4.712393037463343, 5.28006828308011, 2.0505642438361504) q[5]; +u3(4.708230526925601, 0.47849617648089443, 5.438678485367332) q[6]; +u3(4.5551263658752, 3.1829729391170622, 4.65781545732097) q[7]; +u3(0.0, 0.0, 0.0) q[8]; +u3(1.5817935106268783, 2.1211716826928546, 1.098055274909864) q[9]; +u3(1.5662372031815006, 5.160156494184899, 1.7902423688041866) q[2]; +u3(4.438117424266678, 5.831723136425203, 5.569735641913855) q[3]; +u3(6.842140987968218, 2.6755978090714283, 3.9292205794307917) q[4]; +u3(3.472383069346754, 2.664570893966137, 5.102757901617316) q[6]; +u3(-0.24410233712965587, 5.862440537147041, 0.8379848392911975) q[7]; +u3(0.0, 0.0, 0.0) q[8]; +u3(0.1866117853157909, 4.800381580385864, 2.4997943923507324) q[9]; +u3(0.460926360143544, 3.1718236513438276, 2.014374531658772) q[2]; +cx q[5], q[9]; +u3(0.6994182158012909, 2.2581150016299154, 2.5241614420498726) q[8]; +u3(3.3429802940889077, 1.7940925532354683, 3.4208036009126928) q[2]; +u3(5.555760620203913, 4.712159805289027, 5.715694172725523) q[5]; +u3(3.921566564697745, 2.6816530853312663, 2.766712067406482) q[8]; +u3(4.356992150852439, 5.594153065657897, 0.7400150582754648) q[9]; +cx q[7], q[9]; +u3(-2.3645529774684886, 1.5723788249805206, 1.128121475529069) q[7]; +u3(0.005103976693752369, 3.162368208343641, 3.1155808409298302) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/out_qaoa_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_qaoa_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..16b6d8f1 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_qaoa_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,27 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(0.42639050700219194, 3.065442237938425, 0.3273103037531484) q[0]; +u3(1.5714752989468632, 0.00013384228797397313, -3.786262634058096) q[1]; +u3(4.7125493058107795, 4.267995140955728, 3.1416909439478977) q[2]; +u3(4.95787004308975, 3.3301349767393065, 2.568642990797727) q[3]; +u3(1.6498631188623636, 3.2646413547174613, 3.1080961937809315) q[4]; +u3(1.571050073437134, 0.0013948596061459373, 2.115164879426297) q[5]; +u3(1.2508474148802897, -0.014722318596002336, 5.022238650701951) q[6]; +u3(1.5717307707882224, 0.0004985873419509623, -4.167724648345697) q[7]; +u3(0.0, 0.0, 0.0) q[8]; +u3(1.5714773446137233, 0.000830720140711616, 2.115309395335114) q[9]; +u3(4.3082701932390615, 0.14047854101600438, 3.563672502202493) q[0]; +u3(3.398038092712026, 2.8629166783160853, 5.80755693293833) q[3]; +u3(3.0561493383774385, 4.468371756214439, 2.6160303848185755) q[4]; +u3(3.720515272314431, 1.0120990253756275, 5.716031808227701) q[6]; +u3(0.0, 0.0, 0.0) q[8]; +cx q[2], q[6]; +u3(7.7938225972912365, 3.4065676035623937, 0.9687741440152317) q[4]; +u3(0.0, 0.0, 0.0) q[8]; +u3(2.4982712626476853, 4.713094583713299, 5.1569658658054625) q[2]; +u3(1.8809195632979894, 2.814496614303875, 3.4837375115185694) q[4]; +u3(4.6102063746540205, 3.2789598268081837, 5.645057063921604) q[6]; +u3(0.0, 0.0, 0.0) q[8]; +u3(8.157453786451542, 6.2866928162052345, 3.735500276889271) q[8]; +u3(6.5909209929256605, 6.441731812206573, 2.9723106256988805) q[8]; diff --git a/test/circuits/approximateEquivalenceTest/out_vqe_indep_qiskit_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_vqe_indep_qiskit_10_high_error.qasm new file mode 100644 index 00000000..329d6a60 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_vqe_indep_qiskit_10_high_error.qasm @@ -0,0 +1,25 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(1.571945970524166, -1.5416729344346136, 3.1142201840147985) q[0]; +u3(0.0, 0.0, 0.0) q[1]; +u3(1.5683933548274716, -3.1425401983771866, -1.574534477402389) q[2]; +u3(0.0011860195119125772, 0.34232340444286746, 0.06005728803354232) q[3]; +u3(2.7368460810919197, 0.0005494822175939884, 1.5725541135389047) q[4]; +u3(2.1606806512298085, 1.74473677117697, -0.4618126915380293) q[5]; +u3(1.4013444508890258, -0.14725421549339446, -4.233717441593754) q[6]; +u3(7.214733523195288, 2.983749318145844, 1.2976996740201097) q[7]; +u3(3.876473512505923, 5.92864932810349, 1.9450233057723907) q[8]; +u3(4.959984317698359, 8.013346910090654, 5.52792724967543) q[9]; +u3(0.0, 0.0, 0.0) q[0]; +u3(1.5712474652374344, 1.5733287074782505, -3.1391919593989543) q[1]; +u3(2.1581282500612264, 0.5943423038396909, 3.175130225628324) q[7]; +u3(6.706600896198001, 0.797203708624387, 1.7495144131546345) q[8]; +u3(0.0, 0.0, 0.0) q[0]; +cx q[8], q[9]; +u3(0.0, 0.0, 0.0) q[0]; +u3(4.712708466056863, 1.5735566771536544, 0.9902983007753604) q[8]; +u3(2.6324383127303697, 2.9859422277667504, 6.150256274647738) q[9]; +u3(0.0, 0.0, 0.0) q[0]; +u3(0.0, 0.0, 0.0) q[0]; +u3(0.0, 0.0, 0.0) q[0]; diff --git a/test/circuits/approximateEquivalenceTest/out_vqe_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_vqe_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..134d0f81 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_vqe_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,25 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(3.141144995781528, 0.729230580205777, -5.553809272274417) q[0]; +u3(0.0, 0.0, 0.0) q[1]; +u3(1.5709371603453506, 0.0006003266070311319, 5.667998044147341) q[2]; +u3(0.9280326307264981, 9.433415796311628e-05, -1.5693584303407235) q[3]; +u3(1.5703802843994839, -0.0015860331288160001, 1.570193861561292) q[4]; +u3(1.5802339383487496, 0.00013363582176761923, 1.572419766585579) q[5]; +u3(1.5702978068177287, 3.1422127654061307, 1.5710891030344363) q[6]; +u3(4.56452304943476, 6.868521669974106, 5.450410796613644) q[7]; +u3(6.052685819587351, 2.665045009481868, 4.210061453187524) q[8]; +u3(2.313023584442147, 0.9956696247187454, -0.5859299934515115) q[9]; +u3(0.0, 0.0, 0.0) q[0]; +u3(2.2824213000454696, -2.2709816309767326, 3.8007003027944894) q[1]; +u3(4.189367215345096, 1.1999085972927805, 1.4306859648884949) q[7]; +u3(5.169039433755726, 6.205177700176606, 4.162872003624732) q[8]; +u3(0.0, 0.0, 0.0) q[0]; +cx q[8], q[9]; +u3(0.0, 0.0, 0.0) q[0]; +u3(1.5674008723294437, 1.572244164799447, 1.041070546453933) q[8]; +u3(2.6450537836950025, 0.7599254115981949, 0.7302924449778218) q[9]; +u3(0.0, 0.0, 0.0) q[0]; +u3(0.0, 0.0, 0.0) q[0]; +u3(0.0, 0.0, 0.0) q[0]; diff --git a/test/circuits/approximateEquivalenceTest/out_wstate_indep_qiskit_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_wstate_indep_qiskit_10_high_error.qasm new file mode 100644 index 00000000..292e6d50 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_wstate_indep_qiskit_10_high_error.qasm @@ -0,0 +1,42 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(0.08880432894746627, 0.23189520151989743, 4.77518370435655) q[0]; +u3(4.968719305172505, 3.380143352874718, 5.113349871036835) q[1]; +u3(1.409241967610268, 4.984113581729915, 1.7849930153549283) q[2]; +u3(1.7719429180591144, 5.261720069567487, 1.1501426584798664) q[3]; +u3(4.361696837818329, 1.675586172492358, 4.806014700387583) q[4]; +u3(-0.9366710989765981, 5.97976869040335, 1.8590014268957524) q[5]; +u3(1.5715710383793198, 3.727402254136272, 3.2966551291356483) q[6]; +u3(3.8005889857714075, 1.5036083387294208, 5.3171736722443) q[7]; +u3(5.085084400020848, 1.5719055667740385, 6.230141952900043) q[8]; +u3(3.141592653589887, 2.6033475508277157, 7.315736531212332) q[9]; +u3(-0.7946551917789845, 0.12470679383030889, 1.188808075583932) q[0]; +u3(2.9971131207828527, 0.0767695169903223, 5.109690349147795) q[1]; +u3(3.6184830534599506, 5.301589098078638, 2.353602290482522) q[2]; +u3(2.746258745795315, 3.7012748609790314, 4.212350521871979) q[4]; +u3(2.373351060701321, 1.1549603893186093, 5.54724556157436) q[5]; +u3(1.0805244975415562, 5.87655568524475, 4.270208593613963) q[6]; +u3(1.634688915153328, 1.5779305462111157, 0.74569033177784) q[7]; +u3(3.0683881647264797, 2.14998914993376, 5.522140167582976) q[8]; +u3(2.648602842023635, 5.030958794730189, 0.5347168141649181) q[1]; +u3(3.684974509806954, 2.828121645975489, 4.433617387307407) q[2]; +cx q[3], q[4]; +u3(4.392410785267952, 2.216421283665582, 0.660458922515924) q[5]; +u3(1.5766255732596564, 3.8362648105101793, 1.5477551411129582) q[6]; +cx q[8], q[9]; +u3(4.46816909668358, 2.7084361346054546, 3.303891764094752) q[1]; +u3(1.7252050298932085, 1.4260006444360414, 6.33377853281975) q[2]; +u3(6.283124496073446, 6.59774539351529, 4.268139466585652) q[3]; +u3(2.5441383947004796, 1.570761844864247, 4.712315467100208) q[4]; +u3(5.334016041483067, 5.885897274929878, 5.876657337255943) q[5]; +u3(3.165042510671254, 3.3914132215169506, 4.267378998652459) q[6]; +u3(3.1398956388587766, -0.09088192516558817, 4.834789498465474) q[8]; +u3(3.1415926535885683, 0.36270118025369463, 1.936196943153783) q[9]; +u3(1.8026536690025112, 5.812887830004276, 0.5884802958565906) q[3]; +cx q[7], q[8]; +u3(2.141726036255668, 3.4175167637868427, 5.333863636664062) q[3]; +u3(0.0016830466530898163, -0.009491059653115945, 4.185627647750503) q[7]; +u3(3.141710109840958, 5.172322216088836, 3.604401073096564) q[8]; +u3(2.7305848531990606, 6.375945500507991, 1.3913552924492263) q[7]; +u3(5.115785613859014, 4.790587836291266, 5.995018445914517) q[7]; diff --git a/test/circuits/approximateEquivalenceTest/out_wstate_nativegates_ibm_qiskit_opt3_10_high_error.qasm b/test/circuits/approximateEquivalenceTest/out_wstate_nativegates_ibm_qiskit_opt3_10_high_error.qasm new file mode 100644 index 00000000..f8e1d5a8 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/out_wstate_nativegates_ibm_qiskit_opt3_10_high_error.qasm @@ -0,0 +1,42 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +u3(3.003909754504298, 0.9755289691212459, 1.0509096344814997) q[0]; +u3(4.156718440227518, 2.611643357503636, 2.08567806863232) q[1]; +u3(4.779639710281416, 0.3948887108584252, 4.639866888915957) q[2]; +u3(4.913529737153367, 1.8022278630260664, 1.1500829634420369) q[3]; +u3(7.36959198493212, 1.5870727469619421, 3.705345729525691) q[4]; +u3(4.5213194521292905, 3.8962985426187635, 0.9264043971866853) q[5]; +u3(1.922121831592675, 1.2827202706029506, 4.264037426734242) q[6]; +u3(4.943093791569544, 0.10303076460489785, 0.8188385388339069) q[7]; +u3(4.336041653615549, 1.3324893286344945, 6.343377074933315) q[8]; +u3(-1.7838511809976763e-10, 4.203743296059084, 0.5086456834278801) q[9]; +u3(2.4163853189395956, 6.465387066236423, 0.2090068671218588) q[0]; +u3(0.21607052563769302, 4.224862904871233, 3.633251715427373) q[1]; +u3(3.644050523995374, 6.479050866837511, 1.873099425712036) q[2]; +u3(0.6633601445653122, 0.1950915333412193, 5.890474757097994) q[4]; +u3(5.290832759626098, 2.644757609848364, 3.9110307486611813) q[5]; +u3(-0.48815664772476397, 1.448663406745269, 4.7705392187328) q[6]; +u3(2.3487512761759, 2.8040036725094883, 4.35845578829468) q[7]; +u3(5.583800835000085, 4.696957583744842, 1.8900735246008296) q[8]; +u3(1.2737849195603657, 5.609243524170237, 1.613725465604109) q[1]; +u3(4.808378709201391, 3.8771753180928465, -0.3824185919056889) q[2]; +cx q[3], q[4]; +u3(5.338606814057927, 3.1058094049256875, 2.250621063711204) q[5]; +u3(7.962807285656218, 3.488001019075014, 5.038865511119175) q[6]; +cx q[8], q[9]; +u3(3.4419025763850546, 6.143227142050376, 0.5274818522890575) q[1]; +u3(1.951220248929252, 3.2445591686879554, 0.872719601458409) q[2]; +u3(6.283120951089399, 3.072256825969127, 4.130006565382937) q[3]; +u3(-0.0004781938832750595, 0.7107157064457341, 2.4317932982022046) q[4]; +u3(2.251864506562823, 3.9974892422446393, 2.234968321661341) q[5]; +u3(2.798485571380734, 2.813553652975767, 4.056102186411141) q[6]; +u3(3.1441195882424173, 0.356473456783513, 1.8618018838221935) q[8]; +u3(3.1415926535785372, 1.7946677720108122, 0.22820913361587367) q[9]; +u3(1.8936855133449952, -0.6477761474203892, 2.5895021398664824) q[3]; +cx q[7], q[8]; +u3(7.333270418993937, 3.515795153397013, 5.167535516857539) q[3]; +u3(6.280951615105036, 2.948394915703154, 2.0937973302206854) q[7]; +u3(6.282241702901769, 2.5361182373574205, -0.962542980648663) q[8]; +u3(1.5233405245621463, 0.44332681832304566, 2.641077451127197) q[7]; +u3(2.070412344929058, 3.1947281124932627, 1.1533011486972722) q[7]; diff --git a/test/circuits/approximateEquivalenceTest/qaoa_indep_qiskit_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/qaoa_indep_qiskit_10_no_measure.qasm new file mode 100644 index 00000000..80e4fd3f --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/qaoa_indep_qiskit_10_no_measure.qasm @@ -0,0 +1,59 @@ +// Benchmark was created by MQT Bench on 2024-03-18 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +h q[0]; +h q[1]; +rzz(-5.6274199584027285) q[0],q[1]; +h q[2]; +h q[3]; +rzz(-5.6274199584027285) q[1],q[3]; +rx(1.8987267857024446) q[1]; +h q[4]; +rzz(-5.6274199584027285) q[3],q[4]; +rx(1.8987267857024446) q[3]; +h q[5]; +h q[6]; +rzz(-5.6274199584027285) q[0],q[6]; +rx(1.8987267857024446) q[0]; +rzz(1.2427965226498625) q[0],q[1]; +rzz(1.2427965226498625) q[1],q[3]; +rx(-0.655872435747533) q[1]; +rzz(-5.6274199584027285) q[2],q[6]; +rx(1.8987267857024446) q[6]; +rzz(1.2427965226498625) q[0],q[6]; +rx(-0.655872435747533) q[0]; +h q[7]; +rzz(-5.6274199584027285) q[5],q[7]; +h q[8]; +rzz(-5.6274199584027285) q[2],q[8]; +rx(1.8987267857024446) q[2]; +rzz(1.2427965226498625) q[2],q[6]; +rzz(-5.6274199584027285) q[4],q[8]; +rx(1.8987267857024446) q[4]; +rzz(1.2427965226498625) q[3],q[4]; +rx(-0.655872435747533) q[3]; +rx(-0.655872435747533) q[6]; +rx(1.8987267857024446) q[8]; +rzz(1.2427965226498625) q[2],q[8]; +rx(-0.655872435747533) q[2]; +rzz(1.2427965226498625) q[4],q[8]; +rx(-0.655872435747533) q[4]; +rx(-0.655872435747533) q[8]; +h q[9]; +rzz(-5.6274199584027285) q[5],q[9]; +rx(1.8987267857024446) q[5]; +rzz(-5.6274199584027285) q[7],q[9]; +rx(1.8987267857024446) q[7]; +rzz(1.2427965226498625) q[5],q[7]; +rx(1.8987267857024446) q[9]; +rzz(1.2427965226498625) q[5],q[9]; +rx(-0.655872435747533) q[5]; +rzz(1.2427965226498625) q[7],q[9]; +rx(-0.655872435747533) q[7]; +rx(-0.655872435747533) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/qaoa_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/qaoa_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..217b99e1 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/qaoa_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,194 @@ +// Benchmark was created by MQT Bench on 2024-03-18 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +rz(pi/2) q[0]; +sx q[0]; +rz(pi) q[0]; +rz(pi/2) q[1]; +sx q[1]; +rz(pi/2) q[1]; +cx q[0],q[1]; +rz(1.289442989282985) q[1]; +cx q[0],q[1]; +rz(pi/2) q[2]; +sx q[2]; +rz(pi) q[2]; +rz(pi/2) q[3]; +sx q[3]; +rz(pi/2) q[3]; +cx q[1],q[3]; +rz(1.289442989282985) q[3]; +cx q[1],q[3]; +rz(pi/2) q[1]; +sx q[1]; +rz(13.2110965090601) q[1]; +sx q[1]; +rz(5*pi/2) q[1]; +rz(pi/2) q[4]; +sx q[4]; +rz(pi/2) q[4]; +cx q[3],q[4]; +rz(1.289442989282985) q[4]; +cx q[3],q[4]; +rz(pi/2) q[3]; +sx q[3]; +rz(13.2110965090601) q[3]; +sx q[3]; +rz(5*pi/2) q[3]; +rz(pi/2) q[5]; +sx q[5]; +rz(pi) q[5]; +rz(pi/2) q[6]; +sx q[6]; +rz(pi/2) q[6]; +cx q[0],q[6]; +rz(1.289442989282985) q[6]; +cx q[0],q[6]; +sx q[0]; +rz(13.2110965090601) q[0]; +sx q[0]; +rz(3*pi) q[0]; +cx q[0],q[1]; +rz(-0.6447220641786215) q[1]; +cx q[0],q[1]; +cx q[1],q[3]; +cx q[2],q[6]; +rz(-0.6447220641786215) q[3]; +cx q[1],q[3]; +rz(pi/2) q[1]; +sx q[1]; +rz(17.56010762207137) q[1]; +sx q[1]; +rz(5*pi/2) q[1]; +rz(1.289442989282985) q[6]; +cx q[2],q[6]; +rz(pi/2) q[6]; +sx q[6]; +rz(13.2110965090601) q[6]; +sx q[6]; +rz(5*pi/2) q[6]; +cx q[0],q[6]; +rz(-0.6447220641786215) q[6]; +cx q[0],q[6]; +sx q[0]; +rz(17.56010762207137) q[0]; +sx q[0]; +rz(5*pi/2) q[0]; +rz(pi/2) q[7]; +sx q[7]; +rz(pi/2) q[7]; +cx q[5],q[7]; +rz(1.289442989282985) q[7]; +cx q[5],q[7]; +rz(pi/2) q[8]; +sx q[8]; +rz(pi/2) q[8]; +cx q[2],q[8]; +rz(1.289442989282985) q[8]; +cx q[2],q[8]; +sx q[2]; +rz(13.2110965090601) q[2]; +sx q[2]; +rz(3*pi) q[2]; +cx q[2],q[6]; +cx q[4],q[8]; +rz(-0.6447220641786215) q[6]; +cx q[2],q[6]; +rz(pi/2) q[6]; +sx q[6]; +rz(17.56010762207137) q[6]; +sx q[6]; +rz(5*pi/2) q[6]; +rz(1.289442989282985) q[8]; +cx q[4],q[8]; +rz(pi/2) q[4]; +sx q[4]; +rz(13.2110965090601) q[4]; +sx q[4]; +rz(5*pi/2) q[4]; +cx q[3],q[4]; +rz(-0.6447220641786215) q[4]; +cx q[3],q[4]; +rz(pi/2) q[3]; +sx q[3]; +rz(17.56010762207137) q[3]; +sx q[3]; +rz(5*pi/2) q[3]; +rz(pi/2) q[8]; +sx q[8]; +rz(13.2110965090601) q[8]; +sx q[8]; +rz(5*pi/2) q[8]; +cx q[2],q[8]; +rz(-0.6447220641786215) q[8]; +cx q[2],q[8]; +sx q[2]; +rz(17.56010762207137) q[2]; +sx q[2]; +rz(5*pi/2) q[2]; +cx q[4],q[8]; +rz(-0.6447220641786215) q[8]; +cx q[4],q[8]; +rz(pi/2) q[4]; +sx q[4]; +rz(17.56010762207137) q[4]; +sx q[4]; +rz(5*pi/2) q[4]; +rz(pi/2) q[8]; +sx q[8]; +rz(17.56010762207137) q[8]; +sx q[8]; +rz(5*pi/2) q[8]; +rz(pi/2) q[9]; +sx q[9]; +rz(pi/2) q[9]; +cx q[5],q[9]; +rz(1.289442989282985) q[9]; +cx q[5],q[9]; +sx q[5]; +rz(13.2110965090601) q[5]; +sx q[5]; +rz(3*pi) q[5]; +cx q[7],q[9]; +rz(1.289442989282985) q[9]; +cx q[7],q[9]; +rz(pi/2) q[7]; +sx q[7]; +rz(13.2110965090601) q[7]; +sx q[7]; +rz(5*pi/2) q[7]; +cx q[5],q[7]; +rz(-0.6447220641786215) q[7]; +cx q[5],q[7]; +rz(pi/2) q[9]; +sx q[9]; +rz(13.2110965090601) q[9]; +sx q[9]; +rz(5*pi/2) q[9]; +cx q[5],q[9]; +rz(-0.6447220641786215) q[9]; +cx q[5],q[9]; +sx q[5]; +rz(17.56010762207137) q[5]; +sx q[5]; +rz(5*pi/2) q[5]; +cx q[7],q[9]; +rz(-0.6447220641786215) q[9]; +cx q[7],q[9]; +rz(pi/2) q[7]; +sx q[7]; +rz(17.56010762207137) q[7]; +sx q[7]; +rz(5*pi/2) q[7]; +rz(pi/2) q[9]; +sx q[9]; +rz(17.56010762207137) q[9]; +sx q[9]; +rz(5*pi/2) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/toffoli.qasm b/test/circuits/approximateEquivalenceTest/toffoli.qasm new file mode 100644 index 00000000..0bfd2336 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/toffoli.qasm @@ -0,0 +1,4 @@ +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[3]; +ccx q[0], q[1], q[2]; diff --git a/test/circuits/approximateEquivalenceTest/toffoli_out_default_error.qasm b/test/circuits/approximateEquivalenceTest/toffoli_out_default_error.qasm new file mode 100644 index 00000000..d39fa295 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/toffoli_out_default_error.qasm @@ -0,0 +1,27 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +// This file was generated using the Berkeley Quantum Synthesis Toolkit (BQSKit) v1. (DOI: https://doi.org/10.11578/dc.20210603.2) + +qreg q[3]; +u3(4.7123889809248, 4.712388955012845, 1.1036158611244384) q[0]; +u3(4.712388980983968, 3.1415926545103003, 1.6662347254833414) q[1]; +u3(3.1415926535713226, 6.076357271163574, 6.076357271176827) q[2]; +cx q[0], q[1]; +u3(0.7853981560637512, 2.5155207028504378e-08, 3.141592653589793) q[0]; +u3(3.096013314602218, 1.570796327034668, -1.5707963265553742) q[1]; +cx q[0], q[2]; +u3(2.3561944901518754, 1.5119454577217084e-09, -3.141592653589793) q[0]; +u3(0.04474021300781862, 1.5707963267923022, 1.5707963267974883) q[2]; +cx q[0], q[1]; +u3(2.3561944900935923, 1.5707963290638949, -3.141592653589793) q[0]; +u3(1.5707963267948966, 3.1415926530420206, -1.5707963283920234) q[1]; +cx q[0], q[2]; +u3(1.5707963251287866, -0.31821769794434274, -2.7755575615628914e-17) q[0]; +u3(0.21244281346880747, 1.5707963270282943, -1.5707963270230474) q[2]; +cx q[1], q[2]; +u3(2.356194490294979, 4.7123889814189885, 0.0) q[1]; +u3(0.16671345369681514, 1.5707963268690999, -1.570796326868071) q[2]; +cx q[1], q[2]; +u3(1.5707963274803494, -2.4972122270998547, -3.141592653589793) q[1]; +u3(1.20929464362818, 4.712388980360432, 1.5707963268034766) q[2]; diff --git a/test/circuits/approximateEquivalenceTest/toffoli_out_high_error.qasm b/test/circuits/approximateEquivalenceTest/toffoli_out_high_error.qasm new file mode 100644 index 00000000..2b5ae6c9 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/toffoli_out_high_error.qasm @@ -0,0 +1,10 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +// This file was generated using the Berkeley Quantum Synthesis Toolkit (BQSKit) v1. (DOI: https://doi.org/10.11578/dc.20210603.2) +// synthesis_epsilon = error_threshold = 0.5 + +qreg q[3]; +u3(3.2565196422859165e-22, 5.227237758848407, 1.0491742331388518) q[0]; +u3(1.8123414008865951e-28, 5.7511343861911515, 6.808462912975694) q[1]; +u3(0.008788638510032316, 1.5721676760940455, 4.7137603296838595) q[2]; diff --git a/test/circuits/approximateEquivalenceTest/toffoli_out_small_error.qasm b/test/circuits/approximateEquivalenceTest/toffoli_out_small_error.qasm new file mode 100644 index 00000000..fa0128a8 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/toffoli_out_small_error.qasm @@ -0,0 +1,28 @@ +OPENQASM 2.0; +include "qelib1.inc"; + +// This file was generated using the Berkeley Quantum Synthesis Toolkit (BQSKit) v1. (DOI: https://doi.org/10.11578/dc.20210603.2) +// synthesis_epsilon = 1e-3, error_threshold=5e-2 + +qreg q[3]; +u3(4.712388981642913, 6.283185304915111, 5.078180946914554) q[0]; +u3(1.5707963317928202, 4.712388855233761, 4.689633691840316) q[1]; +u3(3.1415926535897967, 4.148171623914443, 1.0065789703246502) q[2]; +cx q[0], q[2]; +u3(1.5707963280523778, 1.7073876520004871, -1.1102230246251565e-16) q[0]; +u3(2.757636203235623, 1.5707963267948961, -4.71238898038469) q[2]; +cx q[1], q[2]; +u3(0.7853981633285405, -3.1415925497946455, 0.0) q[1]; +u3(0.9632687407318458, -1.5707963267948966, 4.71238898038469) q[2]; +cx q[0], q[1]; +u3(3.1415926535897647, 2.492785815397919, 0.0) q[0]; +u3(0.7853981633696963, 3.1415925901703696, -3.1415925639011846) q[1]; +cx q[1], q[2]; +u3(2.35619449020584, 4.305645417979065e-08, -3.141592653589793) q[1]; +u3(2.7447560800167796, -4.71238898038469, -1.5707963267948961) q[2]; +cx q[0], q[1]; +u3(1.5707963285066946, -3.1415926535002154, 3.1415926535897936) q[0]; +u3(1.5707963559474336, 3.9497461051949427, -1.5707963546499848) q[1]; +cx q[0], q[2]; +u3(1.570796328506681, -1.1511901302727185, -3.141592653589793) q[0]; +u3(2.9508419530365497, -1.5707963267948901, 1.570796326794903) q[2]; diff --git a/test/circuits/approximateEquivalenceTest/vqe_indep_qiskit_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/vqe_indep_qiskit_10_no_measure.qasm new file mode 100644 index 00000000..26c7c029 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/vqe_indep_qiskit_10_no_measure.qasm @@ -0,0 +1,57 @@ +// Benchmark was created by MQT Bench on 2024-03-19 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +ry(-3.141235478528481) q[0]; +ry(1.5706979045022578) q[1]; +ry(-2.362236077972896e-05) q[2]; +ry(-3.1399208277229347) q[3]; +ry(-0.0011147396600802526) q[4]; +ry(-1.1042563024883283) q[5]; +ry(2.9801510328183927) q[6]; +ry(3.0545670522151607) q[7]; +ry(-1.3668142934358305) q[8]; +ry(-2.9083999118928885) q[9]; +cx q[8],q[9]; +cx q[7],q[8]; +cx q[6],q[7]; +cx q[5],q[6]; +cx q[4],q[5]; +cx q[3],q[4]; +cx q[2],q[3]; +cx q[1],q[2]; +cx q[0],q[1]; +ry(1.599653982977371) q[0]; +ry(-0.003280589550612297) q[1]; +ry(0.0034061099135506466) q[2]; +ry(-1.1679350002528048) q[3]; +ry(pi) q[4]; +ry(-2.7302797356431983) q[5]; +ry(-2.6925756675472736) q[6]; +ry(-0.941592140077449) q[7]; +ry(-0.8734936311655543) q[8]; +ry(-2.300413555921887) q[9]; +cx q[8],q[9]; +cx q[7],q[8]; +cx q[6],q[7]; +cx q[5],q[6]; +cx q[4],q[5]; +cx q[3],q[4]; +cx q[2],q[3]; +cx q[1],q[2]; +cx q[0],q[1]; +ry(1.5993512590035681) q[0]; +ry(1.5708506148951475) q[1]; +ry(0.0006026837145775064) q[2]; +ry(-1.5710638349849695) q[3]; +ry(1.1673330914635904) q[4]; +ry(-1.9859733062653429) q[5]; +ry(2.8994628483268934) q[6]; +ry(-1.6023537028276675) q[7]; +ry(-1.493367754442654) q[8]; +ry(0.5041276741646578) q[9]; diff --git a/test/circuits/approximateEquivalenceTest/vqe_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/vqe_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..48b460d6 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/vqe_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,140 @@ +// Benchmark was created by MQT Bench on 2024-03-19 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +sx q[0]; +rz(3.1415813049085717) q[0]; +sx q[0]; +rz(-pi) q[0]; +sx q[1]; +rz(1.570786589208974) q[1]; +sx q[1]; +rz(-pi) q[1]; +rz(-pi) q[2]; +sx q[2]; +rz(3.1415799921181318) q[2]; +sx q[2]; +rz(-pi) q[3]; +x q[3]; +sx q[4]; +rz(3.1414744590066235) q[4]; +sx q[4]; +rz(-pi) q[4]; +rz(-pi) q[5]; +x q[5]; +rz(-pi) q[6]; +x q[6]; +sx q[7]; +rz(0.47424615833851735) q[7]; +sx q[7]; +rz(-pi) q[7]; +rz(-pi) q[8]; +sx q[8]; +rz(1.69789688435345) q[8]; +sx q[8]; +rz(-pi) q[9]; +sx q[9]; +rz(1.9415420397245624) q[9]; +sx q[9]; +cx q[8],q[9]; +cx q[7],q[8]; +cx q[6],q[7]; +cx q[5],q[6]; +cx q[4],q[5]; +cx q[3],q[4]; +cx q[2],q[3]; +cx q[1],q[2]; +cx q[0],q[1]; +sx q[0]; +rz(3.141523748482429) q[0]; +sx q[0]; +rz(-pi) q[1]; +sx q[1]; +rz(0.9545951268105295) q[1]; +sx q[1]; +rz(-pi) q[2]; +sx q[2]; +rz(2.1871374559262557) q[2]; +sx q[2]; +rz(-pi) q[3]; +x q[3]; +rz(-pi) q[4]; +sx q[4]; +rz(2.292662039948823e-05) q[4]; +sx q[4]; +rz(0) q[5]; +sx q[5]; +rz(3.141574454779419) q[5]; +sx q[5]; +rz(3*pi) q[5]; +sx q[6]; +rz(0.0002655815817722562) q[6]; +sx q[6]; +rz(-pi) q[6]; +sx q[7]; +rz(0.490262872023405) q[7]; +sx q[7]; +rz(-pi) q[7]; +sx q[8]; +rz(1.3153030676962363) q[8]; +sx q[8]; +rz(-pi) q[8]; +sx q[9]; +rz(2.0164192929845965) q[9]; +sx q[9]; +rz(-pi) q[9]; +cx q[8],q[9]; +cx q[7],q[8]; +cx q[6],q[7]; +cx q[5],q[6]; +cx q[4],q[5]; +cx q[3],q[4]; +cx q[2],q[3]; +cx q[1],q[2]; +cx q[0],q[1]; +sx q[0]; +rz(9.846008903835468e-05) q[0]; +sx q[0]; +rz(-pi) q[1]; +sx q[1]; +rz(2.498619853451748) q[1]; +sx q[1]; +sx q[2]; +rz(3.1415403906446215) q[2]; +sx q[2]; +rz(-pi) q[2]; +sx q[3]; +rz(2.498776476853159) q[3]; +sx q[3]; +rz(-pi) q[3]; +rz(0) q[4]; +sx q[4]; +rz(6.283166696845613) q[4]; +sx q[4]; +rz(3*pi) q[4]; +sx q[5]; +rz(0.008876342139857218) q[5]; +sx q[5]; +rz(-pi) q[5]; +rz(-pi) q[6]; +sx q[6]; +rz(3.141505956672047) q[6]; +sx q[6]; +sx q[7]; +rz(2.8752078813145037) q[7]; +sx q[7]; +rz(-pi) q[7]; +rz(-pi) q[8]; +sx q[8]; +rz(0.35300094805126037) q[8]; +sx q[8]; +rz(-pi) q[9]; +sx q[9]; +rz(0.3635786676337345) q[9]; +sx q[9]; diff --git a/test/circuits/approximateEquivalenceTest/wstate_indep_qiskit_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/wstate_indep_qiskit_10_no_measure.qasm new file mode 100644 index 00000000..09e46da9 --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/wstate_indep_qiskit_10_no_measure.qasm @@ -0,0 +1,46 @@ +// Benchmark was created by MQT Bench on 2024-03-19 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +ry(-pi/4) q[0]; +ry(-0.9553166181245093) q[1]; +ry(-pi/3) q[2]; +ry(-1.1071487177940904) q[3]; +ry(-1.1502619915109316) q[4]; +ry(-1.183199640139716) q[5]; +ry(-1.2094292028881888) q[6]; +ry(-1.2309594173407747) q[7]; +ry(-1.2490457723982544) q[8]; +x q[9]; +cz q[9],q[8]; +ry(1.2490457723982544) q[8]; +cz q[8],q[7]; +ry(1.2309594173407747) q[7]; +cz q[7],q[6]; +ry(1.2094292028881888) q[6]; +cz q[6],q[5]; +ry(1.183199640139716) q[5]; +cz q[5],q[4]; +ry(1.1502619915109316) q[4]; +cz q[4],q[3]; +ry(1.1071487177940904) q[3]; +cz q[3],q[2]; +ry(pi/3) q[2]; +cz q[2],q[1]; +ry(0.9553166181245093) q[1]; +cz q[1],q[0]; +ry(pi/4) q[0]; +cx q[8],q[9]; +cx q[7],q[8]; +cx q[6],q[7]; +cx q[5],q[6]; +cx q[4],q[5]; +cx q[3],q[4]; +cx q[2],q[3]; +cx q[1],q[2]; +cx q[0],q[1]; diff --git a/test/circuits/approximateEquivalenceTest/wstate_nativegates_ibm_qiskit_opt3_10_no_measure.qasm b/test/circuits/approximateEquivalenceTest/wstate_nativegates_ibm_qiskit_opt3_10_no_measure.qasm new file mode 100644 index 00000000..f9c028bf --- /dev/null +++ b/test/circuits/approximateEquivalenceTest/wstate_nativegates_ibm_qiskit_opt3_10_no_measure.qasm @@ -0,0 +1,83 @@ +// Benchmark was created by MQT Bench on 2024-03-19 +// For more information about MQT Bench, please visit https://www.cda.cit.tum.de/mqtbench/ +// MQT Bench version: 1.1.0 +// Qiskit version: 1.0.2 +// Used Gate Set: ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'barrier'] + +OPENQASM 2.0; +include "qelib1.inc"; +qreg q[10]; +creg meas[10]; +sx q[0]; +rz(pi/4) q[0]; +sx q[0]; +sx q[1]; +rz(0.6154797086703874) q[1]; +sx q[1]; +sx q[2]; +rz(pi/6) q[2]; +sx q[2]; +sx q[3]; +rz(0.46364760900080615) q[3]; +sx q[3]; +sx q[4]; +rz(0.42053433528396456) q[4]; +sx q[4]; +sx q[5]; +rz(0.38759668665518054) q[5]; +sx q[5]; +sx q[6]; +rz(0.361367123906708) q[6]; +sx q[6]; +sx q[7]; +rz(0.33983690945412137) q[7]; +sx q[7]; +sx q[8]; +rz(0.32175055439664213) q[8]; +sx q[8]; +x q[9]; +cx q[9],q[8]; +sx q[8]; +rz(0.32175055439664213) q[8]; +sx q[8]; +cx q[8],q[7]; +sx q[7]; +rz(0.3398369094541218) q[7]; +sx q[7]; +cx q[7],q[6]; +sx q[6]; +rz(0.36136712390670755) q[6]; +sx q[6]; +cx q[6],q[5]; +sx q[5]; +rz(0.387596686655181) q[5]; +sx q[5]; +cx q[5],q[4]; +sx q[4]; +rz(0.420534335283965) q[4]; +sx q[4]; +cx q[4],q[3]; +sx q[3]; +rz(0.46364760900080615) q[3]; +sx q[3]; +cx q[3],q[2]; +sx q[2]; +rz(pi/6) q[2]; +sx q[2]; +cx q[2],q[1]; +sx q[1]; +rz(0.6154797086703869) q[1]; +sx q[1]; +cx q[1],q[0]; +sx q[0]; +rz(pi/4) q[0]; +sx q[0]; +cx q[8],q[9]; +cx q[7],q[8]; +cx q[6],q[7]; +cx q[5],q[6]; +cx q[4],q[5]; +cx q[3],q[4]; +cx q[2],q[3]; +cx q[1],q[2]; +cx q[0],q[1]; diff --git a/test/legacy/test_functionality.cpp b/test/legacy/test_functionality.cpp index 2b61c0ce..7af73ee5 100644 --- a/test/legacy/test_functionality.cpp +++ b/test/legacy/test_functionality.cpp @@ -33,6 +33,7 @@ class FunctionalityTest : public testing::TestWithParam { config.execution.runAlternatingChecker = false; config.execution.runSimulationChecker = false; config.execution.runZXChecker = false; + config.execution.runHSFChecker = false; config.simulation.maxSims = 16; config.application.constructionScheme = ec::ApplicationSchemeType::Sequential; diff --git a/test/legacy/test_general.cpp b/test/legacy/test_general.cpp index 90c0f175..882a772c 100644 --- a/test/legacy/test_general.cpp +++ b/test/legacy/test_general.cpp @@ -69,6 +69,7 @@ TEST_F(GeneralTest, NothingToDo) { config.execution.runSimulationChecker = false; config.execution.runConstructionChecker = false; config.execution.runZXChecker = false; + config.execution.runHSFChecker = false; auto ecm = ec::EquivalenceCheckingManager(qc1, qc2, config); ecm.run(); diff --git a/test/legacy/test_journal.cpp b/test/legacy/test_journal.cpp index 9d772079..20e8d0fc 100644 --- a/test/legacy/test_journal.cpp +++ b/test/legacy/test_journal.cpp @@ -154,6 +154,7 @@ TEST_P(JournalTestNonEQ, PowerOfSimulation) { config.execution.runConstructionChecker = false; config.execution.runSimulationChecker = true; config.execution.runZXChecker = false; + config.execution.runHSFChecker = false; config.execution.parallel = false; config.execution.timeout = 60.; config.simulation.maxSims = 16U; @@ -207,6 +208,7 @@ TEST_P(JournalTestNonEQ, PowerOfSimulationParallel) { config.execution.runAlternatingChecker = false; config.execution.runConstructionChecker = false; config.execution.runZXChecker = false; + config.execution.runHSFChecker = false; config.execution.runSimulationChecker = true; config.execution.parallel = true; config.execution.timeout = 60.; @@ -273,6 +275,7 @@ class JournalTestEQ : public testing::TestWithParam { config.execution.runConstructionChecker = false; config.execution.runAlternatingChecker = false; config.execution.runZXChecker = false; + config.execution.runHSFChecker = false; config.execution.runSimulationChecker = false; config.simulation.maxSims = 16; config.application.simulationScheme = ec::ApplicationSchemeType::OneToOne; diff --git a/test/python/test_approximate_equivalence.py b/test/python/test_approximate_equivalence.py new file mode 100644 index 00000000..c57261b8 --- /dev/null +++ b/test/python/test_approximate_equivalence.py @@ -0,0 +1,56 @@ +"""Tests the partial equivalence checking support of QCEC.""" + +from __future__ import annotations + +import pytest +from qiskit import QuantumCircuit + +from mqt import qcec + + +@pytest.fixture +def original_circuit() -> QuantumCircuit: + """Fixture for a simple circuit.""" + qc = QuantumCircuit(3) + qc.mcx([0, 1], 2) + return qc + + +@pytest.fixture +def alternative_circuit() -> QuantumCircuit: + """Fixture for an approximately equivalent version of the simple circuit.""" + qc = QuantumCircuit(3) + qc.id(0) + qc.id(1) + qc.id(2) + return qc + + +def test_configuration_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: + """Test if the flag for approximate equivalence checking works.""" + config = qcec.Configuration() + config.execution.run_alternating_checker = True + config.execution.run_construction_checker = False + config.execution.run_simulation_checker = False + config.execution.run_zx_checker = False + config.functionality.check_approximate_equivalence = True + config.functionality.approximate_checking_threshold = 0.3 + result = qcec.verify(original_circuit, alternative_circuit, configuration=config) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent + + +def test_argument_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: + """Test if the flag for approximate equivalence checking works.""" + config = qcec.Configuration() + config.execution.run_alternating_checker = True + config.execution.run_construction_checker = False + config.execution.run_simulation_checker = False + config.execution.run_zx_checker = False + result = qcec.verify( + original_circuit, + alternative_circuit, + configuration=config, + check_approximate_equivalence=True, + approximate_checking_threshold=0.3, + ) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent diff --git a/test/python/test_hsf.py b/test/python/test_hsf.py new file mode 100644 index 00000000..2b90b643 --- /dev/null +++ b/test/python/test_hsf.py @@ -0,0 +1,60 @@ +"""Tests the partial equivalence checking support of QCEC.""" + +from __future__ import annotations + +import pytest +from qiskit import QuantumCircuit + +from mqt import qcec + + +@pytest.fixture +def original_circuit() -> QuantumCircuit: + """Fixture for a simple circuit.""" + qc = QuantumCircuit(4) + qc.cx(0, 2) + qc.cx(1, 3) + return qc + + +@pytest.fixture +def alternative_circuit() -> QuantumCircuit: + """Fixture of a second circuit that will be checked for equivalence.""" + qc = QuantumCircuit(4) + qc.id(0) + qc.id(1) + qc.id(2) + qc.id(3) + return qc + + +def test_configuration_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: + """Test if the flag for hsf equivalence checking works.""" + config = qcec.Configuration() + config.execution.run_alternating_checker = False + config.execution.run_construction_checker = False + config.execution.run_simulation_checker = False + config.execution.run_zx_checker = False + config.execution.run_hsf_checker = True + config.functionality.check_approximate_equivalence = True + config.functionality.approximate_checking_threshold = 0.8 + result = qcec.verify(original_circuit, alternative_circuit, configuration=config) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent + + +def test_argument_pec(original_circuit: QuantumCircuit, alternative_circuit: QuantumCircuit) -> None: + """Test if the flag for hsf equivalence checking works.""" + config = qcec.Configuration() + config.execution.run_alternating_checker = False + config.execution.run_construction_checker = False + config.execution.run_simulation_checker = False + config.execution.run_zx_checker = False + config.execution.run_hsf_checker = True + result = qcec.verify( + original_circuit, + alternative_circuit, + configuration=config, + check_approximate_equivalence=True, + approximate_checking_threshold=0.8, + ) + assert result.equivalence == qcec.EquivalenceCriterion.equivalent diff --git a/test/test_equality.cpp b/test/test_equality.cpp index fe93893a..9362a2c7 100644 --- a/test/test_equality.cpp +++ b/test/test_equality.cpp @@ -7,6 +7,7 @@ #include "EquivalenceCriterion.hpp" #include "checker/dd/applicationscheme/ApplicationScheme.hpp" #include "dd/DDDefinitions.hpp" +#include "ir/QuantumComputation.hpp" #include "ir/operations/Control.hpp" #include @@ -604,3 +605,154 @@ TEST_F(EqualityTest, StripIdleQubitInOutputPermutationWithAncilla) { EXPECT_EQ(ecm.getResults().numAncillae1, 0); EXPECT_EQ(ecm.getResults().numAncillae2, 0); } + +TEST_F(EqualityTest, ApproximateEquivalenceConstructionEqual) { + // Check that the difference between the circuits is below the + // approximateCheckingThreshold using the ConstructionChecker + qc1 = qc::QuantumComputation(3); + qc2 = qc::QuantumComputation(3); + // Toffoli gate + qc1.mcx({0, 1}, 2); + qc2.i(0); + config.execution.runConstructionChecker = true; + config.functionality.checkApproximateEquivalence = true; + config.functionality.approximateCheckingThreshold = 0.3; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceConstructionNotEqual) { + // Check that the difference between the circuits is above the + // approximateCheckingThreshold using the ConstructionChecker + qc1 = qc::QuantumComputation(3); + qc2 = qc::QuantumComputation(3); + // Toffoli gate + qc1.mcx({0, 1}, 2); + qc2.i(0); + config.execution.runConstructionChecker = true; + config.functionality.checkApproximateEquivalence = true; + config.functionality.approximateCheckingThreshold = 0.2; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceAlternatingEqual) { + // Check that the difference between the circuits is below the + // approximateCheckingThreshold using the AlternatingChecker + qc1 = qc::QuantumComputation(3); + qc2 = qc::QuantumComputation(3); + // Toffoli gate + qc1.mcx({0, 1}, 2); + qc2.i(0); + config.execution.runAlternatingChecker = true; + config.functionality.checkApproximateEquivalence = true; + config.functionality.approximateCheckingThreshold = 0.3; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceAlternatingNotEqual) { + // Check that the difference between the circuits is above the + // approximateCheckingThreshold using the AlternatingChecker + qc1 = qc::QuantumComputation(3); + qc2 = qc::QuantumComputation(3); + // Toffoli gate + qc1.mcx({0, 1}, 2); + qc2.i(0); + config.execution.runAlternatingChecker = true; + config.functionality.checkApproximateEquivalence = true; + config.functionality.approximateCheckingThreshold = 0.2; + ec::EquivalenceCheckingManager ecm(qc1, qc2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceBqskitToffoliDefaultError) { + // Check that the Toffoli gate is equivalent to itself after synthesizing it + // with the BQSKit compiler, which introduces by default a distance up to 1e-8 + const qc::QuantumComputation c1{ + "./circuits/approximateEquivalenceTest/toffoli.qasm"}; + const qc::QuantumComputation c2{"./circuits/approximateEquivalenceTest/" + "toffoli_out_default_error.qasm"}; + config.execution.runAlternatingChecker = true; + config.functionality.checkApproximateEquivalence = true; + // using default error threshold + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceBqskitToffoliSmallError) { + // Check that the Toffoli gate is equivalent to itself after synthesizing it + // with the BQSKit compiler, when setting the error_threshold to 5e-2 + const qc::QuantumComputation c1{ + "./circuits/approximateEquivalenceTest/toffoli.qasm"}; + const qc::QuantumComputation c2{"./circuits/approximateEquivalenceTest/" + "toffoli_out_small_error.qasm"}; + config.execution.runAlternatingChecker = true; + config.functionality.checkApproximateEquivalence = true; + config.functionality.approximateCheckingThreshold = 5e-2; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceBqskitToffoliHighError) { + // Check that the Toffoli gate is equivalent to itself after synthesizing it + // with the BQSKit compiler, when setting the error_threshold to 0.5 Here, the + // computed distance indeed exceeds the default threshold of 1e-8. + const qc::QuantumComputation c1{ + "./circuits/approximateEquivalenceTest/toffoli.qasm"}; + const qc::QuantumComputation c2{"./circuits/approximateEquivalenceTest/" + "toffoli_out_high_error.qasm"}; + config.execution.runAlternatingChecker = true; + config.functionality.checkApproximateEquivalence = true; + // using default error threshold + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); + // using non-default error threshold + config.functionality.approximateCheckingThreshold = 0.5; + ec::EquivalenceCheckingManager ecm2(c1, c2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceBqskitBellDefaultError) { + // Check that the Bell circuit is equivalent to itself after synthesizing it + // with the BQSKit compiler, which introduces by default a distance up to 1e-8 + const qc::QuantumComputation c1{ + "./circuits/approximateEquivalenceTest/bell.qasm"}; + const qc::QuantumComputation c2{"./circuits/approximateEquivalenceTest/" + "bell_out_default_error.qasm"}; + config.execution.runAlternatingChecker = true; + config.functionality.checkApproximateEquivalence = true; + // using default error threshold + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(EqualityTest, ApproximateEquivalenceBqskitBellHighError) { + // Check that the Bell circuit is equivalent to itself after synthesizing it + // with the BQSKit compiler, when setting the error_threshold to 0.5 Here, the + // computed distance indeed exceeds the default threshold of 1e-8. + const qc::QuantumComputation c1{ + "./circuits/approximateEquivalenceTest/bell.qasm"}; + const qc::QuantumComputation c2{"./circuits/approximateEquivalenceTest/" + "bell_out_high_error.qasm"}; + config.execution.runAlternatingChecker = true; + config.functionality.checkApproximateEquivalence = true; + // using default error threshold + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::NotEquivalent); + // using non-default error threshold + config.functionality.approximateCheckingThreshold = 0.5; + ec::EquivalenceCheckingManager ecm2(c1, c2, config); + ecm2.run(); + EXPECT_EQ(ecm2.equivalence(), ec::EquivalenceCriterion::Equivalent); +} diff --git a/test/test_hsf.cpp b/test/test_hsf.cpp new file mode 100644 index 00000000..325828ad --- /dev/null +++ b/test/test_hsf.cpp @@ -0,0 +1,142 @@ + +#include "Configuration.hpp" +#include "EquivalenceCheckingManager.hpp" +#include "EquivalenceCriterion.hpp" +#include "ir/QuantumComputation.hpp" + +#include +#include +/** + * Approximate equivalence checking of an original circuit 'c1' and its + * approximate version 'c2'. The circuits 'c2' were generated using the BQSKit + * compiler with synthesis_epsilon=0.3 and error_threshold=0.5. + * + */ +class HSFTest : public testing::Test { +protected: + ec::Configuration config{}; + + std::string testDir = "./circuits/approximateEquivalenceTest/"; + + void SetUp() override { + config.execution.runConstructionChecker = false; + config.execution.runAlternatingChecker = false; + config.execution.runSimulationChecker = false; + config.execution.runZXChecker = false; + config.execution.runHSFChecker = true; + config.functionality.checkApproximateEquivalence = true; + } +}; + +TEST_F(HSFTest, approximateEquivalenceCheckingWithHSF) { + // Test that enabling the approximate equivalence flag is required to use the + // HSF checker + const qc::QuantumComputation c1{testDir + + "dj_indep_qiskit_10_no_measure.qasm"}; + const qc::QuantumComputation c2{testDir + + "out_dj_indep_qiskit_10_high_error.qasm"}; + config.functionality.checkApproximateEquivalence = false; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); +} + +TEST_F(HSFTest, dj10ParallelChecking) { + // Test the parallel equivalence checking flow with only the HSF checker + // enabled + const qc::QuantumComputation c1{testDir + + "dj_indep_qiskit_10_no_measure.qasm"}; + const qc::QuantumComputation c2{testDir + + "out_dj_indep_qiskit_10_high_error.qasm"}; + config.functionality.approximateCheckingThreshold = 0.912; + config.execution.parallel = true; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(HSFTest, vqe10ParallelChecking) { + // Test the parallel equivalence checking flow with only the HSF checker + // enabled (parallel checking is enabled per default) + const qc::QuantumComputation c1{testDir + + "vqe_indep_qiskit_10_no_measure.qasm"}; + const qc::QuantumComputation c2{testDir + + "out_vqe_indep_qiskit_10_high_error.qasm"}; + config.functionality.approximateCheckingThreshold = 0.998; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(HSFTest, ghz10ParallelChecking) { + // Test the parallel equivalence checking flow where multiple checkers are + // enabled + const qc::QuantumComputation c1{ + testDir + "ghz_nativegates_ibm_qiskit_opt3_10_no_measure.qasm"}; + const qc::QuantumComputation c2{ + testDir + "out_ghz_nativegates_ibm_qiskit_opt3_10_high_error.qasm"}; + config.functionality.approximateCheckingThreshold = 0.956; + config.execution.runConstructionChecker = true; + config.execution.runAlternatingChecker = true; + config.execution.parallel = true; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(HSFTest, ghz10SequentialChecking) { + // Test the sequential equivalence checking flow where multiple checkers are + // enabled + const qc::QuantumComputation c1{ + testDir + "ghz_nativegates_ibm_qiskit_opt3_10_no_measure.qasm"}; + const qc::QuantumComputation c2{ + testDir + "out_ghz_nativegates_ibm_qiskit_opt3_10_high_error.qasm"}; + config.functionality.approximateCheckingThreshold = 0.956; + config.execution.runConstructionChecker = true; + config.execution.runAlternatingChecker = true; + config.execution.parallel = false; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(HSFTest, graphstate10SequentialChecking) { + // Test the sequential equivalence checking flow with only the HSF checker + // enabled + const qc::QuantumComputation c1{testDir + + "graphstate_indep_qiskit_10_no_measure.qasm"}; + const qc::QuantumComputation c2{ + testDir + "out_graphstate_indep_qiskit_10_high_error.qasm"}; + config.functionality.approximateCheckingThreshold = 0.912; + config.execution.parallel = false; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(HSFTest, qftNativegates10DecisionOverflow) { + // Test the HSF checker for overflow errors, ensuring that if an + // `std::overflow_error` occurs, the checker falls back to an alternative + // checker + const qc::QuantumComputation c1{ + testDir + "check/qft_nativegates_ibm_qiskit_opt3_10_no_measure.qasm"}; + const qc::QuantumComputation c2{ + testDir + "check/out_qft_nativegates_ibm_qiskit_opt3_10_high_error.qasm"}; + config.functionality.approximateCheckingThreshold = 0.999; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} + +TEST_F(HSFTest, qaoaIndep10GatesNotSupported) { + // Test the HSF checker for invalid argument errors, such as unsupported + // gates, ensuring that if an `std::invalid_argument` occurs, the checker + // falls back to an alternative checker + const qc::QuantumComputation c1{testDir + + "qaoa_indep_qiskit_10_no_measure.qasm"}; + const qc::QuantumComputation c2{testDir + + "out_qaoa_indep_qiskit_10_high_error.qasm"}; + config.functionality.approximateCheckingThreshold = 0.958; + ec::EquivalenceCheckingManager ecm(c1, c2, config); + ecm.run(); + EXPECT_EQ(ecm.equivalence(), ec::EquivalenceCriterion::Equivalent); +} diff --git a/test/test_partial_equivalence.cpp b/test/test_partial_equivalence.cpp index c330e5aa..24751300 100644 --- a/test/test_partial_equivalence.cpp +++ b/test/test_partial_equivalence.cpp @@ -361,6 +361,7 @@ class PartialEquivalenceTest : public testing::Test { config.execution.runAlternatingChecker = false; config.execution.runConstructionChecker = false; config.execution.runZXChecker = false; + config.execution.runHSFChecker = false; config.execution.nthreads = 1; config.functionality.checkPartialEquivalence = true; diff --git a/test/test_zx.cpp b/test/test_zx.cpp index 60937782..77f1f544 100644 --- a/test/test_zx.cpp +++ b/test/test_zx.cpp @@ -35,6 +35,7 @@ class ZXTest : public testing::TestWithParam { config.execution.runConstructionChecker = false; config.execution.runAlternatingChecker = false; config.execution.runSimulationChecker = false; + config.execution.runHSFChecker = false; config.execution.runZXChecker = true; } @@ -268,6 +269,7 @@ class ZXTestCompFlow : public testing::TestWithParam { config.execution.runConstructionChecker = false; config.execution.runAlternatingChecker = false; config.execution.runSimulationChecker = false; + config.execution.runHSFChecker = false; config.execution.runZXChecker = true; qcOriginal.import(testOriginalDir + GetParam() + ".real"); @@ -407,6 +409,7 @@ TEST_F(ZXTest, IdleQubit) { config.execution.runSimulationChecker = false; config.execution.runAlternatingChecker = false; config.execution.runConstructionChecker = false; + config.execution.runHSFChecker = false; ecm = std::make_unique(qc1, qc2, config); ecm->run(); @@ -443,6 +446,7 @@ TEST_F(ZXTest, TwoQubitRotations) { config.execution.runSimulationChecker = false; config.execution.runAlternatingChecker = false; config.execution.runConstructionChecker = false; + config.execution.runHSFChecker = false; ecm = std::make_unique(qc1, qc2, config); ecm->run();