quantrs2_core/
linalg_stubs.rs

1//! Temporary linear algebra stubs to replace scirs2_linalg types
2//! TODO: Replace with scirs2_linalg when regex dependency issue is fixed
3
4use crate::error::QuantRS2Result;
5use scirs2_core::ndarray::{Array1, Array2, ArrayView2};
6use scirs2_core::Complex64;
7
8/// Sparse CSR matrix stub
9#[derive(Debug, Clone)]
10pub struct CsrMatrix<T> {
11    pub data: Vec<T>,
12    pub indices: Vec<usize>,
13    pub indptr: Vec<usize>,
14    pub shape: (usize, usize),
15}
16
17impl<T: Clone + Default> CsrMatrix<T> {
18    pub fn zeros(shape: (usize, usize)) -> Self {
19        Self {
20            data: Vec::new(),
21            indices: Vec::new(),
22            indptr: vec![0; shape.0 + 1],
23            shape,
24        }
25    }
26
27    pub fn new(
28        data: Vec<T>,
29        indices: Vec<usize>,
30        indptr: Vec<usize>,
31        shape: (usize, usize),
32    ) -> Result<Self, String> {
33        Ok(Self {
34            data,
35            indices,
36            indptr,
37            shape,
38        })
39    }
40
41    pub fn shape(&self) -> (usize, usize) {
42        self.shape
43    }
44
45    pub fn nnz(&self) -> usize {
46        self.data.len()
47    }
48}
49
50impl CsrMatrix<Complex64> {
51    pub fn to_dense(&self) -> Array2<Complex64> {
52        let (rows, cols) = self.shape;
53        let mut dense = Array2::zeros((rows, cols));
54
55        for row in 0..rows {
56            let start = self.indptr[row];
57            let end = self.indptr[row + 1];
58
59            for idx in start..end {
60                let col = self.indices[idx];
61                let val = self.data[idx];
62                dense[(row, col)] = val;
63            }
64        }
65
66        dense
67    }
68}
69
70/// SVD result
71pub struct SvdResult {
72    pub u: Array2<f64>,
73    pub s: Array1<f64>,
74    pub vt: Array2<f64>,
75}
76
77/// Compute SVD
78pub fn svd(
79    matrix: &ArrayView2<f64>,
80    full_matrices: bool,
81    compute_uv: Option<bool>,
82) -> QuantRS2Result<(Array2<f64>, Array1<f64>, Array2<f64>)> {
83    use ndarray_linalg::SVD;
84
85    let compute = compute_uv.unwrap_or(true);
86    let (u, s, vt) = matrix
87        .to_owned()
88        .svd(compute, compute)
89        .map_err(|e| crate::error::QuantRS2Error::ComputationError(format!("SVD failed: {}", e)))?;
90
91    Ok((
92        u.unwrap_or_else(|| Array2::zeros((matrix.nrows(), matrix.nrows()))),
93        s,
94        vt.unwrap_or_else(|| Array2::zeros((matrix.ncols(), matrix.ncols()))),
95    ))
96}
97
98/// Compute SVD (simplified version)
99pub fn svd_simple(matrix: &Array2<f64>) -> QuantRS2Result<SvdResult> {
100    let (u, s, vt) = svd(&matrix.view(), true, Some(true))?;
101    Ok(SvdResult { u, s, vt })
102}
103
104/// Compute randomized SVD
105pub fn randomized_svd(
106    matrix: &ArrayView2<f64>,
107    rank: usize,
108    oversampling: Option<usize>,
109    n_iter: Option<usize>,
110    random_state: Option<u64>,
111) -> QuantRS2Result<(Array2<f64>, Array1<f64>, Array2<f64>)> {
112    // Stub implementation - just call regular SVD and truncate
113    let (u, s, vt) = svd(matrix, false, Some(true))?;
114    let k = rank.min(s.len());
115
116    Ok((
117        u.slice(scirs2_core::ndarray::s![.., ..k]).to_owned(),
118        s.slice(scirs2_core::ndarray::s![..k]).to_owned(),
119        vt.slice(scirs2_core::ndarray::s![..k, ..]).to_owned(),
120    ))
121}
122
123/// Compute truncated SVD
124pub fn truncated_svd(
125    matrix: &ArrayView2<f64>,
126    rank: usize,
127    random_state: Option<u64>,
128) -> QuantRS2Result<(Array2<f64>, Array1<f64>, Array2<f64>)> {
129    randomized_svd(matrix, rank, Some(10), Some(2), random_state)
130}