Skip to content

Commit 4165508

Browse files
committed
Merge remote-tracking branch 'origin/main' into ab/tket-exts-exports
2 parents 0dfadfe + cd42644 commit 4165508

File tree

22 files changed

+433
-167
lines changed

22 files changed

+433
-167
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

badger-optimiser/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ tket = { path = "../tket", features = [
1616
"rewrite-tracing",
1717
"binary-eccs",
1818
] }
19-
tket-qsystem = { path = "../tket-qsystem", version = "0.19.0" }
19+
tket-qsystem = { path = "../tket-qsystem", version = "0.20.0" }
2020
tracing = { workspace = true }
2121
tracing-subscriber = { workspace = true }
2222
tracing-appender = { workspace = true }

tket-py/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ tket = { path = "../tket", version = "0.14.0", features = [
2323
"portmatching",
2424
"binary-eccs",
2525
] }
26-
tket-qsystem = { path = "../tket-qsystem", version = "0.19.0" }
26+
tket-qsystem = { path = "../tket-qsystem", version = "0.20.0" }
2727
serde = { workspace = true, features = ["derive"] }
2828
serde_json = { workspace = true }
2929
tket-json-rs = { workspace = true, features = ["pyo3"] }

tket-py/src/ops.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ impl PyPauliIter {
217217
//
218218
// TODO: These can no longer be constructed from Python. Since `hugr-rs 0.14`
219219
// we need an extension and `OpDef` to defines these.
220-
// If fixing this, make sure to fix `PyHugrType` too.
220+
// When fixing this, make sure to fix `PyHugrType` too.
221221
#[pyclass]
222222
#[pyo3(name = "CustomOp")]
223223
#[repr(transparent)]

tket-qsystem/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# Changelog
22

33

4+
## [0.20.0](https://github.com/CQCL/tket2/compare/tket-qsystem-v0.19.0...tket-qsystem-v0.20.0) - 2025-08-21
5+
6+
### New Features
7+
8+
- [**breaking**] Update WASM extension ([#1047](https://github.com/CQCL/tket2/pull/1047))
9+
- *(qsystem)* native gateset decomposition improvements ([#1059](https://github.com/CQCL/tket2/pull/1059))
10+
411
## [0.19.0](https://github.com/CQCL/tket2/compare/tket-qsystem-v0.18.1...tket-qsystem-v0.19.0) - 2025-08-18
512

613
### New Features

tket-qsystem/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tket-qsystem"
3-
version = "0.19.0"
3+
version = "0.20.0"
44
edition.workspace = true
55
rust-version.workspace = true
66

tket-qsystem/src/extension/qsystem.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -394,27 +394,25 @@ pub trait QSystemOpBuilder: Dataflow + UnwrapBuilder + ArrayOpBuilder {
394394

395395
/// Build a CY gate in terms of QSystem primitives.
396396
fn build_cy(&mut self, a: Wire, b: Wire) -> Result<[Wire; 2], BuildError> {
397+
let pi = pi_mul_f64(self, 1.0);
397398
let pi_2 = pi_mul_f64(self, 0.5);
398399
let pi_minus_2 = pi_mul_f64(self, -0.5);
399-
let zero = pi_mul_f64(self, 0.0);
400400

401-
let a = self.add_phased_x(a, pi_minus_2, zero)?;
401+
let a = self.add_phased_x(a, pi, pi)?;
402+
let b = self.add_phased_x(b, pi_minus_2, pi)?;
402403
let [a, b] = self.build_zz_max(a, b)?;
403-
let a = self.add_rz(a, pi_2)?;
404-
let b = self.add_phased_x(b, pi_2, pi_2)?;
405-
let b = self.add_rz(b, pi_minus_2)?;
404+
let a = self.add_phased_x(a, pi, pi_2)?;
405+
let b = self.add_phased_x(b, pi_minus_2, pi_minus_2)?;
406+
let a = self.add_rz(a, pi_minus_2)?;
407+
let b = self.add_rz(b, pi_2)?;
406408
Ok([a, b])
407409
}
408410

409411
/// Build a CZ gate in terms of QSystem primitives.
410412
fn build_cz(&mut self, a: Wire, b: Wire) -> Result<[Wire; 2], BuildError> {
411-
let pi = pi_mul_f64(self, 1.0);
412413
let pi_2 = pi_mul_f64(self, 0.5);
413-
let pi_minus_2 = pi_mul_f64(self, -0.5);
414414

415-
let a = self.add_phased_x(a, pi, pi_2)?;
416415
let [a, b] = self.build_zz_max(a, b)?;
417-
let a = self.add_phased_x(a, pi, pi_minus_2)?;
418416
let b = self.add_rz(b, pi_2)?;
419417
let a = self.add_rz(a, pi_2)?;
420418

tket-qsystem/src/pytket/qsystem.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ use hugr::extension::simple_op::MakeExtensionOp;
66
use hugr::extension::ExtensionId;
77
use hugr::ops::ExtensionOp;
88
use hugr::HugrView;
9+
use itertools::Itertools as _;
910
use tket::serialize::pytket::decoder::{
10-
DecodeStatus, LoadedParameter, PytketDecoderContext, TrackedBit, TrackedQubit,
11+
DecodeStatus, LoadedParameter, ParameterType, PytketDecoderContext, TrackedBit, TrackedQubit,
1112
};
12-
use tket::serialize::pytket::encoder::EncodeStatus;
13+
use tket::serialize::pytket::encoder::{make_tk1_operation, EncodeStatus};
1314
use tket::serialize::pytket::extension::PytketDecoder;
1415
use tket::serialize::pytket::{
1516
PytketDecodeError, PytketEmitter, PytketEncodeError, PytketEncoderContext,
@@ -83,8 +84,22 @@ impl QSystemEmitter {
8384
}
8485
};
8586

86-
// Most operations map directly to a pytket one.
87-
encoder.emit_node(serial_op, node, circ)?;
87+
// pytket parameters are always in half-turns.
88+
// Since the `tket.qsystem` op inputs are in radians, we have to convert them here.
89+
encoder.emit_node_command(
90+
node,
91+
circ,
92+
|_| Vec::new(),
93+
move |mut inputs| {
94+
for param in inputs.params.to_mut() {
95+
*param = match param.strip_suffix(") * (pi)") {
96+
Some(s) if s.starts_with("(") => s[1..].to_string(),
97+
_ => format!("{param} / (pi)"),
98+
};
99+
}
100+
make_tk1_operation(serial_op, inputs)
101+
},
102+
)?;
88103

89104
Ok(EncodeStatus::Success)
90105
}
@@ -126,15 +141,23 @@ impl PytketDecoder for QSystemEmitter {
126141
PytketOptype::ZZPhase => QSystemOp::ZZPhase,
127142
PytketOptype::ZZMax => {
128143
// This is a ZZPhase with a 1/2 angle.
129-
let param = decoder.load_parameter("pi/2");
144+
let param =
145+
Arc::new(decoder.load_parameter_with_type("pi/2", ParameterType::FloatRadians));
130146
decoder.add_node_with_wires(QSystemOp::ZZPhase, qubits, bits, &[param])?;
131147
return Ok(DecodeStatus::Success);
132148
}
133149
_ => {
134150
return Ok(DecodeStatus::Unsupported);
135151
}
136152
};
137-
decoder.add_node_with_wires(op, qubits, bits, params)?;
153+
154+
// We expect all parameters to be floats in radians.
155+
let params = params
156+
.iter()
157+
.map(|p| Arc::new(p.as_float_radians(&mut decoder.builder)))
158+
.collect_vec();
159+
160+
decoder.add_node_with_wires(op, qubits, bits, &params)?;
138161

139162
Ok(DecodeStatus::Success)
140163
}

tket-qsystem/src/pytket/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ fn compare_serial_circs(a: &SerialCircuit, b: &SerialCircuit) {
128128
let count_b = b_command_count.get(a).copied().unwrap_or_default();
129129
assert_eq!(
130130
count_a, count_b,
131-
"command {a:?} appears {count_a} times in rhs and {count_b} times in lhs"
131+
"command {a:?} appears {count_a} times in rhs and {count_b} times in lhs.\ncounts for a: {a_command_count:#?}\ncounts for b: {b_command_count:#?}"
132132
);
133133
}
134134
assert_eq!(a_command_count.len(), b_command_count.len());

tket/src/serialize/pytket/decoder.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod param;
44
mod tracked_elem;
55
mod wires;
66

7-
pub use param::{LoadedParameter, LoadedParameterType};
7+
pub use param::{LoadedParameter, ParameterType};
88
pub use tracked_elem::{TrackedBit, TrackedQubit};
99
pub use wires::TrackedWires;
1010

@@ -420,8 +420,13 @@ impl<'h> PytketDecoderContext<'h> {
420420
/// the first registers in `wires` for the bit inputs and the remaining
421421
/// registers for the outputs.
422422
///
423-
/// The input wire types must match the operation's input signature,
424-
/// no type conversion is performed.
423+
/// The input wire types must match the operation's input signature, no type
424+
/// conversion is performed.
425+
///
426+
/// The caller must take care of converting the parameter wires to the
427+
/// required types and units expected by the operation. An error will be
428+
/// returned if the parameter does not match the expected wire type, but the
429+
/// unit (radians or half-turns) cannot be checked automatically.
425430
///
426431
/// # Arguments
427432
///
@@ -435,6 +440,8 @@ impl<'h> PytketDecoderContext<'h> {
435440
/// input ports.
436441
/// - Returns an error if the node's output ports cannot be assigned to
437442
/// arguments from the input wire set.
443+
/// - Returns an error if the parameter wires do not match the expected
444+
/// types.
438445
pub fn add_node_with_wires(
439446
&mut self,
440447
op: impl Into<OpType>,
@@ -593,7 +600,18 @@ impl<'h> PytketDecoderContext<'h> {
593600
/// - If the parameter is a variable, adds a new `rotation` input to the region.
594601
/// - If the parameter is a sympy expressions, adds it as a [`SympyOpDef`][crate::extension::sympy::SympyOpDef] black box.
595602
pub fn load_parameter(&mut self, param: &str) -> Arc<LoadedParameter> {
596-
self.wire_tracker.load_parameter(&mut self.builder, param)
603+
Arc::new(
604+
self.wire_tracker
605+
.load_parameter(&mut self.builder, param, None),
606+
)
607+
}
608+
609+
/// Loads the given parameter expression as a [`LoadedParameter`] in the hugr, and converts it to the requested type and unit.
610+
///
611+
/// See [`PytketDecoderContext::load_parameter`] for more details.
612+
pub fn load_parameter_with_type(&mut self, param: &str, typ: ParameterType) -> LoadedParameter {
613+
self.wire_tracker
614+
.load_parameter(&mut self.builder, param, Some(typ))
597615
}
598616
}
599617

0 commit comments

Comments
 (0)