Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert hugr's BOOLs into tket1-compatible LINEAR_BITs #379

Closed
Tracked by #377
aborgna-q opened this issue Jun 4, 2024 · 0 comments · Fixed by #420
Closed
Tracked by #377

Convert hugr's BOOLs into tket1-compatible LINEAR_BITs #379

aborgna-q opened this issue Jun 4, 2024 · 0 comments · Fixed by #420
Assignees

Comments

@aborgna-q
Copy link
Collaborator

No description provided.

@aborgna-q aborgna-q changed the title Convert hugr's s into tket1-compatible s Convert hugr's BOOLs into tket1-compatible LINEAR_BITs Jun 4, 2024
@aborgna-q aborgna-q self-assigned this Jun 4, 2024
github-merge-queue bot pushed a commit that referenced this issue Jun 20, 2024
This is a noisy internal refactor of `::serialize::pytket::op::JsonOp`,
extracted from the work towards #379.

`JsonOp` was a temporary structure used during the encoding/decoding of
pytket circuits that represented two different kinds of operation:
- pytket operations with a direct tket2 counterpart
- other operations that have to be encoded as OpaqueOps

This mixed up the two definitions, and made applying custom logic to one
of the variants more annoying.
(E.g. the special handling of bit input/outputs for tket2 ops needed for
#379).

This PR splits the structs into a `Native` and an `Opaque` variant, so
we can keep the implementation clean. The code is functionally the same.

---------

Co-authored-by: doug-q <141026920+doug-q@users.noreply.github.com>
github-merge-queue bot pushed a commit that referenced this issue Jun 25, 2024
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant