Skip to content

Commit

Permalink
feat(tket2-py): Bind the lower_to_pytket pass in python (#439)
Browse files Browse the repository at this point in the history
This is used to normalise guppy functions into flat pytket-like
circuits.
This is useful for using as pattern match rules.

We may remove the method from `tket2.passes` later, but it's useful to
have as an internal binding in `tket2._tket2.passes`.
  • Loading branch information
aborgna-q authored Jun 27, 2024
1 parent b77b3cb commit 8208324
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 2 deletions.
25 changes: 23 additions & 2 deletions tket2-py/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ use std::{cmp::min, convert::TryInto, fs, num::NonZeroUsize, path::PathBuf};

use pyo3::{prelude::*, types::IntoPyDict};
use tket2::optimiser::badger::BadgerOptions;
use tket2::{op_matches, passes::apply_greedy_commutation, Tk2Op};
use tket2::passes;
use tket2::{op_matches, Tk2Op};

use crate::circuit::CircuitType;
use crate::utils::{create_py_exception, ConvertPyErr};
use crate::{
circuit::{try_update_circ, try_with_circ},
Expand All @@ -20,6 +22,7 @@ use crate::{
pub fn module(py: Python<'_>) -> PyResult<Bound<'_, PyModule>> {
let m = PyModule::new_bound(py, "passes")?;
m.add_function(wrap_pyfunction!(greedy_depth_reduce, &m)?)?;
m.add_function(wrap_pyfunction!(lower_to_pytket, &m)?)?;
m.add_function(wrap_pyfunction!(badger_optimise, &m)?)?;
m.add_class::<self::chunks::PyCircuitChunks>()?;
m.add_function(wrap_pyfunction!(self::chunks::chunks, &m)?)?;
Expand All @@ -46,7 +49,7 @@ create_py_exception!(
fn greedy_depth_reduce<'py>(circ: &Bound<'py, PyAny>) -> PyResult<(Bound<'py, PyAny>, u32)> {
let py = circ.py();
try_with_circ(circ, |mut circ, typ| {
let n_moves = apply_greedy_commutation(&mut circ).convert_pyerrs()?;
let n_moves = passes::apply_greedy_commutation(&mut circ).convert_pyerrs()?;
let circ = typ.convert(py, circ)?;
PyResult::Ok((circ, n_moves))
})
Expand All @@ -72,6 +75,24 @@ fn rebase_nam(circ: &Bound<PyAny>) -> PyResult<()> {
rebase_pass.call1((circ,)).map(|_| ())
}

/// A pass that removes high-level control flow from a HUGR, so it can be used in pytket.
#[pyfunction]
fn lower_to_pytket<'py>(circ: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyAny>> {
let py = circ.py();
try_with_circ(circ, |circ, typ| match typ {
CircuitType::Tket1 => {
// If the circuit is already in tket1 format, just return it.
let circ = typ.convert(py, circ)?;
PyResult::Ok(circ)
}
CircuitType::Tket2 => {
let circ = passes::lower_to_pytket(&circ).convert_pyerrs()?;
let circ = typ.convert(py, circ)?;
PyResult::Ok(circ)
}
})
}

/// Badger optimisation pass.
///
/// HyperTKET's best attempt at optimising a circuit using circuit rewriting
Expand Down
3 changes: 3 additions & 0 deletions tket2-py/tket2/_tket2/passes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ def greedy_depth_reduce(circ: CircuitClass) -> tuple[CircuitClass, int]:
Returns the reduced circuit and the depth reduction.
"""

def lower_to_pytket(circ: CircuitClass) -> CircuitClass:
"""Lower the high-level operations in a Hugr so it can be interpreted by pytket."""

def badger_optimise(
circ: CircuitClass,
optimiser: BadgerOptimiser,
Expand Down
2 changes: 2 additions & 0 deletions tket2-py/tket2/passes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from ._tket2.passes import (
CircuitChunks,
greedy_depth_reduce,
lower_to_pytket,
badger_optimise,
chunks,
PullForwardError,
Expand All @@ -22,6 +23,7 @@
# TODO: Wrap these in Python classes.
"CircuitChunks",
"greedy_depth_reduce",
"lower_to_pytket",
"badger_optimise",
"chunks",
"PullForwardError",
Expand Down

0 comments on commit 8208324

Please sign in to comment.