| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "QuantumDialect.h" |
| #include "QuantumOps.h" |
| #include "QuantumTypes.h" |
|
|
| using namespace mlir; |
| using namespace mlir::quantum; |
|
|
| |
| |
| |
|
|
| |
| |
|
|
| LogicalResult verifyNoCloning(Operation *op) { |
| for (Value result : op->getResults()) { |
| |
| if (!isa<QubitType, QuregType>(result.getType())) |
| continue; |
|
|
| |
| if (!result.hasOneUse()) { |
| |
| if (result.use_empty()) { |
| if (auto funcOp = dyn_cast<func::FuncOp>(op->getParentOp())) { |
| if (op == funcOp.getBody().front().getTerminator()) |
| continue; |
| } |
| return op->emitOpError() |
| << "quantum resource has no use (leak detected)"; |
| } |
|
|
| return op->emitOpError() |
| << "quantum resource has " << result.getUses().size() |
| << " uses (no-cloning violation: expected exactly 1)"; |
| } |
| } |
| return success(); |
| } |
|
|
| |
| |
| |
|
|
| LogicalResult UnitaryOp::verify() { |
| |
| if (failed(verifyNoCloning(getOperation()))) |
| return failure(); |
|
|
| |
| auto angles = getAngles(); |
| auto qubits = getQubits(); |
| if (qubits.size() != angles.size()) { |
| |
| if (angles.size() != 1) |
| return emitOpError("angle count (") |
| << angles.size() << ") must match qubit count (" |
| << qubits.size() << ") or be a single broadcast angle"; |
| } |
|
|
| |
| if (auto axis = getAxis()) { |
| StringRef a = axis.value(); |
| if (a != "X" && a != "Y" && a != "Z" && a != "arbitrary") |
| return emitOpError("axis must be one of X, Y, Z, arbitrary; got '") |
| << a << "'"; |
| } |
|
|
| return success(); |
| } |
|
|
| |
| |
| |
|
|
| LogicalResult EntangleOp::verify() { |
| |
| if (failed(verifyNoCloning(getOperation()))) |
| return failure(); |
|
|
| |
| if (getControls().empty()) |
| return emitOpError("entangle requires at least one control qubit"); |
| if (getTargets().empty()) |
| return emitOpError("entangle requires at least one target qubit"); |
|
|
| |
| if (getOutControls().size() != getControls().size()) |
| return emitOpError("output control count must match input control count"); |
| if (getOutTargets().size() != getTargets().size()) |
| return emitOpError("output target count must match input target count"); |
|
|
| return success(); |
| } |
|
|
| |
| |
| |
|
|
| LogicalResult MeasureOp::verify() { |
| |
| if (failed(verifyNoCloning(getOperation()))) |
| return failure(); |
|
|
| |
| if (getBits().size() != getQubits().size()) |
| return emitOpError("bit count must match qubit count"); |
|
|
| |
| if (getCollapsed().size() != getQubits().size()) |
| return emitOpError("collapsed count must match qubit count"); |
|
|
| return success(); |
| } |
|
|
| |
| |
| |
|
|
| LogicalResult AllocOp::verify() { |
| |
| return verifyNoCloning(getOperation()); |
| } |
|
|
| |
| |
| |
|
|
| LogicalResult ExtractRefOp::verify() { |
| |
| if (auto sizeAttr = getSource().getType().dyn_cast<QuregType>().getSize()) { |
| int64_t idx = getIndex().getSExtValue(); |
| if (idx < 0 || idx >= *sizeAttr) |
| return emitOpError("index ") |
| << idx << " out of bounds for qureg of size " << *sizeAttr; |
| } |
| return success(); |
| } |
|
|
| |
| |
| |
|
|
| LogicalResult SubveqOp::verify() { |
| if (auto sizeAttr = getSource().getType().dyn_cast<QuregType>().getSize()) { |
| int64_t low = getLow().getSExtValue(); |
| int64_t high = getHigh().getSExtValue(); |
| if (low < 0 || high > *sizeAttr || low >= high) |
| return emitOpError("invalid range [") |
| << low << ", " << high << ") for qureg of size " << *sizeAttr; |
| } |
| return success(); |
| } |
|
|
| |
| |
| |
|
|
| LogicalResult ExpPauliOp::verify() { |
| |
| if (failed(verifyNoCloning(getOperation()))) |
| return failure(); |
|
|
| |
| auto pauli = getPauli(); |
| auto qubits = getQubits(); |
| if (pauli.size() != qubits.size()) |
| return emitOpError("pauli string length (") |
| << pauli.size() << ") must match qubit count (" |
| << qubits.size() << ")"; |
|
|
| |
| for (auto [i, val] : llvm::enumerate(pauli)) { |
| int p = val.cast<IntegerAttr>().getSExtValue(); |
| if (p < 0 || p > 3) |
| return emitOpError("pauli[") |
| << i << "] = " << p << " must be 0 (I), 1 (X), 2 (Y), or 3 (Z)"; |
| } |
|
|
| return success(); |
| } |
|
|