Quantum Programs (qprog)

The divi.qprog module contains the core quantum programming abstractions for building and executing quantum algorithms.

Overview

The quantum programming module provides a high-level interface for quantum algorithm development, supporting both single-instance problems and large-scale hyperparameter sweeps. At its core is the QuantumProgram abstract base class that defines the common interface for all quantum algorithms.

Core Architecture

Core Classes

class QuantumProgram(backend, seed=None, progress_queue=None, **kwargs)[source]

Bases: ABC

Abstract base class for quantum programs.

This class defines the interface and provides common functionality for quantum algorithms. It handles circuit execution, result processing, and data persistence.

Subclasses must implement:
  • run(): Execute the quantum algorithm

  • _generate_circuits(): Generate quantum circuits for execution

  • _post_process_results(): Process execution results

backend

The quantum circuit execution backend.

Type:

CircuitRunner

_seed

Random seed for reproducible results.

Type:

int | None

_progress_queue

Queue for progress reporting.

Type:

Queue | None

_circuits

List of circuits to be executed.

Type:

list

_curr_service_job_id

Current service job ID for QoroService backends.

Initialize the QuantumProgram.

Parameters:
  • backend (CircuitRunner) – Quantum circuit execution backend.

  • seed (int | None) – Random seed for reproducible results. Defaults to None.

  • progress_queue (Queue | None) – Queue for progress reporting. Defaults to None.

  • **kwargs – Additional keyword arguments for subclasses.

abstract run(data_file=None, **kwargs)[source]

Execute the quantum algorithm.

Parameters:
  • data_file (str | None) – The file to store the data in. If None, no data is stored. Defaults to None.

  • **kwargs – Additional keyword arguments for subclasses.

Returns:

A tuple containing:
  • int: Total number of circuits executed

  • float: Total runtime in seconds

Return type:

tuple[int, float]

property total_circuit_count: int

Get the total number of circuits executed.

Returns:

Cumulative count of circuits submitted for execution.

Return type:

int

property total_run_time: float

Get the total runtime across all circuit executions.

Returns:

Cumulative execution time in seconds.

Return type:

float

save_iteration(data_file)[source]

Save the current state of the quantum program to a file.

Serializes the entire QuantumProgram instance including parameters, losses, and circuit history using pickle.

Parameters:

data_file (str) – Path to the file where the program state will be saved.

Note

The file is written in binary mode and can be restored using import_iteration().

static import_iteration(data_file)[source]

Load a previously saved quantum program state from a file.

Deserializes a QuantumProgram instance that was saved using save_iteration().

Parameters:

data_file (str) – Path to the file containing the saved program state.

Returns:

The restored QuantumProgram instance with all its state,

including parameters, losses, and circuit history.

Return type:

QuantumProgram

class VariationalQuantumAlgorithm(backend, seed=None, progress_queue=None, **kwargs)[source]

Bases: QuantumProgram

Base class for variational quantum algorithms.

This class provides the foundation for implementing variational quantum algorithms in Divi. It handles circuit execution, parameter optimization, and result management for algorithms that optimize parameterized quantum circuits to minimize cost functions.

Variational algorithms work by: 1. Generating parameterized quantum circuits 2. Executing circuits on quantum hardware/simulators 3. Computing expectation values of cost Hamiltonians 4. Using classical optimizers to update parameters 5. Iterating until convergence

_losses_history

History of loss values during optimization.

Type:

list[dict]

_final_params

Final optimized parameters.

Type:

np.ndarray

_best_params

Parameters that achieved the best loss.

Type:

np.ndarray

_best_loss

Best loss achieved during optimization.

Type:

float

_circuits

Generated quantum circuits.

Type:

list[Circuit]

_total_circuit_count

Total number of circuits executed.

Type:

int

_total_run_time

Total execution time in seconds.

Type:

float

_curr_params

Current parameter values.

Type:

np.ndarray

_seed

Random seed for parameter initialization.

Type:

int | None

_rng

Random number generator.

Type:

np.random.Generator

_grad_mode

Whether currently computing gradients.

Type:

bool

_grouping_strategy

Strategy for grouping quantum operations.

Type:

str

_qem_protocol

Quantum error mitigation protocol.

Type:

QEMProtocol

_cancellation_event

Event for graceful termination.

Type:

Event | None

_meta_circuit_factory

Factory for creating MetaCircuit instances.

Type:

callable

Initialize the VariationalQuantumAlgorithm.

This constructor is specifically designed for hybrid quantum-classical variational algorithms. The instance variables n_layers and n_params must be set by subclasses, where: - n_layers is the number of layers in the quantum circuit. - n_params is the number of parameters per layer.

For exotic variational algorithms where these variables may not be applicable, the _initialize_params method should be overridden to set the parameters.

Parameters:
  • backend (CircuitRunner) – Quantum circuit execution backend.

  • seed (int | None) – Random seed for parameter initialization. Defaults to None.

  • progress_queue (Queue | None) – Queue for progress reporting. Defaults to None.

Keyword Arguments:
  • grouping_strategy (str) – Strategy for grouping operations in Pennylane transforms. Options: “default”, “wires”, “qwc”. Defaults to “qwc”.

  • qem_protocol (QEMProtocol | None) – Quantum error mitigation protocol to apply. Defaults to None.

__init__(backend, seed=None, progress_queue=None, **kwargs)[source]

Initialize the VariationalQuantumAlgorithm.

This constructor is specifically designed for hybrid quantum-classical variational algorithms. The instance variables n_layers and n_params must be set by subclasses, where: - n_layers is the number of layers in the quantum circuit. - n_params is the number of parameters per layer.

For exotic variational algorithms where these variables may not be applicable, the _initialize_params method should be overridden to set the parameters.

Parameters:
  • backend (CircuitRunner) – Quantum circuit execution backend.

  • seed (int | None) – Random seed for parameter initialization. Defaults to None.

  • progress_queue (Queue | None) – Queue for progress reporting. Defaults to None.

Keyword Arguments:
  • grouping_strategy (str) – Strategy for grouping operations in Pennylane transforms. Options: “default”, “wires”, “qwc”. Defaults to “qwc”.

  • qem_protocol (QEMProtocol | None) – Quantum error mitigation protocol to apply. Defaults to None.

property total_circuit_count: int

Get the total number of circuits executed.

Returns:

Cumulative count of circuits submitted for execution.

Return type:

int

property total_run_time: float

Get the total runtime across all circuit executions.

Returns:

Cumulative execution time in seconds.

Return type:

float

property meta_circuits

Get the meta-circuit templates used by this program.

Returns:

Dictionary mapping circuit names to their

MetaCircuit templates.

Return type:

dict[str, MetaCircuit]

property n_params

Get the total number of parameters in the quantum circuit.

Returns:

Total number of trainable parameters (n_layers * n_params_per_layer).

Return type:

int

property losses_history: list[dict]

Get a copy of the optimization loss history.

Each entry is a dictionary mapping parameter indices to loss values.

Returns:

Copy of the loss history. Modifications to this list

will not affect the internal state.

Return type:

list[dict]

property final_params: ndarray

Get a copy of the final optimized parameters.

Returns:

Copy of the final parameters. Modifications to this array

will not affect the internal state.

Return type:

np.ndarray

property best_params: ndarray

Get a copy of the parameters that achieved the best (lowest) loss.

Returns:

Copy of the best parameters. Modifications to this array

will not affect the internal state.

Return type:

np.ndarray

property best_loss: float

Get the best loss achieved so far.

Returns:

The best loss achieved so far.

Return type:

float

property best_probs

Get a copy of the probability distribution for the best parameters.

Returns:

A copy of the best probability distribution.

Return type:

dict

property initial_params: ndarray

Get the current initial parameters.

Returns:

Current initial parameters. If not yet initialized,

they will be generated automatically.

Return type:

np.ndarray

get_expected_param_shape()[source]

Get the expected shape for initial parameters.

Returns:

Shape (n_param_sets, n_layers * n_params) that

initial parameters should have for this quantum program.

Return type:

tuple[int, int]

run(data_file=None, **kwargs)[source]

Run the variational quantum algorithm.

The outputs are stored in the algorithm object. Optionally, the data can be stored in a file.

Parameters:
  • data_file (str | None) – The file to store the data in. If None, no data is stored. Defaults to None.

  • **kwargs – Additional keyword arguments for subclasses.

Algorithms

Divi provides implementations of popular quantum algorithms with a focus on scalability and ease of use.

VQE Algorithm

class VQE(hamiltonian=None, molecule=None, n_electrons=None, n_layers=1, ansatz=None, optimizer=None, max_iterations=10, **kwargs)[source]

Bases: VariationalQuantumAlgorithm

Variational Quantum Eigensolver (VQE) implementation.

VQE is a hybrid quantum-classical algorithm used to find the ground state energy of a given Hamiltonian. It works by preparing a parameterized quantum state (ansatz) and optimizing the parameters to minimize the expectation value of the Hamiltonian.

The algorithm can work with either: - A molecular Hamiltonian (for quantum chemistry problems) - A custom Hamiltonian operator

ansatz

The parameterized quantum circuit ansatz.

Type:

Ansatz

n_layers

Number of ansatz layers.

Type:

int

n_qubits

Number of qubits in the system.

Type:

int

n_electrons

Number of electrons (for molecular systems).

Type:

int

cost_hamiltonian

The Hamiltonian to minimize.

Type:

qml.operation.Operator

loss_constant

Constant term extracted from the Hamiltonian.

Type:

float

molecule

The molecule object (if applicable).

Type:

qml.qchem.Molecule

optimizer

Classical optimizer for parameter updates.

Type:

Optimizer

max_iterations

Maximum number of optimization iterations.

Type:

int

current_iteration

Current optimization iteration.

Type:

int

Initialize the VQE problem.

Parameters:
  • hamiltonian (qml.operation.Operator | None) – A Hamiltonian representing the problem. Defaults to None.

  • molecule (qml.qchem.Molecule | None) – The molecule representing the problem. Defaults to None.

  • n_electrons (int | None) – Number of electrons associated with the Hamiltonian. Only needed when a Hamiltonian is given. Defaults to None.

  • n_layers (int) – Number of ansatz layers. Defaults to 1.

  • ansatz (Ansatz | None) – The ansatz to use for the VQE problem. Defaults to HartreeFockAnsatz.

  • optimizer (Optimizer | None) – The optimizer to use. Defaults to MonteCarloOptimizer.

  • max_iterations (int) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the parent class.

__init__(hamiltonian=None, molecule=None, n_electrons=None, n_layers=1, ansatz=None, optimizer=None, max_iterations=10, **kwargs)[source]

Initialize the VQE problem.

Parameters:
  • hamiltonian (qml.operation.Operator | None) – A Hamiltonian representing the problem. Defaults to None.

  • molecule (qml.qchem.Molecule | None) – The molecule representing the problem. Defaults to None.

  • n_electrons (int | None) – Number of electrons associated with the Hamiltonian. Only needed when a Hamiltonian is given. Defaults to None.

  • n_layers (int) – Number of ansatz layers. Defaults to 1.

  • ansatz (Ansatz | None) – The ansatz to use for the VQE problem. Defaults to HartreeFockAnsatz.

  • optimizer (Optimizer | None) – The optimizer to use. Defaults to MonteCarloOptimizer.

  • max_iterations (int) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the parent class.

property n_params

Get the total number of parameters for the VQE ansatz.

Returns:

Total number of parameters (n_params_per_layer * n_layers).

Return type:

int

property eigenstate: ndarray | None

Get the computed eigenstate as a NumPy array.

Returns:

The array of bits of the lowest energy eigenstate,

or None if not computed.

Return type:

np.ndarray | None

QAOA Algorithm

class QAOA(problem, *, graph_problem=None, n_layers=1, initial_state='Recommended', optimizer=None, max_iterations=10, **kwargs)[source]

Bases: VariationalQuantumAlgorithm

Quantum Approximate Optimization Algorithm (QAOA) implementation.

QAOA is a hybrid quantum-classical algorithm designed to solve combinatorial optimization problems. It alternates between applying a cost Hamiltonian (encoding the problem) and a mixer Hamiltonian (enabling exploration).

The algorithm can solve: - Graph problems (MaxCut, Max Clique, etc.) - QUBO (Quadratic Unconstrained Binary Optimization) problems - Quadratic programs (converted to QUBO)

problem

The problem instance to solve.

Type:

GraphProblemTypes | QUBOProblemTypes

graph_problem

The graph problem type (if applicable).

Type:

GraphProblem | None

n_layers

Number of QAOA layers.

Type:

int

n_qubits

Number of qubits required.

Type:

int

cost_hamiltonian

The cost Hamiltonian encoding the problem.

Type:

qml.Hamiltonian

mixer_hamiltonian

The mixer Hamiltonian for exploration.

Type:

qml.Hamiltonian

initial_state

The initial quantum state.

Type:

str

problem_metadata

Additional metadata from problem setup.

Type:

dict | None

loss_constant

Constant term from the problem.

Type:

float

optimizer

Classical optimizer for parameter updates.

Type:

Optimizer

max_iterations

Maximum number of optimization iterations.

Type:

int

current_iteration

Current optimization iteration.

Type:

int

_n_params

Number of parameters per layer (always 2 for QAOA).

Type:

int

_solution_nodes

Solution nodes for graph problems.

Type:

list[int] | None

_solution_bitstring

Solution bitstring for QUBO problems.

Type:

np.ndarray | None

Initialize the QAOA problem.

Parameters:
  • problem (GraphProblemTypes | QUBOProblemTypes) – The problem to solve, can either be a graph or a QUBO. For graph inputs, the graph problem to solve must be provided through the graph_problem variable.

  • graph_problem (GraphProblem | None) – The graph problem to solve. Defaults to None.

  • n_layers (int) – Number of QAOA layers. Defaults to 1.

  • initial_state (_SUPPORTED_INITIAL_STATES_LITERAL) – The initial state of the circuit. Defaults to “Recommended”.

  • optimizer (Optimizer | None) – The optimizer to use. Defaults to MonteCarloOptimizer.

  • max_iterations (int) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the parent class.

__init__(problem, *, graph_problem=None, n_layers=1, initial_state='Recommended', optimizer=None, max_iterations=10, **kwargs)[source]

Initialize the QAOA problem.

Parameters:
  • problem (GraphProblemTypes | QUBOProblemTypes) – The problem to solve, can either be a graph or a QUBO. For graph inputs, the graph problem to solve must be provided through the graph_problem variable.

  • graph_problem (GraphProblem | None) – The graph problem to solve. Defaults to None.

  • n_layers (int) – Number of QAOA layers. Defaults to 1.

  • initial_state (_SUPPORTED_INITIAL_STATES_LITERAL) – The initial state of the circuit. Defaults to “Recommended”.

  • optimizer (Optimizer | None) – The optimizer to use. Defaults to MonteCarloOptimizer.

  • max_iterations (int) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the parent class.

property solution

Get the solution found by QAOA optimization.

Returns:

For graph problems, returns a list of selected node indices.

For QUBO problems, returns a list/array of binary values.

Return type:

list[int] | np.ndarray

draw_solution()[source]

Visualize the solution found by QAOA for graph problems.

Draws the graph with solution nodes highlighted in red and other nodes in light blue. If the solution hasn’t been computed yet, it will be calculated first.

Raises:

RuntimeError – If called on a QUBO problem instead of a graph problem.

Note

This method only works for graph problems. For QUBO problems, access the solution directly via the solution property.

Graph Problem Types

class GraphProblem(pl_string, constrained_initial_state, unconstrained_initial_state)[source]

Enumeration of supported graph problems for QAOA.

Each problem type defines: - pl_string: The corresponding PennyLane function name - constrained_initial_state: Recommended initial state for constrained problems - unconstrained_initial_state: Recommended initial state for unconstrained problems

Initialize the GraphProblem enum value.

Parameters:
  • pl_string (str) – The corresponding PennyLane function name.

  • constrained_initial_state (str) – Recommended initial state for constrained problems.

  • unconstrained_initial_state (str) – Recommended initial state for unconstrained problems.

MAX_CLIQUE = ('max_clique', 'Zeros', 'Superposition')
MAX_INDEPENDENT_SET = ('max_independent_set', 'Zeros', 'Superposition')
MAX_WEIGHT_CYCLE = ('max_weight_cycle', 'Superposition', 'Superposition')
MAXCUT = ('maxcut', 'Superposition', 'Superposition')
MIN_VERTEX_COVER = ('min_vertex_cover', 'Ones', 'Superposition')
EDGE_PARTITIONING = ('', '', '')
__init__(pl_string, constrained_initial_state, unconstrained_initial_state)[source]

Initialize the GraphProblem enum value.

Parameters:
  • pl_string (str) – The corresponding PennyLane function name.

  • constrained_initial_state (str) – Recommended initial state for constrained problems.

  • unconstrained_initial_state (str) – Recommended initial state for unconstrained problems.

VQE Ansatze

class HartreeFockAnsatz[source]

Bases: Ansatz

Hartree-Fock-based ansatz for quantum chemistry.

This ansatz prepares the Hartree-Fock reference state and applies parameterized single and double excitation gates. It’s a simplified alternative to UCCSD, often used as a starting point for VQE calculations.

static n_params_per_layer(n_qubits, n_electrons, **kwargs)[source]

Calculate the number of parameters per layer for Hartree-Fock ansatz.

Parameters:
  • n_qubits (int) – Number of qubits in the circuit.

  • n_electrons (int) – Number of electrons in the system.

  • **kwargs – Additional unused arguments.

Returns:

Number of parameters (number of single + double excitations).

Return type:

int

build(params, n_qubits, n_layers, n_electrons, **kwargs)[source]

Build the Hartree-Fock ansatz circuit.

Parameters:
  • params – Parameter array for excitation amplitudes.

  • n_qubits (int) – Number of qubits.

  • n_layers (int) – Number of ansatz layers.

  • n_electrons (int) – Number of electrons in the system.

  • **kwargs – Additional unused arguments.

class UCCSDAnsatz[source]

Bases: Ansatz

Unitary Coupled Cluster Singles and Doubles (UCCSD) ansatz.

This ansatz is specifically designed for quantum chemistry calculations, implementing the UCCSD approximation which includes all single and double electron excitations from a reference state.

static n_params_per_layer(n_qubits, n_electrons, **kwargs)[source]

Calculate the number of parameters per layer for UCCSD ansatz.

Parameters:
  • n_qubits (int) – Number of qubits in the circuit.

  • n_electrons (int) – Number of electrons in the system.

  • **kwargs – Additional unused arguments.

Returns:

Number of parameters (number of single + double excitations).

Return type:

int

build(params, n_qubits, n_layers, n_electrons, **kwargs)[source]

Build the UCCSD ansatz circuit.

Parameters:
  • params – Parameter array for excitation amplitudes.

  • n_qubits (int) – Number of qubits.

  • n_layers (int) – Number of UCCSD layers (repeats).

  • n_electrons (int) – Number of electrons in the system.

  • **kwargs – Additional unused arguments.

class QAOAAnsatz[source]

Bases: Ansatz

QAOA-style ansatz using PennyLane’s QAOAEmbedding.

Implements a parameterized ansatz based on the Quantum Approximate Optimization Algorithm structure, alternating between problem and mixer Hamiltonians.

static n_params_per_layer(n_qubits, **kwargs)[source]

Calculate the number of parameters per layer for QAOA ansatz.

Parameters:
  • n_qubits (int) – Number of qubits in the circuit.

  • **kwargs – Additional unused arguments.

Returns:

Number of parameters needed per layer.

Return type:

int

build(params, n_qubits, n_layers, **kwargs)[source]

Build the QAOA ansatz circuit.

Parameters:
  • params – Parameter array to use for the ansatz.

  • n_qubits (int) – Number of qubits.

  • n_layers (int) – Number of QAOA layers.

  • **kwargs – Additional unused arguments.

class HardwareEfficientAnsatz[source]

Bases: Ansatz

Hardware-efficient ansatz (not yet implemented).

This ansatz is designed to be easily implementable on near-term quantum hardware, typically using native gate sets and connectivity patterns.

Note

This class is a placeholder for future implementation.

static n_params_per_layer(n_qubits, **kwargs)[source]

Not yet implemented.

Return type:

int

build(params, n_qubits, n_layers, **kwargs)[source]

Not yet implemented.

Return type:

None

class GenericLayerAnsatz(gate_sequence, entangler=None, entangling_layout=None)[source]

Bases: Ansatz

A flexible ansatz alternating single-qubit gates with optional entanglers.

Parameters:
  • gate_sequence (list[Callable]) – List of one-qubit gate classes (e.g., qml.RY, qml.Rot).

  • entangler (Callable) – Two-qubit entangling gate class (e.g., qml.CNOT, qml.CZ). If None, no entanglement is applied.

  • entangling_layout (str) – Layout for entangling layer (“linear”, “all_to_all”, etc.).

__init__(gate_sequence, entangler=None, entangling_layout=None)[source]
Parameters:
  • gate_sequence (list[Callable]) – List of one-qubit gate classes (e.g., qml.RY, qml.Rot).

  • entangler (Callable) – Two-qubit entangling gate class (e.g., qml.CNOT, qml.CZ). If None, no entanglement is applied.

  • entangling_layout (str) – Layout for entangling layer (“linear”, “all_to_all”, etc.).

n_params_per_layer(n_qubits, **kwargs)[source]

Total parameters = sum of gate.num_params per qubit per layer.

Return type:

int

build(params, n_qubits, n_layers, **kwargs)[source]

Builds the ansatz circuit.

Parameters:
  • params (array) – The parameters (weights) for the ansatz.

  • n_qubits (int) – The number of qubits.

  • n_layers (int) – The number of layers.

  • **kwargs – Additional arguments like n_electrons for chemistry ansaetze.

class Ansatz[source]

Bases: ABC

Abstract base class for all VQE ansaetze.

property name: str

Returns the human-readable name of the ansatz.

abstract static n_params_per_layer(n_qubits, **kwargs)[source]

Returns the number of parameters required by the ansatz for one layer.

Return type:

int

abstract build(params, n_qubits, n_layers, **kwargs)[source]

Builds the ansatz circuit.

Parameters:
  • params (array) – The parameters (weights) for the ansatz.

  • n_qubits (int) – The number of qubits.

  • n_layers (int) – The number of layers.

  • **kwargs – Additional arguments like n_electrons for chemistry ansaetze.

Optimizers

Divi provides multiple optimization strategies for quantum algorithm parameter tuning, from classical gradient-based methods to quantum-inspired approaches.

class Optimizer[source]

Bases: ABC

abstract property n_param_sets

Returns the number of parameter sets the optimizer can handle per optimization run. :returns: Number of parameter sets. :rtype: int

abstract optimize(cost_fn, initial_params, callback_fn=None, **kwargs)[source]

Optimize the given cost function starting from initial parameters.

Parameters:
  • cost_fn (Callable[[ndarray], float]) – The cost function to minimize.

  • initial_params (ndarray) – Initial parameters for the optimization.

  • **kwargs – Additional keyword arguments for the optimizer.

Return type:

OptimizeResult

Returns:

Optimized parameters.

class PymooMethod(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

Supported optimization methods from the pymoo library.

CMAES = 'CMAES'
DE = 'DE'
class PymooOptimizer(method, population_size=50, **kwargs)[source]

Bases: Optimizer

Optimizer wrapper for pymoo optimization algorithms.

Supports population-based optimization methods from the pymoo library, including CMAES (Covariance Matrix Adaptation Evolution Strategy) and DE (Differential Evolution).

Initialize a pymoo-based optimizer.

Parameters:
  • method (PymooMethod) – The optimization algorithm to use (CMAES or DE).

  • population_size (int, optional) – Size of the population for the algorithm. Defaults to 50.

  • **kwargs – Additional algorithm-specific parameters passed to pymoo.

__init__(method, population_size=50, **kwargs)[source]

Initialize a pymoo-based optimizer.

Parameters:
  • method (PymooMethod) – The optimization algorithm to use (CMAES or DE).

  • population_size (int, optional) – Size of the population for the algorithm. Defaults to 50.

  • **kwargs – Additional algorithm-specific parameters passed to pymoo.

property n_param_sets

Get the number of parameter sets (population size) used by this optimizer.

Returns:

Population size for the optimization algorithm.

Return type:

int

optimize(cost_fn, initial_params, callback_fn=None, **kwargs)[source]

Run the pymoo optimization algorithm.

Parameters:
  • cost_fn (Callable) – Function to minimize. Should accept a 2D array of parameter sets and return an array of cost values.

  • initial_params (np.ndarray) – Initial parameter values as a 2D array of shape (n_param_sets, n_params).

  • callback_fn (Callable, optional) – Function called after each iteration with an OptimizeResult object. Defaults to None.

  • **kwargs – Additional keyword arguments: - maxiter (int): Maximum number of iterations - rng (np.random.Generator): Random number generator

Returns:

Optimization result with final parameters and cost value.

Return type:

OptimizeResult

class ScipyMethod(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]

Bases: Enum

Supported optimization methods from scipy.optimize.

NELDER_MEAD = 'Nelder-Mead'
COBYLA = 'COBYLA'
L_BFGS_B = 'L-BFGS-B'
class ScipyOptimizer(method)[source]

Bases: Optimizer

Optimizer wrapper for scipy.optimize methods.

Supports gradient-free and gradient-based optimization algorithms from scipy, including Nelder-Mead simplex, COBYLA, and L-BFGS-B.

Initialize a scipy-based optimizer.

Parameters:

method (ScipyMethod) – The optimization algorithm to use.

__init__(method)[source]

Initialize a scipy-based optimizer.

Parameters:

method (ScipyMethod) – The optimization algorithm to use.

property n_param_sets

Get the number of parameter sets used by this optimizer.

Returns:

Always returns 1, as scipy optimizers use single-point optimization.

Return type:

int

optimize(cost_fn, initial_params, callback_fn=None, **kwargs)[source]

Run the scipy optimization algorithm.

Parameters:
  • cost_fn (Callable) – Function to minimize. Should accept a 1D array of parameters and return a scalar cost value.

  • initial_params (np.ndarray) – Initial parameter values as a 1D or 2D array. If 2D with shape (1, n_params), it will be squeezed to 1D.

  • callback_fn (Callable, optional) – Function called after each iteration. Defaults to None.

  • **kwargs – Additional keyword arguments: - maxiter (int): Maximum number of iterations - jac (Callable): Gradient function (only used for L-BFGS-B)

Returns:

Optimization result with final parameters and cost value.

Return type:

OptimizeResult

class MonteCarloOptimizer(n_param_sets=10, n_best_sets=3)[source]

Bases: Optimizer

Monte Carlo-based parameter search optimizer.

This optimizer samples parameter space randomly, selects the best-performing samples, and uses them as centers for the next generation of samples with decreasing variance. This implements a simple but effective evolutionary strategy.

Initialize a Monte Carlo optimizer.

Parameters:
  • n_param_sets (int, optional) – Total number of parameter sets to evaluate per iteration. Defaults to 10.

  • n_best_sets (int, optional) – Number of top-performing parameter sets to use as seeds for the next generation. Defaults to 3.

Raises:

ValueError – If n_best_sets is greater than n_param_sets.

__init__(n_param_sets=10, n_best_sets=3)[source]

Initialize a Monte Carlo optimizer.

Parameters:
  • n_param_sets (int, optional) – Total number of parameter sets to evaluate per iteration. Defaults to 10.

  • n_best_sets (int, optional) – Number of top-performing parameter sets to use as seeds for the next generation. Defaults to 3.

Raises:

ValueError – If n_best_sets is greater than n_param_sets.

property n_param_sets

Get the number of parameter sets evaluated per iteration.

Returns:

Total number of parameter sets.

Return type:

int

property n_best_sets

Get the number of best parameter sets used for seeding the next generation.

Returns:

Number of best-performing sets kept.

Return type:

int

optimize(cost_fn, initial_params, callback_fn=None, **kwargs)[source]

Perform Monte Carlo optimization on the cost function.

Parameters:
Return type:

OptimizeResult

Returns:

Optimized parameters.

Scipy Optimizer

class ScipyOptimizer(method)[source]

Bases: Optimizer

Optimizer wrapper for scipy.optimize methods.

Supports gradient-free and gradient-based optimization algorithms from scipy, including Nelder-Mead simplex, COBYLA, and L-BFGS-B.

Initialize a scipy-based optimizer.

Parameters:

method (ScipyMethod) – The optimization algorithm to use.

__init__(method)[source]

Initialize a scipy-based optimizer.

Parameters:

method (ScipyMethod) – The optimization algorithm to use.

property n_param_sets

Get the number of parameter sets used by this optimizer.

Returns:

Always returns 1, as scipy optimizers use single-point optimization.

Return type:

int

optimize(cost_fn, initial_params, callback_fn=None, **kwargs)[source]

Run the scipy optimization algorithm.

Parameters:
  • cost_fn (Callable) – Function to minimize. Should accept a 1D array of parameters and return a scalar cost value.

  • initial_params (np.ndarray) – Initial parameter values as a 1D or 2D array. If 2D with shape (1, n_params), it will be squeezed to 1D.

  • callback_fn (Callable, optional) – Function called after each iteration. Defaults to None.

  • **kwargs – Additional keyword arguments: - maxiter (int): Maximum number of iterations - jac (Callable): Gradient function (only used for L-BFGS-B)

Returns:

Optimization result with final parameters and cost value.

Return type:

OptimizeResult

Monte Carlo Optimizer

class MonteCarloOptimizer(n_param_sets=10, n_best_sets=3)[source]

Bases: Optimizer

Monte Carlo-based parameter search optimizer.

This optimizer samples parameter space randomly, selects the best-performing samples, and uses them as centers for the next generation of samples with decreasing variance. This implements a simple but effective evolutionary strategy.

Initialize a Monte Carlo optimizer.

Parameters:
  • n_param_sets (int, optional) – Total number of parameter sets to evaluate per iteration. Defaults to 10.

  • n_best_sets (int, optional) – Number of top-performing parameter sets to use as seeds for the next generation. Defaults to 3.

Raises:

ValueError – If n_best_sets is greater than n_param_sets.

__init__(n_param_sets=10, n_best_sets=3)[source]

Initialize a Monte Carlo optimizer.

Parameters:
  • n_param_sets (int, optional) – Total number of parameter sets to evaluate per iteration. Defaults to 10.

  • n_best_sets (int, optional) – Number of top-performing parameter sets to use as seeds for the next generation. Defaults to 3.

Raises:

ValueError – If n_best_sets is greater than n_param_sets.

property n_param_sets

Get the number of parameter sets evaluated per iteration.

Returns:

Total number of parameter sets.

Return type:

int

property n_best_sets

Get the number of best parameter sets used for seeding the next generation.

Returns:

Number of best-performing sets kept.

Return type:

int

optimize(cost_fn, initial_params, callback_fn=None, **kwargs)[source]

Perform Monte Carlo optimization on the cost function.

Parameters:
Return type:

OptimizeResult

Returns:

Optimized parameters.

Workflows

Divi provides workflow classes for managing large-scale quantum computations, including hyperparameter sweeps and graph partitioning.

VQE Hyperparameter Sweep

class VQEHyperparameterSweep(ansatze, molecule_transformer, optimizer=None, max_iterations=10, **kwargs)[source]

Bases: ProgramBatch

Allows user to carry out a grid search across different values for the ansatz and the bond length used in a VQE program.

Initialize a VQE hyperparameter sweep.

Parameters:
  • ansatze (Sequence[Ansatz]) – A sequence of ansatz circuits to test.

  • molecule_transformer (MoleculeTransformer) – A MoleculeTransformer object defining the configuration for generating the molecule variants.

  • optimizer (Optimizer) – The optimization algorithm for the VQE runs.

  • max_iterations (int) – The maximum number of optimizer iterations for each VQE run.

  • **kwargs (Forwarded to parent class.)

__init__(ansatze, molecule_transformer, optimizer=None, max_iterations=10, **kwargs)[source]

Initialize a VQE hyperparameter sweep.

Parameters:
  • ansatze (Sequence[Ansatz]) – A sequence of ansatz circuits to test.

  • molecule_transformer (MoleculeTransformer) – A MoleculeTransformer object defining the configuration for generating the molecule variants.

  • optimizer (Optimizer) – The optimization algorithm for the VQE runs.

  • max_iterations (int) – The maximum number of optimizer iterations for each VQE run.

  • **kwargs (Forwarded to parent class.)

create_programs()[source]

Create VQE programs for all combinations of ansatze and molecule variants.

Generates molecule variants using the configured MoleculeTransformer, then creates a VQE program for each (ansatz, molecule_variant) pair.

Note

Program IDs are tuples of (ansatz_name, bond_modifier_value).

aggregate_results()[source]

Find the best ansatz and bond configuration from all VQE runs.

Compares the final energies across all ansatz/molecule combinations and returns the configuration that achieved the lowest ground state energy.

Returns:

A tuple containing:
  • best_config (tuple): (ansatz_name, bond_modifier) of the best result.

  • best_energy (float): The lowest energy achieved.

Return type:

tuple

Raises:

RuntimeError – If programs haven’t been run or have empty losses.

visualize_results(graph_type='line')[source]

Visualize the results of the VQE problem.

class MoleculeTransformer(base_molecule, bond_modifiers, atom_connectivity=None, bonds_to_transform=None, alignment_atoms=None)[source]

Bases: object

A class for transforming molecular structures by modifying bond lengths.

This class generates variants of a base molecule by adjusting bond lengths according to specified modifiers. The modification mode is detected automatically.

base_molecule

The reference molecule used as a template for generating variants.

Type:

qml.qchem.Molecule

bond_modifiers

A list of values used to adjust bond lengths. The class will generate one new molecule for each modifier in this list. The modification mode is detected automatically: - Scale mode: If all values are positive, they are used as scaling factors (e.g., 1.1 for a 10% increase). - Delta mode: If any value is zero or negative, all values are treated as additive changes to the bond length, in Ångstroms.

Type:

Sequence[float]

atom_connectivity

A sequence of atom index pairs specifying the bonds in the molecule. If not provided, a chain structure will be assumed e.g.: [(0, 1), (1, 2), (2, 3), …].

Type:

Sequence[tuple[int, int]] | None

bonds_to_transform

A subset of atom_connectivity that specifies the bonds to modify. If None, all bonds will be transformed.

Type:

Sequence[tuple[int, int]] | None

alignment_atoms

Indices of atoms onto which to align the orientation of the resulting variants of the molecule. Only useful for visualization and debugging. If None, no alignment is carried out.

Type:

Sequence[int] | None

base_molecule: Molecule
bond_modifiers: Sequence[float]
atom_connectivity: Sequence[tuple[int, int]] | None = None
bonds_to_transform: Sequence[tuple[int, int]] | None = None
alignment_atoms: Sequence[int] | None = None
generate()[source]
Return type:

dict[float, Molecule]

__init__(base_molecule, bond_modifiers, atom_connectivity=None, bonds_to_transform=None, alignment_atoms=None)

Graph Partitioning QAOA

class GraphPartitioningQAOA(graph, graph_problem, n_layers, backend, partitioning_config, initial_state='Recommended', aggregate_fn=<function linear_aggregation>, optimizer=None, max_iterations=10, **kwargs)[source]

Bases: ProgramBatch

Initializes the graph partitioning class.

Parameters:
  • graph (nx.Graph | rx.PyGraph) – The input graph to be partitioned.

  • graph_problem (GraphProblem) – The type of graph partitioning problem (e.g., EDGE_PARTITIONING).

  • n_layers (int) – Number of layers for the QAOA circuit.

  • backend (CircuitRunner) – Backend used to run quantum/classical circuits.

  • partitioning_config (PartitioningConfig) – the configuration of the partitioning as to the algorithm and

  • output. (expected)

  • initial_state ("Zeros", "Ones", "Superposition", "Recommended", optional) – Initial state for the QAOA algorithm. Defaults to “Recommended”.

  • aggregate_fn (optional) – Aggregation function to combine results. Defaults to linear_aggregation.

  • optimizer (optional) – Optimizer to use for QAOA. Defaults to Optimizers.MONTE_CARLO.

  • max_iterations (int, optional) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the QAOA constructor.

__init__(graph, graph_problem, n_layers, backend, partitioning_config, initial_state='Recommended', aggregate_fn=<function linear_aggregation>, optimizer=None, max_iterations=10, **kwargs)[source]

Initializes the graph partitioning class.

Parameters:
  • graph (nx.Graph | rx.PyGraph) – The input graph to be partitioned.

  • graph_problem (GraphProblem) – The type of graph partitioning problem (e.g., EDGE_PARTITIONING).

  • n_layers (int) – Number of layers for the QAOA circuit.

  • backend (CircuitRunner) – Backend used to run quantum/classical circuits.

  • partitioning_config (PartitioningConfig) – the configuration of the partitioning as to the algorithm and

  • output. (expected)

  • initial_state ("Zeros", "Ones", "Superposition", "Recommended", optional) – Initial state for the QAOA algorithm. Defaults to “Recommended”.

  • aggregate_fn (optional) – Aggregation function to combine results. Defaults to linear_aggregation.

  • optimizer (optional) – Optimizer to use for QAOA. Defaults to Optimizers.MONTE_CARLO.

  • max_iterations (int, optional) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the QAOA constructor.

create_programs()[source]

Creates and initializes QAOA programs for each partitioned subgraph.

The main graph is partitioned into node-based subgraphs according to the specified partitioning configuration. Each subgraph is relabeled with integer node labels for QAOA compatibility, and a reverse index map is stored for later result aggregation.

Each program is assigned a unique program ID, which is a tuple of:
  • An uppercase letter (A, B, C, …) corresponding to the partition index.

  • The number of nodes in the subgraph.

Example program ID: (‘A’, 5) for the first partition with 5 nodes.

The created QAOA programs are stored in the self.programs dictionary, keyed by their program IDs.

aggregate_results()[source]

Aggregates the results from all QAOA subprograms to form a global solution.

This method collects the final bitstring solutions from each partitioned subgraph’s QAOA program, using the aggregation function specified at initialization (e.g., linear or dominance aggregation). It reconstructs the global solution by mapping each subgraph’s solution back to the original node indices using the stored reverse index maps.

The final solution is stored in self.solution as a list of node indices assigned to the selected partition.

Raises:

RuntimeError – If no programs exist, if programs have not been run, or if results are incomplete.

Returns:

The list of node indices in the final aggregated solution.

Return type:

list[int]

draw_partitions(pos=None, figsize=(10, 8), node_size=300)[source]

Draw a NetworkX graph with nodes colored by partition.

Parameters:

posdict, optional

Node positions. If None, uses spring layout

figsizetuple, optional

Figure size (width, height)

node_sizeint, optional

Size of nodes

draw_solution()[source]

Visualizes the main graph with nodes highlighted according to the final aggregated solution.

If the solution has not yet been computed, this method calls aggregate_results() to obtain it.

class PartitioningConfig(max_n_nodes_per_cluster=None, minimum_n_clusters=None, partitioning_algorithm='spectral')[source]

Bases: object

Configuration for graph partitioning algorithms.

This class defines the parameters and constraints for partitioning large graphs into smaller subgraphs for quantum algorithm execution. It supports multiple partitioning algorithms and allows specification of size constraints.

max_n_nodes_per_cluster

Maximum number of nodes allowed in each cluster. If None, no upper limit is enforced. Must be a positive integer.

minimum_n_clusters

Minimum number of clusters to create. If None, no lower limit is enforced. Must be a positive integer.

partitioning_algorithm

Algorithm to use for partitioning. Options are: - “spectral”: Spectral partitioning using Fiedler vector (default) - “metis”: METIS graph partitioning library - “kernighan_lin”: Kernighan-Lin algorithm

Note

At least one of max_n_nodes_per_cluster or minimum_n_clusters must be specified. Both constraints cannot be None.

Examples

>>> # Partition into clusters of at most 10 nodes
>>> config = PartitioningConfig(max_n_nodes_per_cluster=10)
>>> # Create at least 5 clusters using METIS
>>> config = PartitioningConfig(
...     minimum_n_clusters=5,
...     partitioning_algorithm="metis"
... )
>>> # Both constraints: clusters of max 8 nodes, min 3 clusters
>>> config = PartitioningConfig(
...     max_n_nodes_per_cluster=8,
...     minimum_n_clusters=3
... )
max_n_nodes_per_cluster: int | None = None
minimum_n_clusters: int | None = None
partitioning_algorithm: Literal['spectral', 'metis', 'kernighan_lin'] = 'spectral'
__init__(max_n_nodes_per_cluster=None, minimum_n_clusters=None, partitioning_algorithm='spectral')

QUBO Partitioning QAOA

class QUBOPartitioningQAOA(qubo, decomposer, n_layers, backend, composer=SplatComposer(), optimizer=None, max_iterations=10, **kwargs)[source]

Bases: ProgramBatch

Initialize a QUBOPartitioningQAOA instance for solving QUBO problems using partitioning and QAOA.

Parameters:
  • qubo (QUBOProblemTypes | BinaryQuadraticModel) – The QUBO problem to solve, provided as a supported type or a BinaryQuadraticModel. Note: Variable types are assumed to be binary (not Spin).

  • decomposer (hybrid.traits.ProblemDecomposer) – The decomposer used to partition the QUBO problem into subproblems.

  • n_layers (int) – Number of QAOA layers to use for each subproblem.

  • backend (CircuitRunner) – Backend responsible for running quantum circuits.

  • composer (hybrid.traits.SubsamplesComposer, optional) – Composer to aggregate subsamples from subproblems. Defaults to hybrid.SplatComposer().

  • optimizer (Optimizer, optional) – Optimizer to use for QAOA. Defaults to Optimizer.MONTE_CARLO.

  • max_iterations (int, optional) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the QAOA constructor.

__init__(qubo, decomposer, n_layers, backend, composer=SplatComposer(), optimizer=None, max_iterations=10, **kwargs)[source]

Initialize a QUBOPartitioningQAOA instance for solving QUBO problems using partitioning and QAOA.

Parameters:
  • qubo (QUBOProblemTypes | BinaryQuadraticModel) – The QUBO problem to solve, provided as a supported type or a BinaryQuadraticModel. Note: Variable types are assumed to be binary (not Spin).

  • decomposer (hybrid.traits.ProblemDecomposer) – The decomposer used to partition the QUBO problem into subproblems.

  • n_layers (int) – Number of QAOA layers to use for each subproblem.

  • backend (CircuitRunner) – Backend responsible for running quantum circuits.

  • composer (hybrid.traits.SubsamplesComposer, optional) – Composer to aggregate subsamples from subproblems. Defaults to hybrid.SplatComposer().

  • optimizer (Optimizer, optional) – Optimizer to use for QAOA. Defaults to Optimizer.MONTE_CARLO.

  • max_iterations (int, optional) – Maximum number of optimization iterations. Defaults to 10.

  • **kwargs – Additional keyword arguments passed to the QAOA constructor.

create_programs()[source]

Partition the main QUBO problem and instantiate QAOA programs for each subproblem.

This implementation: - Uses the configured decomposer to split the main QUBO into subproblems. - For each subproblem, creates a QAOA program with the specified parameters. - Stores each program in self.programs with a unique identifier.

Unique Identifier Format:
Each key in self.programs is a tuple of the form (letter, size), where:
  • letter: An uppercase letter (‘A’, ‘B’, ‘C’, …) indicating the partition index.

  • size: The number of variables in the subproblem.

Example: (‘A’, 5) refers to the first partition with 5 variables.

aggregate_results()[source]

Aggregate results from all QUBO subproblems into a global solution.

Collects solutions from each partitioned subproblem (both QAOA-optimized and trivial ones) and uses the hybrid framework composer to combine them into a final solution for the original QUBO problem.

Returns:

A tuple containing:
  • solution (np.ndarray): Binary solution vector for the QUBO problem.

  • solution_energy (float): Energy/cost of the solution.

Return type:

tuple

Raises:

RuntimeError – If programs haven’t been run or if final probabilities haven’t been computed.

Exceptions

exception _CancelledError[source]

Bases: Exception

Internal exception to signal a task to stop due to cancellation.