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

fix: extract_dfg inserting the output node with an invalid child order #442

Merged
merged 3 commits into from
Jun 28, 2024
Merged
Changes from 1 commit
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
Next Next commit
fix: extract_dfg re-adding the output node in the wrong child order
aborgna-q committed Jun 27, 2024
commit eb1b1501c649cbeca3173663d6a89f7f8e51a369
6 changes: 3 additions & 3 deletions tket2/src/circuit/extract_dfg.rs
Original file line number Diff line number Diff line change
@@ -47,7 +47,7 @@ fn remove_cfg_empty_output_tuple(
signature: FunctionType,
) -> Result<FunctionType, CircuitMutError> {
let sig = signature;
let parent = circ.parent();
let input_node = circ.input_node();

let output_node = circ.output_node();
let output_nodetype = circ.hugr.get_nodetype(output_node).clone();
@@ -89,8 +89,8 @@ fn remove_cfg_empty_output_tuple(
let new_op = Output {
types: new_types.clone().into(),
};
let new_node = hugr.add_node_with_parent(
parent,
let new_node = hugr.add_node_after(
input_node,
Comment on lines +92 to +93
Copy link
Member

Choose a reason for hiding this comment

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

this should be covered right? the test looks ok to me

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Turns out the "guppy-like" circuit was not guppy-like. I was loading a constant tag instead of using the Tag operation...

It should be fixed now.

NodeType::new(
new_op,
output_nodetype
100 changes: 100 additions & 0 deletions tket2/src/passes/pytket.rs
Original file line number Diff line number Diff line change
@@ -38,3 +38,103 @@ pub enum PytketLoweringError {
#[error("Non-local operations found. Function calls are not supported.")]
NonLocalOperations,
}

#[cfg(test)]
mod test {
use crate::Tk2Op;

use super::*;
use hugr::builder::{
Container, Dataflow, DataflowSubContainer, HugrBuilder, ModuleBuilder, SubContainer,
};
use hugr::extension::prelude::QB_T;
use hugr::extension::{ExtensionSet, PRELUDE_REGISTRY};
use hugr::ops::handle::NodeHandle;
use hugr::ops::{MakeTuple, OpType, UnpackTuple, Value};
use hugr::types::FunctionType;
use hugr::{type_row, HugrView};
use rstest::{fixture, rstest};

/// Builds a circuit in the style of guppy's output.
///
/// This is composed of a `Module`, containing a `FuncDefn`, containing a
/// `CFG`, containing an `Exit` and a `DataflowBlock` with the actual
/// circuit.
#[fixture]
fn guppy_like_circuit() -> Circuit {
fn build() -> Result<Circuit, hugr::builder::BuildError> {
let two_qbs = type_row![QB_T, QB_T];
let circ_signature = FunctionType::new_endo(two_qbs.clone());
let circ;

let mut builder = ModuleBuilder::new();
let _func = {
let mut func = builder.define_function("main", circ_signature.into())?;
let [q1, q2] = func.input_wires_arr();

let cfg = {
let mut cfg = func.cfg_builder(
[(QB_T, q1), (QB_T, q2)],
None,
two_qbs.clone(),
ExtensionSet::new(),
)?;

circ = {
let mut dfg =
cfg.simple_entry_builder(two_qbs.clone(), 1, ExtensionSet::new())?;
let [q1, q2] = dfg.input_wires_arr();

let [q1] = dfg.add_dataflow_op(Tk2Op::H, [q1])?.outputs_arr();
let [q1, q2] = dfg.add_dataflow_op(Tk2Op::CX, [q1, q2])?.outputs_arr();

let [tup] = dfg
.add_dataflow_op(MakeTuple::new(two_qbs.clone()), [q1, q2])?
.outputs_arr();
let [q1, q2] = dfg
.add_dataflow_op(UnpackTuple::new(two_qbs), [tup])?
.outputs_arr();

let branch = dfg.add_load_const(Value::tuple([]));

dfg.finish_with_outputs(branch, [q1, q2])?
};
cfg.branch(&circ, 0, &cfg.exit_block())?;

cfg.finish_sub_container()?
};
let [q1, q2] = cfg.outputs_arr();

func.finish_with_outputs([q1, q2])?
};

let hugr = builder.finish_hugr(&PRELUDE_REGISTRY)?;
Ok(Circuit::new(hugr, circ.node()))
}
build().unwrap()
}

#[rstest]
#[case::guppy_like_circuit(guppy_like_circuit())]
fn test_pytket_lowering(#[case] circ: Circuit) {
use cool_asserts::assert_matches;

assert_eq!(circ.num_operations(), 2);

let lowered_circ = lower_to_pytket(&circ).unwrap();

assert_eq!(lowered_circ.num_operations(), 2);
assert_matches!(
lowered_circ.hugr().get_optype(lowered_circ.parent()),
OpType::DFG(_)
);
assert_matches!(
lowered_circ.hugr().get_optype(lowered_circ.input_node()),
OpType::Input(_)
);
assert_matches!(
lowered_circ.hugr().get_optype(lowered_circ.output_node()),
OpType::Output(_)
);
}
}