-
Notifications
You must be signed in to change notification settings - Fork 6
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
refactor: Cleanup tket1 serialized op structures #419
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #419 +/- ##
==========================================
+ Coverage 81.00% 81.33% +0.33%
==========================================
Files 57 59 +2
Lines 5411 5423 +12
Branches 4926 4938 +12
==========================================
+ Hits 4383 4411 +28
+ Misses 819 793 -26
- Partials 209 219 +10
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
I fixed the CI error. |
29bfe9e
to
385e881
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks much better. I've not looked at coverage lines yet, that may induce further comments.
tket2/src/ops.rs
Outdated
} | ||
|
||
// Internal implementation for `TryFrom<Optype> for Tk2Op` that doesn't copy the `OpType` when it errors. | ||
fn optype_to_tk2op(op: &OpType) -> Option<Tk2Op> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both callsites create the same error anyway, I would prefer to do it once here. Not a big deal though.
tket2/src/serialize/pytket/op.rs
Outdated
|
||
/// A serialized operation, containing the operation type and all its attributes. | ||
/// An operation originated from pytket, containing the operation type and all its attributes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// An operation originated from pytket, containing the operation type and all its attributes. | |
/// An operation originating from pytket, containing the operation type and all its attributes. |
tket2/src/serialize/pytket/op.rs
Outdated
op.compute_param_fields(); | ||
Some(op) | ||
|
||
tk1_op.ok_or_else(|| OpConvertError::UnsupportedOpSerialization(op)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tk1_op.ok_or_else(|| OpConvertError::UnsupportedOpSerialization(op)) | |
tk1_op.ok_or(OpConvertError::UnsupportedOpSerialization(op)) |
tket2/src/serialize/pytket/op.rs
Outdated
/// Requires specifying the number of qubits and bits in the operation in | ||
/// case the `serial_op` does not define a signature. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Requires specifying the number of qubits and bits in the operation in | |
/// case the `serial_op` does not define a signature. | |
/// If `serial_op` defines a signature then `num_qubits` and `num_qubits` are ignored. Otherwise, a signature is synthesised from those parameters. |
param_inputs, | ||
num_params, | ||
/// Get the hugr optype for the operation. | ||
pub fn optype(&self) -> OpType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps this should take self
by value, since it unconditionally clones. I am not sure whether this would work having not inspected all methods used below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Opaque
path doesn't consume the json_op, so we avoid a clone by using &self
.
But Native
is the other way, returning an Optype
consumes it.
I'll define both options, so the caller can choose.
// TODO: Throw an error? We should never get here if the name matches. | ||
return None; | ||
}; | ||
let op = serde_yaml::from_value(arg.value.clone()).ok()?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we return a Result? Swallowing this error is a bit gross.
|
||
/// Compute the signature of the operation. | ||
/// | ||
/// We assume the operation has `num_qubits` qubit inputs and outputs, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// We assume the operation has `num_qubits` qubit inputs and outputs, | |
/// The signature returned has `num_qubits` qubit inputs, followed by `num_bits` bit inputs, followed by `num_params` `f64` inputs. It has `num_qubits` qubit outputs follwed by `num_bits` bit outputs. |
|
||
/// Wraps the op into a [`TKET1_OP_NAME`] opaque operation. | ||
pub fn as_custom_op(&self) -> CustomOp { | ||
let op = serde_yaml::to_value(self).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have looked at all think these unwraps and I think they're ok.
//let sig = self.signature(); | ||
//OpaqueOp::new( | ||
// TKET1_EXTENSION_ID, | ||
// TKET1_OP_NAME, | ||
// "".into(), | ||
// vec![payload], | ||
// sig, | ||
//) | ||
//.into() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//let sig = self.signature(); | |
//OpaqueOp::new( | |
// TKET1_EXTENSION_ID, | |
// TKET1_OP_NAME, | |
// "".into(), | |
// vec![payload], | |
// sig, | |
//) | |
//.into() |
tket2/src/extension.rs
Outdated
"An opaque TKET1 operation.".into(), | ||
JsonOpSignature([json_op_payload]) | ||
JsonOpSignature([tket1_op_payload]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we rename JsonOpSignature
?
I suggest grepping for |
} | ||
|
||
/// Consumes the `NativeOp` and returns the underlying `OpType`. | ||
pub fn into_op(self) -> OpType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub fn into_op(self) -> OpType { | |
pub fn into_optype(self) -> OpType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a couple of nits, and one suspicious coverage gap. Happy to approve if you don't think it's a problem.
tket2/src/ops.rs
Outdated
} | ||
} | ||
|
||
// Internal implementation for `TryFrom<Optype> for Tk2Op` that doesn't copy the `OpType` when it errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Internal implementation for `TryFrom<Optype> for Tk2Op` that doesn't copy the `OpType` when it errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, the original function that returned an Option
was meant as an optimisation to avoid cloning the optype on the error path of TryFrom<OpType>
. I guess it's too much of a micro optimisation, so I'll just leave the TryFrom<&OpType
impl as we had before.
@@ -169,16 +148,44 @@ pub fn save_tk1_json_str(circ: &Circuit) -> Result<String, TK1ConvertError> { | |||
|
|||
/// Error type for conversion between `Op` and `OpType`. | |||
#[derive(Debug, Error)] | |||
#[non_exhaustive] | |||
pub enum OpConvertError { | |||
/// The serialized operation is not supported. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these comments duplicating the error messages right next to them are very annoying. 😠 . No action required on your part.
if ty == &QB_T { | ||
num_qubits += 1 | ||
} else if *ty == *LINEAR_BIT { | ||
num_bits += 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this line seems to be missing coverage? somewhat concerning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't support native measurements yet (that's coming in the PR eliminating linear bits), so this path is never taken.
There's a test with a pytket measurement, but that gets encoded as an opaque op instead.
/// | ||
/// # Errors | ||
/// | ||
/// Returns a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
incomplete comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aborgna-q I think you missed this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, I can't work computers. It's perfect
## 🤖 New release * `tket2`: 0.1.0-alpha.2 -> 0.1.0 * `tket2-hseries`: 0.1.0 <details><summary><i><b>Changelog</b></i></summary><p> ## `tket2` <blockquote> ## [0.1.0](tket2-v0.1.0-alpha.2...tket2-v0.1.0) - 2024-08-01 ### Bug Fixes - Single source of truth for circuit names, and better circuit errors ([#390](#390)) - Support non-DFG circuits ([#391](#391)) - Portmatching not matching const edges ([#444](#444)) - Pattern matcher discriminating on opaqueOp description ([#441](#441)) - `extract_dfg` inserting the output node with an invalid child order ([#442](#442)) - Recompile ecc sets after [#441](#441) ([#484](#484)) ### Documentation - Update tket2-py readme ([#431](#431)) - Better error reporting in portmatching ([#437](#437)) - Improved multi-threading docs for Badger ([#495](#495)) ### New Features - `Circuit::operations` ([#395](#395)) - tuple unpack rewrite ([#406](#406)) - guppy → pytket conversion ([#407](#407)) - Drop linear bits, improve pytket encoding/decoding ([#420](#420)) - *(py)* Allow using `Tk2Op`s in the builder ([#436](#436)) - Initial support for `TailLoop` as circuit parent ([#417](#417)) - Support tuple unpacking with multiple unpacks ([#470](#470)) - Partial tuple unpack ([#475](#475)) - [**breaking**] Compress binary ECCs using zlib ([#498](#498)) - Add timeout options and stats to Badger ([#496](#496)) - Expose advanced Badger timeout options to tket2-py ([#506](#506)) ### Refactor - [**breaking**] Simplify tket1 conversion errors ([#408](#408)) - Cleanup tket1 serialized op structures ([#419](#419)) ### Testing - Add coverage for Badger split circuit multi-threading ([#505](#505)) </blockquote> ## `tket2-hseries` <blockquote> ## [0.1.0](https://github.com/CQCL/tket2/releases/tag/tket2-hseries-v0.1.0) - 2024-08-01 ### New Features - [**breaking**] init tket2-hseries ([#368](#368)) - *(tket2-hseries)* Add `tket2.futures` Hugr extension ([#471](#471)) - Add lazify-measure pass ([#482](#482)) - add results extensions ([#494](#494)) - *(tket2-hseries)* [**breaking**] Add `HSeriesPass` ([#487](#487)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/MarcoIeni/release-plz/). --------- Co-authored-by: Douglas Wilson <[email protected]>
## 🤖 New release * `tket2`: 0.1.0 -> 0.1.1 * `tket2-hseries`: 0.1.0 -> 0.1.1 <details><summary><i><b>Changelog</b></i></summary><p> ## `tket2` <blockquote> ## [0.1.0](tket2-v0.1.0-alpha.2...tket2-v0.1.0) - 2024-08-01 ### Bug Fixes - Single source of truth for circuit names, and better circuit errors ([#390](#390)) - Support non-DFG circuits ([#391](#391)) - Portmatching not matching const edges ([#444](#444)) - Pattern matcher discriminating on opaqueOp description ([#441](#441)) - `extract_dfg` inserting the output node with an invalid child order ([#442](#442)) - Recompile ecc sets after [#441](#441) ([#484](#484)) ### Documentation - Update tket2-py readme ([#431](#431)) - Better error reporting in portmatching ([#437](#437)) - Improved multi-threading docs for Badger ([#495](#495)) ### New Features - `Circuit::operations` ([#395](#395)) - tuple unpack rewrite ([#406](#406)) - guppy → pytket conversion ([#407](#407)) - Drop linear bits, improve pytket encoding/decoding ([#420](#420)) - *(py)* Allow using `Tk2Op`s in the builder ([#436](#436)) - Initial support for `TailLoop` as circuit parent ([#417](#417)) - Support tuple unpacking with multiple unpacks ([#470](#470)) - Partial tuple unpack ([#475](#475)) - [**breaking**] Compress binary ECCs using zlib ([#498](#498)) - Add timeout options and stats to Badger ([#496](#496)) - Expose advanced Badger timeout options to tket2-py ([#506](#506)) ### Refactor - [**breaking**] Simplify tket1 conversion errors ([#408](#408)) - Cleanup tket1 serialized op structures ([#419](#419)) ### Testing - Add coverage for Badger split circuit multi-threading ([#505](#505)) </blockquote> ## `tket2-hseries` <blockquote> ## [0.1.1](tket2-hseries-v0.1.0...tket2-hseries-v0.1.1) - 2024-08-15 ### New Features - *(tket2-hseries)* make result operation internals public ([#542](#542)) </blockquote> </p></details> --- This PR was generated with [release-plz](https://github.com/MarcoIeni/release-plz/). --------- Co-authored-by: Seyon Sivarajah <[email protected]>
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: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 anOpaque
variant, so we can keep the implementation clean. The code is functionally the same.