Overview

3 Implement quantum operations

This chapter presents a practical roadmap for implementing quantum operations from their matrix descriptions, moving from high-level algorithmic intent to executable circuits. It frames quantum programs across three abstraction layers: logical algorithm steps, language-level primitives (in Q# and Qiskit), and hardware-specific instructions handled by compilers. Focusing on real-valued unitaries for clarity, the chapter shows how to build, inspect, and validate operations, emphasizing how to observe the matrix implemented by code and how to write robust tests that compare matrices within numerical tolerances.

The journey starts with single-qubit gates: any real 2×2 unitary is classified as symmetric or antisymmetric, enabling an implementation with a single Ry(2α) rotation, optionally preceded by Z to fix signs. The chapter then demonstrates how to extract a circuit’s matrix (via Qiskit’s unitary tools and Q# utilities) and how to unit test those results. It scales to two-qubit building blocks by analyzing controlled-gate matrix structure and endianness, implementing block-diagonal unitaries with most-significant-bit controls, and constructing the two-qubit CS unitary by splitting it into two controlled single-qubit rotations on the least significant bit. A block-antidiagonal example further illustrates factoring a unitary into block-diagonal parts around a fixed CS core.

General multi-qubit synthesis is achieved through the cosine–sine (CS) decomposition: any 2^n×2^n unitary is expressed as left and right block-diagonal unitaries around a CS matrix. The chapter builds the required components: an n-qubit two-block block-diagonal “multiplexer” via controlled smaller unitaries and an arbitrary-size CS unitary as a product of 2^(n−1) multi-controlled single-qubit rotations keyed by control patterns. The final recursive construction applies (right block-diagonal) → (CS) → (left block-diagonal), using SciPy’s cossin in Qiskit to obtain the factors; Q# illustrates all intermediate pieces but omits the final decomposition step due to external library constraints. Throughout, the chapter highlights endianness conventions, practical simulator-based verification, and the role of compilers in mapping high-level gates to device-level instructions.

Any quantum algorithm can be broken down into several steps: prepare the initial state, evolve it by applying unitary transformations, and measure the final state. In this chapter, we’ll learn to perform the second step, implementing unitary transformations as the algorithm dictates.
figure
The transformation the quantum state undergoes following a quantum algorithm is typically broken down into simpler building blocks. First, the whole algorithm is expressed as a sequence of operations described in terms of the input parameters of the problem. These operations are further represented as sequences of primitives provided by the high-level programming language used to implement the algorithm. Finally, to execute the algorithm on a quantum device, programming language primitives have to be expressed as sequences of low-level instructions that are natively available on this device.
figure
Cosine-sine decomposition for an example \(4 \times 4\) matrix. This matrix is represented as a product of three matrices: a block-diagonal matrix defined by \(2 \times 2\) matrices \(A_l\) and \(B_l\), a block matrix of special shape called CS matrix defined by \(2 \times 2\) diagonal matrices \(C\) and \(S\), and another block-diagonal matrix defined by \(2 \times 2\) matrices \(A_r\) and \(B_r\).
figure
figure
The row and column indices of \(4 \times 4\) matrices. The indices are written in binary using little endian notation: the least significant bit is written first. You can see that the top left and bottom right blocks group the elements for which the most significant (the last) bit of the row index equals that of the column index: for the matrix \(A\) in the top left block the most significant bit is \(0\), and for the matrix \(B\) in the bottom right block the most significant bit is \(1\).
figure
figure
figure
figure
The non-zero elements of a two-qubit CS matrix can be separated and grouped together in two matrices \(M_0\) and \(M_1\). Each of these matrices is unitary.
figure
figure
figure
figure
The row and column indices of an \(8 \times 8\) block-diagonal matrix. The indices are written in binary using little endian notation: the least significant bit is written first. The top left and bottom right blocks group the elements for which the most significant (the last) bit of the row index equals that of the column index, and is \(0\) for the top left block and \(1\) for the bottom right block.
figure
figure
figure

Summary

  • Quantum operations that make up an algorithm can be expressed in different ways. On the conceptual level, the operations are described in terms of the problem solved by the algorithm and its input parameters.
  • When writing the code, these operations are implemented in a quantum programming language as sequences of primitive gates, language constructs, and library operations available in that language.
  • On the lowest level, the gates used in the high-level program are represented as sequences of low-level instructions native to the hardware device and/or the error correction scheme used with the hardware.
  • The goal of the unitary implementation task is to convert the matrix description of a unitary operation into a sequence of quantum gates that implements the unitary described by this matrix.
  • Unitary operations can be implemented recursively, by decomposing their matrices as products of matrices of special shapes and implementing each of these matrices using controlled variants of unitary operations acting on fewer qubits.
  • Many quantum algorithms are hybrid, combining classical and quantum computation; getting the cosine-sine decomposition as a step of unitary implementation is one example. It is important for a quantum programming language to express hybrid computations efficiently.
  • We can use quantum simulators and the way they allow us to access quantum states during the program execution to get the matrices implemented by quantum operations and test that a quantum operation implements the right matrix.

FAQ

What does “implement a quantum operation” mean in this chapter?It means turning an algorithm’s high-level description into a sequence of unitary transformations built from language primitives (Qiskit/Q# gates) that a compiler can later map to device-level instructions. We work at the high-level (using built-in gates and controlled variants), not at the hardware-synthesis layer.
Why restrict to real-valued unitary matrices, and what special shapes matter?Real unitaries simplify the math and coding while still covering many useful cases. Special shapes include: - Permutation matrices (reversible classical computations) - Block-diagonal and block-antidiagonal forms - CS (cosine–sine) matrices used in cosine–sine decomposition (CSD) These structures let us build general unitaries from simpler pieces.
How do I implement a single-qubit unitary U from its 2×2 real matrix?Any real single-qubit unitary falls into one of two forms: - Antisymmetric: [[cos α, −sin α], [sin α, cos α]] = Ry(2α) - “Symmetric” (in this chapter’s sense): [[cos α, sin α], [sin α, −cos α]] = Ry(2α) · Z Find α with α = atan2(u10, u00). Detect the form using tolerant comparisons (floating-point), and beware diagonal/anti-diagonal edge cases when classifying.
How can I see the matrix my circuit actually implements?Qiskit: - Aer unitary_simulator → result.get_unitary() - qiskit.quantum_info.Operator(circuit_or_gate).data Q#: - From Python: qsharp.utils.dump_operation("Namespace.OpName(_, ...)", num_qubits) - From Q#: Std.Diagnostics.DumpOperation Use partial application to bind classical parameters before dumping the operation.
What’s a good strategy to test my unitary implementations?- Simulate to obtain the implemented matrix. - Compare to the target matrix elementwise with tolerance (e.g., pytest.approx). - Include corner cases (diagonal/anti-diagonal, symmetric/antisymmetric). - Add randomized instances where appropriate. In Qiskit use Operator; in Q#, use dump_operation via Python.
How do controlled gates look in matrix form, and why does endianness matter?For a 2-qubit controlled-U: - Control on MSB yields contiguous 2×2 blocks (top-left for control-on-0, bottom-right for control-on-1). - Control on LSB spreads U’s entries in a checkerboard pattern. Qiskit uses little endian; Q# uses big endian. When matching integer control patterns in Q#, reverse the control-qubit order (or the bit pattern) to align with ApplyControlledOnInt’s little-endian expectation.
How do I implement a two-qubit block-diagonal unitary diag(A, B)?Apply two controlled single-qubit (or sub-unitary) gates using the most significant qubit as control: - Controlled B (control-on-1) - Controlled-on-zero A Order is irrelevant (they commute). In Qiskit, pass [control, target] with MSB as the first index; in Q#, MSB is typically qs[0].
What is a CS (cosine–sine) unitary and how is it implemented?A CS unitary has the form [[C, −S], [S, C]], where C and S are diagonal and satisfy C²+S²=I. - Two qubits: group nonzeros into two 2×2 rotations M0 and M1; implement as controlled single-qubit gates using the LSB as control (one control-on-0, one control-on-1). - n qubits: as a product over k of controlled single-qubit rotations Mk = [[cₖ, −sₖ], [sₖ, cₖ]] acting on the MSB, with the remaining n−1 LSBs as controls and ctrl_state = k.
How do I implement a two-qubit block-antidiagonal unitary with off-diagonal blocks A and B?Use a fixed CSD factorization: - Apply block-diagonal diag(I, −A) - Apply CS with C=0, S=I (a fixed pattern) - Apply block-diagonal diag(I, B) Each step uses previously built primitives (block-diagonal and CS constructions).
How do I implement an arbitrary n-qubit real unitary?Use cosine–sine decomposition (CSD): 1) Compute U = blockdiag(Al, Bl) · CS · blockdiag(Ar, Br) (e.g., SciPy’s cossin in Qiskit code). 2) Implement blockdiag(Ar, Br) recursively via controlled sub-unitaries. 3) Implement the CS unitary as many (2^(n−1)) multi-controlled single-qubit rotations on the MSB. 4) Implement blockdiag(Al, Bl). Base case: n=1 handled by the single-qubit routine. Note: In Q#, you’d typically rely on compiler/library support (no built-in CSD API), while Qiskit can call SciPy directly.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Quantum Programming in Depth ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Quantum Programming in Depth ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • Quantum Programming in Depth ebook for free