Skip to content

Commit 6fce47a

Browse files
committed
Strategy for linearly dependent vectors
1 parent 10c1fd1 commit 6fce47a

File tree

1 file changed

+43
-8
lines changed

1 file changed

+43
-8
lines changed

src/arnoldi.rs

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,19 @@ impl<A: Scalar> MGS<A> {
7373
/// # use ndarray::*;
7474
/// # use ndarray_linalg::*;
7575
/// 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();
7777
/// close_l2(&coef, &array![1.0], 1e-9).unwrap();
7878
///
7979
/// let coef = mgs.append(array![1.0, 1.0, 0.0], 1e-9).unwrap();
8080
/// close_l2(&coef, &array![1.0, 1.0], 1e-9).unwrap();
8181
///
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+
/// }
8387
/// ```
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>>
8589
where
8690
A: Lapack,
8791
S: Data<Elem = A>,
@@ -91,11 +95,11 @@ impl<A: Scalar> MGS<A> {
9195
let nrm = coef[coef.len() - 1].re();
9296
if nrm < rtol {
9397
// Linearly dependent
94-
return None;
98+
return Err(coef);
9599
}
96100
azip!(mut a in { *a = *a / A::from_real(nrm) });
97101
self.q.push(a);
98-
Some(coef)
102+
Ok(coef)
99103
}
100104

101105
/// Get orthogonal basis as Q matrix
@@ -104,7 +108,34 @@ impl<A: Scalar> MGS<A> {
104108
}
105109
}
106110

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>)
108139
where
109140
A: Scalar + Lapack,
110141
S: Data<Elem = A>,
@@ -113,8 +144,12 @@ where
113144
let mut coefs = Vec::new();
114145
for a in iter {
115146
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+
},
118153
}
119154
}
120155
let m = coefs.len();

0 commit comments

Comments
 (0)