-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Move python bindings of structs to
tket-py
- Loading branch information
Showing
16 changed files
with
372 additions
and
321 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
//! Utilities for calling Hugr functions on generic python objects. | ||
use pyo3::{prelude::*, PyTypeInfo}; | ||
|
||
use hugr::{Hugr, HugrView}; | ||
use tket2::extension::REGISTRY; | ||
use tket2::json::TKETDecode; | ||
use tket2::passes::CircuitChunks; | ||
use tket2::rewrite::CircuitRewrite; | ||
use tket_json_rs::circuit_json::SerialCircuit; | ||
|
||
/// A manager for tket 2 operations on a tket 1 Circuit. | ||
#[pyclass] | ||
#[derive(Clone, Debug, PartialEq)] | ||
pub struct T2Circuit { | ||
/// Rust representation of the circuit. | ||
pub hugr: Hugr, | ||
} | ||
|
||
#[pymethods] | ||
impl T2Circuit { | ||
#[new] | ||
fn from_circuit(circ: PyObject) -> PyResult<Self> { | ||
Ok(Self { | ||
hugr: super::to_hugr(circ)?, | ||
}) | ||
} | ||
|
||
fn finish(&self) -> PyResult<PyObject> { | ||
SerialCircuit::encode(&self.hugr)?.to_tket1_with_gil() | ||
} | ||
|
||
fn apply_match(&mut self, rw: CircuitRewrite) { | ||
rw.apply(&mut self.hugr).expect("Apply error."); | ||
} | ||
} | ||
impl T2Circuit { | ||
/// Tries to extract a T2Circuit from a python object. | ||
/// | ||
/// Returns an error if the py object is not a T2Circuit. | ||
pub fn try_extract(circ: Py<PyAny>) -> PyResult<Self> { | ||
Python::with_gil(|py| circ.as_ref(py).extract::<T2Circuit>()) | ||
} | ||
} | ||
|
||
/// Apply a fallible function expecting a hugr on a pytket circuit. | ||
pub fn try_with_hugr<T, E, F>(circ: Py<PyAny>, f: F) -> PyResult<T> | ||
where | ||
E: Into<PyErr>, | ||
F: FnOnce(Hugr) -> Result<T, E>, | ||
{ | ||
let hugr = Python::with_gil(|py| -> PyResult<Hugr> { | ||
let circ = circ.as_ref(py); | ||
match T2Circuit::extract(circ) { | ||
// hugr circuit | ||
Ok(t2circ) => Ok(t2circ.hugr), | ||
// tket1 circuit | ||
Err(_) => Ok(SerialCircuit::from_tket1(circ)?.decode()?), | ||
} | ||
})?; | ||
(f)(hugr).map_err(|e| e.into()) | ||
} | ||
|
||
/// Apply a function expecting a hugr on a pytket circuit. | ||
pub fn with_hugr<T, F>(circ: Py<PyAny>, f: F) -> PyResult<T> | ||
where | ||
F: FnOnce(Hugr) -> T, | ||
{ | ||
try_with_hugr(circ, |hugr| Ok::<T, PyErr>((f)(hugr))) | ||
} | ||
|
||
/// Apply a hugr-to-hugr function on a pytket circuit, and return the modified circuit. | ||
pub fn try_update_hugr<E, F>(circ: Py<PyAny>, f: F) -> PyResult<Py<PyAny>> | ||
where | ||
E: Into<PyErr>, | ||
F: FnOnce(Hugr) -> Result<Hugr, E>, | ||
{ | ||
let hugr = try_with_hugr(circ, f)?; | ||
SerialCircuit::encode(&hugr)?.to_tket1_with_gil() | ||
} | ||
|
||
/// Apply a hugr-to-hugr function on a pytket circuit, and return the modified circuit. | ||
pub fn update_hugr<F>(circ: Py<PyAny>, f: F) -> PyResult<Py<PyAny>> | ||
where | ||
F: FnOnce(Hugr) -> Hugr, | ||
{ | ||
let hugr = with_hugr(circ, f)?; | ||
SerialCircuit::encode(&hugr)?.to_tket1_with_gil() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//! Circuit chunking utilities. | ||
use derive_more::From; | ||
use pyo3::exceptions::PyAttributeError; | ||
use pyo3::prelude::*; | ||
use tket2::json::TKETDecode; | ||
use tket2::passes::CircuitChunks; | ||
use tket2::Circuit; | ||
use tket_json_rs::circuit_json::SerialCircuit; | ||
|
||
use crate::circuit::{with_hugr, T2Circuit}; | ||
|
||
/// Split a circuit into chunks of a given size. | ||
#[pyfunction] | ||
pub fn chunks(c: Py<PyAny>, max_chunk_size: usize) -> PyResult<PyCircuitChunks> { | ||
with_hugr(c, |hugr| { | ||
// TODO: Detect if the circuit is in tket1 format or T2Circuit. | ||
let is_tket1 = true; | ||
let chunks = CircuitChunks::split(&hugr, max_chunk_size); | ||
(chunks, is_tket1).into() | ||
}) | ||
} | ||
|
||
/// A pattern that match a circuit exactly | ||
/// | ||
/// Python equivalent of [`CircuitChunks`]. | ||
/// | ||
/// [`CircuitChunks`]: tket2::passes::chunks::CircuitChunks | ||
#[pyclass] | ||
#[pyo3(name = "CircuitChunks")] | ||
#[derive(Debug, Clone, From)] | ||
pub struct PyCircuitChunks { | ||
/// Rust representation of the circuit chunks. | ||
pub chunks: CircuitChunks, | ||
/// Whether to reassemble the circuit in the tket1 format. | ||
pub in_tket1: bool, | ||
} | ||
|
||
#[pymethods] | ||
impl PyCircuitChunks { | ||
/// Reassemble the chunks into a circuit. | ||
fn reassemble(&self) -> PyResult<Py<PyAny>> { | ||
let hugr = self.clone().chunks.reassemble()?; | ||
Python::with_gil(|py| match self.in_tket1 { | ||
true => Ok(SerialCircuit::encode(&hugr)?.to_tket1(py)?.into_py(py)), | ||
false => Ok(T2Circuit { hugr }.into_py(py)), | ||
}) | ||
} | ||
|
||
/// Returns clones of the split circuits. | ||
fn circuits(&self) -> PyResult<Vec<Py<PyAny>>> { | ||
self.chunks | ||
.iter() | ||
.map(|hugr| SerialCircuit::encode(hugr)?.to_tket1_with_gil()) | ||
.collect() | ||
} | ||
|
||
/// Replaces a chunk's circuit with an updated version. | ||
fn update_circuit(&mut self, index: usize, new_circ: Py<PyAny>) -> PyResult<()> { | ||
let hugr = SerialCircuit::from_tket1_with_gil(new_circ)?.decode()?; | ||
if hugr.circuit_signature() != self.chunks[index].circuit_signature() { | ||
return Err(PyAttributeError::new_err( | ||
"The new circuit has a different signature.", | ||
)); | ||
} | ||
self.chunks[index] = hugr; | ||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.