Skip to main content
Quantum computers natively implement unitary operations. Many real-world problems, however, are naturally expressed in terms of matrices that are not unitary. For instance, a correlation matrix between assets in a financial portfolio, or a differential operator discretizing a partial differential equation in engineering design. To process such a matrix on a quantum computer, it must first be embedded into a larger unitary matrix acting on additional qubits. This embedding procedure is known as block encoding. Given a matrix AA, block encoding it means embedding it into the top-left block of a larger unitary UU: applying UU to ∣0⟩⊗b∣ψ⟩\vert 0 \rangle^{\otimes b} \vert \psi \rangle and post-selecting the first bb qubits on ∣0⟩\vert 0 \rangle recovers A∣ψ⟩A \vert \psi \rangle up to a scaling factor. Formally, a unitary UU is an (α,b,ϵ)(\alpha, b, \epsilon)-block-encoding of AA if ∥A−α(⟨0∣⊗b⊗I)U(∣0⟩⊗b⊗I)∥≤ϵ,\left\lVert A - \alpha \left(\langle 0 \vert^{\otimes b} \otimes I\right) U \left(\vert 0 \rangle^{\otimes b} \otimes I\right) \right\rVert \le \epsilon, where α\alpha is a normalization factor, bb is the number of extra (“block”) qubits, and ϵ\epsilon is the approximation error (0 for an exact encoding). Classiq’s BlockEncoding class represents UU as a qfunc, together with the (α,b,ϵ)(\alpha, b, \epsilon) triple, as a single Python object. It also provides constructors and algebraic operations so you can build and combine block encodings without hand-managing quantum variables.

The BlockEncoding class

BlockEncoding is a frozen dataclass with the following fields: You rarely construct a BlockEncoding by filling in these fields directly. Instead, use one of its classmethod constructors — covered in Constructing Block Encodings — to build one from a NumPy matrix, a set of diagonals, a sum of Pauli operators, and more.

Quick start

be.unitary is a qfunc like any other, so you call it directly on your own variables inside main. The following example block-encodes a diagonal matrix AA, loads a non-uniform vector x_vector onto the data variable, applies the block encoding, synthesizes and executes the resulting circuit. Filtering the state vector on block == 0 recovers (A/α)⋅x_vector(A / \alpha) \cdot \text{x\_vector}, which is the block-encoded action of AA on the input, up to the scaling factor α\alpha:
The first print gives: And the second gives 8.0, matching be.alpha. See State Vector Filtering for more on calculate_state_vector and filtering by variable.

Where to go next