Core Conceptsο
This guide explains the fundamental concepts and architecture that make Divi work. Understanding these concepts will help you use Divi more effectively and build custom quantum algorithms.
The QuantumProgram Base Classο
All quantum algorithms in Divi inherit from the abstract base class QuantumProgram, which provides a streamlined interface for all quantum programs. Its primary role is to establish a common structure for executing circuits and managing backend communication.
Core Features:
Backend Integration π - Unified interface for simulators and hardware
Execution Lifecycle π - Standardized methods for running programs
Result Handling π - A common structure for processing backend results
Error Handling π‘οΈ - Graceful handling of execution failures
Key Properties:
total_circuit_count- Total circuits executed so fartotal_run_time- Cumulative execution time in seconds
The VariationalQuantumAlgorithm Classο
For algorithms that rely on optimizing parameters, Divi provides the VariationalQuantumAlgorithm class. This is the base class for algorithms like VQE and QAOA, and it extends QuantumProgram with advanced features for optimization and result tracking.
Every variational quantum program in Divi follows a consistent lifecycle:
Initialization π― - Set up your problem and algorithm parameters
Circuit Generation β‘ - Create quantum circuits from your problem specification
Optimization π - Iteratively improve parameters to minimize cost functions
Execution π - Run circuits on quantum backends
Result Processing π - Extract and analyze final results
Hereβs how a typical VQE program flows through this lifecycle:
from divi.qprog import VQE, HartreeFockAnsatz
from divi.backends import ParallelSimulator
# 1. Initialization - Define your quantum problem
vqe = VQE(
molecule=molecule, # Your molecular system
ansatz=HartreeFockAnsatz(), # Quantum circuit template
n_layers=2, # Circuit depth
backend=ParallelSimulator() # Where to run circuits
)
# 2. Circuit Generation - Automatically creates circuits
# (happens internally during run())
# 3. Optimization - Iteratively improve parameters
vqe.run() # This handles steps 2-5 automatically!
# 4. Execution & 5. Result Processing - All done!
print(f"Ground state energy: {vqe.best_loss:.6f}")
Key Features:
Parameter Management βοΈ - Automatic initialization and validation of parameters
Optimization Loop π - Built-in integration with classical optimizers
Loss Tracking π - Detailed history of loss values during optimization
Best Result Storage πΎ - Automatic tracking of the best parameters and loss value found
Key Properties:
losses_history- History of loss values from each optimization iterationinitial_params- The starting parameters for the optimization. These allow you to set custom initial parameters for the optimization.final_params- The last set of parameters from the optimizationbest_params- The parameters that achieved the lowest lossbest_loss- The best loss value recorded during the run
Advanced Usage:
# Access execution statistics
print(f"Circuits executed: {vqe.total_circuit_count}")
print(f"Total runtime: {vqe.total_run_time:.2f}s")
# Examine optimization history
for i, loss_dict in enumerate(vqe.losses_history):
best_loss_in_iter = min(loss_dict.values())
print(f"Iteration {i}: {best_loss_in_iter:.6f}")
# Get the best parameters found during optimization
best_params = vqe.best_params
Circuit Architectureο
Divi uses a two-tier circuit system for maximum efficiency:
- MetaCircuit ποΈ
Symbolic circuit templates with parameters that can be instantiated multiple times:
from divi.circuits import MetaCircuit import pennylane as qml import sympy as sp # Define symbolic parameters params = sp.symarray("theta", 3) # Create parameterized circuit with qml.tape.QuantumTape() as tape: qml.RY(params[0], wires=0) qml.RX(params[1], wires=1) qml.CNOT(wires=[0, 1]) qml.RY(params[2], wires=0) qml.expval(qml.PauliZ(0)) # Create reusable template meta_circuit = MetaCircuit(tape, params) # Generate specific circuits circuit1 = meta_circuit.initialize_circuit_from_params([0.1, 0.2, 0.3]) circuit2 = meta_circuit.initialize_circuit_from_params([0.4, 0.5, 0.6])
- Circuit β‘
Concrete circuit instances with specific parameter values and QASM representations:
# Each Circuit contains: print(f"Circuit ID: {circuit1.circuit_id}") print(f"Tags: {circuit1.tags}") print(f"QASM circuits: {len(circuit1.qasm_circuits)}") # Access the underlying PennyLane circuit pl_circuit = circuit1.main_circuit
Backend Abstractionο
Diviβs backend system provides a unified interface for different execution environments:
- CircuitRunner Interface π―
All backends implement this common interface:
class MyCustomBackend(CircuitRunner): def submit_circuits(self, circuits: dict[str, str]) -> Any: # Your custom execution logic here pass
Available Backends:
ParallelSimulator π» - Local high-performance simulator
QoroService βοΈ - Cloud quantum computing service
Backend Selection:
# For development and testing
backend = ParallelSimulator(
shots=1000, # Measurement precision
n_processes=4 # Parallel execution
)
# For production and real hardware
backend = QoroService(
auth_token="your-api-key", # From environment or .env
shots=1000
)
# Use the same quantum program with either backend!
vqe = VQE(molecule=molecule, backend=backend)
Parameter Managementο
Divi handles parameter optimization automatically, but you can also set custom initial parameters:
- Automatic Initialization β‘
Parameters are randomly initialized between 0 and 2Ο:
vqe = VQE(molecule=molecule, n_layers=2) print(f"Parameters per layer: {vqe.n_params}") print(f"Total parameters: {vqe.n_params * vqe.n_layers}") # Access current parameters initial_params = vqe.initial_params print(f"Shape: {initial_params.shape}") # (n_sets, total_params)
- Custom Initial Parameters π―
Set specific starting points for better convergence:
import numpy as np # Set custom initial parameters custom_params = np.array([[0.1, 0.2, 0.3, 0.4, 0.5, 0.6]]) vqe.initial_params = custom_params # Verify the shape matches expectations expected_shape = vqe.get_expected_param_shape() print(f"Expected shape: {expected_shape}")
- Parameter Validation β
Divi validates parameter shapes automatically:
try: vqe.initial_params = np.array([[1, 2, 3]]) # Wrong shape except ValueError as e: print(f"Validation error: {e}") # "Initial parameters must have shape (1, 6), got (1, 3)"
Result Processingο
After execution, Divi provides rich result analysis capabilities:
- Loss History π
Track optimization progress over time:
# Plot convergence import matplotlib.pyplot as plt losses = [min(loss_dict.values()) for loss_dict in vqe.losses_history] plt.plot(losses) plt.xlabel('Iteration') plt.ylabel('Energy (Hartree)') plt.title('VQE Convergence') plt.show()
- Performance Metrics β‘
Monitor execution efficiency:
print(f"Total circuits: {vqe.total_circuit_count}") print(f"Total runtime: {vqe.total_run_time:.2f}s") print(f"Average time per circuit: {vqe.total_run_time / vqe.total_circuit_count:.3f}s")
Next Stepsο
π Algorithms: Learn about specific algorithms in VQE and QAOA
β‘ Backends: Explore execution options in Backends Guide
π οΈ Customization: Create custom algorithms using the Quantum Programs (qprog)
π‘ Examples: See practical applications in the Tutorials section
Understanding these core concepts will help you leverage Diviβs full power for your quantum computing projects!