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

refactor: Drop dead code from circuits, Hugr updates #30

Merged
merged 5 commits into from
Jul 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 7 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,21 @@ serde_json = "1.0"
downcast-rs = "1.2.0"
portgraph = "0.7.0"
priority-queue = "1.3.0"
quantinuum-hugr = { git = "https://github.com/CQCL-DEV/hugr", tag = "v0.0.0-alpha.1" }
quantinuum-hugr = { git = "https://github.com/CQCL-DEV/hugr", tag = "v0.0.0-alpha.3" }
smol_str = "0.2.0"
typetag = "0.2.8"

itertools = "0.11.0"
petgraph = { version = "0.6.3", default-features = false }

[features]
pyo3 = [
"dep:pyo3",
"tket-json-rs/pyo3",
"tket-json-rs/tket2ops",
"portgraph/pyo3",
]
pyo3 = ["dep:pyo3", "tket-json-rs/pyo3", "tket-json-rs/tket2ops", "portgraph/pyo3", "quantinuum-hugr/pyo3"]
tkcxx = ["dep:tket-rs", "dep:num-complex"]

[dev-dependencies]
rstest = "0.17.0"
rstest = "0.18.1"
criterion = { version = "0.5.1", features = ["html_reports"] }

webbrowser = "0.8.10"
urlencoding = "2.1.2"

#[[bench]]
#name = "tket2_bench"
Expand Down
2 changes: 1 addition & 1 deletion pyrs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ portgraph = { version = "0.7.0", features = ["pyo3"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tket-json-rs = { git = "https://github.com/CQCL/tket-json-rs", features = ["pyo3"] }
quantinuum-hugr = { version = "0.1.0", git="https://github.com/CQCL-DEV/hugr", tag = "v0.0.0-alpha.1" }
quantinuum-hugr = { version = "0.1.0", git="https://github.com/CQCL-DEV/hugr", tag = "v0.0.0-alpha.3" }
110 changes: 106 additions & 4 deletions src/circuit.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,114 @@
#[allow(clippy::module_inception)]
pub mod circuit;
//pub mod dag;
//pub mod operation;
//! Quantum circuit representation and operations.

pub mod command;

//#[cfg(feature = "pyo3")]
//pub mod py_circuit;

//#[cfg(feature = "tkcxx")]
//pub mod unitarybox;

// TODO: Move TKET1's custom op definition to tket-rs (or hugr?)
//mod tk1ops;

use self::command::{Command, CommandIterator, Unit};

use hugr::ops::OpTrait;

pub use hugr::hugr::region::Region;
pub use hugr::ops::OpType;
pub use hugr::types::{ClassicType, EdgeKind, LinearType, Signature, SimpleType, TypeRow};
pub use hugr::{Node, Port, Wire};
use petgraph::visit::{GraphBase, IntoNeighborsDirected, IntoNodeIdentifiers};

/// An object behaving like a quantum circuit.
//
// TODO: More methods:
// - other_{in,out}puts (for non-linear i/o + const inputs)?
// - Vertical slice iterator
// - Gate count map
// - Depth
pub trait Circuit<'circ> {
/// An iterator over the commands in the circuit.
type Commands: Iterator<Item = Command<'circ>>;

/// An iterator over the commands applied to an unit.
type UnitCommands: Iterator<Item = Command<'circ>>;

/// Return the name of the circuit
fn name(&self) -> Option<&str>;

/// Get the linear inputs of the circuit and their types.
fn units(&self) -> Vec<(Unit, SimpleType)>;

/// Returns the ports corresponding to qubits inputs to the circuit.
#[inline]
fn qubits(&self) -> Vec<Unit> {
self.units()
.iter()
.filter(|(_, typ)| typ == &LinearType::Qubit.into())
.map(|(unit, _)| *unit)
.collect()
}

/// Given a linear port in a node, returns the corresponding port on the other side of the node (if any).
fn follow_linear_port(&self, node: Node, port: Port) -> Option<Port>;

/// Returns all the commands in the circuit, in some topological order.
fn commands<'a: 'circ>(&'a self) -> Self::Commands;

/// Returns all the commands applied to the given unit, in order.
fn unit_commands<'a: 'circ>(&'a self) -> Self::UnitCommands;
}

impl<'circ, T> Circuit<'circ> for T
where
T: 'circ + Region<'circ>,
for<'a> &'a T: GraphBase<NodeId = Node> + IntoNeighborsDirected + IntoNodeIdentifiers,
{
type Commands = CommandIterator<'circ, T>;
type UnitCommands = std::iter::Empty<Command<'circ>>;

#[inline]
fn name(&self) -> Option<&str> {
let meta = self.get_metadata(self.root()).as_object()?;
meta.get("name")?.as_str()
}

#[inline]
fn units(&self) -> Vec<(Unit, SimpleType)> {
let root = self.root();
let optype = self.get_optype(root);
optype
.signature()
.input_df_types()
.iter()
.filter(|typ| typ.is_linear())
.enumerate()
.map(|(i, typ)| (i.into(), typ.clone()))
.collect()
}

fn follow_linear_port(&self, node: Node, port: Port) -> Option<Port> {
let optype = self.get_optype(node);
if !optype.port_kind(port)?.is_linear() {
return None;
}
// TODO: We assume the linear data uses the same port offsets on both sides of the node.
// In the future we may want to have a more general mechanism to handle this.
let other_port = Port::new(port.direction().reverse(), port.index());
debug_assert_eq!(optype.port_kind(other_port), optype.port_kind(port));
Some(other_port)
}

fn commands<'a: 'circ>(&'a self) -> Self::Commands {
// Traverse the circuit in topological order.
CommandIterator::new(self)
}

fn unit_commands<'a: 'circ>(&'a self) -> Self::UnitCommands {
// TODO Can we associate linear i/o with the corresponding unit without
// doing the full toposort?
todo!()
}
}
Loading