Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions doc/releases/changelog-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
program outputs are typically probabilistic and statistics produced by measurement processes are
conditional on the selected decision tree path.

* Two new verifiers were added to the `quantum.paulirot` operation. They verify that the Pauli word
length and the number of qubit operands are the same, and that all of the Pauli words are legal.
[(#2405)](https://github.com/PennyLaneAI/catalyst/pull/2405)

<h3>Breaking changes 💔</h3>

<h3>Deprecations 👋</h3>
Expand Down Expand Up @@ -47,7 +51,8 @@
<h3>Contributors ✍️</h3>

This release contains contributions from (in alphabetical order):
Ali Asadi
Ali Asadi,
Sengthai Heng,
Jeffrey Kam,
Mudit Pandey.
Mudit Pandey,
Paul Haochen Wang.
1 change: 1 addition & 0 deletions mlir/include/Quantum/IR/QuantumAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,6 @@ def NamedObservable : I32EnumAttr<"NamedObservable",

def NamedObservableAttr : EnumAttr<QuantumDialect, NamedObservable, "named_observable">;

def PauliWord : TypedArrayAttrBase<StrAttr, "A product of Pauli operators, aka a Pauli word.">;

#endif // QUANTUM_ATTR_DEFS
4 changes: 2 additions & 2 deletions mlir/include/Quantum/IR/QuantumOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -534,8 +534,6 @@ def CustomOp : UnitaryGate_Op<"custom", [DifferentiableGate, NoMemoryEffect,
let hasVerifier = 1;
}

def PauliWord : TypedArrayAttrBase<StrAttr, "A product of Pauli operators, aka a Pauli word.">;

def PauliRotOp : UnitaryGate_Op<"paulirot", [DifferentiableGate, NoMemoryEffect,
AttrSizedOperandSegments, AttrSizedResultSegments]> {
let summary = "Apply a Pauli Product Rotation";
Expand Down Expand Up @@ -571,6 +569,8 @@ def PauliRotOp : UnitaryGate_Op<"paulirot", [DifferentiableGate, NoMemoryEffect,
return getODSOperands(getParamOperandIdx());
}
}];

let hasVerifier = 1;
}

def GlobalPhaseOp : UnitaryGate_Op<"gphase", [DifferentiableGate, AttrSizedOperandSegments]> {
Expand Down
21 changes: 21 additions & 0 deletions mlir/lib/Quantum/IR/QuantumOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,27 @@ static LogicalResult verifyTensorResult(Type ty, int64_t length0, int64_t length

// ----- gates

static const mlir::StringSet<> validPauliWords = {"X", "Y", "Z", "I"};

LogicalResult PauliRotOp::verify()
{
size_t pauliWordLength = getPauliProduct().size();
size_t numQubits = getInQubits().size();
if (pauliWordLength != numQubits) {
return emitOpError() << "length of Pauli word (" << pauliWordLength
<< ") and number of qubits (" << numQubits << ") must be the same";
}

if (!llvm::all_of(getPauliProduct(), [](mlir::Attribute attr) {
auto pauliStr = llvm::cast<mlir::StringAttr>(attr);
return validPauliWords.contains(pauliStr.getValue());
})) {
return emitOpError() << "Only \"X\", \"Y\", \"Z\", and \"I\" are valid Pauli words.";
}

return success();
}

LogicalResult QubitUnitaryOp::verify()
{
size_t dim = std::pow(2, getInQubits().size());
Expand Down
17 changes: 17 additions & 0 deletions mlir/test/Quantum/VerifierTest.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,23 @@ func.func @controlled2(%1 : !quantum.bit, %2 : !quantum.bit, %3 : !quantum.bit)
return
}

// -----

func.func @test_paulirot_length_mismatch(%1 : !quantum.bit, %angle: f64) {
// expected-error@+1 {{length of Pauli word (2) and number of qubits (1) must be the same}}
%q = quantum.paulirot ["Z", "X"](%angle) %1 : !quantum.bit
return
}

// -----

func.func @test_paulirot_bad_pauli_word(%1 : !quantum.bit, %angle: f64) {
// expected-error@+1 {{Only "X", "Y", "Z", and "I" are valid Pauli words.}}
%q = quantum.paulirot ["bad"](%angle) %1 : !quantum.bit
return
}

// -----

//////////////////
// Measurements //
Expand Down