Skip to content

Commit

Permalink
♻️ operations: simplify getStandardOperationDD
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshy-R committed Nov 14, 2024
1 parent fcff7d5 commit bc1b9c7
Showing 1 changed file with 77 additions and 125 deletions.
202 changes: 77 additions & 125 deletions include/mqt-core/dd/Operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,83 +22,87 @@
#include <vector>

namespace dd {
// single-target Operations
template <class Config>
qc::MatrixDD
getStandardOperationDD(const qc::StandardOperation* op, Package<Config>& dd,
const qc::Controls& controls, const qc::Qubit target,
const bool inverse) {
GateMatrix gm;

const auto type = op->getType();
inline std::tuple<qc::OpType, fp, fp, fp>
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<qc::OpType>(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 <class Config>
qc::MatrixDD getStandardOperationDD(const qc::StandardOperation* op,
Package<Config>& 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
Expand All @@ -107,64 +111,11 @@ qc::MatrixDD
getStandardOperationDD(const qc::StandardOperation* op, Package<Config>& 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
Expand Down Expand Up @@ -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<DDType, qc::VectorDD>) {
on = dd.multiply(swapDD, on);
} else {
Expand Down

0 comments on commit bc1b9c7

Please sign in to comment.