tket_json_rs/pass/
standard.rs

1//! Standard pass definitions.
2
3#[cfg(feature = "schemars")]
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6
7use crate::pass::{Architecture, Placement};
8use crate::{register::ElementId, SerialCircuit};
9
10/// A serialized standard pass.
11//
12// NOTE: The pytket schema defines serializations for `SquashCustom` and
13// `RebaseCustom`, but they are not actually supported by pytket so we have
14// removed them here.
15#[cfg_attr(feature = "schemars", derive(JsonSchema))]
16#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
17#[serde(tag = "name")]
18#[non_exhaustive]
19pub enum StandardPass {
20    /// A convenience custom rebase that targets TK2.
21    RebaseCustomViaTK2,
22    /// Automatically rebase to a given gate set.
23    AutoRebase(AutoRebase),
24    /// Automatically squash single-qubit gates.
25    AutoSquash(AutoSquash),
26    /// Commute multi-qubit gates past other operations.
27    CommuteThroughMultis,
28    /// Decompose arbitrarily controlled gates.
29    DecomposeArbitrarilyControlledGates,
30    /// Decompose generic boxes using filters.
31    DecomposeBoxes(DecomposeBoxes),
32    /// Decompose multi-qubit CX boxes.
33    DecomposeMultiQubitsCX,
34    /// Decompose single-qubit TK1 boxes.
35    DecomposeSingleQubitsTK1,
36    /// Two-qubit peephole optimiser.
37    PeepholeOptimise2Q(PeepholeOptimise2Q),
38    /// Rebase to TKET's default gate set.
39    RebaseTket,
40    /// Rebase to the UFR gate set.
41    RebaseUFR,
42    /// Remove redundant operations.
43    RemoveRedundancies,
44    /// Synthesis pass for TK gate set.
45    SynthesiseTK,
46    /// Synthesis pass for TKET gate set.
47    SynthesiseTket,
48    /// Synthesis pass targeting OQC hardware.
49    SynthesiseOQC,
50    /// Squash TK1 gates.
51    SquashTK1,
52    /// Squash Rz/PhasedX patterns.
53    SquashRzPhasedX,
54    /// Flatten registers.
55    FlattenRegisters,
56    /// Delay measurements.
57    DelayMeasures(DelayMeasures),
58    /// Convert ZZPhase into Rz rotations.
59    ZZPhaseToRz,
60    /// Remove discarded outputs.
61    RemoveDiscarded,
62    /// Simplify measured wires.
63    SimplifyMeasured,
64    /// Remove explicit barrier operations.
65    RemoveBarriers,
66    /// Remove phase-only operations.
67    RemovePhaseOps,
68    /// Decompose bridge gadgets.
69    DecomposeBridges,
70    /// Run the KAK decomposition.
71    KAKDecomposition(KAKDecomposition),
72    /// Squash arbitrary three-qubit unitaries.
73    ThreeQubitSquash(ThreeQubitSquash),
74    /// Full peephole optimisation.
75    FullPeepholeOptimise(FullPeepholeOptimise),
76    /// Compose Phase-Polynomial boxes.
77    ComposePhasePolyBoxes(ComposePhasePolyBoxes),
78    /// Reduce Euler angles for single qubits.
79    EulerAngleReduction(EulerAngleReduction),
80    /// Standard routing pipeline.
81    RoutingPass(RoutingPass),
82    /// Custom routing configuration.
83    CustomRoutingPass(CustomRoutingPass),
84    /// Configure placements explicitly.
85    PlacementPass(PlacementPass),
86    /// Naive placement pass.
87    NaivePlacementPass(NaivePlacementPass),
88    /// Rename qubits.
89    RenameQubitsPass(RenameQubitsPass),
90    /// Clifford simplification.
91    CliffordSimp(CliffordSimp),
92    /// Decompose swaps into CXs.
93    DecomposeSwapsToCXs(DecomposeSwapsToCXs),
94    /// Decompose swaps into custom circuits.
95    DecomposeSwapsToCircuit(DecomposeSwapsToCircuit),
96    /// Optimise phase gadgets.
97    OptimisePhaseGadgets(OptimisePhaseGadgets),
98    /// Optimise pairwise gadgets.
99    OptimisePairwiseGadgets,
100    /// Pauli simplification.
101    PauliSimp(PauliSynthesisConfig),
102    /// Pauli exponentials synthesis.
103    PauliExponentials(PauliSynthesisConfig),
104    /// Guided Pauli simplification.
105    GuidedPauliSimp(PauliSynthesisConfig),
106    /// Simplify initial states.
107    SimplifyInitial(SimplifyInitial),
108    /// Full mapping pipeline.
109    FullMappingPass(FullMappingPass),
110    /// Default mapping pipeline.
111    DefaultMappingPass(DefaultMappingPass),
112    /// CX-focused mapping pipeline.
113    CXMappingPass(CXMappingPass),
114    /// Pauli squashing.
115    PauliSquash(PauliSynthesisConfig),
116    /// Context simplification.
117    ContextSimp(ContextSimp),
118    /// Decompose TK2 gates.
119    DecomposeTK2(DecomposeTK2),
120    /// Pairwise decomposition of CnX.
121    CnXPairwiseDecomposition,
122    /// Remove implicit permutation annotations.
123    RemoveImplicitQubitPermutation,
124    /// Normalise TK2 parameters.
125    NormaliseTK2,
126    /// Round angles to coarse precision.
127    RoundAngles(RoundAngles),
128    /// Greedy Pauli simplification with heuristics.
129    GreedyPauliSimp(GreedyPauliSimp),
130    /// RX synthesis from SX.
131    RxFromSX,
132    /// Flatten and relabel registers.
133    FlattenRelabelRegistersPass(FlattenRelabelRegistersPass),
134}
135
136/// Automatically rebase to a given gate set.
137#[cfg_attr(feature = "schemars", derive(JsonSchema))]
138#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
139pub struct AutoRebase {
140    /// OpTypes of supported gates.
141    pub basis_allowed: Vec<String>,
142    /// Whether swaps can be introduced while rebasing.
143    pub allow_swaps: bool,
144}
145
146/// Automatically squash single-qubit gates.
147#[cfg_attr(feature = "schemars", derive(JsonSchema))]
148#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
149pub struct AutoSquash {
150    /// OpTypes of supported single-qubit gates.
151    pub basis_singleqs: Vec<String>,
152}
153
154/// Parameters for decomposing boxes.
155#[cfg_attr(feature = "schemars", derive(JsonSchema))]
156#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
157pub struct DecomposeBoxes {
158    /// Operation types excluded from decomposition.
159    pub excluded_types: Vec<String>,
160    /// Operation groups excluded from decomposition.
161    pub excluded_opgroups: Vec<String>,
162    /// Operation types explicitly included in decomposition.
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub included_types: Option<Vec<String>>,
165    /// Operation groups explicitly included in decomposition.
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub included_opgroups: Option<Vec<String>>,
168}
169
170/// Configure the two-qubit peephole optimiser.
171#[cfg_attr(feature = "schemars", derive(JsonSchema))]
172#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
173pub struct PeepholeOptimise2Q {
174    /// Whether swaps can be introduced.
175    pub allow_swaps: bool,
176}
177
178/// KAK decomposition configuration.
179#[cfg_attr(feature = "schemars", derive(JsonSchema))]
180#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
181pub struct KAKDecomposition {
182    /// Fidelity threshold to preserve semantics.
183    pub fidelity: f64,
184    /// Whether swaps are allowed during optimisation.
185    pub allow_swaps: bool,
186    /// Target native 2-qubit gate.
187    pub target_2qb_gate: TargetTwoQubitGate,
188}
189
190/// Three-qubit squash configuration.
191#[cfg_attr(feature = "schemars", derive(JsonSchema))]
192#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
193pub struct ThreeQubitSquash {
194    /// Whether swaps are allowed during squashing.
195    pub allow_swaps: bool,
196}
197
198/// Full peephole optimisation configuration.
199#[cfg_attr(feature = "schemars", derive(JsonSchema))]
200#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
201pub struct FullPeepholeOptimise {
202    /// Whether swaps are allowed.
203    pub allow_swaps: bool,
204    /// Target native 2-qubit gate.
205    pub target_2qb_gate: TargetTwoQubitGate,
206}
207
208/// Compose Phase-Polynomial boxes configuration.
209#[cfg_attr(feature = "schemars", derive(JsonSchema))]
210#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
211pub struct ComposePhasePolyBoxes {
212    /// Minimal number of CX gates per phase.
213    pub min_size: u32,
214}
215
216/// Euler angle reduction configuration.
217#[cfg_attr(feature = "schemars", derive(JsonSchema))]
218#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
219pub struct EulerAngleReduction {
220    /// Axis used for the P rotation.
221    pub euler_p: RotationAxis,
222    /// Axis used for the Q rotation.
223    pub euler_q: RotationAxis,
224    /// Whether to enforce strict P-Q-P reductions.
225    pub euler_strict: bool,
226}
227
228/// Routing pass configuration.
229#[cfg_attr(feature = "schemars", derive(JsonSchema))]
230#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
231pub struct RoutingPass {
232    /// Target architecture.
233    pub architecture: Architecture,
234    /// Routing configuration.
235    pub routing_config: RoutingConfig,
236}
237
238/// Custom routing pass configuration.
239#[cfg_attr(feature = "schemars", derive(JsonSchema))]
240#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
241pub struct CustomRoutingPass {
242    /// Target architecture.
243    pub architecture: Architecture,
244    /// Routing configuration.
245    pub routing_config: RoutingConfig,
246}
247
248/// Placement pass configuration.
249#[cfg_attr(feature = "schemars", derive(JsonSchema))]
250#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
251pub struct PlacementPass {
252    /// Placement strategy.
253    pub placement: Placement,
254}
255
256/// Naive placement configuration.
257#[cfg_attr(feature = "schemars", derive(JsonSchema))]
258#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
259pub struct NaivePlacementPass {
260    /// Target architecture.
261    pub architecture: Architecture,
262}
263
264/// Renaming map for qubits.
265#[cfg_attr(feature = "schemars", derive(JsonSchema))]
266#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
267pub struct RenameQubitsPass {
268    /// Mapping between source and destination qubits.
269    pub qubit_map: Vec<QubitMapping>,
270}
271
272/// Clifford simplification configuration.
273#[cfg_attr(feature = "schemars", derive(JsonSchema))]
274#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
275pub struct CliffordSimp {
276    /// Whether swaps can be introduced.
277    pub allow_swaps: bool,
278    /// Target native 2-qubit gate.
279    pub target_2qb_gate: TargetTwoQubitGate,
280}
281
282/// Decompose swaps into CXs.
283#[cfg_attr(feature = "schemars", derive(JsonSchema))]
284#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
285pub struct DecomposeSwapsToCXs {
286    /// Target architecture.
287    pub architecture: Architecture,
288    /// Whether the architecture edges are directed.
289    pub directed: bool,
290}
291
292/// Decompose swaps into custom circuits.
293#[cfg_attr(feature = "schemars", derive(JsonSchema))]
294#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
295pub struct DecomposeSwapsToCircuit {
296    /// Replacement circuit for a swap.
297    pub swap_replacement: Box<SerialCircuit>,
298}
299
300/// Phase gadget optimisation configuration.
301#[cfg_attr(feature = "schemars", derive(JsonSchema))]
302#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
303pub struct OptimisePhaseGadgets {
304    /// Preferred CX configuration.
305    pub cx_config: CxConfig,
306}
307
308/// Shared configuration for Pauli synthesis style passes.
309#[cfg_attr(feature = "schemars", derive(JsonSchema))]
310#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
311pub struct PauliSynthesisConfig {
312    /// Strategy for synthesising Pauli gadgets.
313    pub pauli_synth_strat: PauliSynthStrategy,
314    /// Preferred CX configuration.
315    pub cx_config: CxConfig,
316}
317
318/// Simplify initial states configuration.
319#[cfg_attr(feature = "schemars", derive(JsonSchema))]
320#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
321pub struct SimplifyInitial {
322    /// Whether classical information can be used for simplification.
323    pub allow_classical: bool,
324    /// Whether to annotate all qubits as initialised to zero.
325    pub create_all_qubits: bool,
326    /// Optional witness circuit.
327    #[serde(skip_serializing_if = "Option::is_none")]
328    pub x_circuit: Option<Box<SerialCircuit>>,
329}
330
331/// Full mapping pass configuration.
332#[cfg_attr(feature = "schemars", derive(JsonSchema))]
333#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
334pub struct FullMappingPass {
335    /// Target architecture.
336    pub architecture: Architecture,
337    /// Placement configuration.
338    pub placement: Placement,
339    /// Routing configuration.
340    pub routing_config: RoutingConfig,
341}
342
343/// Default mapping pass configuration.
344#[cfg_attr(feature = "schemars", derive(JsonSchema))]
345#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
346pub struct DefaultMappingPass {
347    /// Target architecture.
348    pub architecture: Architecture,
349    /// Whether to delay measurements.
350    pub delay_measures: bool,
351}
352
353/// CX-focused mapping configuration.
354#[cfg_attr(feature = "schemars", derive(JsonSchema))]
355#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
356pub struct CXMappingPass {
357    /// Target architecture.
358    pub architecture: Architecture,
359    /// Placement configuration.
360    pub placement: Placement,
361    /// Routing configuration.
362    pub routing_config: RoutingConfig,
363    /// Whether the architecture is directed.
364    pub directed: bool,
365    /// Whether to delay measurements.
366    pub delay_measures: bool,
367}
368
369/// Pauli context simplification configuration.
370#[cfg_attr(feature = "schemars", derive(JsonSchema))]
371#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
372pub struct ContextSimp {
373    /// Whether classical information can be used for simplification.
374    pub allow_classical: bool,
375    /// Reference circuit required by the pass.
376    pub x_circuit: Box<SerialCircuit>,
377}
378
379/// Decompose TK2 configuration.
380#[cfg_attr(feature = "schemars", derive(JsonSchema))]
381#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
382pub struct DecomposeTK2 {
383    /// Optional fidelity hints.
384    #[serde(skip_serializing_if = "Option::is_none")]
385    pub fidelities: Option<DecomposeTK2Fidelities>,
386    /// Whether to allow swaps.
387    ///
388    /// NOTE: This field is missing from the pytket schema.
389    pub allow_swaps: bool,
390}
391
392/// Round angles configuration.
393#[cfg_attr(feature = "schemars", derive(JsonSchema))]
394#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
395pub struct RoundAngles {
396    /// Level of precision.
397    pub n: i64,
398    /// Whether only zero rounding is allowed.
399    pub only_zeros: bool,
400}
401
402/// Greedy Pauli simplification configuration.
403#[cfg_attr(feature = "schemars", derive(JsonSchema))]
404#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
405pub struct GreedyPauliSimp {
406    /// Cost discount parameter.
407    pub discount_rate: f64,
408    /// Depth optimisation weight.
409    pub depth_weight: f64,
410    /// Maximum lookahead.
411    pub max_lookahead: f64,
412    /// Maximum number of TQE candidates.
413    pub max_tqe_candidates: f64,
414    /// Seed for randomness.
415    pub seed: f64,
416    /// Whether ZZPhase gates may be emitted.
417    pub allow_zzphase: bool,
418    /// Maximum runtime per thread.
419    pub thread_timeout: f64,
420    /// Whether only reductions are allowed.
421    pub only_reduce: bool,
422    /// Number of random trials.
423    pub trials: f64,
424}
425
426/// Delay measures configuration.
427#[cfg_attr(feature = "schemars", derive(JsonSchema))]
428#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
429pub struct DelayMeasures {
430    /// Whether partial delays are allowed.
431    pub allow_partial: bool,
432}
433
434/// Flatten and relabel registers configuration.
435///
436/// NOTE: The pytket schema declares an additional `relabel_classical_registers`
437/// field that is not actually present in the pass definition.
438#[cfg_attr(feature = "schemars", derive(JsonSchema))]
439#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
440pub struct FlattenRelabelRegistersPass {
441    /// Label to assign to flattened registers.
442    pub label: String,
443}
444
445/*
446 * ------------------------------------------------------------
447 * Pass attribute types.
448 * ------------------------------------------------------------
449 */
450
451/// Mapping between qubits for renaming operations.
452#[cfg_attr(feature = "schemars", derive(JsonSchema))]
453#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
454pub struct QubitMapping(pub ElementId, pub ElementId);
455
456/// Serialized routing configuration.
457pub type RoutingConfig = Vec<RoutingMethod>;
458
459/// Routing method descriptor.
460#[cfg_attr(feature = "schemars", derive(JsonSchema))]
461#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
462pub struct RoutingMethod {
463    /// Name of the routing method.
464    pub name: String,
465}
466
467/// Configuration for decomposing TK2 gates.
468#[cfg_attr(feature = "schemars", derive(JsonSchema))]
469#[derive(Deserialize, Serialize, Clone, Debug, PartialEq)]
470pub struct DecomposeTK2Fidelities {
471    /// Optional CX fidelity.
472    #[serde(rename = "CX", skip_serializing_if = "Option::is_none")]
473    pub cx: Option<f64>,
474    /// Optional ZZMax fidelity.
475    #[serde(rename = "ZZMax", skip_serializing_if = "Option::is_none")]
476    pub zz_max: Option<f64>,
477    /// Optional ZZPhase fidelity.
478    #[serde(rename = "ZZPhase", skip_serializing_if = "Option::is_none")]
479    pub zz_phase: Option<f64>,
480}
481
482/// Rotation axes used during Euler angle reduction.
483#[cfg_attr(feature = "schemars", derive(JsonSchema))]
484#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
485pub enum RotationAxis {
486    /// Rotation around the X axis.
487    Rx,
488    /// Rotation around the Y axis.
489    Ry,
490    /// Rotation around the Z axis.
491    Rz,
492}
493
494/// Target native two-qubit gate for optimisation passes.
495#[cfg_attr(feature = "schemars", derive(JsonSchema))]
496#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
497pub enum TargetTwoQubitGate {
498    /// Controlled-NOT
499    CX,
500    /// TK2 gate.
501    TK2,
502}
503
504/// Preferred CX configuration for gadget construction.
505#[cfg_attr(feature = "schemars", derive(JsonSchema))]
506#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
507pub enum CxConfig {
508    /// Snake configuration.
509    Snake,
510    /// Tree configuration.
511    Tree,
512    /// Star configuration.
513    Star,
514    /// Support for multi-qubit architectures, decomposing to 3-qubit XXPhase3 gates instead of CXs where possible.
515    ///
516    /// NOTE: This field is missing from the pytket schema.
517    MultiQGate,
518}
519
520/// Strategy for synthesising Pauli gadgets.
521#[cfg_attr(feature = "schemars", derive(JsonSchema))]
522#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, Eq)]
523pub enum PauliSynthStrategy {
524    /// Synthesise gadgets individually.
525    Individual,
526    /// Synthesise gadgets pairwise.
527    ///
528    /// Based on Cowtan et. al. <https://arxiv.org/abs/1906.01734>
529    Pairwise,
530    /// Synthesise gadgets in commuting sets.
531    Sets,
532    /// Synthesise gadgets using a greedy algorithm adapted from <https://arxiv.org/abs/2103.08602>.
533    ///
534    /// This strategy is currently only accepted by TermSequenceBox. For synthesising general circuits try using GreedyPauliSimp.
535    ///
536    /// WARNING: This strategy will not preserve the global phase of the circuit.
537    ///
538    /// NOTE: This field is missing from the pytket schema.
539    Greedy,
540}