Skip to content

✨ MLIR - Rotation Gate Merge Pass/Pattern #898

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
DRovara opened this issue Apr 2, 2025 · 0 comments
Open

✨ MLIR - Rotation Gate Merge Pass/Pattern #898

DRovara opened this issue Apr 2, 2025 · 0 comments
Labels
c++ Anything related to C++ code enhancement New feature or request good first issue Good for newcomers MLIR Anything related to MLIR
Milestone

Comments

@DRovara
Copy link
Collaborator

DRovara commented Apr 2, 2025

What's the problem this feature will solve?

We recently introduced the first optimization passes for the MLIR ecosystem we are building #892.
Now this opens up a flood of options for implementing further optimization passes.
One that would be nice to have is an optimization pass that merges rotation gates wherever possible.

Example (qasm-style):

rx(pi/2) q[0];
rx(pi/2) q[0];

could be merged into

rx(pi) q[0];

Currently, we only have a pass that cancels consecutive inverse gates (see

def CancelConsecutiveInverses : Pass<"cancel-consecutive-inverses", "mlir::ModuleOp"> {
let summary = "This pass searches for consecutive applications of gates and their inverses and cancels them.";
let description = [{
This pass searches for applications of gates that are their own inverses. Walking down their def-use chain,
it then checks if the same gate is applied once again. In that case, the two gates are cancelled.
}];
}
, https://github.com/munich-quantum-toolkit/core/blob/main/mlir/lib/Dialect/MQTOpt/Transforms/CancelConsecutiveInverses.cpp, and https://github.com/munich-quantum-toolkit/core/blob/main/mlir/lib/Dialect/MQTOpt/Transforms/CancelConsecutiveInversesPattern.cpp).
However, that pass does not handle parametrized gates such as rotation gates.

Describe the solution you'd like

I see two possible ways to implement this:

  • This new feature could be added as a new pattern to that pass as the features are related and might use similar helper methods (in that case, the pass would have to be renamed).
  • This new feature could be added as an entirely new transformation pass.

Both strategies seem reasonable at first glance.

In any case, the pass should at least cover the following rotation gates:

  • rx, ry, rz, phase
  • rxx, ryy, rzz, rzx
  • xx_minus_yy, xx_plus_yy
  • U, U2

Most likely, an optional parameter for defining a tolerance value would be useful for controlling, when two parametrized gates cancel one another.

Cancellation rules could be derived from

core/src/dd/Operations.cpp

Lines 74 to 142 in d88d1f0

// invert the operation
std::vector<fp> params = op.getParameter();
std::vector<qc::Qubit> targetQubits = targets;
switch (type) {
// operations that are self-inverse do not need any changes
case qc::I:
case qc::H:
case qc::X:
case qc::Y:
case qc::Z:
case qc::SWAP:
case qc::ECR:
break;
// operations that have an inverse gate with the same parameters
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:
type = static_cast<qc::OpType>(+type ^ qc::OpTypeInv);
break;
// operations that can be inversed by negating the first parameter
case qc::RXX:
case qc::RYY:
case qc::RZZ:
case qc::RZX:
case qc::RX:
case qc::RY:
case qc::RZ:
case qc::P:
case qc::XXminusYY:
case qc::XXplusYY:
params[0U] = -params[0U];
break;
// other special cases
case qc::DCX:
if (targetQubits.size() != 2) {
throw std::runtime_error("Invalid target qubits for DCX");
}
// DCX is not self-inverse, but the inverse is just swapping the targets
std::swap(targetQubits[0], targetQubits[1]);
break;
// invert all parameters
case qc::U:
// swap [a, b, c] to [a, c, b]
std::swap(params[1U], params[2U]);
for (auto& param : params) {
param = -param;
}
break;
case qc::U2:
std::swap(params[0U], params[1U]);
params[0U] = -params[0U] - PI;
params[1U] = -params[1U] + PI;
break;
default:
std::ostringstream oss{};
oss << "negation for gate " << op.getName() << " not available!";
throw std::runtime_error(oss.str());
}

@DRovara DRovara added c++ Anything related to C++ code enhancement New feature or request MLIR Anything related to MLIR labels Apr 2, 2025
@github-project-automation github-project-automation bot moved this to In Progress in MQT Core Apr 2, 2025
@burgholzer burgholzer added this to the MLIR Support milestone Apr 9, 2025
@burgholzer burgholzer moved this from In Progress to Todo in MQT Core Apr 11, 2025
@burgholzer burgholzer added the good first issue Good for newcomers label Apr 14, 2025
@github-project-automation github-project-automation bot moved this to Todo in MQT Core Apr 14, 2025
@burgholzer burgholzer added unitaryHack Issues and PRs intended for unitaryHack and removed good first issue Good for newcomers labels Apr 14, 2025
@burgholzer burgholzer added good first issue Good for newcomers and removed unitaryHack Issues and PRs intended for unitaryHack labels Apr 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Anything related to C++ code enhancement New feature or request good first issue Good for newcomers MLIR Anything related to MLIR
Projects
Status: Todo
Development

No branches or pull requests

2 participants