From bc1b9c764bc92d3bc96799b3ef9510f1eecf8011 Mon Sep 17 00:00:00 2001 From: joshy Date: Wed, 13 Nov 2024 11:48:49 +0100 Subject: [PATCH] :recycle: operations: simplify getStandardOperationDD --- include/mqt-core/dd/Operations.hpp | 202 +++++++++++------------------ 1 file changed, 77 insertions(+), 125 deletions(-) diff --git a/include/mqt-core/dd/Operations.hpp b/include/mqt-core/dd/Operations.hpp index 6b3b5753a..1b8fc0c9f 100644 --- a/include/mqt-core/dd/Operations.hpp +++ b/include/mqt-core/dd/Operations.hpp @@ -22,83 +22,87 @@ #include namespace dd { -// single-target Operations -template -qc::MatrixDD -getStandardOperationDD(const qc::StandardOperation* op, Package& dd, - const qc::Controls& controls, const qc::Qubit target, - const bool inverse) { - GateMatrix gm; - const auto type = op->getType(); +inline std::tuple +getOperationParameters(const qc::StandardOperation* op, qc::Qubit* target0, + qc::Qubit* target1, bool inverse) { + auto type = op->getType(); const auto& parameter = op->getParameter(); switch (type) { - case qc::I: - gm = I_MAT; - break; - case qc::H: - gm = H_MAT; - break; - case qc::X: - gm = X_MAT; - break; - case qc::Y: - gm = Y_MAT; - break; - case qc::Z: - gm = Z_MAT; - break; - case qc::S: - gm = inverse ? SDG_MAT : S_MAT; - break; - case qc::Sdg: - gm = inverse ? S_MAT : SDG_MAT; - break; - case qc::T: - gm = inverse ? TDG_MAT : T_MAT; - break; - case qc::Tdg: - gm = inverse ? T_MAT : TDG_MAT; - break; - case qc::V: - gm = inverse ? VDG_MAT : V_MAT; - break; - case qc::Vdg: - gm = inverse ? V_MAT : VDG_MAT; - break; + // clang-format off + case qc::iSWAP: case qc::iSWAPdg: + case qc::Peres: case qc::Peresdg: + case qc::S: case qc::Sdg: + case qc::T: case qc::Tdg: + case qc::V: case qc::Vdg: + case qc::SX: case qc::SXdg: + case qc::I: case qc::H: case qc::X: case qc::Y: case qc::Z: + // clang-format on + if (inverse) { + type = static_cast(type ^ qc::OP_TYPE_INV); + } + case qc::SWAP: + case qc::ECR: + return std::make_tuple(type, 0., 0., 0.); + + case qc::DCX: + if (inverse) { + if (target0 == nullptr || target1 == nullptr) { + throw qc::QFRException("Invalid target qubits for DCX"); + } + + // DCX is not self-inverse, but the inverse is just swapping the targets + std::swap(*target0, *target1); + } + return std::make_tuple(type, 0., 0., 0.); + case qc::XXminusYY: + case qc::XXplusYY: + if (inverse) { + return std::make_tuple(type, -parameter[0U], parameter[1U], 0.); + } + return std::make_tuple(type, parameter[0U], parameter[1U], 0.); + // clang-format off + case qc::RXX: case qc::RYY: case qc::RZZ: case qc::RZX: + case qc::RX: case qc::RY: case qc::RZ: + case qc::P: + // clang-format on + if (inverse) { + return std::make_tuple(type, -parameter[0U], 0., 0.); + } + + return std::make_tuple(type, parameter[0U], 0., 0.); case qc::U: - gm = inverse ? uMat(-parameter[1U], -parameter[2U], -parameter[0U]) - : uMat(parameter[2U], parameter[1U], parameter[0U]); - break; + if (inverse) { + return std::make_tuple(type, -parameter[1U], -parameter[2U], + -parameter[0U]); + } + + return std::make_tuple(type, parameter[2U], parameter[1U], parameter[0U]); case qc::U2: - gm = inverse ? u2Mat(-parameter[0U] + PI, -parameter[1U] - PI) - : u2Mat(parameter[1U], parameter[0U]); - break; - case qc::P: - gm = inverse ? pMat(-parameter[0U]) : pMat(parameter[0U]); - break; - case qc::SX: - gm = inverse ? SXDG_MAT : SX_MAT; - break; - case qc::SXdg: - gm = inverse ? SX_MAT : SXDG_MAT; - break; - case qc::RX: - gm = inverse ? rxMat(-parameter[0U]) : rxMat(parameter[0U]); - break; - case qc::RY: - gm = inverse ? ryMat(-parameter[0U]) : ryMat(parameter[0U]); - break; - case qc::RZ: - gm = inverse ? rzMat(-parameter[0U]) : rzMat(parameter[0U]); - break; + if (inverse) { + return std::make_tuple(type, -parameter[1U] + PI, -parameter[1U] - PI, + 0.); + } + return std::make_tuple(type, parameter[1U], parameter[1U], 0.); default: std::ostringstream oss{}; - oss << "DD for gate" << op->getName() << " not available!"; + oss << "DD for gate " << op->getName() << " not available!"; throw qc::QFRException(oss.str()); } - return dd.makeGateDD(gm, controls, target); +} + +// single-target Operations +template +qc::MatrixDD getStandardOperationDD(const qc::StandardOperation* op, + Package& dd, + const qc::Controls& controls, + qc::Qubit target, const bool inverse) { + auto [type, lambda, phi, theta] = + getOperationParameters(op, &target, nullptr, inverse); + + return dd.makeGateDD(opToSingleGateMatrix(type, lambda, phi, theta), controls, + target); } // two-target Operations @@ -107,64 +111,11 @@ qc::MatrixDD getStandardOperationDD(const qc::StandardOperation* op, Package& dd, const qc::Controls& controls, qc::Qubit target0, qc::Qubit target1, const bool inverse) { - const auto type = op->getType(); - const auto& parameter = op->getParameter(); - - if (type == qc::DCX && inverse) { - // DCX is not self-inverse, but the inverse is just swapping the targets - std::swap(target0, target1); - } - - TwoQubitGateMatrix gm; - switch (type) { - case qc::SWAP: - gm = SWAP_MAT; - break; - case qc::iSWAP: - gm = inverse ? ISWAPDG_MAT : ISWAP_MAT; - break; - case qc::iSWAPdg: - gm = inverse ? ISWAP_MAT : ISWAPDG_MAT; - break; - case qc::Peres: - gm = inverse ? PERESDG_MAT : PERES_MAT; - break; - case qc::Peresdg: - gm = inverse ? PERES_MAT : PERESDG_MAT; - break; - case qc::DCX: - gm = DCX_MAT; - break; - case qc::ECR: - gm = ECR_MAT; - break; - case qc::RXX: - gm = inverse ? rxxMat(-parameter[0U]) : rxxMat(parameter[0U]); - break; - case qc::RYY: - gm = inverse ? ryyMat(-parameter[0U]) : ryyMat(parameter[0U]); - break; - case qc::RZZ: - gm = inverse ? rzzMat(-parameter[0U]) : rzzMat(parameter[0U]); - break; - case qc::RZX: - gm = inverse ? rzxMat(-parameter[0U]) : rzxMat(parameter[0U]); - break; - case qc::XXminusYY: - gm = inverse ? xxMinusYYMat(-parameter[0U], parameter[1U]) - : xxMinusYYMat(parameter[0U], parameter[1U]); - break; - case qc::XXplusYY: - gm = inverse ? xxPlusYYMat(-parameter[0U], parameter[1U]) - : xxPlusYYMat(parameter[0U], parameter[1U]); - break; - default: - std::ostringstream oss{}; - oss << "DD for gate " << op->getName() << " not available!"; - throw qc::QFRException(oss.str()); - } + auto [type, theta, beta, _] = + getOperationParameters(op, &target0, &target1, inverse); - return dd.makeTwoQubitGateDD(gm, controls, target0, target1); + return dd.makeTwoQubitGateDD(opToTwoQubitGateMatrix(type, theta, beta), + controls, target0, target1); } // The methods with a permutation parameter apply these Operations according to @@ -305,7 +256,8 @@ void changePermutation(DDType& on, qc::Permutation& from, // swap i and j auto saved = on; - const auto swapDD = dd.makeTwoQubitGateDD(SWAP_MAT, from.at(i), from.at(j)); + const auto swapDD = dd.makeTwoQubitGateDD(opToTwoQubitGateMatrix(qc::SWAP), + from.at(i), from.at(j)); if constexpr (std::is_same_v) { on = dd.multiply(swapDD, on); } else {