Page
Library
Module
Module type
Parameter
Class
Class type
Source
Voqc.MainMain entry point for VOQC.
VOQC contains utilities for optimizing quantum circuits and mapping them to a connectivity graph. VOQC was first presented at POPL 2021. The extended version of the paper is available here. In the remainder of this document we will refer to this paper as "POPL VOQC".
This file lists the functions we provide in VOQC, as well as properties we have verified about them. In general, our goal is to prove that VOQC circuit transformations are semantics preserving, meaning that the behavior of a circuit (its "semantics") does not change after our transformations are applied. The semantics of a unitary circuit over d qubits is a 2^d x 2^d unitary matrix, so proving semantics-preservation requires showing that two (symbolic) matrices are equal. Sometimes we also show that the output of a transformation has a particular property, such as using a particular gate set.
In the remainder of this document, we will use the following shorthand for properties proved:
Preserves semantics -- The semantics-preservation property is written in Coq as forall (c : circ), [[opt c]] = [[c]] for optimization opt. In our development, we support several variations on semantics-preservation:
forall c, well_typed c -> [[opt c]] = [[c]]. forall c, exists x, [[opt c]] = e^(ix) [[c]]. forall c, [[c]] = P1 x [[opt c]] x P2.The circ type is a list of gates from the standard gate set.
gate_counts is the return type for count_gates. It stores the count of each gate type in the following order: { I, X, Y, Z, H, S, T, Sdg, Tdg, Rx, Ry, Rz, Rz, U1, U2, U3, CX, CZ , SWAP, CCX, CCZ }.
A layout describes a mapping from logical to physical qubits. For an architecture with n qubits, a layout should be a bijection on integers {0, ..., n-1}. Under the hood, layout is a pair of functions (nat -> nat) * (nat -> nat) that maps logical qubits to physical qubits and physical qubits back to logical qubits. A layout is well-formed if these two functions accurately represent a bijection and its inverse.
You can construct a layout using the function list_to_layout.
A connectivity graph (c_graph) is a triple nat * (nat -> nat -> list nat) * (nat -> nat -> bool), which consists of the total number of qubits in the system, a function to generate an undirected path between any two qubits, and an oracle that indicates whether a directed edge exists between two qubits. A connectivity graph is well-formed if the function to get paths returns a valid path between any two qubits in the system.
You can construct a connectivity graph using make_tenerife, make_lnn, make_lnn_ring, or make_grid.
val check_well_typed : circ -> int -> boolCheck if a circuit is well-typed with the given number of qubits (i.e. every gate is applied to qubits within range and never applied to duplicates).
Restrict a program to use gates in the IBM gate set (this may be done implicitly when calling certain optimizations).
Verified Properties: preserves semantics, preserves WT, preserves mapping, uses gates {U1, U2, U3, CX}
Restrict a circuit to use gates in the RzQ gate set (this may be done implicitly when calling certain optimizations).
Verified properties: preserves semantics (phase), preserves WT, preserves mapping, uses gates {H, X, Rzq, CX}
Replace the (non-standard) Rzq gate with its equivalent Rz, Z, T, S, Tdg, or Sdg gate.
Verified Properties: preserves semantics, preserves WT, preserves mapping, uses any gate in the standard set except Rzq
Decompose CZ, SWAP, CCX, and CCZ gates so that the only multi-qubit gate is CX (also called "CNOT").
Verified Properties: preserves semantics, preserves WT, uses any gate in the standard set except {CZ, SWAP, CCX, CCZ}
val count_gates : circ -> gate_countsCount all types of gates in the program. Note that this count is syntactic in the sense that gates like Rz, Rzq, and U1 are counted separately even though they all could be considered a U1 gate. Similarly, the count for X does not include gates of the form U3(PI,0,PI), even though this is functionally the same.
val total_gate_count : circ -> intCount the total number of gates (i.e. length of the instruction list).
val count_clifford_rzq : circ -> intCount the Rzq gates parameterized by a multiple of PI/2 (i.e. "Clifford" Rz gates).
val scale_count : gate_counts -> int -> gate_countsMultiply all gate counts by a factor n.
val add_counts : gate_counts -> gate_counts -> gate_countsAdd gate counts.
val count_gates_lcr : ((circ * circ) * circ) -> int -> gate_countsCompute the gates required for n iterations of the input LCR decomposition (see optimize_nam_lcr).
Implementation of Qiskit's Optimize1qGates routine, which merges adjacent 1-qubit gates. Internally uses the IBM gate set.
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Implementation of Qiskit's CXCancellation routine, which cancels adjacent CX gates. Internally uses the IBM gate set.
Verified Properties: Preserves semantics (WT), preserves WT, preserves mapping
Run optimize_1q_gates followed by cx_cancellation.
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Implementation of Nam et al.'s "NOT propagation," which commutes X gates rightward through the circuit, cancelling them when possible (see VOQC POPL Sec 4.3). Internally uses the RzQ gate set.
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Implementation of Nam et al.'s "Hadamard gate reduction," which applies a series of identities to reduce the number of H gates (see VOQC POPL Sec 4.4). Internally uses the RzQ gate set.
Verified Properties: Preserves semantics (phase), preserves WT, preserves mapping
Implementation of Nam et al.'s "single-qubit gate cancellation," which commutes single-qubit gates rightward through the circuit, cancelling them when possible, and reverting them to their original positions if they fail to cancel (see VOQC POPL Sec 4.3). Internally uses the RzQ gate set.
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Implementation of Nam et al.'s "two-qubit gate cancellation," which commutes CX gates rightward through the circuit, cancelling them when possible, and reverting them to their original positions if they fail to cancel (see VOQC POPL Sec 4.3). Internally uses the RzQ gate set.
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Implementation of Nam et al.'s "rotation merging using phase polynomials," which combines Rz gates that act on the same logical state (see VOQC POPL Sec 4.4). Internally uses the RzQ gate set.
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Run optimizations in the order 0, 1, 3, 2, 3, 1, 2, 4, 3, 2 where 0 is not_propagation, 1 hadamard_reduction, 2 is cancel_single_qubit_gates, 3 is cancel_two_qubit_gates, and 4 is merge_rotations (see VOQC POPL Sec 4.6).
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Run optimizations in the order 0, 1, 3, 2, 3, 1, 2, using the same numbering scheme as above. This will be faster than optimize_nam because it excludes rotation merging, which is our slowest optimization.
Verified Properties: Preserves semantics (WT, phase), preserves WT, preserves mapping
Use optimize_nam to optimize across loop iterations. To count the gates required for n iterations, use count_gates_lcr.
Verified Properties: Say that this function returns Some (l, c, r) on input c0. Then for any n >= 3, iterating c0 n times is equivalent to running l once, c n-2 times, and r once. If c0 is well-typed then l, c, r are also well-typed. If c0 is properly mapped then l, c, r are also properly mapped.
val check_layout : layout -> int -> boolCheck if a layout is well-formed.
val check_graph : c_graph -> boolCheck if a graph is well-formed. This function will make O(n^2) calls to the path finding function for n qubits, so it will likely be slow.
Check if a circuit satisfies the constraints of a connectivity graph.
Return (c, la) where c is the mapped circuit and la is the final layout.
Verified properties: Provided that that the input circuit is well-typed using the dimension stored in the input graph and the input layout and graph are well-formed, this transformation preserves semantics (WT, perm) and preserves WT. Furthermore, the output c respects the constraints the input graph and la is well-formed.
val make_tenerife : unit -> c_graphCreate a graph for IBM's 5-qubit Tenerife machine).
Verified Properties: The output connectivity graph is well-formed.
val make_lnn : int -> c_graphCreate a 1D LNN graph with n qubits (see POPL VOQC Fig 8(b)).
Verified Properties: The output connectivity graph is well-formed.
val make_lnn_ring : int -> c_graphCreate a 1D LNN ring graph with n qubits (see POPL VOQC Fig 8(c)).
Verified Properties: The output connectivity graph is well-formed.
val make_grid : int -> int -> c_graphCreate a m x n 2D grid (see POPL VOQC Fig 8(d)).
Verified Properties: The output connectivity graph is well-formed.
val trivial_layout : int -> layoutCreate a trivial layout on n qubits (i.e. logical qubit i is mapped to physical qubit i).
Verified Properties: The output layout is well-formed.
val list_to_layout : int list -> layoutMake a layout from a list. Example: the list [3; 4; 1; 2; 0] is transformed to a layout with physical to logical qubit mapping {0->3, 1->4, 2->1, 3->2, 4->0} (so physical qubit 0 stores logical qubit 3) and the appropriate inverse logical to physical mapping.
val layout_to_list : layout -> int -> int listConvert a layout to a list for easier printing. Example: the layout with physical to logical qubit mapping {0->3, 1->4, 2->1, 3->2, 4->0} is transformed to the list [3; 4; 1; 2; 0].