quantrs2-device 0.2.0

Quantum device connectors for the QuantRS2 framework
Documentation
//! Variational Quantum Algorithm (VQA) Support - Modular Implementation
//!
//! This module provides comprehensive support for variational quantum algorithms
//! leveraging SciRS2's advanced optimization, statistical analysis, and machine learning capabilities
//! for robust and efficient VQA execution on quantum hardware.
//!
//! The module is organized into focused submodules for maintainability and clarity:
//! - `config`: Configuration structures and enums for all VQA types
//! - `optimization`: Optimization algorithms and strategies
//! - `statistical`: Statistical analysis and validation tools
//! - `hardware`: Hardware-aware optimization and calibration
//! - `noise`: Noise mitigation and error correction
//! - `circuits`: Parametric circuit definitions and execution
//! - `objectives`: Objective function definitions and evaluation
//! - `executor`: Main VQA execution coordinator
//! - `analysis`: Performance analysis and validation

pub mod analysis;
pub mod circuits;
pub mod config;
pub mod executor;
pub mod hardware;
pub mod noise;
pub mod objectives;
pub mod optimization;
pub mod statistical;

// Re-export main types for backward compatibility
pub use analysis::*;
pub use circuits::*;
pub use config::{
    AdaptiveShotConfig, ConvergenceCriterion, GradientMethod, MultiStartConfig, VQAAlgorithmType,
    VQAConfig, VQAHardwareConfig, VQANoiseMitigation, VQAOptimizationConfig, VQAOptimizer,
    VQAStatisticalConfig, VQAValidationConfig,
}; // Selective re-export to avoid VQAResult conflicts
pub use executor::{VQAExecutor, VQAExecutorConfig, VQAResult}; // VQAResult from executor only
pub use hardware::*;
pub use noise::*;
pub use objectives::*;
pub use optimization::*;
pub use statistical::*;

// Convenient type aliases
pub type DeviceResult<T> = crate::DeviceResult<T>;
pub type DeviceError = crate::DeviceError;

// Feature-gated SciRS2 imports (re-exported for use in submodules)
#[cfg(feature = "scirs2")]
pub use scirs2_graph;
#[cfg(feature = "scirs2")]
pub use scirs2_linalg;
#[cfg(feature = "scirs2")]
pub use scirs2_optimize;
#[cfg(feature = "scirs2")]
pub use scirs2_stats;

// Fallback implementations when SciRS2 is not available
#[cfg(not(feature = "scirs2"))]
pub mod fallback_scirs2 {
    use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};

    pub fn mean(_data: &ArrayView1<f64>) -> Result<f64, String> {
        Ok(0.0)
    }
    pub fn std(_data: &ArrayView1<f64>, _ddof: i32) -> Result<f64, String> {
        Ok(1.0)
    }
    pub fn var(_data: &ArrayView1<f64>, _ddof: i32) -> Result<f64, String> {
        Ok(1.0)
    }
    pub fn pearsonr(
        _x: &ArrayView1<f64>,
        _y: &ArrayView1<f64>,
        _alt: &str,
    ) -> Result<(f64, f64), String> {
        Ok((0.0, 0.5))
    }
    pub fn trace(_matrix: &ArrayView2<f64>) -> Result<f64, String> {
        Ok(1.0)
    }
    pub fn inv(_matrix: &ArrayView2<f64>) -> Result<Array2<f64>, String> {
        Ok(Array2::eye(2))
    }

    pub struct OptimizeResult {
        pub x: Array1<f64>,
        pub fun: f64,
        pub success: bool,
        pub nit: usize,
        pub nfev: usize,
        pub message: String,
    }

    pub fn minimize(
        _func: fn(&Array1<f64>) -> f64,
        _x0: &Array1<f64>,
        _method: &str,
    ) -> Result<OptimizeResult, String> {
        Ok(OptimizeResult {
            x: Array1::zeros(2),
            fun: 0.0,
            success: true,
            nit: 0,
            nfev: 0,
            message: "Fallback optimization".to_string(),
        })
    }

    pub fn differential_evolution(
        _func: fn(&Array1<f64>) -> f64,
        _bounds: &[(f64, f64)],
    ) -> Result<OptimizeResult, String> {
        Ok(OptimizeResult {
            x: Array1::zeros(2),
            fun: 0.0,
            success: true,
            nit: 0,
            nfev: 0,
            message: "Fallback optimization".to_string(),
        })
    }
}

#[cfg(not(feature = "scirs2"))]
pub use fallback_scirs2::*;

/// Main VQA execution entry point — synchronous gradient-descent loop.
///
/// Uses the parameter-shift gradient via `objective_function.compute_gradient`
/// with a fixed step size of 0.01. Runs for `config.optimization_config.max_iterations`
/// steps and reports convergence when the objective change falls below `config.optimization_config.convergence_tolerance`.
pub fn execute_vqa(
    config: VQAConfig,
    ansatz: &circuits::ParametricCircuit,
    objective_function: &dyn ObjectiveFunction,
) -> DeviceResult<VQAResult> {
    use scirs2_core::ndarray::Array1;
    use std::time::Instant;

    let max_iter = config.optimization_config.max_iterations;
    let tol = config.optimization_config.convergence_tolerance;
    let step = 0.01_f64;

    let mut params = Array1::from_vec(ansatz.parameters.clone());
    let mut best_value = f64::INFINITY;
    let mut best_params = params.clone();
    let mut history = Vec::with_capacity(max_iter);
    let mut converged = false;
    let start = Instant::now();

    for _ in 0..max_iter {
        let result = objective_function.evaluate(&params)?;
        history.push(result.value);
        if result.value < best_value {
            best_value = result.value;
            best_params = params.clone();
        }
        if history.len() > 1 {
            let prev = history[history.len() - 2];
            if (prev - result.value).abs() < tol {
                converged = true;
                break;
            }
        }
        // Gradient descent step.
        let grad = objective_function.compute_gradient(&params)?;
        params = params - grad * step;
    }

    let statistics = statistical::analyze_convergence(&history);
    Ok(VQAResult {
        optimal_parameters: best_params.to_vec(),
        best_value,
        iterations: history.len(),
        execution_time: start.elapsed(),
        converged,
        statistics,
        history,
    })
}

/// Create VQA configuration for VQE algorithm
pub fn vqe_config() -> VQAConfig {
    VQAConfig::new(VQAAlgorithmType::VQE)
}

/// Create VQA configuration for QAOA algorithm
pub fn qaoa_config(num_layers: usize) -> VQAConfig {
    let mut config = VQAConfig::new(VQAAlgorithmType::QAOA);
    config.optimization_config.max_iterations = num_layers * 100;
    config
}