Skip to content

Commit

Permalink
feat: add num_gates to Circuit (#61)
Browse files Browse the repository at this point in the history
- feat: expose JSON loading API
- feat: add num_gates to Circuit

---------

Co-authored-by: Agustín Borgna <[email protected]>
  • Loading branch information
lmondada and aborgna-q authored Aug 30, 2023
1 parent b13dcea commit 0f8bebe
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ pub trait Circuit<'circ>: HugrView {
fn command_optype(&self, command: &Command) -> &OpType {
self.get_optype(command.node())
}

/// The number of gates in the circuit.
fn num_gates(&self) -> usize;
}

impl<'circ, T> Circuit<'circ> for T
Expand Down Expand Up @@ -143,4 +146,49 @@ where
fn output(&self) -> Node {
return self.children(self.root()).nth(1).unwrap();
}

#[inline]
fn num_gates(&self) -> usize {
self.children(self.root()).count() - 2
}
}

#[cfg(test)]
mod tests {
use std::sync::OnceLock;

use hugr::{
hugr::views::{DescendantsGraph, HierarchyView},
ops::handle::DfgID,
Hugr, HugrView,
};

use crate::{circuit::Circuit, json::load_tk1_json_str};

static CIRC: OnceLock<Hugr> = OnceLock::new();

fn test_circuit() -> DescendantsGraph<'static, DfgID> {
let hugr = CIRC.get_or_init(|| {
load_tk1_json_str(
r#"{
"phase": "0",
"bits": [],
"qubits": [["q", [0]], ["q", [1]]],
"commands": [
{"args": [["q", [0]]], "op": {"type": "H"}},
{"args": [["q", [0]], ["q", [1]]], "op": {"type": "CX"}}
],
"implicit_permutation": [[["q", [0]], ["q", [0]]], [["q", [1]], ["q", [1]]]]
}"#,
)
.unwrap()
});
DescendantsGraph::new(hugr, hugr.root())
}

#[test]
fn test_num_gates() {
let circ = test_circuit();
assert_eq!(circ.num_gates(), 2);
}
}
58 changes: 58 additions & 0 deletions src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub mod op;
#[cfg(test)]
mod tests;

use std::{fs, io};

use hugr::ops::OpType;
use hugr::std_extensions::arithmetic::float_types::ConstF64;
use hugr::values::Value;
Expand Down Expand Up @@ -81,6 +83,62 @@ pub enum OpConvertError {
NonSerializableInputs(OpType),
}

/// Load a TKET1 circuit from a JSON file.
pub fn load_tk1_json_file(path: &str) -> Result<Hugr, TK1LoadError> {
let file = fs::File::open(path)?;
let reader = io::BufReader::new(file);
let ser: SerialCircuit = serde_json::from_reader(reader)?;
Ok(ser.decode()?)
}

/// Load a TKET1 circuit from a JSON string.
pub fn load_tk1_json_str(json: &str) -> Result<Hugr, TK1LoadError> {
let ser: SerialCircuit = serde_json::from_str(json)?;
Ok(ser.decode()?)
}

/// Error type for conversion between `Op` and `OpType`.
#[derive(Debug, Error)]
pub enum TK1LoadError {
/// The serialized operation is not supported.
#[error("unsupported serialized operation: {0:?}")]
UnsupportedSerializedOp(JsonOpType),
/// The serialized operation is not supported.
#[error("cannot serialize operation: {0:?}")]
UnsupportedOpSerialization(OpType),
/// The serialized operation is not supported.
#[error("cannot serialize operation: {0:?}")]
NonSerializableInputs(OpType),
/// Invalid JSON,
#[error("invalid JSON")]
InvalidJson,
/// File not found.,
#[error("unable to load file")]
FileLoadError,
}

impl From<serde_json::Error> for TK1LoadError {
fn from(_: serde_json::Error) -> Self {
Self::InvalidJson
}
}

impl From<io::Error> for TK1LoadError {
fn from(_: io::Error) -> Self {
Self::FileLoadError
}
}

impl From<OpConvertError> for TK1LoadError {
fn from(value: OpConvertError) -> Self {
match value {
OpConvertError::UnsupportedSerializedOp(op) => Self::UnsupportedSerializedOp(op),
OpConvertError::UnsupportedOpSerialization(op) => Self::UnsupportedOpSerialization(op),
OpConvertError::NonSerializableInputs(op) => Self::NonSerializableInputs(op),
}
}
}

/// Try to interpret a TKET1 parameter as a constant value.
#[inline]
fn try_param_to_constant(param: &str) -> Option<Value> {
Expand Down

0 comments on commit 0f8bebe

Please sign in to comment.