Skip to content

fix: guppy_to_circuit always returns num_operations = 0#1200

Merged
aborgna-q merged 10 commits intoQuantinuum:mainfrom
ankurmagdum:bug/circ-num-ops
Nov 12, 2025
Merged

fix: guppy_to_circuit always returns num_operations = 0#1200
aborgna-q merged 10 commits intoQuantinuum:mainfrom
ankurmagdum:bug/circ-num-ops

Conversation

@ankurmagdum
Copy link
Copy Markdown
Contributor

@ankurmagdum ankurmagdum commented Oct 23, 2025

Addresses #1130

Fixes the bug where the num_operations method of tket::circuit::Circuit always returned 0 for circuits whose top-level FuncDef contained only Input, Output, and Cfg nodes. Additionally, the existing implementation never visited sibling FuncDefs.

Root cause

  • The traversal only descended into nodes tagged as DataflowParent, but Cfg and Conditional nodes (which also contain ExtensionOp and OpaqueOp ops) do not have that tag.
  • The traversal started from self.parent(), which is the entry-point of the underlying hugr, without any explicit handling of Call ops.

Fix

  • Treat Cfg and Conditional nodes as traversal parents in addition to DataflowParent nodes.
  • Start traversal from self.hugr().module_root() to cover all FuncDefs.

Testing
The script test_count_ops.py extends the script in the issue by creating a variety of Guppy circuits and checks that num_operations() returns nonzero and scales with circuit complexity.

I’d appreciate guidance on:

  • whether this traversal logic matches the intended semantics and behaviour,
  • and where to best write the tests; in tket or tket-py.

PS: The error in the example tket-py/examples/2-Rewriting-Circuits.ipynb is resolved, however the rendered merged_circuit doesn't show the intended rewrite.

@ankurmagdum ankurmagdum marked this pull request as ready for review October 24, 2025 13:51
@ankurmagdum ankurmagdum requested a review from a team as a code owner October 24, 2025 13:51
@ankurmagdum ankurmagdum requested a review from aborgna-q October 24, 2025 13:51
@codecov
Copy link
Copy Markdown

codecov bot commented Oct 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.14%. Comparing base (fffb14a) to head (0d3f46f).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1200      +/-   ##
==========================================
+ Coverage   78.87%   79.14%   +0.27%     
==========================================
  Files         160      160              
  Lines       20421    20412       -9     
  Branches    19489    19480       -9     
==========================================
+ Hits        16107    16156      +49     
+ Misses       3324     3275      -49     
+ Partials      990      981       -9     
Flag Coverage Δ
python 92.65% <ø> (ø)
qis-compiler 100.00% <ø> (ø)
rust 78.48% <100.00%> (+0.28%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@aborgna-q aborgna-q linked an issue Oct 24, 2025 that may be closed by this pull request
@aborgna-q
Copy link
Copy Markdown
Collaborator

Hi, thanks for the PR!

The code looks good. Counting operations on an structure program is not well defined, so defaulting to "count everything on all function definitions" sounds reasonable. We'll have to think about alternative count operations in the future.

Your test should go in tket-py/test. As a comment, you should be able to use pytest.mark.parameterize and/or pytest fixtures to test the different circuits separatedly.

@ankurmagdum
Copy link
Copy Markdown
Contributor Author

ankurmagdum commented Oct 25, 2025

I have added the tests using pytest.mark.parameterize. Please take a look.

Update: For the CI tests to succeed, I would need to add guppylang as dependency in tket-py/pyproject.toml. Should I do that?

@aborgna-q
Copy link
Copy Markdown
Collaborator

For the CI tests to succeed, I would need to add guppylang as dependency in tket-py/pyproject.toml.

Ah, yes. Let me push a commit to your branch that sets it up (we have to move the dependency from elsewhere to the root workspace).

@aborgna-q
Copy link
Copy Markdown
Collaborator

As a side note, I think the tests may fail since the guppy functions are all defined on the same file (so you'll end up counting all the operations in all of the definitions).

The alternative is to create circuits for each test case separatedly,

def global_calls() -> Tk2Circuit:
    @guppy
    def inner(q0: qubit @ owned, angle: angle) -> qubit:
        rz(q0, angle)
        return q0

    @guppy
    def mid(q0: qubit @ owned) -> qubit:
        a = angle(3.14)
        return inner(q0, a)

    @guppy
    def outer(q0: qubit @ owned) -> qubit:
        h(q0)
        return mid(q0)

    return guppy_to_circuit(outer)
    
 testdata = [
    (global_calls, 3),
    ...
]

@aborgna-q
Copy link
Copy Markdown
Collaborator

aborgna-q commented Oct 28, 2025

Sorry for the noise. Adding guppy as a dependency here is somewhat annoying since we're trying to avoid the tket -> guppy -> tket circular dependency.

Our previous solution was pinning a specific commit of guppylang for the tests that required it in qis-compiler. But if we move that to the root workspace then all of CI requires some patches -.-
I'll try to fix things later, sorry for the wait.

The ideal alternative to avoid this is to use pre-compiled guppy programs here (like the ones in /test_files/guppy_optimization), but that's a bigger change so I was planning to leave it for later (#1210).

@aborgna-q
Copy link
Copy Markdown
Collaborator

I moved your tests to pre-compiled hugrs, to avoid the guppylang dependency.

Thanks again for the PR!

@aborgna-q aborgna-q enabled auto-merge November 12, 2025 17:42
@aborgna-q aborgna-q added this pull request to the merge queue Nov 12, 2025
Merged via the queue into Quantinuum:main with commit 49c5996 Nov 12, 2025
24 checks passed
This was referenced Nov 12, 2025
github-merge-queue bot pushed a commit that referenced this pull request Nov 13, 2025
🤖 I have created a release *beep* *boop*
---


##
[0.12.11](tket-py-v0.12.10...tket-py-v0.12.11)
(2025-11-13)


### Bug Fixes

* **ci:** Make wheels compatible with MacOS 15.0
(#1248)
([49c5996](49c5996))
* Don't use opgroup in pytket barrier encoding
(#1251)
([49c5996](49c5996))
* guppy_to_circuit always returns num_operations = 0
(#1200)
([49c5996](49c5996))
* **pytket-decoder:** Avoid QAllocating and immediately freeing qubits
([#1256](#1256))
([228ff52](228ff52))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

---------

Co-authored-by: Agustín Borgna <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Feb 3, 2026
## 🤖 New release

* `tket`: 0.16.0 -> 0.17.0 (✓ API compatible changes)
* `tket-qsystem`: 0.22.0 -> 0.23.0 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

## `tket`

<blockquote>

##
[0.17.0](tket-v0.16.0...tket-v0.17.0)
- 2026-02-02

### Bug Fixes

- *(encoded-circ)* Track unsupported wires between input and output
([#1224](#1224))
- Multiple fixes to the pytket encoder
([#1226](#1226))
- Don't use opgroup in pytket barrier encoding
([#1251](#1251))
- guppy_to_circuit always returns num_operations = 0
([#1200](#1200))
- *(pytket-decoder)* Avoid QAllocating and immediately freeing qubits
([#1256](#1256))
- Encoding of opaque subgraphs with no associated qubit/bit
([#1295](#1295))
- [**breaking**] Don't rely on command params for pytket barriers
([#1298](#1298))
- Track output qubits in CircuitInfo
([#1304](#1304))
- Wrongly reused qubit IDs in pytket encoding
([#1358](#1358))

### New Features

- Deprecate local find_tuple_unpack rewrite
([#1188](#1188))
- Add CopyableExpressionAST
([#1209](#1209))
- `NormalizeGuppy` pass to simplify generated structure
([#1220](#1220))
- [**breaking**] pytket EncodedCircuit struct for in-place pytket
optimisation ([#1211](#1211))
- [**breaking**] Interval is independent of resource IDs and scope
position ([#1205](#1205))
- Don't translate usizes to pytket
([#1241](#1241))
- BorrowSquashPass to elide redundant borrow/return ops
([#1159](#1159))
- [**breaking**] Bump hugr to 0.25.0
([#1325](#1325))
- Remove order edges in NormalizeGuppy pass
([#1326](#1326))
- [**breaking**] Remove deprecated unpack tuple pass
([#1387](#1387))

### Refactor

- Remove contain_qubits, use TypeUnpacker
([#1283](#1283))
- [**breaking**] Replace Subcircuit with SiblingSubgraph
([#1288](#1288))
- *(metadata)* [**breaking**] Migrate all metadata keys onto the new
metadata traits ([#1328](#1328))
</blockquote>

## `tket-qsystem`

<blockquote>

##
[0.23.0](tket-qsystem-v0.22.0...tket-qsystem-v0.23.0)
- 2026-02-02

### Bug Fixes

- [**breaking**] Don't rely on command params for pytket barriers
([#1298](#1298))
- Wrongly reused qubit IDs in pytket encoding
([#1358](#1358))

### New Features

- `NormalizeGuppy` pass to simplify generated structure
([#1220](#1220))
- Allow running arbitrary serializable pytket passes on hugrs
([#1266](#1266))
- BorrowSquashPass to elide redundant borrow/return ops
([#1159](#1159))
- [**breaking**] Bump hugr to 0.25.0
([#1325](#1325))
- Remove order edges in NormalizeGuppy pass
([#1326](#1326))
- hide new public funcs introduced by linearization
([#1333](#1333))

### Testing

- regenerate guppy_opt examples, and count gates
([#1249](#1249))
- run pytket on guppy_opt tests, measure (very limited) success
([#1250](#1250))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).
@hugrbot hugrbot mentioned this pull request Feb 5, 2026
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 this pull request may close these issues.

guppy_to_circuit always returns num_operations = 0

2 participants