Skip to Content

Fundamental Algorithms

Overview

The unitarylab_algorithms.fundamental_algorithm package provides the core quantum primitives that form the foundation of more advanced algorithms:

AlgorithmClassPurpose
Grover SearchGroverAlgorithmQuadratic speedup for unstructured search
Quantum Phase EstimationQPEAlgorithmExtract eigenphases of a unitary operator
Amplitude AmplificationAmplitudeAmplificationAlgorithmBoost the measurement probability of the target state
Quantum Amplitude Estimation (QAE)AmplitudeEstimationAlgorithmEstimate the amplitude of the target state
Hadamard TestHadamardTestAlgorithmEstimate expectation values and state overlap
Hadamard TransformHadamardTransformAlgorithm-qubit global Hadamard transform

status indicates whether the call completed normally; the accuracy of estimation-type algorithms’ results should be judged via their error, probability, or estimate fields. The status of amplitude amplification additionally reflects whether the target probability exceeds the initial probability. See the corresponding section for each algorithm’s specific determination method.


Background

Grover’s algorithm finds a target in an unsorted database of entries using oracle queries, compared to queries required classically. It is the optimal algorithm for unstructured quantum search, and also serves as an important subroutine in many other algorithms.

The algorithm achieves amplification by iterating the Grover diffusion operator (inversion about the mean) together with an Oracle that flips the phase of the target state; the number of iterations is automatically computed from the initial success probability .

Import

from unitarylab_algorithms import GroverAlgorithm

.run() Parameters

def run(self, n: int, target: str, backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]
ParameterTypeDefaultDescription
nint— (required)Number of qubits in the data register
targetstr— (required)Target state as a binary string (e.g., '101' for 3 qubits)

Return Value

{ 'status': 'ok', # Always 'ok'; does not reflect true search success/failure, see note above 'circuit_path': '/path/to/grover_algorithm_circuit.svg', 'plot': [{'format': 'txt', 'filename': 'grover_algorithm_result.txt'}], 'circuit': <Circuit>, 'Amplified target-state probability': 0.9453, 'Result': '101', # The bit string actually measured with highest probability -- compare with target to determine true success/failure }

Example

from unitarylab_algorithms import GroverAlgorithm algo = GroverAlgorithm() result = algo.run(n=3, target='101') is_really_success = (result['Result'] == '101') # True success/failure determination; do not rely on result['status'] print(is_really_success)

Quick Demo

from unitarylab_algorithms.fundamental_algorithm.grover.algorithm import test test(n=3, target='101')

Notes

  • status='ok' indicates the call completed; to determine whether the target was hit, compare result['Result'] with the target you passed in.
  • The length of target should in principle equal n (the web frontend’s parameters.json states this as well), but the Python API performs no explicit length validation — a length mismatch will not raise a clear ValueError; instead it will trigger a low-level error or produce an unexpected circuit when building the multi-controlled Oracle circuit (mcx). Be sure the two match.

Quantum Phase Estimation (QPE)

Background

QPE extracts the eigenphase of a unitary operator , where . With ancilla qubits, the phase estimation precision is .

QPE is a key subroutine in Shor’s algorithm, HHL, and quantum chemistry simulation.

Import

from unitarylab_algorithms import QPEAlgorithm

.run() Parameters

def run(self, U: Circuit, d: int, prepare_target: Optional[Circuit] = None, backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]
ParameterTypeDefaultDescription
UCircuit— (required)Unitary operator circuit whose eigenphase is to be estimated
dint— (required)Number of phase register qubits (precision )
prepare_targetCircuit | NoneNoneCircuit preparing the eigenstate (defaults to ); if provided, its qubit count must match U, otherwise a ValueError is raised

Building the QPE Circuit Directly

QPEAlgorithm also provides a utility method for embedding QPE into a larger circuit:

from unitarylab import Circuit from unitarylab_algorithms import QPEAlgorithm U = Circuit(1) U.z(0) algo = QPEAlgorithm() qpe_circuit = algo.build_qpe_circuit(U=U, d=4)

Return Value

{ 'status': 'ok', # Indicates the estimation process has completed 'circuit_path': '/path/to/quantum_phase_estimation_algorithm_circuit.svg', 'plot': [{'format': 'txt', 'filename': 'quantum_phase_estimation_algorithm_result.txt'}], 'circuit': <Circuit>, 'Estimated phase': 0.125, 'Best phase bit string': '0010', 'Best phase probability': 0.98, 'Computation time (s)': 0.0123, 'Phase probabilities': [('0010', 0.98), ('0011', 0.01), ('0001', 0.005)], # The top 3 candidate phases by probability }

Example

from unitarylab.core import Circuit from unitarylab_algorithms import QPEAlgorithm # The T gate has eigenphase π/4, i.e. φ = 1/8 = 0.125 in units of 2π U = Circuit(1) U.t(0) algo = QPEAlgorithm() result = algo.run(U=U, d=4) print(result['Estimated phase']) # Approximately 0.125

Quick Demo

from unitarylab_algorithms.fundamental_algorithm.qpe.algorithm import test test(p=0.25, n=3)

Notes

  • status='ok' indicates the estimation process completed; assess precision by comparing Estimated phase with the theoretical value.
  • The module-level test(p, n) function’s p represents the eigenphase (as a fraction in units of ): the T gate corresponds to p=0.125, and the S gate corresponds to p=0.25. Alternatively, you can build the unitary circuit U directly as shown in the example above.

Amplitude Amplification

Background

Amplitude amplification is a generalization of Grover’s algorithm: given a state preparation unitary and an oracle that marks the “good” states, it amplifies the amplitude of the good states by repeatedly applying a Grover-like reflection operator. The number of iterations is automatically inferred from the initial success probability , or can be specified manually.

Import

from unitarylab_algorithms import AmplitudeAmplificationAlgorithm

.run() Parameters

def run(self, U: Circuit, good_zero_qubits: List[int], p: float, reps: Optional[int] = None, backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]
ParameterTypeDefaultDescription
UCircuit— (required)State preparation circuit (excluding the ancilla qubit)
good_zero_qubitsList[int]— (required)Qubit indices that must be in the target state
pfloat— (required)Initial success probability; when reps=None, used to automatically compute the iteration count, in which case must hold, otherwise a ValueError is raised; regardless of whether reps is explicitly passed, it is used for log display and the final status determination (target_prob > p)
repsint | NoneNoneManually specified iteration count (overrides the -based automatic calculation when provided; in this case p is no longer constrained by , but still participates in the final status determination, i.e. target_prob > p)

Return Value

This algorithm is the only one among the 6 algorithms in this package whose top-level status genuinely reflects success or failure (is_success = target_prob > p):

{ 'status': 'ok', # Genuinely reflects whether the amplified target-state probability actually exceeds the initial probability p 'circuit_path': '/path/to/amplitude_amplification_algorithm_circuit.svg', 'plot': [{'format': 'txt', 'filename': 'amplitude_amplification_algorithm_result.txt'}], 'circuit': <Circuit>, 'Amplified Target Probability': 0.98, 'Initial Success Probability': 0.1, 'Repetitions': 3, 'Computation Time (s)': 0.0234, 'Data register size': 2, }

Example

from unitarylab_algorithms import AmplitudeAmplificationAlgorithm algo = AmplitudeAmplificationAlgorithm() result = algo.run(U=my_circuit, good_zero_qubits=[0], p=0.1, reps=3) print(result['status'])

Quick Demo

from unitarylab_algorithms.fundamental_algorithm.amplitude_amplification.algorithm import test test(p=0.1, reps=3)

Notes

  • p is used by the algorithm to compute the iteration count only when reps=None, in which case must hold; once reps is explicitly passed, p only participates as the “initial probability” in log display and the final status determination (target_prob > p), and no longer affects the iteration count itself.
  • Unlike algorithms such as Grover / QPE / Hadamard Transform, this algorithm’s status can safely be used in business logic to judge the true amplification effect.

Quantum Amplitude Estimation (QAE)

Background

Quantum Amplitude Estimation (QAE) estimates the amplitude of the target state within a state preparation unitary . It combines amplitude amplification with QPE, achieving a root-mean-square error of using ancilla qubits.

Import

from unitarylab_algorithms import AmplitudeEstimationAlgorithm

.run() Parameters

def run(self, U: Circuit, good_zero_qubits: List[int], d: int = 6, backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]
ParameterTypeDefaultDescription
UCircuit— (required)State preparation unitary
good_zero_qubitsList[int]— (required)Qubit indices defining the target state
dint6Number of phase register qubits (precision )

Note: .run() itself has no p parameterp only appears in the module-level test(p=0.36, d=6) function, where it is used to construct a test state preparation circuit U; when calling the Python API directly, you need to build U yourself.

Return Value

{ 'status': 'ok', # Indicates the estimation process has completed 'circuit_path': '/path/to/amplitude_estimation_algorithm_circuit.svg', 'plot': [{'format': 'txt', 'filename': 'amplitude_estimation_algorithm_result.txt'}], 'circuit': <Circuit>, 'Target amplitude': 0.36, 'Most likely phase (bits)': '001001', 'Phase': 0.140625, 'Computation time (s)': 0.0456, 'Total qubits': 9, }

Example

from unitarylab_algorithms import AmplitudeEstimationAlgorithm algo = AmplitudeEstimationAlgorithm() result = algo.run(U=my_circuit, good_zero_qubits=[0], d=6) print(result['Target amplitude'])

Quick Demo

from unitarylab_algorithms.fundamental_algorithm.amplitude_estimation.algorithm import test test(p=0.36, d=6)

Notes

  • status='ok' indicates the estimation process completed; compare Target amplitude with the theoretical value to assess precision.
  • .run() has no p parameter — only test() does; when calling the Python API you must build U (the state preparation circuit) and good_zero_qubits yourself.

Hadamard Test

Background

The Hadamard test uses a single ancilla qubit to estimate the expectation value of a unitary operator with respect to a state . It supports three modes:

  • expectation — Estimates (estimates the imaginary part when imag=True)
  • swap_test — Estimates the overlap between two states
  • phase_estimation — Performs single-qubit phase estimation

Import

from unitarylab_algorithms import HadamardTestAlgorithm

.run() Parameters

def run(self, mode: str = "expectation", U: Optional[Circuit] = None, prepare_psi: Optional[Circuit] = None, prepare_phi: Optional[Circuit] = None, imag: bool = False, shots: int = 20000, backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]
ParameterTypeDefaultDescription
modestr'expectation'Run mode: one of 'expectation', 'swap_test', 'phase_estimation'; other values raise a ValueError
UCircuit | NoneNoneUnitary operator circuit (required in expectation/phase_estimation mode, otherwise raises a ValueError; not used in swap_test mode)
prepare_psiCircuit | NoneNoneCircuit preparing $
prepare_phiCircuit | NoneNoneCircuit preparing $
imagboolFalseExtract the imaginary part (valid only in expectation mode)
shotsint20000Number of measurement shots for statistical sampling; when shots<=0, no binomial sampling noise is simulated, and the exact expectation value is returned directly

The default value of shots for .run() itself is 20000 (introducing sampling noise), whereas the module-level test() function and the web frontend’s parameters.json both default to shots=0 (exact computation, no noise). When you directly instantiate HadamardTestAlgorithm().run(...) without explicitly passing shots, you get an estimate with sampling noise, which differs from the exact value shown by default by test()/the web frontend.

Return Value

Unlike the other 5 algorithms, circuit_path here is a list of paths rather than a single string — in expectation mode it has 1 element (main), in swap_test mode it has 1 element (real), and in phase_estimation mode it has 2 elements (real, imag):

{ 'status': 'ok', # Always 'ok'; the Hadamard test is a pure estimator with no inherent success/failure determination 'circuit_path': ['/path/to/HadamardTest_expectation_main.svg'], 'plot': [{'format': 'txt', 'filename': 'hadamard_test_algorithm_result.txt'}], 'circuit': <Circuit>, # One of the circuits built under the given mode (a representative circuit) 'Estimated Value': 0.7071, 'Computation Time (s)': 0.0089, }

Example

from unitarylab_algorithms import HadamardTestAlgorithm algo = HadamardTestAlgorithm() result = algo.run(mode='expectation', U=my_U, prepare_psi=my_psi, shots=0) # Explicitly pass shots=0 to get the exact value print(result['Estimated Value'])

Quick Demo

from unitarylab_algorithms.fundamental_algorithm.hadamard_test.algorithm import test test(U=[[1, 0], [0, 1]], psi=[1, 2], shots=0)

Notes

  • .run() and test()/the web frontend have inconsistent shots defaults (20000 vs. 0); if you want reproducible exact results, explicitly pass shots=0.
  • circuit_path is a list rather than a string, unlike other algorithms in this package (HadamardTransformAlgorithm, etc.) — be mindful of this type difference when handling the return value.
  • This module’s __init__.py __all__ exports only 'HadamardTestAlgorithm', not 'test' (even though the test function itself has been imported); therefore from ...hadamard_test import * will not bring in test. If you need the quick-demo function, import it directly from the hadamard_test.algorithm module, as shown in the example above.

Hadamard Transform

Background

The -qubit Hadamard transform applies a Hadamard gate to every qubit simultaneously, mapping the computational basis state to an equal-weight superposition of all basis states (when starting from ). The transform is its own inverse (reflexive).

mode='superposition' generates the superposition state and verifies whether the probability of each basis state is uniform (theoretical value ); mode='reflexive_test' first prepares a random state, applies the Hadamard transform twice in succession, and verifies whether it recovers the original state.

Import

from unitarylab_algorithms import HadamardTransformAlgorithm

.run() Parameters

def run(self, n: int = 3, mode: str = "superposition", backend='torch', device='cpu', dtype=np.complex128) -> Dict[str, Any]
ParameterTypeDefaultDescription
nint3Number of qubits; must be , otherwise raises a ValueError
modestr'superposition''superposition' (generates the superposition state) or 'reflexive_test' (verifies reflexivity); other values raise a ValueError

Return Value

{ 'status': 'ok', # Indicates the transform process has completed 'circuit_path': '/path/to/hadamard_transform_algorithm_circuit.svg', 'plot': [{'format': 'txt', 'filename': 'hadamard_transform_algorithm_result.txt'}], 'circuit': <Circuit>, 'Computation time (s)': 0.0034, 'Probability distribution': {'000': 0.125, '001': 0.125, ...}, # Non-empty only in superposition mode; an empty dict {} in reflexive_test mode 'State vector': array([...]), }

Example

from unitarylab_algorithms import HadamardTransformAlgorithm algo = HadamardTransformAlgorithm() result = algo.run(n=4, mode='superposition') print(result['Probability distribution'])

Quick Demo

from unitarylab_algorithms.fundamental_algorithm.hadamard_transform.algorithm import test test(n=3)

Notes

  • status='ok' indicates the transform process completed. When you need to verify uniformity or reflexivity, check the returned Probability distribution, State vector, or the summary in the result text.
  • When mode='reflexive_test', Probability distribution is always an empty dict {} (this field is only computed in superposition mode) — do not mistake this for an algorithm error.
Last updated on