Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Drop linear bits, improve pytket encoding/decoding (#420)
Removes the ad-hoc `LINEAR_BIT` used for decoding pytket circuits, and uses non-linear `BOOL_T`s instead. This now lets us encode guppy circuits with measurements; ```python module = GuppyModule("test") module.load(quantum) @guppy(module) def my_func(q0: qubit, q1: qubit) -> tuple[bool,]: q0 = phased_x(q0, py(math.pi / 2), py(-math.pi / 2)) q0 = rz(q0, py(math.pi)) q1 = phased_x(q1, py(math.pi / 2), py(-math.pi / 2)) q1 = rz(q1, py(math.pi)) q0, q1 = zz_max(q0, q1) _ = measure(q0) return (measure(q1),) circ = guppy_to_circuit(my_func) print(to_hugr_mermaid(circ)) tk1 = circ.to_tket1() render_circuit_jupyter(tk1) circ2 = Tk2Circuit(tk1) print(to_hugr_mermaid(circ2)) ``` Mermaid diagram (rooted on the `DataflowBlock`): ```mermaid graph LR subgraph 0 ["(0) Module"] direction LR subgraph 7 ["(7) FuncDefn"] direction LR 3["(3) Input"] 3--"0:0<br>qubit"-->8 3--"1:1<br>qubit"-->8 6["(6) Output"] subgraph 8 ["(8) CFG"] direction LR subgraph 1 ["(1) DataflowBlock"] direction LR 4["(4) Input"] 4--"0:0<br>qubit"-->13 4--"1:0<br>qubit"-->21 5["(5) Output"] 9["(9) const:custom:f64(1.5707963267948966)"] 9--"0:0<br>float64"-->10 10["(10) LoadConstant"] 10--"0:1<br>float64"-->13 11["(11) const:custom:f64(-1.5707963267948966)"] 11--"0:0<br>float64"-->12 12["(12) LoadConstant"] 12--"0:2<br>float64"-->13 13["(13) quantum.tket2.PhasedX"] 13--"0:0<br>qubit"-->16 14["(14) const:custom:f64(3.141592653589793)"] 14--"0:0<br>float64"-->15 15["(15) LoadConstant"] 15--"0:1<br>float64"-->16 16["(16) quantum.tket2.RzF64"] 16--"0:0<br>qubit"-->25 17["(17) const:custom:f64(1.5707963267948966)"] 17--"0:0<br>float64"-->18 18["(18) LoadConstant"] 18--"0:1<br>float64"-->21 19["(19) const:custom:f64(-1.5707963267948966)"] 19--"0:0<br>float64"-->20 20["(20) LoadConstant"] 20--"0:2<br>float64"-->21 21["(21) quantum.tket2.PhasedX"] 21--"0:0<br>qubit"-->24 22["(22) const:custom:f64(3.141592653589793)"] 22--"0:0<br>float64"-->23 23["(23) LoadConstant"] 23--"0:1<br>float64"-->24 24["(24) quantum.tket2.RzF64"] 24--"0:1<br>qubit"-->25 25["(25) quantum.tket2.ZZMax"] 25--"0:0<br>qubit"-->26 25--"1:1<br>qubit"-->26 26["(26) MakeTuple"] 26--"0:0<br>[qubit, qubit]"-->27 27["(27) UnpackTuple"] 27--"0:0<br>qubit"-->28 27--"1:0<br>qubit"-->30 28["(28) quantum.tket2.Measure"] 28--"0:0<br>qubit"-->29 29["(29) quantum.tket2.QFree"] 30["(30) quantum.tket2.Measure"] 30--"0:0<br>qubit"-->31 30--"1:0<br>[]+[]"-->32 31["(31) quantum.tket2.QFree"] 32["(32) MakeTuple"] 32--"0:0<br>[[]+[]]"-->33 33["(33) UnpackTuple"] 33--"0:1<br>[]+[]"-->5 34["(34) Tag"] 34--"0:0<br>[]"-->5 end 1-."0:0".->2 2["(2) ExitBlock"] end 8--"0:0<br>[]+[]"-->6 end end ``` tket1 circuit: ![circuit](https://github.com/CQCL/tket2/assets/121866228/62877218-dd24-4e5e-a8f7-ce738e05662c) Re-extracted circuit: ```mermaid graph LR subgraph 0 ["(0) FuncDefn"] direction LR 1["(1) Input"] 1--"0:0<br>qubit"-->7 1--"1:0<br>qubit"-->12 2["(2) Output"] 3["(3) const:custom:f64(1.5707963267948966)"] 3--"0:0<br>float64"-->4 4["(4) LoadConstant"] 4--"0:1<br>float64"-->7 5["(5) const:custom:f64(-1.5707963267948966)"] 5--"0:0<br>float64"-->6 6["(6) LoadConstant"] 6--"0:2<br>float64"-->7 7["(7) quantum.tket2.PhasedX"] 7--"0:0<br>qubit"-->15 8["(8) const:custom:f64(1.5707963267948966)"] 8--"0:0<br>float64"-->9 9["(9) LoadConstant"] 9--"0:1<br>float64"-->12 10["(10) const:custom:f64(-1.5707963267948966)"] 10--"0:0<br>float64"-->11 11["(11) LoadConstant"] 11--"0:2<br>float64"-->12 12["(12) quantum.tket2.PhasedX"] 12--"0:0<br>qubit"-->18 13["(13) const:custom:f64(3.141592653589793)"] 13--"0:0<br>float64"-->14 14["(14) LoadConstant"] 14--"0:1<br>float64"-->15 15["(15) quantum.tket2.RzF64"] 15--"0:0<br>qubit"-->19 16["(16) const:custom:f64(3.141592653589793)"] 16--"0:0<br>float64"-->17 17["(17) LoadConstant"] 17--"0:1<br>float64"-->18 18["(18) quantum.tket2.RzF64"] 18--"0:1<br>qubit"-->19 19["(19) quantum.tket2.ZZMax"] 19--"0:0<br>qubit"-->21 19--"1:0<br>qubit"-->20 20["(20) quantum.tket2.Measure"] 20--"0:1<br>qubit"-->2 20--"1:2<br>[]+[]"-->2 21["(21) quantum.tket2.Measure"] 21--"0:0<br>qubit"-->2 21--"1:3<br>[]+[]"-->2 end ``` This required multiple improvements to the encoder/decoder logic, including - `Tk1Op::Native` operations (backed by a `Tk2Op`) can now have different number of input/output qubit/bits. - Added support for tket2 circuits with different input and output signatures. - Added support for `QAlloc`/`QFree` operations (generated by guppy) by adding extra input/outputs to the circuit. - Added support for pytket's implicit permutations, and recalculates the value when encoding a tket2 circuit. - Preserve the `opgroup` value from decoded pytket operations. - Improved error reporting. Closes #379 --------- Co-authored-by: Seyon Sivarajah <seyon.sivarajah@cambridgequantum.com>
- Loading branch information