Skip to content

feat: Add HUGR extension for toy_k2 architecture - #321

Open
PabloAndresCQ wants to merge 11 commits into
feat/toyk2_primitivesfrom
toyk2_extension
Open

PabloAndresCQ wants to merge 11 commits into
feat/toyk2_primitivesfrom
toyk2_extension

Conversation

@PabloAndresCQ

Copy link
Copy Markdown
Collaborator

Closes #244

@PabloAndresCQ
PabloAndresCQ requested review from a team and hsemenenko September 7, 2026 14:56
@PabloAndresCQ
PabloAndresCQ changed the base branch from main to feat/toyk2_primitives September 7, 2026 14:57
Comment on lines +53 to +56
/// Decode a qubit measurement of a ToyK2 block.
decode_qubit_measurement,
/// Decode a block measurement (both qubits) of a ToyK2 block.
decode_block_measurement,

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Do you agree this is the right way to go about this? I couldn't think of anything else.

For now, I'm thinking the measurement_logical_qubit_type is just a glorified bool_t under the hood, similarly for the _block_ one being vec![bool_t; 2]. Basically, the decode primitives will be replaced with identity functions for now, since the primitives for measurement currently do call .read() and do the decoding themselves. This should change in the future, but I want to have a full architecture first.

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 not sure why but this doesn't feel right, but I also cannot think of another solution. We cannot use the guppylang.std.Measurement type as it will likely cause errors during type replacement. The block measurement is "just" a collection of two qubit measurements, but cannot be treated independently so should not be a tuple of qubit measurements.

We could only have a block measurement type, and then during implementation it gets replaced by a Guppy struct that wraps Option[Measurement]. Only measurements that have been performed would be some. This is likely too complicated for this example but we could consider in the future. More thought needed I think.

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.

Follow up thought that I don't know if there is a real-world example of - Is it possible that a measurement of an entire k>1 block could fail for only some logical qubits? If yes, the collection of Option[Measurement] would be useful.

@PabloAndresCQ PabloAndresCQ Sep 8, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Note that the decoding for QubitMeasurement and for BlockMeasurement are different, see the decode part of measure_z and measure_z_all in primitives.py. Atm these decode_ functions will be trivial ops, but once we upgrade them to do the physical .read() themselves, they'll need to do what measure_z and measure_z_all do after the read, which are completely different.

I'm fairly convinced this is the way. More so now that I've seen with #326 that they can then both be called with the .decode() syntax on the outcome of a measurement: measure_z(block, idx).decode() and measure_z_all(block).decode(). The difference is only for type checking and being explicit in the primitive definition, both things that we want.

Is it possible that a measurement of an entire k>1 block could fail for only some logical qubits?

I have not seen this, and I doubt that'll come up.

@PabloAndresCQ PabloAndresCQ left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

@hsemenenko I'll make the changes you request on #315 now and rebase this branch.

EDIT: done

@PabloAndresCQ
PabloAndresCQ force-pushed the toyk2_extension branch 2 times, most recently from c46be8e to 661347a Compare September 7, 2026 16:32

@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 Pablo. I'm satisfied with the justification to have both measurement types. Just a couple of small edits to fix.

cx_transversal,
/// Swap the two logical qubits of a ToyK2 block.
swap_intra,
/// Prepare a ToyK2 block with both logical qubits on the |0> state.

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
/// Prepare a ToyK2 block with both logical qubits on the |0> state.
/// Prepare a ToyK2 block with both logical qubits on the |0>|0> state.

Comment thread extensions/src/toy_k2.rs
@@ -0,0 +1,4 @@
//! HUGR extension for the logical operations and types for
//! the `[[4,2,2]]` C4 QEC code.

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
//! the `[[4,2,2]]` C4 QEC code.
//! the `[[4,2,2]]` ToyK2 QEC code.

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 extension for "Toy k2" primitives

2 participants