@@ -73,15 +73,19 @@ impl<A: Scalar> MGS<A> {
73
73
/// # use ndarray::*;
74
74
/// # use ndarray_linalg::*;
75
75
/// let mut mgs = arnoldi::MGS::new(3);
76
- /// let coef = mgs.append(array![1 .0, 0 .0, 0.0], 1e-9).unwrap();
76
+ /// let coef = mgs.append(array![0 .0, 1 .0, 0.0], 1e-9).unwrap();
77
77
/// close_l2(&coef, &array![1.0], 1e-9).unwrap();
78
78
///
79
79
/// let coef = mgs.append(array![1.0, 1.0, 0.0], 1e-9).unwrap();
80
80
/// close_l2(&coef, &array![1.0, 1.0], 1e-9).unwrap();
81
81
///
82
- /// assert!(mgs.append(array![1.0, 2.0, 0.0], 1e-9).is_none()); // Cannot append dependent vector
82
+ /// assert!(mgs.append(array![1.0, 2.0, 0.0], 1e-9).is_err()); // Fail if the vector is linearly dependend
83
+ ///
84
+ /// if let Err(coef) = mgs.append(array![1.0, 2.0, 0.0], 1e-9) {
85
+ /// close_l2(&coef, &array![2.0, 1.0, 0.0], 1e-9).unwrap(); // You can get coefficients of dependent vector
86
+ /// }
83
87
/// ```
84
- pub fn append < S > ( & mut self , a : ArrayBase < S , Ix1 > , rtol : A :: Real ) -> Option < Array1 < A > >
88
+ pub fn append < S > ( & mut self , a : ArrayBase < S , Ix1 > , rtol : A :: Real ) -> Result < Array1 < A > , Array1 < A > >
85
89
where
86
90
A : Lapack ,
87
91
S : Data < Elem = A > ,
@@ -91,11 +95,11 @@ impl<A: Scalar> MGS<A> {
91
95
let nrm = coef[ coef. len ( ) - 1 ] . re ( ) ;
92
96
if nrm < rtol {
93
97
// Linearly dependent
94
- return None ;
98
+ return Err ( coef ) ;
95
99
}
96
100
azip ! ( mut a in { * a = * a / A :: from_real( nrm) } ) ;
97
101
self . q . push ( a) ;
98
- Some ( coef)
102
+ Ok ( coef)
99
103
}
100
104
101
105
/// Get orthogonal basis as Q matrix
@@ -104,7 +108,34 @@ impl<A: Scalar> MGS<A> {
104
108
}
105
109
}
106
110
107
- pub fn mgs < A , S > ( iter : impl Iterator < Item = ArrayBase < S , Ix1 > > , dim : usize , rtol : A :: Real ) -> ( Q < A > , R < A > )
111
+ /// Strategy for linearly dependent vectors appearing in iterative QR decomposition
112
+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
113
+ pub enum Strategy {
114
+ /// Terminate iteration if dependent vector comes
115
+ Terminate ,
116
+
117
+ /// Skip dependent vector
118
+ Skip ,
119
+
120
+ /// Orghotonalize dependent vector without adding to Q,
121
+ /// thus R must be non-regular like following:
122
+ ///
123
+ /// ```ignore
124
+ /// x x x x x
125
+ /// 0 x x x x
126
+ /// 0 0 0 x x
127
+ /// 0 0 0 0 x
128
+ /// 0 0 0 0 0 // 0-filled to be square matrix
129
+ /// ```
130
+ Full ,
131
+ }
132
+
133
+ pub fn mgs < A , S > (
134
+ iter : impl Iterator < Item = ArrayBase < S , Ix1 > > ,
135
+ dim : usize ,
136
+ rtol : A :: Real ,
137
+ strategy : Strategy ,
138
+ ) -> ( Q < A > , R < A > )
108
139
where
109
140
A : Scalar + Lapack ,
110
141
S : Data < Elem = A > ,
@@ -113,8 +144,12 @@ where
113
144
let mut coefs = Vec :: new ( ) ;
114
145
for a in iter {
115
146
match ortho. append ( a, rtol) {
116
- Some ( coef) => coefs. push ( coef) ,
117
- None => break ,
147
+ Ok ( coef) => coefs. push ( coef) ,
148
+ Err ( coef) => match strategy {
149
+ Strategy :: Terminate => break ,
150
+ Strategy :: Skip => continue ,
151
+ Strategy :: Full => coefs. push ( coef) ,
152
+ } ,
118
153
}
119
154
}
120
155
let m = coefs. len ( ) ;
0 commit comments