Skip to content
Merged
32 changes: 31 additions & 1 deletion tket-py/src/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ use std::{cmp::min, convert::TryInto, fs, num::NonZeroUsize, path::PathBuf};

use pyo3::prelude::*;
use tket::optimiser::badger::BadgerOptions;
use tket::passes;
use tket::passes::composable::{ComposablePass, WithScope};
use tket::{Circuit, TketOp, op_matches};

use tket::passes;

use crate::optimiser::PyBadgerOptimiser;
use crate::state::CompilationState;
use crate::utils::{ConvertPyErr, create_py_exception};
Expand All @@ -32,6 +33,7 @@ pub fn module(py: Python<'_>) -> PyResult<Bound<'_, PyModule>> {
m.add_function(wrap_pyfunction!(self::chunks::chunks, &m)?)?;
m.add_function(wrap_pyfunction!(self::tket1::tket1_pass, &m)?)?;
m.add_function(wrap_pyfunction!(resolve_modifiers, &m)?)?;
m.add_function(wrap_pyfunction!(qsystem_rebase_pass, &m)?)?;
m.add("PullForwardError", py.get_type::<PyPullForwardError>())?;
m.add(
"InlineFunctionsError",
Expand Down Expand Up @@ -64,6 +66,13 @@ create_py_exception!(
PyInlineFunctionsError,
"Errors from the function inlining pass."
);

create_py_exception!(
tket_qsystem::QSystemPassError,
PyQSystemPassError,
"Errors from the QSystem rebase pass."
);

/// Flatten the structure of a Guppy-generated program to enable additional optimisations.
///
/// This should normally be called first before other optimisations.
Expand Down Expand Up @@ -203,3 +212,24 @@ fn resolve_modifiers(circ: &mut CompilationState, scope: Option<PyPassScope>) ->
pass.run(&mut circ.hugr).convert_pyerrs()?;
Ok(())
}

#[pyfunction]
#[pyo3(signature=(circ, *, constant_fold = true, monomorphize = true, force_order = true, lazify = true, scope = None))]
fn qsystem_rebase_pass(
circ: &mut CompilationState,
constant_fold: bool,
monomorphize: bool,
force_order: bool,
lazify: bool,
scope: Option<PyPassScope>,
) -> PyResult<()> {
let py_scope = scope.unwrap_or_default();
let qsystem_pass = tket_qsystem::QSystemPass::default_with_scope(py_scope.scope)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

One flag that's missing here is hide_funcs which is in the QSystemPass rust struct. We should also expose this to Python right? There is no corresponding "with" method that I'm aware of.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

That looks like an unintended omission.

Could you add a with_hide_funcs method, and propagate it here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

added in 739870d739870d. Do the docs make sense?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

.with_constant_fold(constant_fold)
.with_monomorphize(monomorphize)
.with_force_order(force_order)
.with_lazify(lazify);

qsystem_pass.run(&mut circ.hugr).convert_pyerrs()?;
Ok(())
}
4 changes: 4 additions & 0 deletions tket-py/test/test_pass.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,7 @@ def test_inline_functions() -> None:
all = InlineFunctions(heuristic=inline_funcs.All())(hugr)

assert _count_ops(all, "Call") == 0


def test_qsystem_pass() -> None:
pass
10 changes: 10 additions & 0 deletions tket-py/tket/_tket/passes.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,13 @@ def resolve_modifiers(
:param circ: The input program as a CompilationState.
:param scope: A scope to control how the pass is applied to HUGR regions.
"""

def qsystem_rebase_pass(
circ: CompilationState,
constant_fold: bool = True,
monomorphize: bool = True,
force_order: bool = True,
lazify: bool = True,
scope: PassScope | None = None,
) -> None:
"""Runs a rust backed pass to convert quantum ops to qsystem ops."""
Comment thread
CalMacCQ marked this conversation as resolved.
Outdated
46 changes: 46 additions & 0 deletions tket-py/tket/passes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,49 @@ def _run_tk(self, program: _state.CompilationState) -> _state.CompilationState:
scope=self._scope,
)
return program


@dataclass
Comment thread
CalMacCQ marked this conversation as resolved.
Outdated
class QSystemPass(ComposablePass):
"""A pass to convert quantum ops to qsystem ops."""

Comment thread
CalMacCQ marked this conversation as resolved.
constant_fold: bool = True
monomorphize: bool = True
force_order: bool = True
lazify: bool = True
_scope: PassScope = GlobalScope.PRESERVE_PUBLIC

def run(self, hugr: Hugr, *, inplace: bool = True) -> PassResult:
return implement_pass_run(
self,
hugr=hugr,
inplace=inplace,
copy_call=lambda h: self._qsystem_rebase(h, inplace),
)

def with_scope(self, scope: PassScope) -> QSystemPass:
"""Set the scope of this pass and return self."""
self._scope = scope
return self

def _qsystem_rebase(self, hugr: Hugr, inplace: bool) -> PassResult:
tk_program = _state.CompilationState.from_python(hugr)

self._run_tk(tk_program)

package = tk_program.to_python()
return PassResult.for_pass(
self, hugr=package.modules[0], inplace=inplace, result=None
)

def _run_tk(self, program: _state.CompilationState) -> _state.CompilationState:
"""Run the pass in the CompilationState"""
_passes.qsystem_rebase_pass(
program._inner,
constant_fold=self.constant_fold,
monomorphize=self.monomorphize,
force_order=self.force_order,
lazify=self.lazify,
scope=self._scope,
)
return program
Loading