Skip to content

Decomposition hangs when no basis supplied #5106

Description

@atgeller

Required prerequisites

  • Consult the security policy. If reporting a security vulnerability, do not report the bug using this form. Use the process described in the policy to report the issue.
  • Make sure you've read the documentation. Your issue may be addressed there.
  • Search the issue tracker to verify that this hasn't already been reported. +1 or comment there if it has.
  • If possible, make a PR with a failing test to give us a starting point to work on!

Describe the bug

Decomposition on Quake with multi-qubit exp_pauli with no basis hangs instead of failing/backing out. Looks like there's no check for this case which should cause the pass to fail immediately.

The below report is from Claude:

The culprit is in Decomposition.cpp lines 52–55. When basis is empty and enabledPatterns is also empty, it loads all decomposition patterns with populateWithAllDecompositionPatterns and then runs applyPatternsGreedily. With no basis:

There's no conversion target telling the rewriter which ops are already "done" — so it never stops firing
Patterns can cycle: e.g. decomposing exp_paulix(1) → something that fires another pattern that reconstitutes the same structure
The applyPatternsGreedily worklist keeps refilling and never reaches a fixed point, so it spins. The code comment in Passes.td says "the pass application will fail" when no basis is given, but there's no early-exit guard in the implementation — it falls through to the hang instead.

The fix would be a quick guard at the top of initialize:

if (basis.empty() && enabledPatterns.empty()) {
  mlir::emitWarning(mlir::UnknownLoc::get(context),
                  "Decomposition: 'basis' must be specified");
  return failure();
}

Steps to reproduce the bug

module {
  func.func @__nvqpp__mlirgen__exp_pauli_veq2()
      attributes {"cudaq-entrypoint", "cudaq-kernel"} {
    %0 = quake.alloca !quake.veq<2>
    %a = arith.constant 0.5 : f64
    quake.exp_pauli (%a) %0 to "ZZ" : (f64, !quake.veq<2>) -> ()
    quake.dealloc %0 : !quake.veq<2>
    return
  }
}

With cudaq-opt --decomposition

Expected behavior

Warning and pass backs out to fail compositionally

Is this a regression? If it is, put the last known working version (or commit) here.

Not a regression

Environment

  • CUDA-Q version:
  • Python version:
  • C++ compiler:
  • Operating system:

Suggestions

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions