diff --git a/.github/workflows/issue.yml b/.github/workflows/issue.yml index 3ba0f656..311494ef 100644 --- a/.github/workflows/issue.yml +++ b/.github/workflows/issue.yml @@ -15,21 +15,55 @@ jobs: JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + - name: Parse the priority label into a Jira priority + id: set_priority_var + env: + LABELS: ${{ join(github.event.issue.labels.*.name, ' ') }} + run: | + MY_RESULT="" + for label in $LABELS + do + case $label in + P-low) + MY_RESULT=Low + break;; + P-medium) + MY_RESULT=Medium + break;; + P-high) + MY_RESULT=High + break;; + P-critical) + MY_RESULT=Highest + break;; + esac + done + if [ ! -z $MY_RESULT ] + then + MY_RESULT=", \"priority\": { \"name\": \"$MY_RESULT\" }" + fi + echo "JIRA_PRIORITY_FIELD=$MY_RESULT" >> $GITHUB_OUTPUT + - name: Create Bug uses: atlassian/gajira-create@v3.0.1 - if: "contains(github.event.issue.labels.*.name, 'bug')" + if: ${{ contains(github.event.issue.labels.*.name, 'bug') }} + env: + JIRA_PRIORITY_FIELD: ${{ steps.set_priority_var.outputs.JIRA_PRIORITY_FIELD }} with: project: TKET issuetype: Bug summary: « [tket2] ${{ github.event.issue.title }}» description: ${{ github.event.issue.html_url }} - fields: '{"labels": ["tket2"]}' + fields: '{ "labels": ["tket2"] ${{ env.JIRA_PRIORITY_FIELD }} }' + - name: Create Task uses: atlassian/gajira-create@v3.0.1 - if: "! contains(github.event.issue.labels.*.name, 'bug')" + if: ${{ ! contains(github.event.issue.labels.*.name, 'bug') }} + env: + JIRA_PRIORITY_FIELD: ${{ steps.set_priority_var.outputs.JIRA_PRIORITY_FIELD }} with: project: TKET issuetype: Task summary: « [tket2] ${{ github.event.issue.title }}» description: ${{ github.event.issue.html_url }} - fields: '{"labels": ["tket2"]}' + fields: '{ "labels": ["tket2"] ${{ env.JIRA_PRIORITY_FIELD }} }' diff --git a/src/json.rs b/src/json.rs index 37ddbb59..f6f6f94f 100644 --- a/src/json.rs +++ b/src/json.rs @@ -30,8 +30,14 @@ use self::encoder::JsonEncoder; /// Prefix used for storing metadata in the hugr nodes. pub const METADATA_PREFIX: &str = "TKET1_JSON"; +/// The global phase specified as metadata. const METADATA_PHASE: &str = "TKET1_JSON.phase"; +/// The implicit permutation of qubits. const METADATA_IMPLICIT_PERM: &str = "TKET1_JSON.implicit_permutation"; +/// Explicit names for the input qubit registers. +const METADATA_Q_REGISTERS: &str = "TKET1_JSON.qubit_registers"; +/// Explicit names for the input bit registers. +const METADATA_B_REGISTERS: &str = "TKET1_JSON.bit_registers"; /// A JSON-serialized circuit that can be converted to a [`Hugr`]. pub trait TKETDecode: Sized { @@ -123,21 +129,24 @@ pub fn load_tk1_json_str(json: &str) -> Result { } /// Save a circuit to file in TK1 JSON format. -pub fn save_tk1_json_file(path: impl AsRef, circ: &Hugr) -> Result<(), TK1ConvertError> { +pub fn save_tk1_json_file( + circ: &impl Circuit, + path: impl AsRef, +) -> Result<(), TK1ConvertError> { let file = fs::File::create(path)?; let writer = io::BufWriter::new(file); save_tk1_json_writer(circ, writer) } /// Save a circuit in TK1 JSON format to a writer. -pub fn save_tk1_json_writer(circ: &Hugr, w: impl io::Write) -> Result<(), TK1ConvertError> { +pub fn save_tk1_json_writer(circ: &impl Circuit, w: impl io::Write) -> Result<(), TK1ConvertError> { let serial_circ = SerialCircuit::encode(circ)?; serde_json::to_writer(w, &serial_circ)?; Ok(()) } /// Save a circuit in TK1 JSON format to a String. -pub fn save_tk1_json_str(circ: &Hugr) -> Result { +pub fn save_tk1_json_str(circ: &impl Circuit) -> Result { let mut buf = io::BufWriter::new(Vec::new()); save_tk1_json_writer(circ, &mut buf)?; let bytes = buf.into_inner().unwrap(); diff --git a/src/json/decoder.rs b/src/json/decoder.rs index 19c4cd0b..38c712ba 100644 --- a/src/json/decoder.rs +++ b/src/json/decoder.rs @@ -22,6 +22,7 @@ use tket_json_rs::circuit_json::SerialCircuit; use super::op::JsonOp; use super::{try_param_to_constant, METADATA_IMPLICIT_PERM, METADATA_PHASE}; use crate::extension::{LINEAR_BIT, REGISTRY}; +use crate::json::{METADATA_B_REGISTERS, METADATA_Q_REGISTERS}; use crate::symbolic_constant_op; /// The state of an in-progress [`DFGBuilder`] being built from a [`SerialCircuit`]. @@ -76,6 +77,8 @@ impl JsonDecoder { "name": serialcirc.name, METADATA_PHASE: serialcirc.phase, METADATA_IMPLICIT_PERM: serialcirc.implicit_permutation, + METADATA_Q_REGISTERS: serialcirc.qubits, + METADATA_B_REGISTERS: serialcirc.bits, }); dfg.set_metadata(metadata); diff --git a/src/json/encoder.rs b/src/json/encoder.rs index ca7fe187..cd026005 100644 --- a/src/json/encoder.rs +++ b/src/json/encoder.rs @@ -16,7 +16,10 @@ use crate::extension::LINEAR_BIT; use crate::ops::match_symb_const_op; use super::op::JsonOp; -use super::{OpConvertError, METADATA_IMPLICIT_PERM, METADATA_PHASE}; +use super::{ + OpConvertError, METADATA_B_REGISTERS, METADATA_IMPLICIT_PERM, METADATA_PHASE, + METADATA_Q_REGISTERS, +}; /// The state of an in-progress [`SerialCircuit`] being built from a [`Circuit`]. #[derive(Debug, PartialEq)] @@ -30,9 +33,13 @@ pub(super) struct JsonEncoder { /// The current commands commands: Vec, /// The TKET1 qubit registers associated to each qubit unit of the circuit. - qubit_regs: HashMap, + qubit_to_reg: HashMap, /// The TKET1 bit registers associated to each linear bit unit of the circuit. - bit_regs: HashMap, + bit_to_reg: HashMap, + /// The ordered TKET1 names for the input qubit registers. + qubit_registers: Vec, + /// The ordered TKET1 names for the input bit registers. + bit_registers: Vec, /// A register of wires with constant values, used to recover TKET1 /// parameters. parameters: HashMap, @@ -43,48 +50,63 @@ impl JsonEncoder { pub fn new(circ: &impl Circuit) -> Self { let name = circ.name().map(str::to_string); - // Compute the linear qubit and bit registers. Each one have independent - // indices starting from zero. - // - // TODO Throw an error on non-recognized unit types, or just ignore? - let mut bit_units = HashMap::new(); - let mut qubit_units = HashMap::new(); + let mut qubit_registers = vec![]; + let mut bit_registers = vec![]; + let mut phase = "0".to_string(); + let mut implicit_permutation = vec![]; + + // Recover other parameters stored in the metadata + if let Some(meta) = circ.get_metadata(circ.root()).as_object() { + if let Some(p) = meta.get(METADATA_PHASE) { + // TODO: Check for invalid encoded metadata + phase = p.as_str().unwrap().to_string(); + } + if let Some(perm) = meta.get(METADATA_IMPLICIT_PERM) { + // TODO: Check for invalid encoded metadata + implicit_permutation = serde_json::from_value(perm.clone()).unwrap(); + } + if let Some(q_regs) = meta.get(METADATA_Q_REGISTERS) { + qubit_registers = serde_json::from_value(q_regs.clone()).unwrap(); + } + if let Some(b_regs) = meta.get(METADATA_B_REGISTERS) { + bit_registers = serde_json::from_value(b_regs.clone()).unwrap(); + } + } + + // Map the Hugr units to tket1 register names. + // Uses the names from the metadata if available, or initializes new sequentially-numbered registers. + let mut bit_to_reg = HashMap::new(); + let mut qubit_to_reg = HashMap::new(); + let get_register = |registers: &mut Vec, prefix: &str, index| { + registers.get(index).cloned().unwrap_or_else(|| { + let r = Register(prefix.to_string(), vec![index as i64]); + registers.push(r.clone()); + r + }) + }; for (unit, _, ty) in circ.units() { if ty == QB_T { - let index = vec![qubit_units.len() as i64]; - let reg = circuit_json::Register("q".to_string(), index); - qubit_units.insert(unit, reg); + let index = qubit_to_reg.len(); + let reg = get_register(&mut qubit_registers, "q", index); + qubit_to_reg.insert(unit, reg); } else if ty == *LINEAR_BIT { - let index = vec![bit_units.len() as i64]; - let reg = circuit_json::Register("c".to_string(), index); - bit_units.insert(unit, reg); + let index = bit_to_reg.len(); + let reg = get_register(&mut bit_registers, "b", index); + bit_to_reg.insert(unit, reg.clone()); } } - let mut encoder = Self { + Self { name, - phase: "0".to_string(), - implicit_permutation: vec![], + phase, + implicit_permutation, commands: vec![], - qubit_regs: qubit_units, - bit_regs: bit_units, + qubit_to_reg, + bit_to_reg, + qubit_registers, + bit_registers, parameters: HashMap::new(), - }; - - // Encode other parameters stored in the metadata - if let Some(meta) = circ.get_metadata(circ.root()).as_object() { - if let Some(phase) = meta.get(METADATA_PHASE) { - // TODO: Check for invalid encoded metadata - encoder.phase = phase.as_str().unwrap().to_string(); - } - if let Some(implicit_perm) = meta.get(METADATA_IMPLICIT_PERM) { - // TODO: Check for invalid encoded metadata - encoder.implicit_permutation = - serde_json::from_value(implicit_perm.clone()).unwrap(); - } } - - encoder } /// Add a circuit command to the serialization. @@ -139,8 +161,8 @@ impl JsonEncoder { name: self.name, phase: self.phase, commands: self.commands, - qubits: self.qubit_regs.into_values().collect_vec(), - bits: self.bit_regs.into_values().collect_vec(), + qubits: self.qubit_registers, + bits: self.bit_registers, implicit_permutation: self.implicit_permutation, } } @@ -208,10 +230,11 @@ impl JsonEncoder { true } - fn unit_to_register(&self, unit: CircuitUnit) -> Option { - self.qubit_regs + /// Translate a linear [`CircuitUnit`] into a [`Register`], if possible. + fn unit_to_register(&self, unit: CircuitUnit) -> Option { + self.qubit_to_reg .get(&unit) - .or_else(|| self.bit_regs.get(&unit)) + .or_else(|| self.bit_to_reg.get(&unit)) .cloned() } } diff --git a/src/json/tests.rs b/src/json/tests.rs index 78c8cc3c..90fb3253 100644 --- a/src/json/tests.rs +++ b/src/json/tests.rs @@ -1,6 +1,6 @@ //! General tests. -use std::collections::HashSet; +use std::io::BufReader; use hugr::Hugr; use rstest::rstest; @@ -64,16 +64,27 @@ fn json_roundtrip(#[case] circ_s: &str, #[case] num_commands: usize, #[case] num compare_serial_circs(&ser, &reser); } +#[rstest] +#[cfg_attr(miri, ignore)] // Opening files is not supported in (isolated) miri +#[case::barenco_tof_10("test_files/barenco_tof_10.json")] +fn json_file_roundtrip(#[case] circ: impl AsRef) { + let reader = BufReader::new(std::fs::File::open(circ).unwrap()); + let ser: circuit_json::SerialCircuit = serde_json::from_reader(reader).unwrap(); + let circ: Hugr = ser.clone().decode().unwrap(); + let reser: SerialCircuit = SerialCircuit::encode(&circ).unwrap(); + compare_serial_circs(&ser, &reser); +} + fn compare_serial_circs(a: &SerialCircuit, b: &SerialCircuit) { assert_eq!(a.name, b.name); assert_eq!(a.phase, b.phase); - let qubits_a: HashSet<_> = a.qubits.iter().collect(); - let qubits_b: HashSet<_> = b.qubits.iter().collect(); + let qubits_a: Vec<_> = a.qubits.iter().collect(); + let qubits_b: Vec<_> = b.qubits.iter().collect(); assert_eq!(qubits_a, qubits_b); - let bits_a: HashSet<_> = a.bits.iter().collect(); - let bits_b: HashSet<_> = b.bits.iter().collect(); + let bits_a: Vec<_> = a.bits.iter().collect(); + let bits_b: Vec<_> = b.bits.iter().collect(); assert_eq!(bits_a, bits_b); assert_eq!(a.implicit_permutation, b.implicit_permutation); diff --git a/src/optimiser/taso.rs b/src/optimiser/taso.rs index 67a3f249..a6045a43 100644 --- a/src/optimiser/taso.rs +++ b/src/optimiser/taso.rs @@ -20,17 +20,17 @@ mod worker; use crossbeam_channel::select; pub use eq_circ_class::{load_eccs_json_file, EqCircClass}; +use fxhash::FxHashSet; pub use log::TasoLogger; use std::fmt; use std::num::NonZeroUsize; use std::time::{Duration, Instant}; -use fxhash::FxHashSet; use hugr::Hugr; use crate::circuit::CircuitHash; -use crate::optimiser::taso::hugr_pchannel::HugrPriorityChannel; +use crate::optimiser::taso::hugr_pchannel::{HugrPriorityChannel, PriorityChannelLog}; use crate::optimiser::taso::hugr_pqueue::{Entry, HugrPQ}; use crate::optimiser::taso::worker::TasoWorker; use crate::rewrite::strategy::RewriteStrategy; @@ -81,7 +81,10 @@ where /// Run the TASO optimiser on a circuit. /// /// A timeout (in seconds) can be provided. - pub fn optimise(&self, circ: &Hugr, timeout: Option, n_threads: NonZeroUsize) -> Hugr { + pub fn optimise(&self, circ: &Hugr, timeout: Option, n_threads: NonZeroUsize) -> Hugr + where + S::Cost: Send + Sync + Clone, + { self.optimise_with_log(circ, Default::default(), timeout, n_threads) } @@ -94,7 +97,10 @@ where log_config: TasoLogger, timeout: Option, n_threads: NonZeroUsize, - ) -> Hugr { + ) -> Hugr + where + S::Cost: Send + Sync + Clone, + { match n_threads.get() { 1 => self.taso(circ, log_config, timeout), _ => self.taso_multithreaded(circ, log_config, timeout, n_threads), @@ -110,7 +116,8 @@ where logger.log_best(&best_circ_cost); // Hash of seen circuits. Dot not store circuits as this map gets huge - let mut seen_hashes: FxHashSet<_> = FromIterator::from_iter([(circ.circuit_hash())]); + let mut seen_hashes = FxHashSet::default(); + seen_hashes.insert(circ.circuit_hash()); // The priority queue of circuits to be processed (this should not get big) const PRIORITY_QUEUE_CAPACITY: usize = 10_000; @@ -133,13 +140,14 @@ where let rewrites = self.rewriter.get_rewrites(&circ); for new_circ in self.strategy.apply_rewrites(rewrites, &circ) { let new_circ_hash = new_circ.circuit_hash(); - circ_cnt += 1; logger.log_progress(circ_cnt, Some(pq.len()), seen_hashes.len()); - if seen_hashes.contains(&new_circ_hash) { + if !seen_hashes.insert(new_circ_hash) { + // Ignore this circuit: we've already seen it continue; } - pq.push_with_hash_unchecked(new_circ, new_circ_hash); - seen_hashes.insert(new_circ_hash); + circ_cnt += 1; + let new_circ_cost = self.cost(&new_circ); + pq.push_unchecked(new_circ, new_circ_hash, new_circ_cost); } if pq.len() >= PRIORITY_QUEUE_CAPACITY { @@ -170,7 +178,10 @@ where mut logger: TasoLogger, timeout: Option, n_threads: NonZeroUsize, - ) -> Hugr { + ) -> Hugr + where + S::Cost: Send + Sync + Clone, + { let n_threads: usize = n_threads.get(); const PRIORITY_QUEUE_CAPACITY: usize = 10_000; @@ -179,51 +190,36 @@ where let strategy = self.strategy.clone(); move |circ: &'_ Hugr| strategy.circuit_cost(circ) }; - let (tx_work, rx_work) = - HugrPriorityChannel::init(cost_fn, PRIORITY_QUEUE_CAPACITY * n_threads); - // channel for sending circuits from threads back to main - let (tx_result, rx_result) = crossbeam_channel::unbounded(); + let mut pq = HugrPriorityChannel::init(cost_fn, PRIORITY_QUEUE_CAPACITY * n_threads); let initial_circ_hash = circ.circuit_hash(); let mut best_circ = circ.clone(); let mut best_circ_cost = self.cost(&best_circ); - logger.log_best(&best_circ_cost); - - // Hash of seen circuits. Dot not store circuits as this map gets huge - let mut seen_hashes: FxHashSet<_> = FromIterator::from_iter([(initial_circ_hash)]); // Each worker waits for circuits to scan for rewrites using all the // patterns and sends the results back to main. let joins: Vec<_> = (0..n_threads) .map(|i| { TasoWorker::spawn( - rx_work.clone(), - tx_result.clone(), + pq.pop.clone().unwrap(), + pq.push.clone().unwrap(), self.rewriter.clone(), self.strategy.clone(), Some(format!("taso-worker-{i}")), ) }) .collect(); - // Drop our copy of the worker channels, so we don't count as a - // connected worker. - drop(rx_work); - drop(tx_result); // Queue the initial circuit - tx_work + pq.push + .as_ref() + .unwrap() .send(vec![(initial_circ_hash, circ.clone())]) .unwrap(); + // Drop our copy of the priority queue channels, so we don't count as a + // connected worker. + pq.drop_pop_push(); - // A counter of circuits seen. - let mut circ_cnt = 1; - - // A counter of jobs sent to the workers. - #[allow(unused)] - let mut jobs_sent = 0usize; - // A counter of completed jobs received from the workers. - #[allow(unused)] - let mut jobs_completed = 0usize; // TODO: Report dropped jobs in the queue, so we can check for termination. // Deadline for the optimisation timeout @@ -232,66 +228,51 @@ where Some(t) => crossbeam_channel::at(Instant::now() + Duration::from_secs(t)), }; - // Process worker results until we have seen all the circuits, or we run - // out of time. + // Main loop: log best circuits as they come in from the priority queue, + // until the timeout is reached. let mut timeout_flag = false; loop { select! { - recv(rx_result) -> msg => { + recv(pq.log) -> msg => { match msg { - Ok(hashed_circs) => { - let send_result = tracing::trace_span!(target: "taso::metrics", "recv_result").in_scope(|| { - jobs_completed += 1; - for (circ_hash, circ) in &hashed_circs { - circ_cnt += 1; - logger.log_progress(circ_cnt, None, seen_hashes.len()); - if seen_hashes.contains(circ_hash) { - continue; - } - seen_hashes.insert(*circ_hash); - - let cost = self.cost(circ); - - // Check if we got a new best circuit - if cost < best_circ_cost { - best_circ = circ.clone(); - best_circ_cost = cost; - logger.log_best(&best_circ_cost); - } - jobs_sent += 1; - } - // Fill the workqueue with data from pq - tx_work.send(hashed_circs) - }); - if send_result.is_err() { - eprintln!("All our workers panicked. Stopping optimisation."); - break; - } - - // If there is no more data to process, we are done. - // - // TODO: Report dropped jobs in the workers, so we can check for termination. - //if jobs_sent == jobs_completed { - // break 'main; - //}; + Ok(PriorityChannelLog::NewBestCircuit(circ, cost)) => { + best_circ = circ; + best_circ_cost = cost; + logger.log_best(&best_circ_cost); }, + Ok(PriorityChannelLog::CircuitCount(circuit_cnt, seen_cnt)) => { + logger.log_progress(circuit_cnt, None, seen_cnt); + } Err(crossbeam_channel::RecvError) => { - eprintln!("All our workers panicked. Stopping optimisation."); + eprintln!("Priority queue panicked. Stopping optimisation."); break; } } } recv(timeout_event) -> _ => { timeout_flag = true; + pq.timeout(); break; } } } - logger.log_processing_end(circ_cnt, best_circ_cost, true, timeout_flag); + // Empty the log from the priority queue and store final circuit count. + let mut circuit_cnt = None; + while let Ok(log) = pq.log.recv() { + match log { + PriorityChannelLog::NewBestCircuit(circ, cost) => { + best_circ = circ; + best_circ_cost = cost; + logger.log_best(&best_circ_cost); + } + PriorityChannelLog::CircuitCount(circ_cnt, _) => { + circuit_cnt = Some(circ_cnt); + } + } + } + logger.log_processing_end(circuit_cnt.unwrap_or(0), best_circ_cost, true, timeout_flag); - // Drop the channel so the threads know to stop. - drop(tx_work); joins.into_iter().for_each(|j| j.join().unwrap()); best_circ @@ -303,20 +284,25 @@ mod taso_default { use std::io; use std::path::Path; + use hugr::ops::OpType; + use crate::rewrite::ecc_rewriter::RewriterSerialisationError; - use crate::rewrite::strategy::NonIncreasingCXCountStrategy; + use crate::rewrite::strategy::NonIncreasingGateCountStrategy; use crate::rewrite::ECCRewriter; use super::*; /// The default TASO optimiser using ECC sets. - pub type DefaultTasoOptimiser = TasoOptimiser; + pub type DefaultTasoOptimiser = TasoOptimiser< + ECCRewriter, + NonIncreasingGateCountStrategy usize, fn(&OpType) -> usize>, + >; impl DefaultTasoOptimiser { /// A sane default optimiser using the given ECC sets. pub fn default_with_eccs_json_file(eccs_path: impl AsRef) -> io::Result { let rewriter = ECCRewriter::try_from_eccs_json_file(eccs_path)?; - let strategy = NonIncreasingCXCountStrategy::default_cx(); + let strategy = NonIncreasingGateCountStrategy::default_cx(); Ok(TasoOptimiser::new(rewriter, strategy)) } @@ -325,7 +311,7 @@ mod taso_default { rewriter_path: impl AsRef, ) -> Result { let rewriter = ECCRewriter::load_binary(rewriter_path)?; - let strategy = NonIncreasingCXCountStrategy::default_cx(); + let strategy = NonIncreasingGateCountStrategy::default_cx(); Ok(TasoOptimiser::new(rewriter, strategy)) } } diff --git a/src/optimiser/taso/hugr_pchannel.rs b/src/optimiser/taso/hugr_pchannel.rs index 1ec0d2e4..2e1751fa 100644 --- a/src/optimiser/taso/hugr_pchannel.rs +++ b/src/optimiser/taso/hugr_pchannel.rs @@ -1,9 +1,9 @@ //! A multi-producer multi-consumer min-priority channel of Hugrs. -use std::marker::PhantomData; use std::thread; use crossbeam_channel::{select, Receiver, Sender}; +use fxhash::FxHashSet; use hugr::Hugr; use super::hugr_pqueue::{Entry, HugrPQ}; @@ -13,83 +13,201 @@ use super::hugr_pqueue::{Entry, HugrPQ}; /// Queues hugrs using a cost function `C` that produces priority values `P`. /// /// Uses a thread internally to orchestrate the queueing. -pub struct HugrPriorityChannel { - _phantom: PhantomData<(P, C)>, +pub(super) struct HugrPriorityChannel { + // Channels to add and remove circuits from the queue. + push: Receiver>, + pop: Sender<(u64, Hugr)>, + // Outbound channel to log to main thread. + log: Sender>, + // Inbound channel to be terminated. + timeout: Receiver<()>, + // The queue capacity. Queue size is halved when it exceeds this. + queue_capacity: usize, + // The priority queue data structure. + pq: HugrPQ, + // The set of hashes we've seen. + seen_hashes: FxHashSet, + // The minimum cost we've seen. + min_cost: Option

, + // The number of circuits we've seen (for logging). + circ_cnt: usize, } -pub type Item = (u64, Hugr); +pub(super) type Item = (u64, Hugr); -impl HugrPriorityChannel +/// Logging information from the priority channel. +pub(super) enum PriorityChannelLog { + NewBestCircuit(Hugr, C), + CircuitCount(usize, usize), +} + +/// Channels for communication with the priority channel. +pub(super) struct PriorityChannelCommunication { + pub(super) push: Option>>, + pub(super) pop: Option>, + pub(super) log: Receiver>, + timeout: Sender<()>, +} + +impl PriorityChannelCommunication { + /// Send Timeout signal to the priority channel. + pub(super) fn timeout(&self) { + self.timeout.send(()).unwrap(); + } + + /// Close the local copies of the push and pop channels. + pub(super) fn drop_pop_push(&mut self) { + self.pop = None; + self.push = None; + } +} + +impl HugrPriorityChannel where C: Fn(&Hugr) -> P + Send + Sync + 'static, + P: Ord + Send + Sync + Clone + 'static, { /// Initialize the queueing system. /// - /// Get back a channel on which to queue hugrs with their hash, and - /// a channel on which to receive the output. - pub fn init(cost_fn: C, queue_capacity: usize) -> (Sender>, Receiver) { - let (ins, inr) = crossbeam_channel::unbounded(); - let (outs, outr) = crossbeam_channel::bounded(0); - Self::run(inr, outs, cost_fn, queue_capacity); - (ins, outr) + /// Start the Hugr priority queue in a new thread. + /// + /// Get back channels for communication with the priority queue + /// - push/pop channels for adding and removing circuits to/from the queue, + /// - a channel on which to receive logging information, and + /// - a channel on which to send a timeout signal. + pub(super) fn init(cost_fn: C, queue_capacity: usize) -> PriorityChannelCommunication

{ + // channels for pushing and popping circuits from pqueue + let (tx_push, rx_push) = crossbeam_channel::unbounded(); + let (tx_pop, rx_pop) = crossbeam_channel::bounded(0); + // channels for communication with main (logging, minimum circuits and timeout) + let (tx_log, rx_log) = crossbeam_channel::unbounded(); + let (tx_timeout, rx_timeout) = crossbeam_channel::bounded(0); + let pq = + HugrPriorityChannel::new(rx_push, tx_pop, tx_log, rx_timeout, cost_fn, queue_capacity); + pq.run(); + PriorityChannelCommunication { + push: Some(tx_push), + pop: Some(rx_pop), + log: rx_log, + timeout: tx_timeout, + } } - /// Run the queuer as a thread. - fn run( - in_channel_orig: Receiver>, - out_channel_orig: Sender<(u64, Hugr)>, + fn new( + push: Receiver>, + pop: Sender<(u64, Hugr)>, + log: Sender>, + timeout: Receiver<()>, cost_fn: C, queue_capacity: usize, - ) { + ) -> Self { + // The priority queue, local to this thread. + let pq = HugrPQ::with_capacity(cost_fn, queue_capacity); + // The set of hashes we've seen. + let seen_hashes = FxHashSet::default(); + // The minimum cost we've seen. + let min_cost = None; + // The number of circuits we've seen (for logging). + let circ_cnt = 0; + + HugrPriorityChannel { + push, + pop, + log, + timeout, + queue_capacity, + pq, + seen_hashes, + min_cost, + circ_cnt, + } + } + + /// Run the queuer as a thread. + fn run(mut self) { let builder = thread::Builder::new().name("priority queueing".into()); - let in_channel = in_channel_orig.clone(); - let out_channel = out_channel_orig.clone(); let _ = builder .name("priority-channel".into()) .spawn(move || { - // The priority queue, local to this thread. - let mut pq: HugrPQ = - HugrPQ::with_capacity(cost_fn, queue_capacity); - loop { - if pq.is_empty() { - // Nothing queued to go out. Wait for input. - match in_channel.recv() { - Ok(new_circs) => { - for (hash, circ) in new_circs { - pq.push_with_hash_unchecked(circ, hash); - } - } - // The sender has closed the channel, we can stop. - Err(_) => break, - } + if self.pq.is_empty() { + let Ok(new_circs) = self.push.recv() else { + // The senders have closed the channel, we can stop. + break; + }; + self.enqueue_circs(new_circs); } else { select! { - recv(in_channel) -> result => { - match result { - Ok(new_circs) => { - for (hash, circ) in new_circs { - pq.push_with_hash_unchecked(circ, hash); - } - } - // The sender has closed the channel, we can stop. - Err(_) => break, - } + recv(self.push) -> result => { + let Ok(new_circs) = result else { + // The senders have closed the channel, we can stop. + break; + }; + self.enqueue_circs(new_circs); } - send(out_channel, {let Entry {hash, circ, ..} = pq.pop().unwrap(); (hash, circ)}) -> result => { + send(self.pop, {let Entry {hash, circ, ..} = self.pq.pop().unwrap(); (hash, circ)}) -> result => { match result { Ok(()) => {}, // The receivers have closed the channel, we can stop. Err(_) => break, } } + recv(self.timeout) -> _ => { + // We've timed out. + break + } } } - if pq.len() >= queue_capacity { - pq.truncate(queue_capacity / 2); - } } + // Send a last set of logs before terminating. + self.log + .send(PriorityChannelLog::CircuitCount( + self.circ_cnt, + self.seen_hashes.len(), + )) + .unwrap(); }) .unwrap(); } + + /// Add circuits to queue. + #[tracing::instrument(target = "taso::metrics", skip(self, circs))] + fn enqueue_circs(&mut self, circs: Vec<(u64, Hugr)>) { + for (hash, circ) in circs { + let cost = (self.pq.cost_fn)(&circ); + if !self.seen_hashes.insert(hash) { + // Ignore this circuit: we've seen it before. + continue; + } + + // A new best circuit + if self.min_cost.is_none() || Some(&cost) < self.min_cost.as_ref() { + self.min_cost = Some(cost.clone()); + self.log + .send(PriorityChannelLog::NewBestCircuit( + circ.clone(), + cost.clone(), + )) + .unwrap(); + } + + self.circ_cnt += 1; + self.pq.push_unchecked(circ, hash, cost); + + // Send logs every 1000 circuits. + if self.circ_cnt % 1000 == 0 { + // TODO: Add a minimum time between logs + self.log + .send(PriorityChannelLog::CircuitCount( + self.circ_cnt, + self.seen_hashes.len(), + )) + .unwrap(); + } + } + // If the queue got too big, truncate it. + if self.pq.len() >= self.queue_capacity { + self.pq.truncate(self.queue_capacity / 2); + } + } } diff --git a/src/optimiser/taso/hugr_pqueue.rs b/src/optimiser/taso/hugr_pqueue.rs index f362b5dc..e3ae8c27 100644 --- a/src/optimiser/taso/hugr_pqueue.rs +++ b/src/optimiser/taso/hugr_pqueue.rs @@ -13,7 +13,7 @@ use crate::circuit::CircuitHash; pub(super) struct HugrPQ { queue: DoublePriorityQueue, hash_lookup: FxHashMap, - cost_fn: C, + pub(super) cost_fn: C, } pub(super) struct Entry { @@ -51,20 +51,20 @@ impl HugrPQ { C: Fn(&Hugr) -> P, { let hash = hugr.circuit_hash(); - self.push_with_hash_unchecked(hugr, hash); + let cost = (self.cost_fn)(&hugr); + self.push_unchecked(hugr, hash, cost); } - /// Push a Hugr into the queue with a precomputed hash. + /// Push a Hugr into the queue with a precomputed hash and cost. /// - /// This is useful to avoid recomputing the hash in [`HugrPQ::push`] when - /// it is already known. + /// This is useful to avoid recomputing the hash and cost function in + /// [`HugrPQ::push`] when they are already known. /// /// This does not check that the hash is valid. - pub(super) fn push_with_hash_unchecked(&mut self, hugr: Hugr, hash: u64) + pub(super) fn push_unchecked(&mut self, hugr: Hugr, hash: u64, cost: P) where C: Fn(&Hugr) -> P, { - let cost = (self.cost_fn)(&hugr); self.queue.push(hash, cost); self.hash_lookup.insert(hash, hugr); } @@ -86,6 +86,12 @@ impl HugrPQ { } } + /// The largest cost in the queue. + #[allow(unused)] + pub(super) fn max_cost(&self) -> Option<&P> { + self.queue.peek_max().map(|(_, cost)| cost) + } + delegate! { to self.queue { pub(super) fn len(&self) -> usize; diff --git a/src/optimiser/taso/worker.rs b/src/optimiser/taso/worker.rs index 0d8667c8..a2aadbf7 100644 --- a/src/optimiser/taso/worker.rs +++ b/src/optimiser/taso/worker.rs @@ -51,7 +51,7 @@ where let send = tracing::trace_span!(target: "taso::metrics", "TasoWorker::send_result") .in_scope(|| tx_result.send(hashed_circs)); if send.is_err() { - // The main thread closed the send channel, we can stop. + // The priority queue closed the send channel, we can stop. break; } } diff --git a/src/passes/chunks.rs b/src/passes/chunks.rs index ff10d3b7..2f436cdf 100644 --- a/src/passes/chunks.rs +++ b/src/passes/chunks.rs @@ -263,6 +263,8 @@ impl CircuitChunks { } } + reassembled.set_metadata(root, self.root_meta)?; + Ok(reassembled) } diff --git a/src/rewrite/strategy.rs b/src/rewrite/strategy.rs index aae2e810..38a63e3f 100644 --- a/src/rewrite/strategy.rs +++ b/src/rewrite/strategy.rs @@ -8,7 +8,7 @@ //! possible rewrite (with some pruning strategy): //! - [`NonIncreasingGateCountStrategy`], which only considers rewrites that //! do not increase some cost function (e.g. cx gate count, implemented as -//! [`NonIncreasingCXCountStrategy`]), and +//! [`NonIncreasingGateCountStrategy::default_cx`]), and //! - [`ExhaustiveGammaStrategy`], which ignores rewrites that increase the //! cost function beyond a threshold given by a f64 parameter gamma. @@ -95,6 +95,65 @@ impl RewriteStrategy for GreedyRewriteStrategy { } } +/// Exhaustive strategies based on cost functions and thresholds. +/// +/// Every possible rewrite is applied to a copy of the input circuit. Thus for +/// one circuit, up to `n` rewritten circuits will be returned, each obtained +/// by applying one of the `n` rewrites to the original circuit. +/// +/// Whether a rewrite is allowed or not is determined by a cost function and a +/// threshold function: if the cost of the target of the rewrite is below the +/// threshold given by the cost of the original circuit, the rewrite is +/// performed. +/// +/// The cost function must return a value of type `Self::OpCost`. All op costs +/// are summed up to obtain a total cost that is then compared using the +/// threshold function. +pub trait ExhaustiveThresholdStrategy { + /// The cost of a single operation. + type OpCost; + /// The sum of the cost of all operations in a circuit. + type SumOpCost; + + /// Whether the rewrite is allowed or not, based on the cost of the pattern and target. + fn threshold(&self, pattern_cost: &Self::SumOpCost, target_cost: &Self::SumOpCost) -> bool; + + /// The cost of a single operation. + fn op_cost(&self, op: &OpType) -> Self::OpCost; +} + +impl RewriteStrategy for T +where + T::SumOpCost: Sum + Ord, +{ + type Cost = T::SumOpCost; + + #[tracing::instrument(skip_all)] + fn apply_rewrites( + &self, + rewrites: impl IntoIterator, + circ: &Hugr, + ) -> Vec { + rewrites + .into_iter() + .filter(|rw| { + let pattern_cost = pre_rewrite_cost(rw, circ, |op| self.op_cost(op)); + let target_cost = post_rewrite_cost(rw, circ, |op| self.op_cost(op)); + self.threshold(&pattern_cost, &target_cost) + }) + .map(|rw| { + let mut circ = circ.clone(); + rw.apply(&mut circ).expect("invalid pattern match"); + circ + }) + .collect() + } + + fn circuit_cost(&self, circ: &Hugr) -> Self::Cost { + cost(circ.nodes(), circ, |op| self.op_cost(op)) + } +} + /// Exhaustive rewrite strategy allowing smaller or equal cost rewrites. /// /// Rewrites are permitted based on a cost function called the major cost: if @@ -132,15 +191,13 @@ where } } -/// Non-increasing rewrite strategy based on CX count. -/// -/// The minor cost to break ties between equal CX counts is the number of -/// quantum gates. -pub type NonIncreasingCXCountStrategy = - NonIncreasingGateCountStrategy usize, fn(&OpType) -> usize>; - -impl NonIncreasingCXCountStrategy { - /// Create rewrite strategy based on non-increasing CX count. +impl NonIncreasingGateCountStrategy usize, fn(&OpType) -> usize> { + /// Non-increasing rewrite strategy based on CX count. + /// + /// The minor cost to break ties between equal CX counts is the number of + /// quantum gates. + /// + /// This is probably a good default for NISQ-y circuit optimisation. pub fn default_cx() -> Self { Self { major_cost: |op| is_cx(op) as usize, @@ -218,65 +275,6 @@ impl ExhaustiveGammaStrategy usize> { } } -/// Exhaustive strategies based on cost functions and thresholds. -/// -/// Every possible rewrite is applied to a copy of the input circuit. Thus for -/// one circuit, up to `n` rewritten circuits will be returned, each obtained -/// by applying one of the `n` rewrites to the original circuit. -/// -/// Whether a rewrite is allowed or not is determined by a cost function and a -/// threshold function: if the cost of the target of the rewrite is below the -/// threshold given by the cost of the original circuit, the rewrite is -/// performed. -/// -/// The cost function must return a value of type `Self::OpCost`. All op costs -/// are summed up to obtain a total cost that is then compared using the -/// threshold function. -pub trait ExhaustiveThresholdStrategy { - /// The cost of a single operation. - type OpCost; - /// The sum of the cost of all operations in a circuit. - type SumOpCost; - - /// Whether the rewrite is allowed or not, based on the cost of the pattern and target. - fn threshold(&self, pattern_cost: &Self::SumOpCost, target_cost: &Self::SumOpCost) -> bool; - - /// The cost of a single operation. - fn op_cost(&self, op: &OpType) -> Self::OpCost; -} - -impl RewriteStrategy for T -where - T::SumOpCost: Sum + Ord, -{ - type Cost = T::SumOpCost; - - #[tracing::instrument(skip_all)] - fn apply_rewrites( - &self, - rewrites: impl IntoIterator, - circ: &Hugr, - ) -> Vec { - rewrites - .into_iter() - .filter(|rw| { - let pattern_cost = pre_rewrite_cost(rw, circ, |op| self.op_cost(op)); - let target_cost = post_rewrite_cost(rw, circ, |op| self.op_cost(op)); - self.threshold(&pattern_cost, &target_cost) - }) - .map(|rw| { - let mut circ = circ.clone(); - rw.apply(&mut circ).expect("invalid pattern match"); - circ - }) - .collect() - } - - fn circuit_cost(&self, circ: &Hugr) -> Self::Cost { - cost(circ.nodes(), circ, |op| self.op_cost(op)) - } -} - /// A pair of major and minor cost. /// /// This is used to order circuits based on major cost first, then minor cost. @@ -459,7 +457,7 @@ mod tests { #[test] fn test_exhaustive_default_cx_cost() { - let strat = NonIncreasingCXCountStrategy::default_cx(); + let strat = NonIncreasingGateCountStrategy::default_cx(); let circ = n_cx(3); assert_eq!(strat.circuit_cost(&circ), (3, 3).into()); let circ = build_simple_circuit(2, |circ| { @@ -474,7 +472,7 @@ mod tests { #[test] fn test_exhaustive_default_cx_threshold() { - let strat = NonIncreasingCXCountStrategy::default_cx(); + let strat = NonIncreasingGateCountStrategy::default_cx(); assert!(strat.threshold(&(3, 0).into(), &(3, 0).into())); assert!(strat.threshold(&(3, 0).into(), &(3, 5).into())); assert!(!strat.threshold(&(3, 10).into(), &(4, 0).into())); diff --git a/src/utils.rs b/src/utils.rs index 124cda37..22456624 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -36,13 +36,26 @@ pub(crate) fn build_simple_circuit( #[allow(dead_code)] #[cfg(test)] pub(crate) mod test { + #[allow(unused_imports)] + use hugr::HugrView; + /// Open a browser page to render a dot string graph. /// /// This can be used directly on the output of `Hugr::dot_string` + /// + /// Only for use in local testing. Will fail to compile on CI. #[cfg(not(ci_run))] - pub(crate) fn viz_dotstr(dotstr: &str) { + pub(crate) fn viz_dotstr(dotstr: impl AsRef) { let mut base: String = "https://dreampuf.github.io/GraphvizOnline/#".into(); - base.push_str(&urlencoding::encode(dotstr)); + base.push_str(&urlencoding::encode(dotstr.as_ref())); webbrowser::open(&base).unwrap(); } + + /// Open a browser page to render a HugrView's dot string graph. + /// + /// Only for use in local testing. Will fail to compile on CI. + #[cfg(not(ci_run))] + pub(crate) fn viz_hugr(hugr: &impl HugrView) { + viz_dotstr(hugr.dot_string()); + } } diff --git a/taso-optimiser/src/main.rs b/taso-optimiser/src/main.rs index c31afb0d..1d06c646 100644 --- a/taso-optimiser/src/main.rs +++ b/taso-optimiser/src/main.rs @@ -10,11 +10,9 @@ use std::path::PathBuf; use std::process::exit; use clap::Parser; -use hugr::Hugr; -use tket2::json::{load_tk1_json_file, TKETDecode}; +use tket2::json::{load_tk1_json_file, save_tk1_json_file}; use tket2::optimiser::taso::log::TasoLogger; use tket2::optimiser::TasoOptimiser; -use tket_json_rs::circuit_json::SerialCircuit; #[cfg(feature = "peak_alloc")] use peak_alloc::PeakAlloc; @@ -82,14 +80,6 @@ struct CmdLineArgs { n_threads: Option, } -fn save_tk1_json_file(path: impl AsRef, circ: &Hugr) -> Result<(), std::io::Error> { - let file = File::create(path)?; - let writer = BufWriter::new(file); - let serial_circ = SerialCircuit::encode(circ).unwrap(); - serde_json::to_writer_pretty(writer, &serial_circ)?; - Ok(()) -} - fn main() -> Result<(), Box> { let opts = CmdLineArgs::parse(); @@ -129,7 +119,7 @@ fn main() -> Result<(), Box> { let opt_circ = optimiser.optimise_with_log(&circ, taso_logger, opts.timeout, n_threads); println!("Saving result"); - save_tk1_json_file(output_path, &opt_circ)?; + save_tk1_json_file(&opt_circ, output_path)?; #[cfg(feature = "peak_alloc")] println!("Peak memory usage: {} GB", PEAK_ALLOC.peak_usage_as_gb()); diff --git a/test_files/barenco_tof_10.json b/test_files/barenco_tof_10.json new file mode 100755 index 00000000..ebb40575 --- /dev/null +++ b/test_files/barenco_tof_10.json @@ -0,0 +1,7576 @@ +{ + "phase": "0.0", + "commands": [ + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 18 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 1 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 1 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "H", + "n_qb": 1, + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 17 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 16 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 15 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 14 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 13 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 12 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 11 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "Rz", + "n_qb": 1, + "params": [ + "-0.25" + ], + "signature": [ + "Q" + ] + }, + "args": [ + [ + "q", + [ + 10 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 1 + ] + ] + ] + }, + { + "op": { + "type": "CX", + "n_qb": 2, + "signature": [ + "Q", + "Q" + ] + }, + "args": [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 1 + ] + ] + ] + } + ], + "qubits": [ + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 18 + ] + ], + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 17 + ] + ], + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 11 + ] + ] + ], + "bits": [], + "implicit_permutation": [ + [ + [ + "q", + [ + 0 + ] + ], + [ + "q", + [ + 0 + ] + ] + ], + [ + [ + "q", + [ + 1 + ] + ], + [ + "q", + [ + 1 + ] + ] + ], + [ + [ + "q", + [ + 2 + ] + ], + [ + "q", + [ + 2 + ] + ] + ], + [ + [ + "q", + [ + 3 + ] + ], + [ + "q", + [ + 3 + ] + ] + ], + [ + [ + "q", + [ + 4 + ] + ], + [ + "q", + [ + 4 + ] + ] + ], + [ + [ + "q", + [ + 5 + ] + ], + [ + "q", + [ + 5 + ] + ] + ], + [ + [ + "q", + [ + 6 + ] + ], + [ + "q", + [ + 6 + ] + ] + ], + [ + [ + "q", + [ + 7 + ] + ], + [ + "q", + [ + 7 + ] + ] + ], + [ + [ + "q", + [ + 8 + ] + ], + [ + "q", + [ + 8 + ] + ] + ], + [ + [ + "q", + [ + 9 + ] + ], + [ + "q", + [ + 9 + ] + ] + ], + [ + [ + "q", + [ + 10 + ] + ], + [ + "q", + [ + 10 + ] + ] + ], + [ + [ + "q", + [ + 11 + ] + ], + [ + "q", + [ + 11 + ] + ] + ], + [ + [ + "q", + [ + 12 + ] + ], + [ + "q", + [ + 12 + ] + ] + ], + [ + [ + "q", + [ + 13 + ] + ], + [ + "q", + [ + 13 + ] + ] + ], + [ + [ + "q", + [ + 14 + ] + ], + [ + "q", + [ + 14 + ] + ] + ], + [ + [ + "q", + [ + 15 + ] + ], + [ + "q", + [ + 15 + ] + ] + ], + [ + [ + "q", + [ + 16 + ] + ], + [ + "q", + [ + 16 + ] + ] + ], + [ + [ + "q", + [ + 17 + ] + ], + [ + "q", + [ + 17 + ] + ] + ], + [ + [ + "q", + [ + 18 + ] + ], + [ + "q", + [ + 18 + ] + ] + ] + ] +} \ No newline at end of file