Skip to content

Commit

Permalink
doc: Add missing docs everywhere (#9)
Browse files Browse the repository at this point in the history
* Add missing docs everywhere

* Apply suggestions from code review

Co-authored-by: Seyon Sivarajah <[email protected]>

* Drop stale tket2ops feature (#11)

---------

Co-authored-by: Seyon Sivarajah <[email protected]>
  • Loading branch information
aborgna-q and ss2165 authored Aug 18, 2023
1 parent 619db15 commit c041a1a
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 418 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,4 @@ pythonize = { version = "0.19.0", optional = true }


[features]
pyo3 = ["dep:pyo3", "dep:pythonize", "tket2ops"]
tket2ops = []
pyo3 = ["dep:pyo3", "dep:pythonize"]
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ tket-json-rs
[![msrv][]](https://github.com/CQCL/tket-json-rs)
[![docs][]](https://docs.rs/tket-json-rs)

Serializable definition of TKET circuits and operations.
Serializable Rust definition for circuits and operations of the
[TKET](https://github.com/CQCL/tket) quantum compiler.

## Features

- `pyo3`: Enable Python bindings via pyo3.
- `tket2ops`: Enable definitions for TKET2 operations.

## Recent Changes

Expand All @@ -27,4 +27,4 @@ This project is licensed under Apache License, Version 2.0 ([LICENSE][] or http:
[crates]: https://img.shields.io/crates/v/tket-json-rs
[LICENSE]: LICENCE
[msrv]: https://img.shields.io/badge/rust-1.60.0%2B-blue.svg?maxAge=3600
[RELEASES]: RELEASES.rst
[RELEASES]: RELEASES.md
4 changes: 3 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Release notes

## [unreleased]
## v0.1.0 (2023-08-18)

- Initial release.
70 changes: 63 additions & 7 deletions src/circuit_json.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
//! Contains structs for serializing and deserializing TKET circuits to and from
//! JSON.
use crate::optype::OpType;
use serde::{Deserialize, Serialize};

/// A register of locations sharing the same name.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Register(pub String, pub Vec<i64>);

/// A gate defined by a circuit.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct CompositeGate {
// List of Symbols
Expand All @@ -12,33 +17,43 @@ pub struct CompositeGate {
name: String,
}

/// A classical bit register.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash)]
pub struct BitRegister {
name: String,
size: u32,
}

/// The units used in a [`ClassicalExp`].
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash)]
#[serde(untagged)]
pub enum ClassicalExpUnit {
/// Unsigned 32-bit integer.
U32(u32),
/// Register of locations.
Register(Register),
/// Register of bits.
BitRegister(BitRegister),
/// A nested classical expression.
ClassicalExpUnit(ClassicalExp),
}

/// A box for holding classical expressions on Bits.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ClassicalExp {
args: Vec<ClassicalExpUnit>,
op: String,
}

/// A simple struct for Pauli strings with +/- phase, used to represent Pauli
/// strings in a stabiliser subgroup.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash)]
pub struct PauliStabiliser {
coeff: bool,
string: Vec<String>,
}

/// Unique identifier for an [`OpBox`].
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash)]
pub struct BoxID(uuid::Uuid);

Expand All @@ -47,40 +62,55 @@ pub struct BoxID(uuid::Uuid);
/// to the operation is differently named when serializing.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
#[serde(tag = "type")]
#[allow(missing_docs)]
#[non_exhaustive]
pub enum OpBox {
/// Operation defined as a circuit.
CircBox {
id: BoxID,
/// The circuit defining the operation.
circuit: SerialCircuit,
},
/// One-qubit operation defined as a unitary matrix.
Unitary1qBox {
id: BoxID,
// 2x2 matrix of complex numbers
/// 2x2 matrix of complex numbers
matrix: [[(f32, f32); 2]; 2],
},
/// Two-qubit operation defined as a unitary matrix.
Unitary2qBox {
id: BoxID,
// 4x4 matrix of complex numbers
/// 4x4 matrix of complex numbers
matrix: [[(f32, f32); 4]; 4],
},
/// Three-qubit operation defined as a unitary matrix.
Unitary3qBox {
id: BoxID,
// 8x8 matric of complex numbers
/// 8x8 matrix of complex numbers
matrix: Box<[[(f32, f32); 8]; 8]>,
},
/// Two-qubit operation defined in terms of a hermitian matrix and a phase.
ExpBox {
id: BoxID,
// 4x4 matrix of complex numbers
/// 4x4 matrix of complex numbers
matrix: [[(f32, f32); 4]; 4],
/// Phase of the operation.
phase: f64,
},
/// Operation defined as the exponential of a tensor of Pauli operators.
PauliExpBox {
id: BoxID,
/// List of Pauli operators.
paulis: Vec<String>,
// Symengine Expr
/// Symengine expression
phase: String,
},
/// An operation capable of representing arbitrary Circuits made up of CNOT
/// and RZ, as a PhasePolynomial plus a boolean matrix representing an
/// additional linear transformation.
PhasePolyBox {
id: BoxID,
/// Number of qubits.
n_qubits: u32,
qubit_indices: Vec<(u32, u32)>,
},
Expand All @@ -98,11 +128,15 @@ pub enum OpBox {
// Vec of Symengine Expr
params: Vec<String>,
},
/// Wraps another quantum op, adding control qubits.
QControlBox {
id: BoxID,
/// Number of control qubits.
n_controls: u32,
/// The operation to be controlled.
op: Box<Operation>,
},
/// Holding box for abstract expressions on Bits.
ClassicalExpBox {
id: BoxID,
n_i: u32,
Expand All @@ -112,55 +146,77 @@ pub enum OpBox {
},
}

/// Decorates another op, adding a QASM-style classical condition.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct Conditional {
op: Box<Operation>,
width: u32,
value: u32,
}

/// Serializable operation descriptor.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct Operation<P = String> {
/// The type of operation.
#[serde(rename = "type")]
pub op_type: OpType,
/// Number of input and output qubits.
#[serde(skip_serializing_if = "Option::is_none")]
pub n_qb: Option<u32>,
/// Expressions for the parameters of the operation.
#[serde(skip_serializing_if = "Option::is_none")]
pub params: Option<Vec<P>>,
/// Internal box for the operation.
#[serde(rename = "box")]
#[serde(skip_serializing_if = "Option::is_none")]
pub op_box: Option<OpBox>,
/// The pre-computed signature.
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<Vec<String>>,
/// A QASM-style classical condition for the operation.
#[serde(skip_serializing_if = "Option::is_none")]
pub conditional: Option<Conditional>,
}

/// Operation applied in a circuit, with defined arguments.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct Command<P = String> {
/// The operation to be applied.
pub op: Operation<P>,
/// The arguments to the operation.
pub args: Vec<Register>,
/// Operation group identifier.
#[serde(skip_serializing_if = "Option::is_none")]
pub opgroup: Option<String>,
}

/// A permutation of the elements of a register.
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Permutation(pub Register, pub Register);

/// Pytket canonical circuit
/// Pytket canonical serialized circuit
#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
pub struct SerialCircuit<P = String> {
/// The name of the circuit.
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
// Symengine Expr
/// The global phase, as a symengine expression.
pub phase: P,
/// List of commands in the circuit.
pub commands: Vec<Command<P>>,
/// Input qubit registers.
pub qubits: Vec<Register>,
/// Input bit registers.
pub bits: Vec<Register>,
/// Implicit permutation of the output qubits.
pub implicit_permutation: Vec<Permutation>,
}

impl<P> Operation<P> {
/// Returns a default-initialized Operation with the given type.
///
/// For optypes that require additional parameters, this may generate
/// invalid operations.
pub fn from_optype(op_type: OpType) -> Self {
Self {
op_type,
Expand Down
5 changes: 4 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#![warn(missing_docs)]
//! Serializable Rust definition for circuits and operations of the
//! [TKET](https://github.com/CQCL/tket) quantum compiler.
pub mod circuit_json;
pub mod optype;
#[cfg(feature = "pyo3")]
Expand All @@ -9,7 +13,6 @@ mod tests {
use serde_json::to_string;
#[test]
fn read_json() {
// let expr = symengine::Expression::new("a + b + 3");
let circ_s = r#"{"bits": [["c", [0]], ["c", [1]]], "commands": [{"args": [["q", [0]]], "op": {"type": "H"}}, {"args": [["q", [0]], ["q", [1]]], "op": {"type": "CX"}}, {"args": [["q", [0]], ["c", [0]]], "op": {"type": "Measure"}}, {"args": [["q", [1]], ["c", [1]]], "op": {"type": "Measure"}}], "implicit_permutation": [[["q", [0]], ["q", [0]]], [["q", [1]], ["q", [1]]]], "phase": "0.0", "qubits": [["q", [0]], ["q", [1]]]}"#;
let ser: SerialCircuit = serde_json::from_str(circ_s).unwrap();

Expand Down
Loading

0 comments on commit c041a1a

Please sign in to comment.