A Qiskit implementation of arbitrary quantum state preparation: given a
normalized complex vector
The circuit uses only single-qubit gates and multi-controlled
The construction loops over a binary tree, with data loaded as follows:
-
Magnitudes are loaded by conditional-probability
$R_Y$ rotations: at each node the rotation splits the remaining probability mass between its two subtrees. -
Phases are loaded by an argument-averaging
$R_Z$ tree: each node applies the phase difference between its children and carries their average upward. The leftover root average is the overall global phase; it is unobservable on its own, but is recorded on the circuit so that a controlled version remains correct.
The function state_preparation_data returns the tree as a plain list of operation
dictionaries together with that global phase, and build_state_prep_circuit
translates them into gates.
Two implementation notes:
- Multi-controlled
$R_Y$ is realized as a multi-controlled$R_Z$ conjugated by single-qubit gates ($S H R_Z H S^\dagger = R_Y$ ). - Controls on an arbitrary bit-pattern are implemented by applying
$X$ gates to set all qubits equal to$1$ , and reversing them afterwards.
Amplitudes are indexed in Qiskit's standard ordering (qubit 0 least
significant), so the statevector index equals the integer
See walkthrough.ipynb for the full derivation and a worked example.
-
state_prep.py— the implementation (angle helper, tree builder, circuit builder). -
walkthrough.ipynb— a derivation of the method, with an$n=3$ demonstration. -
testing_suite.ipynb— the test suite (correctness, error isolation, path coverage, contract).
uv sync
uv run jupyter labThen open walkthrough.ipynb. To prepare a state directly:
import numpy as np
from state_prep import state_preparation_data, build_state_prep_circuit
psi = np.array([...], dtype=complex) # length 2^n, will be normalized
n = len(psi).bit_length() - 1
ops, global_phase = state_preparation_data(psi)
qc = build_state_prep_circuit(n, ops, global_phase)MIT.