Skip to content

feat: Add logical API to the toy_k2 architecture - #326

Open
PabloAndresCQ wants to merge 4 commits into
toyk2_extensionfrom
feat/toyk2_logicals
Open

PabloAndresCQ wants to merge 4 commits into
toyk2_extensionfrom
feat/toyk2_logicals

Conversation

@PabloAndresCQ

@PabloAndresCQ PabloAndresCQ commented Sep 8, 2026

Copy link
Copy Markdown
Collaborator

Closes #308

Includes enough non-primitive logicals to allow for 1-to-1 replacement of Clifford+T computational programs.

Caveat: the non-primitive logicals (cx_inter, s_all, s, etc...) have not been tested (beyond a smoke test), since we can't immediately use the Clifford verifier framework on these. We'd need to be able to run implement_ops on functions (rather than executables) and have a way to wire it up with the framework (which does its own generation of physical programs for automated Bell state prep).

I will be able to add some sanity checks once I add implement_ops in a separate PR. These won't be exhaustive, but should give confidence of correctness.

Why are these not in primitives.py?

Multiple reasons:

  • Because no QEC knowledge is needed to implement these, beyond being aware of what are the logical actions of the primiives we are composing.
  • Can trivially wire up any state prep done in the implementation of these to state factories via implement_ops.
  • Best for the sake of QEC cycle insertion, since these are built out of other ops that can be provided a cost for, and are actual "primitives"
  • Better for optimisation, since there's no need to keep these black boxed for the sake of FT.
  • Less fluff in the HUGR extension.

@hsemenenko hsemenenko left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, few minor suggestions.

@hugr_op(toy_k2_op("measure_z"))
@no_type_check
def measure_z(blk: "Block", idx: int) -> QubitMeasurement:
"""Measure the chosen qubit in the Z basis."""

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm annoyed that I've only just realised that the equivalent Guppy is project_z and perhaps we should have adopted that for non-destructive measurements. Too late now to change I think.

Suggested change
"""Measure the chosen qubit in the Z basis."""
"""Non-destructively measure the chosen qubit in the Z basis."""

Comment on lines +79 to +80
This consists of a syndrome extraction followed by discarding of the
shot if the syndrome is not trivial.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could the discarding happen in decode?

Comment on lines +154 to +155
This consists of a syndrome extraction followed by discarding of the
shot if the syndrome is not trivial.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

@guppy
@no_type_check
def cx_inter(ctrl_block: Block, ctrl_idx: int, tgt_block: Block, tgt_idx: int) -> None:
"""Logical CX between two blocks, targeting the specified logical qubits.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this architecture is a demonstration, we could add a note to the docstring to highlight that this is an example of a composite logical operation.

Suggested change
"""Logical CX between two blocks, targeting the specified logical qubits.
"""Logical CX between two blocks, targeting the specified logical qubits.
Note:
`cx_inter` is not itself a logical primitive of the code, but is instead composed of `swap` and `cx` logical primitives. Therefore, it is defined here rather than with the primitives.

Comment on lines +274 to +280
# Prepare an ancilla `|0+>` state, with the `|+>` on the index where we want
# to apply the Hadamard.
ancilla = Block() # |00>
h_all(ancilla) # |++>
# Project the other ancilla logical qubit to |0>
if measure_z(ancilla, 1 - idx).decode():
x(ancilla, idx)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a good place to use _encode_state_non_ft from primitives.

(This comment makes me think that the module naming is incorrect: why is _encode_state_non_ft in a module called primitives if it is not itself a primitive?)


def test_op_instantiations() -> None:
ops_extn = toy_k2_ops()
# No operations take indices

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean there are no parametrised ops?

Comment on lines +91 to +92
Normalize()(h, inplace=True)
InlineFunctions()(h, inplace=True)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run selene_hugr_qis_compiler.check_hugr to validate?

entrypoint = h.entrypoint
children = h.children(entrypoint)
# When https://github.com/Quantinuum/tket2/issues/1691 is implemented, this
# test will have to change: all the logical ops including `prep_zero`

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# test will have to change: all the logical ops including `prep_zero`
# test will have to change: all the logical ops including `prep_zero_ft`

pkg = main.compile()
h = pkg.modules[0]
Normalize()(h, inplace=True)
InlineFunctions()(h, inplace=True)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also add a check_hugr here.

Comment thread src/guppyft/code/toy_k2/logical.py Outdated
@@ -0,0 +1,403 @@
from collections.abc import Callable

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest adding a docstring to the top to explain that this module contains logical primitives of the ToyK2 architecture (including ops comprising other primitives) but does not contain any references to the physical implementations (i.e. guppylang.std.quantum)

@PabloAndresCQ
PabloAndresCQ requested a review from a team as a code owner September 15, 2026 13:19
@PabloAndresCQ
PabloAndresCQ force-pushed the feat/toyk2_logicals branch 2 times, most recently from 54efabd to 158a64f Compare September 15, 2026 14:41
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.

[Feature]: Add logical API for "Toy k2" architecture

2 participants