Skip to content

Conversation

@daniel-mills-cqc
Copy link

No description provided.

@codecov
Copy link

codecov bot commented Jul 4, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Please upload report for BASE (dan-commit-factory-base@6e170cb). Learn more about missing BASE report.

Additional details and impacted files
@@                    Coverage Diff                     @@
##             dan-commit-factory-base     #954   +/-   ##
==========================================================
  Coverage                           ?   79.46%           
==========================================================
  Files                              ?       90           
  Lines                              ?    10892           
  Branches                           ?    10618           
==========================================================
  Hits                               ?     8655           
  Misses                             ?     1648           
  Partials                           ?      589           
Flag Coverage Δ
python 81.75% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@lmondada lmondada left a comment

Choose a reason for hiding this comment

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

Hey Dan!

The logic is great and I like the names (SearchingWalker, frontier etc). Most of my comments are about Rust or some inconsistencies.

General Rust code standards:

  • make sure you build this and run your tests: cargo test (will run all tket2 tests) or cargo test kak (will run the tests in this file);
  • I highly recommend you use cargo fmt to format your file in the standard way. Some formatting conventions in rust get a second to get used to (esp. around iterators imo), but the consistency is very nice to have;
  • less important but good to know: cargo clippy is the Rust linter. If you run cargo clippy --fix it will adjust your code to follow all best practices. Note that --fix will not work if you have any files not commited in your repo. Either clean up your directory or use cargo clippy --fix --allow-dirty.

Let me know if you have any issues with making your code compile :) For clippy and fmt, you might have to install them first: rustup component add clippy and rustup component add rustfmt (assuming you installed Rust with rustup?).

You should be pretty close to a working solution and I look forward to testing it!

Comment on lines 30 to 34
walker: Walker <'w>, // Initial state of walker.
frontier_wires: Vec<PersistentWire>, // Wires to be expanded.
pattern: KAKResynthesis, // Current pattern.
two_qubit_node: Option<PatchNode>, // If a 2q gate has been found along one wire,
// but not yet the other, then it is stored here.
Copy link
Contributor

Choose a reason for hiding this comment

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

Put the documentation for the fields on a separate line above the fields, starting with ///. That way rust will automatically pick it up as docstrings (and include it in automatically generated documentation) :)

Suggested change
walker: Walker <'w>, // Initial state of walker.
frontier_wires: Vec<PersistentWire>, // Wires to be expanded.
pattern: KAKResynthesis, // Current pattern.
two_qubit_node: Option<PatchNode>, // If a 2q gate has been found along one wire,
// but not yet the other, then it is stored here.
/// Initial state of walker.
walker: Walker <'w>,
/// Wires to be expanded.
frontier_wires: Vec<PersistentWire>,
/// Current pattern.
pattern: KAKResynthesis,
/// If a 2q gate has been found along one wire,
/// but not yet the other, then it is stored here.
two_qubit_node: Option<PatchNode>,

Comment on lines 245 to 249
for node in pers_hugr.nodes() {
let walker = Walker::from_pinned_node(node, pers_hugr.as_state_space());
// walker.get_wire(node, OutgoingPort::from(0));
factory.find_pattern_matches(node, walker);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Add an assertion to check this does what you expect.

The simplest would be to add a variable let mut n_matches = 0 before the loop, and then count the number of matches you find:

n_matches += factory.find_pattern_matches(node, walker).count();

After the loop, you would write assert_eq(n_matches, 1).

A stronger test would involve looking into the matches obtained and checking it contains the gates you expect.

Comment on lines 252 to 255
#[test]
fn test_my_test() {
println!("hello world")
}
Copy link
Contributor

Choose a reason for hiding this comment

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

remove :)

Comment on lines 216 to 217
#[test]
fn test_kak_resynthesis_init() {
Copy link
Contributor

Choose a reason for hiding this comment

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

not important but useful to know:

if you replace #[test] with #[rstest] (you need to import it with use rstest::rstest) and you add #[fixture] (also imported from rstest) in front of your helper function one_cz_2qb_hugr, then you can write the test as

#[rstest]
fn test_kak_resynthesis_init(one_cz_2qb_hugr: Hugr) { ... }

It's just syntactic sugar to move the construction of the Hugr from a function call in your function body as you have it now, to something that looks like an argument passed to the test.

Comment on lines 21 to 25
impl IterMatchedWires for KAKResynthesis {
fn matched_wires(&self) -> impl Iterator<Item = &PersistentWire> + '_ {
self.wires[0].iter().chain(self.wires[1].iter())
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

There's something weird here: the way this is written worked for wires: [Vec<PersistentWire>; 2], but it looks like you've changed it to a simple Vec<_>. In this case, self.wires.iter() should be all you need here.

// Get the new expanded version of the wire to search along.
let expanded_wire = expanded_walker.get_wire(
frontier_node,
IncomingPort::from(0),
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this will always be port 0? Also, if you change the above direction, you will need to change it here too.


// Get the type of operation this node implements
let ext_op = expanded_walker.as_hugr_view().get_optype(expanded_node).as_extension_op().expect("Not extension op");
let tket2_op = Tk2Op::from_extension_op(ext_op).expect("Not TKET2 OP");
Copy link
Contributor

Choose a reason for hiding this comment

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

I wouldn't error if it is not a TKET2 (it could be an input/output node). Instead you could write

Suggested change
let tket2_op = Tk2Op::from_extension_op(ext_op).expect("Not TKET2 OP");
let Ok(tket2_op) = Tk2Op::from_extension_op(ext_op) else {
continue;
};

Copy link
Contributor

Choose a reason for hiding this comment

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

See also comment below about adding searching_walker back to the queue in this case.

Comment on lines 105 to 107
if !tket2_op.is_quantum() {
continue;

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, both here and just above in the suggestion I made about ignoring non-tket2 ops: you need to make sure that in this case you still add the existing match to the list of completed matches to be returned.

Probably the simplest way to do this would be to add searching_walker back to the queue.


searching_walker.pattern.wires.push(expanded_wire);

matches.push((searching_walker.pattern, searching_walker.walker));
Copy link
Contributor

Choose a reason for hiding this comment

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

I suspect the compiler must be complaining here about using searching_walker.pattern and searching_walker.walker in more than one place (more specifically, it will say "use of moved value" further below). You must clone the data:

Suggested change
matches.push((searching_walker.pattern, searching_walker.walker));
matches.push((searching_walker.pattern.clone(), searching_walker.walker.clone()));

That being said, this will add all possible subcircuits (not just the maximal ones). Is this what you want? Might indeed be the right way to go provided we don't get far too many matches.

Copy link
Author

Choose a reason for hiding this comment

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

Thanks!
Adding all matches was indeed what I was going for as a first try.

let [q0, q1] = cz1.outputs_arr();
builder.finish_hugr_with_outputs(vec![q0, q1]).unwrap()
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Add a Hugr with more CZ and more than one match to test on. E.g.:

fn three_cz_hugr() -> Hugr {
    let mut builder = DFGBuilder::new(endo_sig(vec![qb_t(); 3])).unwrap();
    let [q0, q1, q2] = builder.input_wires_arr();
    let cz1 = builder.add_dataflow_op(Tk2Op::CZ, vec![q0, q1]).unwrap();
    let [q0, q1] = cz1.outputs_arr();
    let cz2 = builder.add_dataflow_op(Tk2Op::CZ, vec![q0, q1]).unwrap();
    let [q0, q1] = cz2.outputs_arr();
    let cz3 = builder.add_dataflow_op(Tk2Op::CZ, vec![q0, q2]).unwrap();
    let [q0, q2] = cz3.outputs_arr();
    builder.finish_hugr_with_outputs(vec![q0, q1, q2]).unwrap()
}

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.

4 participants