1
+ //! Truncated eigenvalue decomposition
2
+ //!
3
+
1
4
use super :: lobpcg:: { lobpcg, LobpcgResult , Order } ;
2
5
use crate :: { generate, Scalar } ;
3
6
use lax:: Lapack ;
4
7
5
- ///! Implements truncated eigenvalue decomposition
6
- ///
7
8
use ndarray:: prelude:: * ;
8
9
use ndarray:: stack;
9
10
use ndarray:: ScalarOperand ;
@@ -15,6 +16,20 @@ use num_traits::{Float, NumCast};
15
16
/// parameter like maximal iteration, precision and constraint matrix. Furthermore it allows
16
17
/// conversion into a iterative solver where each iteration step yields a new eigenvalue/vector
17
18
/// pair.
19
+ ///
20
+ /// # Example
21
+ ///
22
+ /// ```rust
23
+ /// let diag = arr1(&[1., 2., 3., 4., 5.]);
24
+ /// let a = Array2::from_diag(&diag);
25
+ ///
26
+ /// let eig = TruncatedEig::new(a, Order::Largest)
27
+ /// .precision(1e-5)
28
+ /// .maxiter(500);
29
+ ///
30
+ /// let res = eig.decompose();
31
+ /// ```
32
+
18
33
pub struct TruncatedEig < A : Scalar > {
19
34
order : Order ,
20
35
problem : Array2 < A > ,
@@ -25,6 +40,11 @@ pub struct TruncatedEig<A: Scalar> {
25
40
}
26
41
27
42
impl < A : Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default > TruncatedEig < A > {
43
+ /// Create a new truncated eigenproblem solver
44
+ ///
45
+ /// # Properties
46
+ /// * `problem`: problem matrix
47
+ /// * `order`: ordering of the eigenvalues with [TruncatedOrder](crate::TruncatedOrder)
28
48
pub fn new ( problem : Array2 < A > , order : Order ) -> TruncatedEig < A > {
29
49
TruncatedEig {
30
50
precision : 1e-5 ,
@@ -36,31 +56,68 @@ impl<A: Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default> Truncate
36
56
}
37
57
}
38
58
59
+ /// Set desired precision
60
+ ///
61
+ /// This argument specifies the desired precision, which is passed to the LOBPCG solver. It
62
+ /// controls at which point the opimization of each eigenvalue is stopped. The precision is
63
+ /// global and applied to all eigenvalues with respect to their L2 norm.
64
+ ///
65
+ /// If the precision can't be reached and the maximum number of iteration is reached, then an
66
+ /// error is returned in [LobpcgResult](crate::lobpcg::LobpcgResult).
39
67
pub fn precision ( mut self , precision : f32 ) -> Self {
40
68
self . precision = precision;
41
69
42
70
self
43
71
}
44
72
73
+ /// Set the maximal number of iterations
74
+ ///
75
+ /// The LOBPCG is an iterative approach to eigenproblems and stops when this maximum
76
+ /// number of iterations are reached.
45
77
pub fn maxiter ( mut self , maxiter : usize ) -> Self {
46
78
self . maxiter = maxiter;
47
79
48
80
self
49
81
}
50
82
83
+ /// Construct a solution, which is orthogonal to this
84
+ ///
85
+ /// If a number of eigenvectors are already known, then this function can be used to construct
86
+ /// a orthogonal subspace. Also used with an iterative approach.
51
87
pub fn orthogonal_to ( mut self , constraints : Array2 < A > ) -> Self {
52
88
self . constraints = Some ( constraints) ;
53
89
54
90
self
55
91
}
56
92
93
+ /// Apply a preconditioner
94
+ ///
95
+ /// A preconditioning matrix can speed up the solving process by improving the spectral
96
+ /// distribution of the eigenvalues. It requires prior knowledge of the problem.
57
97
pub fn precondition_with ( mut self , preconditioner : Array2 < A > ) -> Self {
58
98
self . preconditioner = Some ( preconditioner) ;
59
99
60
100
self
61
101
}
62
102
63
- // calculate the eigenvalues decompose
103
+ /// Calculate the eigenvalue decomposition
104
+ ///
105
+ /// # Parameters
106
+ ///
107
+ /// * `num`: number of eigenvalues ordered by magnitude
108
+ ///
109
+ /// # Example
110
+ ///
111
+ /// ```rust
112
+ /// let diag = arr1(&[1., 2., 3., 4., 5.]);
113
+ /// let a = Array2::from_diag(&diag);
114
+ ///
115
+ /// let eig = TruncatedEig::new(a, Order::Largest)
116
+ /// .precision(1e-5)
117
+ /// .maxiter(500);
118
+ ///
119
+ /// let res = eig.decompose();
120
+ /// ```
64
121
pub fn decompose ( & self , num : usize ) -> LobpcgResult < A > {
65
122
let x: Array2 < f64 > = generate:: random ( ( self . problem . len_of ( Axis ( 0 ) ) , num) ) ;
66
123
let x = x. mapv ( |x| NumCast :: from ( x) . unwrap ( ) ) ;
@@ -104,10 +161,24 @@ impl<A: Float + Scalar + ScalarOperand + Lapack + PartialOrd + Default> IntoIter
104
161
}
105
162
}
106
163
107
- /// Truncate eigenproblem iterator
164
+ /// Truncated eigenproblem iterator
108
165
///
109
166
/// This wraps a truncated eigenproblem and provides an iterator where each step yields a new
110
167
/// eigenvalue/vector pair. Useful for generating pairs until a certain condition is met.
168
+ ///
169
+ /// # Example
170
+ ///
171
+ /// ```rust
172
+ /// let teig = TruncatedEig::new(a, Order::Largest)
173
+ /// .precision(1e-5)
174
+ /// .maxiter(500);
175
+ ///
176
+ /// // solve eigenproblem until eigenvalues get smaller than 0.5
177
+ /// let res = teig.into_iter()
178
+ /// .take_while(|x| x.0[0] > 0.5)
179
+ /// .flat_map(|x| x.0)
180
+ /// .collect();
181
+ /// ```
111
182
pub struct TruncatedEigIterator < A : Scalar > {
112
183
step_size : usize ,
113
184
remaining : usize ,
0 commit comments