diff --git a/Cargo.toml b/Cargo.toml index 56ea6ca..d06402d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,8 @@ strum = { workspace = true, features = ["derive"] } [dev-dependencies] pyo3 = { workspace = true } +rstest = { workspace = true } +assert-json-diff = { workspace = true } [features] pyo3 = ["dep:pyo3", "dep:pythonize"] @@ -37,7 +39,9 @@ path = "tests/lib.rs" [workspace.dependencies] pyo3 = "0.21.1" pythonize = "0.21.1" +rstest = "0.21.0" serde = "1.0" serde_json = "1.0" strum = "0.26.2" uuid = "1.4" +assert-json-diff = "2.0.2" diff --git a/src/lib.rs b/src/lib.rs index f529722..5410829 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,19 +10,3 @@ pub mod pytket; pub use circuit_json::SerialCircuit; pub use optype::OpType; - -#[cfg(test)] -mod tests { - use crate::circuit_json::SerialCircuit; - use serde_json::to_string; - #[test] - fn read_json() { - 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(); - - assert_eq!(ser.commands.len(), 4); - - let reser: SerialCircuit = serde_json::from_str(&to_string(&ser).unwrap()[..]).unwrap(); - assert_eq!(ser, reser); - } -} diff --git a/src/opbox.rs b/src/opbox.rs index 10862a6..ae8f30e 100644 --- a/src/opbox.rs +++ b/src/opbox.rs @@ -117,7 +117,7 @@ pub enum OpBox { /// The phase polynomial definition. /// Represented by a map from bitstring to expression of coefficient. phase_polynomial: Vec>, - /// + /// The additional linear transformation. linear_transformation: Matrix, }, /// A user-defined assertion specified by a list of Pauli stabilisers. diff --git a/tests/data/diagonal-box.json b/tests/data/diagonal-box.json new file mode 100644 index 0000000..b6e1c2b --- /dev/null +++ b/tests/data/diagonal-box.json @@ -0,0 +1,137 @@ +{ + "bits": [], + "commands": [ + { + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 2 + ] + ] + ], + "op": { + "box": { + "control_state": 1, + "id": "0dadbfea-5391-41c2-ad71-fb01fdaecddd", + "n_controls": 1, + "op": { + "box": { + "diagonal": [ + [ + [ + 1.0, + 0.0 + ] + ], + [ + [ + 1.0, + 0.0 + ] + ], + [ + [ + 0.7071067811865476, + 0.7071067811865475 + ] + ], + [ + [ + 0.9238795325112867, + 0.3826834323650898 + ] + ] + ], + "id": "919b6c13-b9c4-4ffc-ad1a-660088402d02", + "type": "DiagonalBox", + "upper_triangle": true + }, + "type": "DiagonalBox" + }, + "type": "QControlBox" + }, + "type": "QControlBox" + } + } + ], + "created_qubits": [], + "discarded_qubits": [], + "implicit_permutation": [ + [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 0 + ] + ] + ], + [ + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 1 + ] + ] + ], + [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 2 + ] + ] + ] + ], + "phase": "0.0", + "qubits": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 2 + ] + ] + ] +} \ No newline at end of file diff --git a/tests/data/simple.json b/tests/data/simple.json new file mode 100644 index 0000000..855dbaa --- /dev/null +++ b/tests/data/simple.json @@ -0,0 +1,133 @@ +{ + "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 + ] + ] + ] +} \ No newline at end of file diff --git a/tests/roundtrip.rs b/tests/roundtrip.rs new file mode 100644 index 0000000..d7d85cf --- /dev/null +++ b/tests/roundtrip.rs @@ -0,0 +1,26 @@ +//! Roundtrip tests +use assert_json_diff::assert_json_include; +use rstest::rstest; +use serde_json::Value; +use tket_json_rs::SerialCircuit; + +const SIMPLE: &str = include_str!("data/simple.json"); +const DIAGONAL: &str = include_str!("data/diagonal-box.json"); + +#[rstest] +#[case::simple(SIMPLE, 4)] +#[case::diagonal_box(DIAGONAL, 1)] +fn roundtrip(#[case] json: &str, #[case] num_commands: usize) { + let initial_json: Value = serde_json::from_str(json).unwrap(); + let ser: SerialCircuit = serde_json::from_value(initial_json.clone()).unwrap(); + + assert_eq!(ser.commands.len(), num_commands); + + let reencoded_json = serde_json::to_value(&ser).unwrap(); + // Do a partial comparison. The re-encoded circuit does not include "created_qubits" nor "discarded_qubits". + assert_json_include!(actual: initial_json, expected: reencoded_json); + + let reser: SerialCircuit = serde_json::from_value(reencoded_json).unwrap(); + + assert_eq!(ser, reser); +}