Quantum Machine Learning API

Complete API documentation for the QML module (v0.4.0).

Parameterized Gates

Parameterized Quantum Gates

Gates with trainable parameters for variational quantum algorithms.

class quantum_debugger.qml.gates.parameterized.ParameterizedGate(target: int, parameter: float, trainable: bool = True, name: str = 'Param')[source]

Bases: object

Base class for parameterized quantum gates.

A parameterized gate is a quantum gate whose operation depends on one or more continuous parameters (e.g., rotation angles). These gates are the foundation of variational quantum algorithms like VQE and QAOA.

target

Index of the qubit this gate acts on

Type:

int

parameter

The parameter value (e.g., rotation angle)

Type:

float

trainable

Whether this parameter should be optimized during training

Type:

bool

gradient

Stored gradient value for optimization

Type:

float

name

Name of the gate (e.g., “RX”, “RY”, “RZ”)

Type:

str

Examples

>>> from quantum_debugger.qml import RXGate
>>> import numpy as np
>>>
>>> # Create a trainable RX gate
>>> rx = RXGate(target=0, parameter=np.pi/4, trainable=True)
>>>
>>> # Get the unitary matrix
>>> U = rx.matrix()
>>>
>>> # Update the parameter
>>> rx.parameter = np.pi/2
>>>
>>> # Store gradient from optimizer
>>> rx.gradient = 0.123
matrix() → ndarray[source]

Return the unitary matrix for this gate.

Returns:

2x2 complex numpy array representing the gate’s unitary matrix

class quantum_debugger.qml.gates.parameterized.RXGate(target: int, parameter: float, trainable: bool = True)[source]

Bases: ParameterizedGate

Rotation gate around the X-axis.

The RX gate performs a rotation around the X-axis of the Bloch sphere.

Matrix representation:
RX(θ) = cos(θ/2) * I - i*sin(θ/2) * X
= [[cos(θ/2), -i*sin(θ/2)],

[-i*sin(θ/2), cos(θ/2) ]]

Examples

>>> rx = RXGate(target=0, parameter=np.pi)
>>> U = rx.matrix()
>>> # RX(π) = -iX (Pauli X with phase)
matrix() → ndarray[source]

Compute RX rotation matrix.

class quantum_debugger.qml.gates.parameterized.RYGate(target: int, parameter: float, trainable: bool = True)[source]

Bases: ParameterizedGate

Rotation gate around the Y-axis.

The RY gate performs a rotation around the Y-axis of the Bloch sphere.

Matrix representation:
RY(θ) = cos(θ/2) * I - i*sin(θ/2) * Y
= [[cos(θ/2), -sin(θ/2)],

[sin(θ/2), cos(θ/2)]]

Examples

>>> ry = RYGate(target=0, parameter=np.pi/2)
>>> U = ry.matrix()
>>> # Creates superposition (|0⟩ + |1⟩)/√2
matrix() → ndarray[source]

Compute RY rotation matrix.

class quantum_debugger.qml.gates.parameterized.RZGate(target: int, parameter: float, trainable: bool = True)[source]

Bases: ParameterizedGate

Rotation gate around the Z-axis.

The RZ gate performs a rotation around the Z-axis of the Bloch sphere. This is a phase gate that adds relative phase between |0> and |1>.

Matrix representation:
RZ(θ) = [[e^(-iθ/2), 0 ],

[ 0, e^(iθ/2) ]]

Examples

>>> rz = RZGate(target=0, parameter=np.pi/2)
>>> U = rz.matrix()
>>> # RZ(π/2) is the S gate
matrix() → ndarray[source]

Compute RZ rotation matrix.

VQE Algorithm

VQE (Variational Quantum Eigensolver)

Find ground state energies of molecules using variational principles.

class quantum_debugger.qml.algorithms.vqe.VQE(hamiltonian, ansatz_builder: Callable, num_qubits: int, optimizer: str = 'COBYLA', max_iterations: int = 100)[source]

Bases: object

Variational Quantum Eigensolver

Finds the ground state energy of a Hamiltonian using a parameterized quantum circuit (ansatz) and classical optimization.

cost_function(params: ndarray) → float[source]

Compute energy expectation value.

E(θ) = ⟨ψ(θ)|H|ψ(θ)⟩

exact_ground_state() → float[source]

Compute exact ground state energy by diagonalization.

run(initial_params: ndarray, method: str | None = None) → Dict[source]

Run VQE optimization.

QAOA Algorithm

QAOA (Quantum Approximate Optimization Algorithm)

Solve combinatorial optimization problems.

class quantum_debugger.qml.algorithms.qaoa.QAOA(graph: List[Tuple[int, int]], p: int = 1, optimizer: str = 'COBYLA', max_iterations: int = 100)[source]

Bases: object

Quantum Approximate Optimization Algorithm

Solves combinatorial optimization problems like MaxCut using a parameterized quantum circuit.

graph

List of edges [(i,j), …] defining the problem

p

Number of QAOA layers

num_qubits

Number of qubits (nodes in graph)

Examples

>>> # MaxCut on a square graph
>>> graph = [(0,1), (1,2), (2,3), (3,0)]
>>> qaoa = QAOA(graph=graph, p=2)
>>> result = qaoa.run()
>>> print(f"Best cut value: {result['best_value']}")
cost_function(params: ndarray) → float[source]

Compute cost function (negative for maximization).

For MaxCut: maximize number of edges between different partitions.

Parameters:

params – Parameters [γ₀, γ₁, …, γₚ, β₀, β₁, …, βₚ]

Returns:

Negative cost value (for minimization)

run(initial_params: ndarray | None = None) → Dict[source]

Run QAOA optimization.

Parameters:

initial_params – Starting parameters (optional)

Returns:

Result dictionary

Optimizers

Optimizers module for quantum machine learning

class quantum_debugger.qml.optimizers.Adam(learning_rate: float = 0.01, beta1: float = 0.9, beta2: float = 0.999, epsilon: float = 1e-08)[source]

Bases: object

Adam optimizer.

Adaptive Moment Estimation (Adam) computes adaptive learning rates for each parameter.

step(params: ndarray, gradients: ndarray) → ndarray[source]

Perform one Adam optimization step.

Parameters:
  • params – Current parameters

  • gradients – Gradient vector

Returns:

Updated parameters

class quantum_debugger.qml.optimizers.COBYLAOptimizer(max_iterations: int = 1000, tolerance: float = 1e-06)[source]

Bases: object

COBYLA optimizer (Constrained Optimization BY Linear Approximation).

Gradient-free optimizer that supports constraints. Already exists in the codebase, included here for completeness.

minimize(cost_function: Callable, initial_params: ndarray, constraints: list | None = None, **kwargs) → Dict[str, Any][source]

Minimize using COBYLA.

Parameters:
  • cost_function – Function to minimize

  • initial_params – Starting parameters

  • constraints – Optional constraints

  • **kwargs – Additional arguments

Returns:

Optimization result

class quantum_debugger.qml.optimizers.GradientDescent(learning_rate: float = 0.01)[source]

Bases: object

Vanilla Gradient Descent optimizer.

step(params: ndarray, gradients: ndarray) → ndarray[source]

Perform one optimization step.

Parameters:
  • params – Current parameters

  • gradients – Gradient vector

Returns:

Updated parameters

class quantum_debugger.qml.optimizers.LBFGSBOptimizer(max_iterations: int = 1000, tolerance: float = 1e-06, bounds: list | None = None)[source]

Bases: object

L-BFGS-B optimizer (Limited-memory BFGS with bounds).

Quasi-Newton method that’s memory-efficient and supports bound constraints. Excellent for medium-scale optimization problems.

minimize(cost_function: Callable, initial_params: ndarray, gradient_function: Callable | None = None, **kwargs) → Dict[str, Any][source]

Minimize cost function using L-BFGS-B.

Parameters:
  • cost_function – Function to minimize

  • initial_params – Starting parameters

  • gradient_function – Optional gradient function (computed if None)

  • **kwargs – Additional arguments

Returns:

Optimization result dictionary

class quantum_debugger.qml.optimizers.NelderMeadOptimizer(max_iterations: int = 1000, tolerance: float = 1e-06)[source]

Bases: object

Nelder-Mead simplex optimizer.

Gradient-free optimization using simplex method. Good for noisy cost functions and when gradients are unavailable.

minimize(cost_function: Callable, initial_params: ndarray, **kwargs) → Dict[str, Any][source]

Minimize cost function using Nelder-Mead.

Parameters:
  • cost_function – Function to minimize

  • initial_params – Starting parameters

  • **kwargs – Additional arguments for scipy.optimize.minimize

Returns:

Optimization result dictionary

class quantum_debugger.qml.optimizers.QuantumNaturalGradient(learning_rate: float = 0.01, epsilon: float = 1e-08)[source]

Bases: object

Quantum Natural Gradient optimizer.

Uses the quantum Fisher information metric to precondition gradients, leading to faster convergence in quantum optimization landscapes.

Reference: Stokes et al., “Quantum Natural Gradient”, Quantum 4, 269 (2020)

compute_metric_tensor(circuit_fn: Callable, params: ndarray, shift: float = 0.0001) → ndarray[source]

Compute the Fubini-Study metric tensor (quantum geometric tensor, real part).

g_ij = Re[<d_i psi | d_j psi> - <d_i psi | psi><psi | d_j psi>]

where |psi(theta)> = circuit_fn(theta) must return the state vector. The derivative states are obtained by central finite differences. When circuit_fn does not return a usable state vector (e.g. returns None), the metric cannot be computed and we fall back to the identity (equivalent to plain gradient descent) rather than returning a fabricated value.

Parameters:
  • circuit_fn – Function mapping parameters -> state vector (np.ndarray)

  • params – Current parameters

  • shift – Finite-difference step for the derivative states

Returns:

Metric tensor (n x n), symmetric positive semidefinite (+ epsilon I)

step(params: ndarray, gradient: ndarray, circuit_fn: Callable | None = None) → ndarray[source]

Perform one optimization step.

Parameters:
  • params – Current parameters

  • gradient – Gradient vector

  • circuit_fn – Circuit function (for metric computation)

Returns:

Updated parameters

class quantum_debugger.qml.optimizers.SPSA(a: float = 0.2, c: float = 0.1, alpha: float = 0.602, gamma: float = 0.101, A: float = None, maxiter: int = 200, seed: int = None)[source]

Bases: object

SPSA optimizer with the standard gain sequences.

a_k = a / (k + 1 + A)**alpha , c_k = c / (k + 1)**gamma

Examples

>>> opt = SPSA(a=0.2, c=0.1, maxiter=200)
>>> result = opt.minimize(lambda x: (x[0] - 3) ** 2 + (x[1] + 1) ** 2, [0.0, 0.0])
>>> result["x"]        # ~[3, -1]
minimize(objective, x0, iterations: int = None) → dict[source]

Minimize objective starting from x0.

Returns:

dict with ‘x’ (best params), ‘fun’ (best value), and ‘history’.

step(objective, params: ndarray, k: int) → ndarray[source]

One SPSA update from params at iteration k (2 evaluations).

quantum_debugger.qml.optimizers.compare_optimizers(cost_function: Callable, initial_params: ndarray, optimizers: list, **kwargs) → Dict[str, Any][source]

Compare multiple optimizers on the same problem.

Parameters:
  • cost_function – Function to minimize

  • initial_params – Starting point

  • optimizers – List of optimizer names or instances

  • **kwargs – Additional arguments

Returns:

Comparison results

Example

>>> results = compare_optimizers(
...     cost_fn,
...     params,
...     ['adam', 'lbfgs', 'nelder-mead']
... )
quantum_debugger.qml.optimizers.get_optimizer(name: str, **kwargs)[source]

Factory function to get optimizer by name.

Parameters:
  • name – Optimizer name (‘qng’, ‘nelder-mead’, ‘lbfgs’, ‘cobyla’)

  • **kwargs – Optimizer-specific parameters

Returns:

Optimizer instance

Example

>>> opt = get_optimizer('lbfgs', max_iterations=500)
>>> result = opt.minimize(cost_fn, initial_params)

Training Framework

Quantum Training Module

Training loops and utilities for quantum machine learning.

class quantum_debugger.qml.training.QuantumTrainer(circuit_builder: Callable, cost_function: Callable, optimizer: str = 'adam', learning_rate: float = 0.01, gradient_method: str = 'parameter_shift')[source]

Bases: object

Training framework for parameterized quantum circuits.

Handles the training loop, gradient computation, optimization, and tracking of training metrics.

Examples

>>> from quantum_debugger.qml.training import QuantumTrainer
>>>
>>> def circuit(params): ...
>>> def cost(circuit): ...
>>>
>>> trainer = QuantumTrainer(
...     circuit_builder=circuit,
...     cost_function=cost,
...     optimizer='adam',
...     learning_rate=0.01
... )
>>> result = trainer.train(initial_params, epochs=100)
get_gradient_norms() → List[float][source]

Get list of gradient norms from training

get_loss_history() → List[float][source]

Get list of loss values from training history

train(initial_params: ndarray, epochs: int = 100, callback: Callable | None = None, verbose: bool = True) → Dict[source]

Train the quantum circuit.

Parameters:
  • initial_params – Starting parameter values

  • epochs – Number of training epochs

  • callback – Optional callback function(epoch, loss, params)

  • verbose – Print progress

Returns:

Training results dictionary

Hamiltonians

Molecular Hamiltonians for Quantum Chemistry

Provides pre-computed Hamiltonians for common molecules used in VQE.

quantum_debugger.qml.hamiltonians.molecular.beh2_hamiltonian(bond_length: float = 1.33) → Tuple[ndarray, float][source]

Beryllium Hydride (BeH2) Hamiltonian.

Linear molecule: H-Be-H Requires 5 qubits for minimal basis representation.

Parameters:

bond_length – Be-H bond length in Angstroms (default: 1.33 Å)

Returns:

(hamiltonian_matrix, nuclear_repulsion_energy)

Example

>>> H, E_nuc = beh2_hamiltonian()
>>> print(H.shape)
(32, 32)
quantum_debugger.qml.hamiltonians.molecular.get_ground_state_energy(molecule: str, **kwargs) → float[source]

Get the exact ground state energy for a molecule (for comparison).

Parameters:
  • molecule – Molecule name

  • **kwargs – Molecule parameters

Returns:

Ground state energy (eigenvalue of Hamiltonian + nuclear repulsion)

quantum_debugger.qml.hamiltonians.molecular.get_molecule_hamiltonian(molecule: str, **kwargs) → Tuple[ndarray, float][source]

Factory function to get molecular Hamiltonian by name.

Parameters:
  • molecule – Molecule name (‘H2’, ‘LiH’, ‘H2O’, ‘BeH2’)

  • **kwargs – Molecule-specific parameters (bond_length, angle, etc.)

Returns:

(hamiltonian_matrix, nuclear_repulsion_energy)

Example

>>> H, E_nuc = get_molecule_hamiltonian('H2', bond_length=0.74)
>>> H_lih, E_nuc_lih = get_molecule_hamiltonian('LiH')
quantum_debugger.qml.hamiltonians.molecular.get_molecule_info(molecule: str) → Dict[str, any][source]

Get information about a molecule.

Parameters:

molecule – Molecule name

Returns:

Dictionary with molecule information

quantum_debugger.qml.hamiltonians.molecular.h2_hamiltonian(bond_length: float = 0.735) → Tuple[ndarray, float][source]

Hydrogen molecule (H2) Hamiltonian.

Parameters:

bond_length – H-H bond length in Angstroms (default: 0.735 Å)

Returns:

(hamiltonian_matrix, nuclear_repulsion_energy)

Example

>>> H, E_nuc = h2_hamiltonian(0.735)
>>> print(H.shape)
(4, 4)
quantum_debugger.qml.hamiltonians.molecular.h2o_hamiltonian(angle: float = 104.5) → Tuple[ndarray, float][source]

Water molecule (H2O) Hamiltonian.

H2O is more complex with 3 atoms. This uses a minimal basis set. Requires 6 qubits for proper representation.

Parameters:

angle – H-O-H bond angle in degrees (default: 104.5° equilibrium)

Returns:

(hamiltonian_matrix, nuclear_repulsion_energy)

Example

>>> H, E_nuc = h2o_hamiltonian()
>>> print(H.shape)
(64, 64)
quantum_debugger.qml.hamiltonians.molecular.lih_hamiltonian(bond_length: float = 1.546) → Tuple[ndarray, float][source]

Lithium Hydride (LiH) Hamiltonian.

More complex than H2, requires 4 qubits (8 spin orbitals mapped to 4 qubits).

Parameters:

bond_length – Li-H bond length in Angstroms (default: 1.546 Å equilibrium)

Returns:

(hamiltonian_matrix, nuclear_repulsion_energy)

Example

>>> H, E_nuc = lih_hamiltonian()
>>> print(H.shape)
(16, 16)

Ansatz Library

Ansatz module for variational quantum circuits

Provides various ansatz (trial wavefunctions) for VQE and QAOA.

quantum_debugger.qml.ansatz.excitation_preserving(num_qubits: int, reps: int = 1, entanglement: str = 'linear', skip_final_rotation: bool = False) → Callable[source]

Create an ExcitationPreserving ansatz.

This ansatz preserves the total number of excitations (number of |1> states). It uses RZ rotations and special two-qubit gates that preserve excitation number.

Useful for: - Molecular simulations (particle number conservation) - VQE for fermionic systems - Chemistry applications

Parameters:
  • num_qubits – Number of qubits

  • reps – Number of repetitions

  • entanglement – Connection pattern (‘linear’, ‘full’, ‘circular’)

  • skip_final_rotation – If True, skip last rotation layer

Returns:

Function that builds circuit with parameters

Example

>>> # For H2 molecule (2 electrons, 4 orbitals)
>>> ansatz = excitation_preserving(num_qubits=4, reps=2)
>>> circuit = ansatz(params)
quantum_debugger.qml.ansatz.hardware_efficient_ansatz(num_qubits: int, depth: int = 0)[source]

Hardware-efficient ansatz with RY rotations and CNOT entanglement

Parameters:
  • num_qubits – Number of qubits

  • depth – Circuit depth (number of layers)

quantum_debugger.qml.ansatz.real_amplitudes(num_qubits: int, reps: int = 1, entanglement: str = 'linear') → Callable[source]

Create a RealAmplitudes ansatz circuit.

This ansatz uses RY rotation gates exclusively, which means the resulting state vector will have only real-valued amplitudes (no imaginary components).

Parameters:
  • num_qubits – Number of qubits

  • reps – Number of repetitions of the structure

  • entanglement – Entanglement pattern: - ‘linear’: Linear chain (0-1, 1-2, 2-3, …) - ‘full’: All-to-all connections - ‘circular’: Circular chain (includes last-to-first)

Returns:

Function that builds the circuit with given parameters

Example

>>> ansatz = real_amplitudes(num_qubits=3, reps=2)
>>> circuit = ansatz(params)  # params is array of angles
quantum_debugger.qml.ansatz.strongly_entangling(num_qubits: int, reps: int = 1) → Callable[source]

Create a StronglyEntangling ansatz.

This ansatz creates highly entangled states through: 1. Arbitrary single-qubit rotations (RX, RY, RZ on each qubit) 2. Circular CNOT entanglement (each qubit entangled with next)

Produces very expressive circuits capable of representing a large variety of quantum states.

Parameters:
  • num_qubits – Number of qubits

  • reps – Number of repetitions (layers)

Returns:

Function that builds circuit with parameters

Example

>>> ansatz = strongly_entangling(num_qubits=4, reps=3)
>>> # Requires 4*3*3 = 36 parameters for 3 reps
>>> params = np.random.uniform(0, 2*np.pi, 36)
>>> circuit = ansatz(params)
quantum_debugger.qml.ansatz.two_local(num_qubits: int, rotation_blocks: str | List[str] = 'ry', entanglement_blocks: str = 'cnot', entanglement: str = 'linear', reps: int = 1) → Callable[source]

Create a highly customizable TwoLocal ansatz.

This ansatz alternates between rotation layers (single-qubit gates) and entanglement layers (two-qubit gates), allowing full customization.

Parameters:
  • num_qubits – Number of qubits

  • rotation_blocks – Single-qubit gates to use. Can be: - Single gate: ‘ry’, ‘rz’, ‘rx’ - List of gates: [‘ry’, ‘rz’] (alternates between them)

  • entanglement_blocks – Two-qubit gate to use: - ‘cnot’: CNOT gates - ‘cz’: CZ gates - ‘swap’: SWAP gates

  • entanglement – Connection pattern: - ‘linear’: Chain 0-1, 1-2, 2-3, … - ‘full’: All-to-all - ‘circular’: Ring with wrap-around

  • reps – Number of repetitions

Returns:

Function that builds circuit with given parameters

Example

>>> # Simple RY + CNOT ansatz
>>> ansatz = two_local(3, rotation_blocks='ry', reps=2)
>>>
>>> # Mixed rotations
>>> ansatz = two_local(3, rotation_blocks=['ry', 'rz'], reps=2)

Gradient Utilities

Gradient Computation Utilities

Methods for computing gradients of quantum circuits.

quantum_debugger.qml.utils.gradients.compute_gradients(circuit_builder: Callable, cost_function: Callable, params: ndarray, method: str = 'parameter_shift') → ndarray[source]

Compute all gradients for a parameter vector.

Parameters:
  • circuit_builder – Circuit builder function

  • cost_function – Cost function

  • params – Parameters

  • method – ‘parameter_shift’ or ‘finite_difference’

Returns:

Gradient vector ∇f

quantum_debugger.qml.utils.gradients.finite_difference_gradient(cost_function: Callable, params: ndarray, param_index: int, epsilon: float = 1e-07) → float[source]

Compute gradient using finite differences.

∂f/∂θ ≈ [f(θ + ε) - f(θ)] / ε

Less accurate than parameter shift but works for any function.

Parameters:
  • cost_function – Function to differentiate

  • params – Current parameters

  • param_index – Parameter to differentiate

  • epsilon – Small perturbation

Returns:

Approximate gradient

quantum_debugger.qml.utils.gradients.gradient_descent_step(params: ndarray, gradients: ndarray, learning_rate: float) → ndarray[source]

Perform one gradient descent step.

θ_new = θ_old - η * ∇f

Parameters:
  • params – Current parameters

  • gradients – Gradient vector

  • learning_rate – Step size η

Returns:

Updated parameters

quantum_debugger.qml.utils.gradients.parameter_shift_gradient(circuit_builder: Callable, cost_function: Callable, params: ndarray, param_index: int, shift: float = 1.5707963267948966) → float[source]

Compute gradient using parameter shift rule.

For a gate U(θ) = exp(-iθG/2), the gradient is: ∂f/∂θ = [f(θ + π/2) - f(θ - π/2)] / 2

where f is the cost function.

Parameters:
  • circuit_builder – Function that builds circuit from parameters

  • cost_function – Function that evaluates cost from circuit

  • params – Current parameter values

  • param_index – Index of parameter to differentiate

  • shift – Shift amount (default π/2 for standard gates)

Returns:

Gradient value ∂f/∂θᵢ

Examples

>>> def circuit(p): return build_circuit(p)
>>> def cost(c): return evaluate_energy(c)
>>> grad = parameter_shift_gradient(circuit, cost, params, 0)