Add quantum.operator to Catalyst [Operator2 work]#2883
Conversation
These will be tackled in a separate PR.
|
Hello. You may have forgotten to update the changelog!
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2883 +/- ##
==========================================
- Coverage 97.01% 96.90% -0.11%
==========================================
Files 167 166 -1
Lines 18828 19008 +180
Branches 1768 1760 -8
==========================================
+ Hits 18266 18420 +154
- Misses 417 433 +16
- Partials 145 155 +10 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Similar to qubit_map, a single param arg in python can map to multiple parameter SSA values (e.g. with pytrees), so we need a list here.
| Use this when the operator acts on a statically known set of wires. Qubits are | ||
| threaded through the op explicitly and can carry per-control values through | ||
| `in_ctrl_qubits` / `in_ctrl_values` (with matching `out_ctrl_qubits`). | ||
| This is the natural representation for fixed-arity gates and operators. |
There was a problem hiding this comment.
Generally, the number of inputs a mathematical operator acts on, in this case wires. Honestly we can just remove that sentence though:
| This is the natural representation for fixed-arity gates and operators. |
| func.func @operator_basic_qubits(%q0 : !quantum.bit, %q1 : !quantum.bit) { | ||
| %o0, %o1 = "quantum.operator"(%q0, %q1) <{op_name = "basic_qubits", operandSegmentSizes = array<i32: 0, 0, 2, 0, 0, 0, 0, 0, 0>, resultSegmentSizes = array<i32: 2, 0, 0>}> : (!quantum.bit, !quantum.bit) -> (!quantum.bit, !quantum.bit) | ||
| return | ||
| } | ||
|
|
||
| ////////////////////// | ||
| // quantum.operator // | ||
| ////////////////////// |
There was a problem hiding this comment.
| func.func @operator_basic_qubits(%q0 : !quantum.bit, %q1 : !quantum.bit) { | |
| %o0, %o1 = "quantum.operator"(%q0, %q1) <{op_name = "basic_qubits", operandSegmentSizes = array<i32: 0, 0, 2, 0, 0, 0, 0, 0, 0>, resultSegmentSizes = array<i32: 2, 0, 0>}> : (!quantum.bit, !quantum.bit) -> (!quantum.bit, !quantum.bit) | |
| return | |
| } | |
| ////////////////////// | |
| // quantum.operator // | |
| ////////////////////// | |
| ////////////////////// | |
| // quantum.operator // | |
| ////////////////////// | |
| func.func @operator_basic_qubits(%q0 : !quantum.bit, %q1 : !quantum.bit) { | |
| %o0, %o1 = "quantum.operator"(%q0, %q1) <{op_name = "basic_qubits", operandSegmentSizes = array<i32: 0, 0, 2, 0, 0, 0, 0, 0, 0>, resultSegmentSizes = array<i32: 2, 0, 0>}> : (!quantum.bit, !quantum.bit) -> (!quantum.bit, !quantum.bit) | |
| return | |
| } |
There was a problem hiding this comment.
Just swapping test and the /////// comment
| // 7. Quantum register | ||
| if (getInQreg()) { | ||
| p.printNewline(); | ||
| p << "quregs(" << getInQreg() << ") indices("; |
There was a problem hiding this comment.
I've always found the inconsistency of using both qureg and qreg to be kind of weird. Though I haven't seem qureg(s) for operand/result names or in assembly formats before, so maybe this should just be qregs?
| p << "quregs(" << getInQreg() << ") indices("; | |
| p << "qregs(" << getInQreg() << ") indices("; |
There was a problem hiding this comment.
This is purely stylistic though, so it's a non-blocking comment
There was a problem hiding this comment.
Yeah I share the frustration. On the one hand, "qureg" is more analogous to "qubit", on the other it is perhaps a bit more unconventional? If we look at precedent in Catalyst, the official name in the type system is QubitType and QuregType (written as quantum.bit and quantum.reg in the IR, avoiding the conundrum). qreg does appear as certain op argument/result names though, and maybe as program variables.
|
|
||
| func.func @operator_custom_with_decompositions(%q : !quantum.bit) { | ||
| %out = quantum.operator "custom_with_decompositions"() qubits(%q) | ||
| decompositions = [@decomp_a, @decomp_b] |
There was a problem hiding this comment.
I would've expected MLIR to have automatic verification about whether symbols exist in the IR or not. Should that be included in the verifier?
There was a problem hiding this comment.
Good idea! There is also a SymbolUser interface, although I'd have to check to see if it allows for optional symbols
There was a problem hiding this comment.
Gemini says yes, but I always take AI answers about MLIR with a grain of salt
|
|
||
| // ----- | ||
|
|
||
| func.func @operator_invalid_forward_args_without_uid(%fwd : i64, %q0 : !quantum.bit, %q1 : !quantum.bit) { |
There was a problem hiding this comment.
Should there be assembly format tests for this and following tests?
There was a problem hiding this comment.
I don't think we gain from testing invalid states in custom assembly necessarily, unless the custom assembly enables invalid states that the generic form doesn't allow?
| The `quantum.operator` is a generic representation for arbitrary quantum operations | ||
| that cannot be expressed by the simpler `quantum.custom` op and don't have a dedicated | ||
| operation. | ||
| It's purpose is to represent high-level operations from frontend languages such as |
There was a problem hiding this comment.
| It's purpose is to represent high-level operations from frontend languages such as | |
| Its purpose is to represent high-level operations from frontend languages such as |
|
Do you mind running Non blocking if it turns out to be too much trouble |
Great idea, thanks! 5937954, it hadn't been updated in a while, so there are few additional changes in there. |
Provides the new MLIR operation for advanced quantum operators as defined by this ADR. The following is provided in this PR:
ParametrizedGateinterfaceFuture PRs will tackle:
[sc-120860]