Skip to content
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

feat!: replace f64 with angle type for tk2 ops #578

Merged
merged 1 commit into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 50 additions & 50 deletions test_files/barenco_tof_10.json

Large diffs are not rendered by default.

Binary file modified test_files/eccs/nam_4_2.rwr
Binary file not shown.
Binary file modified test_files/eccs/nam_6_3.rwr
Binary file not shown.
Binary file modified test_files/eccs/small_eccs.rwr
Binary file not shown.
Binary file modified tket2-eccs/src/tket2_eccs/data/nam_6_3.rwr
Binary file not shown.
7 changes: 3 additions & 4 deletions tket2-hseries/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,13 @@ mod test {
builder::{Container, DFGBuilder, Dataflow, DataflowHugr, DataflowSubContainer},
extension::prelude::{BOOL_T, QB_T},
ops::handle::NodeHandle,
std_extensions::arithmetic::float_types::ConstF64,
type_row,
types::Signature,
HugrView as _,
};
use itertools::Itertools as _;
use petgraph::visit::{Topo, Walker as _};
use tket2::Tk2Op;
use tket2::{extension::angle::ConstAngle, Tk2Op};

use crate::{extension::futures::FutureOpDef, HSeriesPass};

Expand All @@ -120,7 +119,7 @@ mod test {
.node();

// this LoadConstant should be pushed below the quantum ops where possible
let angle = builder.add_load_value(ConstF64::new(1.0));
let angle = builder.add_load_value(ConstAngle::PI);
let f_node = angle.node();

// with no dependencies, this H should be lifted to the start
Expand All @@ -130,7 +129,7 @@ mod test {
.outputs_arr();
let h_node = qb.node();

// depending on the angle means this op can't be lifted above the float ops
// depending on the angle means this op can't be lifted above the angle ops
let [qb] = builder
.add_dataflow_op(Tk2Op::Rx, [qb, angle])
.unwrap()
Expand Down
2 changes: 1 addition & 1 deletion tket2-py/tket2/circuit/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def __call__(self, q: ComWire) -> Command:

Measure = MeasureDef()


# TODO use angle type once extension is serialised.
_RzSig = tys.FunctionType([tys.Qubit, FLOAT_T], [tys.Qubit])


Expand Down
4 changes: 2 additions & 2 deletions tket2/src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,6 @@ fn update_signature(
#[cfg(test)]
mod tests {
use cool_asserts::assert_matches;
use hugr::std_extensions::arithmetic::float_types::ConstF64;
use hugr::CircuitUnit;
use rstest::{fixture, rstest};

Expand All @@ -632,6 +631,7 @@ mod tests {
};

use super::*;
use crate::extension::angle::ConstAngle;
use crate::serialize::load_tk1_json_str;
use crate::utils::{build_module_with_circuit, build_simple_circuit};
use crate::Tk2Op;
Expand Down Expand Up @@ -661,7 +661,7 @@ mod tests {
build_simple_circuit(2, |circ| {
circ.append(Tk2Op::H, [0])?;
circ.append(Tk2Op::CX, [0, 1])?;
let angle = circ.add_constant(ConstF64::new(0.5));
let angle = circ.add_constant(ConstAngle::PI_2);
circ.append_and_consume(
Tk2Op::Rz,
[CircuitUnit::Linear(1), CircuitUnit::Wire(angle)],
Expand Down
12 changes: 7 additions & 5 deletions tket2/src/circuit/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -479,14 +479,13 @@ mod test {
use hugr::hugr::hugrmut::HugrMut;
use hugr::ops::handle::NodeHandle;
use hugr::ops::{NamedOp, Value};
use hugr::std_extensions::arithmetic::float_ops::FLOAT_OPS_REGISTRY;
use hugr::std_extensions::arithmetic::float_types::ConstF64;
use hugr::types::Signature;
use itertools::Itertools;
use rstest::{fixture, rstest};
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

use crate::extension::angle::ConstAngle;
use crate::extension::REGISTRY;
use crate::utils::{build_module_with_circuit, build_simple_circuit};
use crate::Tk2Op;
Expand Down Expand Up @@ -591,12 +590,12 @@ mod test {
let mut h = DFGBuilder::new(Signature::new(qb_row.clone(), qb_row)).unwrap();
let [q_in] = h.input_wires_arr();

let constant = h.add_constant(Value::extension(ConstF64::new(0.5)));
let constant = h.add_constant(Value::extension(ConstAngle::PI_2));
let loaded_const = h.load_const(&constant);
let rz = h.add_dataflow_op(Tk2Op::Rz, [q_in, loaded_const]).unwrap();

let circ: Circuit = h
.finish_hugr_with_outputs(rz.outputs(), &FLOAT_OPS_REGISTRY)
.finish_hugr_with_outputs(rz.outputs(), &REGISTRY)
.unwrap()
.into();

Expand All @@ -606,7 +605,10 @@ mod test {
// First command is the constant definition.
// It has a single output.
let const_cmd = commands.next().unwrap();
assert_eq!(const_cmd.optype().name().as_str(), "const:custom:f64(0.5)");
assert_eq!(
const_cmd.optype().name().as_str(),
"const:custom:a(2π*1/2^2)"
);
assert_eq_iter!(const_cmd.inputs().map(|(u, _, _)| u), [],);
assert_eq_iter!(
const_cmd.outputs().map(|(u, _, _)| u),
Expand Down
13 changes: 4 additions & 9 deletions tket2/src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,13 @@

use crate::serialize::pytket::OpaqueTk1Op;
use crate::Tk2Op;
use angle::ANGLE_TYPE;
use hugr::extension::prelude::PRELUDE;
use hugr::extension::simple_op::MakeOpDef;
use hugr::extension::{
CustomSignatureFunc, ExtensionId, ExtensionRegistry, SignatureError, Version,
};
use hugr::hugr::IdentList;
use hugr::std_extensions::arithmetic::{
float_ops::EXTENSION as FLOAT_OPS_EXTENSION,
float_types::{EXTENSION as FLOAT_TYPES_EXTENSION, FLOAT64_TYPE},
};
use hugr::types::type_param::{TypeArg, TypeParam};
use hugr::types::{CustomType, PolyFuncType, PolyFuncTypeRV, Signature};
use hugr::{type_row, Extension};
Expand Down Expand Up @@ -59,8 +56,6 @@ pub static ref REGISTRY: ExtensionRegistry = ExtensionRegistry::try_new([
TKET1_EXTENSION.to_owned(),
PRELUDE.to_owned(),
TKET2_EXTENSION.to_owned(),
FLOAT_TYPES_EXTENSION.to_owned(),
FLOAT_OPS_EXTENSION.to_owned(),
]).unwrap();


Expand Down Expand Up @@ -96,7 +91,7 @@ pub const TKET2_EXTENSION_ID: ExtensionId = ExtensionId::new_unchecked("quantum.
pub const SYM_EXPR_NAME: SmolStr = SmolStr::new_inline("SymExpr");

/// The name of the symbolic expression opaque type arg.
pub const SYM_OP_ID: SmolStr = SmolStr::new_inline("symbolic_float");
pub const SYM_OP_ID: SmolStr = SmolStr::new_inline("symbolic_angle");

/// Current version of the TKET 2 extension
pub const TKET2_EXTENSION_VERSION: Version = Version::new(0, 1, 0);
Expand All @@ -113,8 +108,8 @@ pub static ref TKET2_EXTENSION: Extension = {

e.add_op(
SYM_OP_ID,
"Store a sympy expression that can be evaluated to a float.".to_string(),
PolyFuncType::new(vec![TypeParam::String], Signature::new(type_row![], type_row![FLOAT64_TYPE])),
"Store a sympy expression that can be evaluated to an angle.".to_string(),
PolyFuncType::new(vec![TypeParam::String], Signature::new(type_row![], type_row![ANGLE_TYPE])),
)
.unwrap();

Expand Down
31 changes: 31 additions & 0 deletions tket2/src/extension/angle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ pub struct ConstAngle {
}

impl ConstAngle {
/// The constant π
pub const PI: Self = Self::new_unchecked(1, 1);
/// The constant 2π
pub const TAU: Self = Self::new_unchecked(0, 1);
/// The constant π/2
pub const PI_2: Self = Self::new_unchecked(2, 1);
/// The constant π/4
pub const PI_4: Self = Self::new_unchecked(3, 1);

/// Create a new [`ConstAngle`] from a log-denominator and a numerator without
/// checking for validity.
const fn new_unchecked(log_denom: u8, value: u64) -> Self {
Self { log_denom, value }
}
/// Create a new [`ConstAngle`] from a log-denominator and a numerator
pub fn new(log_denom: u8, value: u64) -> Result<Self, ConstTypeError> {
if !is_valid_log_denom(log_denom) {
Expand Down Expand Up @@ -73,6 +87,13 @@ impl ConstAngle {
})
}

/// Create a new [`ConstAngle`] from a floating-point value in radians,
/// using the highest possible log-denominator and
/// rounding to the nearest corresponding value. (Ties round away from zero.)
pub fn from_radians_rounding_max(theta: f64) -> Result<Self, ConstTypeError> {
Self::from_radians_rounding(LOG_DENOM_MAX, theta)
}

/// Returns the value of the constant
pub fn value(&self) -> u64 {
self.value
Expand All @@ -82,6 +103,16 @@ impl ConstAngle {
pub fn log_denom(&self) -> u8 {
self.log_denom
}

/// Returns the value of the constant in radians
pub fn to_radians(&self) -> f64 {
self.to_turns() * TAU
}

/// Returns the value of the constant divided by 2π
pub fn to_turns(&self) -> f64 {
(self.value as f64) / (1u64 << self.log_denom) as f64
}
}

#[typetag::serde]
Expand Down
6 changes: 3 additions & 3 deletions tket2/src/ops.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::extension::angle::ANGLE_TYPE;
use crate::extension::{
SYM_OP_ID, TKET2_EXTENSION as EXTENSION, TKET2_EXTENSION_ID as EXTENSION_ID,
};
Expand All @@ -10,7 +11,6 @@ use hugr::{
ExtensionId, OpDef, SignatureFunc,
},
ops::OpType,
std_extensions::arithmetic::float_types::FLOAT64_TYPE,
type_row,
types::{type_param::TypeArg, Signature},
};
Expand Down Expand Up @@ -115,8 +115,8 @@ impl MakeOpDef for Tk2Op {
CX | CZ | CY => Signature::new_endo(type_row![QB_T; 2]),
Toffoli => Signature::new_endo(type_row![QB_T; 3]),
Measure => Signature::new(one_qb_row, type_row![QB_T, BOOL_T]),
Rz | Rx | Ry => Signature::new(type_row![QB_T, FLOAT64_TYPE], one_qb_row),
CRz => Signature::new(type_row![QB_T, QB_T, FLOAT64_TYPE], type_row![QB_T; 2]),
Rz | Rx | Ry => Signature::new(type_row![QB_T, ANGLE_TYPE], one_qb_row),
CRz => Signature::new(type_row![QB_T, QB_T, ANGLE_TYPE], type_row![QB_T; 2]),
QAlloc => Signature::new(type_row![], one_qb_row),
QFree => Signature::new(one_qb_row, type_row![]),
}
Expand Down
11 changes: 5 additions & 6 deletions tket2/src/optimiser/badger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,20 +544,19 @@ mod tests {
use hugr::{
builder::{DFGBuilder, Dataflow, DataflowHugr},
extension::prelude::QB_T,
std_extensions::arithmetic::float_types::FLOAT64_TYPE,
types::Signature,
};
use rstest::{fixture, rstest};

use crate::optimiser::badger::BadgerOptions;
use crate::serialize::load_tk1_json_str;
use crate::{extension::angle::ANGLE_TYPE, optimiser::badger::BadgerOptions};
use crate::{extension::REGISTRY, Circuit, Tk2Op};

use super::{BadgerOptimiser, DefaultBadgerOptimiser};

#[fixture]
fn rz_rz() -> Circuit {
let input_t = vec![QB_T, FLOAT64_TYPE, FLOAT64_TYPE];
let input_t = vec![QB_T, ANGLE_TYPE, ANGLE_TYPE];
let output_t = vec![QB_T];
let mut h = DFGBuilder::new(Signature::new(input_t, output_t)).unwrap();

Expand Down Expand Up @@ -623,9 +622,9 @@ mod tests {
#[case::compiled(badger_opt_compiled())]
#[case::json(badger_opt_json())]
fn rz_rz_cancellation(rz_rz: Circuit, #[case] badger_opt: DefaultBadgerOptimiser) {
use hugr::{ops::OpType, std_extensions::arithmetic::float_ops::FloatOps};
use hugr::ops::OpType;

use crate::op_matches;
use crate::{extension::angle::AngleOp, op_matches};

let opt_rz = badger_opt.optimise(
&rz_rz,
Expand All @@ -642,7 +641,7 @@ mod tests {
.unwrap();

// Rzs combined into a single one.
assert_eq!(op1.cast::<FloatOps>(), Some(FloatOps::fadd));
assert_eq!(op1.cast(), Some(AngleOp::aadd));
assert!(op_matches(op2, Tk2Op::Rz));
}

Expand Down
6 changes: 3 additions & 3 deletions tket2/src/optimiser/badger/qtz_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ use std::path::Path;
use hugr::builder::{DFGBuilder, Dataflow, DataflowHugr};
use hugr::extension::prelude::QB_T;
use hugr::ops::OpType as Op;
use hugr::std_extensions::arithmetic::float_types::FLOAT64_TYPE;
use hugr::types::{Signature, Type};
use hugr::{CircuitUnit, Hugr};
use itertools::Itertools;
use serde::{Deserialize, Serialize};

use crate::extension::angle::{AngleOp, ANGLE_TYPE};
use crate::{Circuit, Tk2Op};

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -41,7 +41,7 @@ struct RepCircData {

fn map_op(opstr: &str) -> Op {
if opstr == "add" {
return hugr::std_extensions::arithmetic::float_ops::FloatOps::fadd.into();
return AngleOp::aadd.into();
}
// TODO, more
match opstr {
Expand All @@ -64,7 +64,7 @@ fn map_op(opstr: &str) -> Op {
impl From<RepCircData> for Circuit<Hugr> {
fn from(RepCircData { circ: rc, meta }: RepCircData) -> Self {
let qb_types: Vec<Type> = vec![QB_T; meta.n_qb];
let param_types: Vec<Type> = vec![FLOAT64_TYPE; meta.n_input_param];
let param_types: Vec<Type> = vec![ANGLE_TYPE; meta.n_input_param];
let mut builder = DFGBuilder::new(Signature::new(
[qb_types.clone(), param_types].concat(),
qb_types,
Expand Down
9 changes: 6 additions & 3 deletions tket2/src/passes/commutation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,14 @@ pub fn apply_greedy_commutation(circ: &mut Circuit) -> Result<u32, PullForwardEr
#[cfg(test)]
mod test {

use crate::{extension::REGISTRY, ops::test::t2_bell_circuit, utils::build_simple_circuit};
use crate::{
extension::{angle::ANGLE_TYPE, REGISTRY},
ops::test::t2_bell_circuit,
utils::build_simple_circuit,
};
use hugr::{
builder::{DFGBuilder, Dataflow, DataflowHugr},
extension::prelude::{BOOL_T, QB_T},
std_extensions::arithmetic::float_types::FLOAT64_TYPE,
type_row,
types::Signature,
};
Expand Down Expand Up @@ -436,7 +439,7 @@ mod test {
fn non_linear_inputs() -> Circuit {
let build = || {
let mut dfg = DFGBuilder::new(Signature::new(
type_row![QB_T, QB_T, FLOAT64_TYPE],
type_row![QB_T, QB_T, ANGLE_TYPE],
type_row![QB_T, QB_T],
))?;

Expand Down
6 changes: 3 additions & 3 deletions tket2/src/portmatching/pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ mod tests {
use hugr::builder::{DFGBuilder, Dataflow, DataflowHugr};
use hugr::extension::prelude::QB_T;
use hugr::ops::OpType;
use hugr::std_extensions::arithmetic::float_types::FLOAT64_TYPE;
use hugr::types::Signature;

use crate::extension::angle::ANGLE_TYPE;
use crate::extension::REGISTRY;
use crate::utils::build_simple_circuit;
use crate::Tk2Op;
Expand All @@ -188,7 +188,7 @@ mod tests {

/// A circuit with two rotation gates in sequence, sharing a param
fn circ_with_copy() -> Circuit {
let input_t = vec![QB_T, FLOAT64_TYPE];
let input_t = vec![QB_T, ANGLE_TYPE];
let output_t = vec![QB_T];
let mut h = DFGBuilder::new(Signature::new(input_t, output_t)).unwrap();

Expand All @@ -206,7 +206,7 @@ mod tests {

/// A circuit with two rotation gates in parallel, sharing a param
fn circ_with_copy_disconnected() -> Circuit {
let input_t = vec![QB_T, QB_T, FLOAT64_TYPE];
let input_t = vec![QB_T, QB_T, ANGLE_TYPE];
let output_t = vec![QB_T, QB_T];
let mut h = DFGBuilder::new(Signature::new(input_t, output_t)).unwrap();

Expand Down
Loading
Loading