pub fn arpack_rnsolve<F: FnMut(&[f64], &mut [f64])>(
n: usize,
matvec: F,
options: &ArpackOptions,
storage: Option<&mut ArpackStorage>,
) -> Result<ArpackNonSymmetricResult>Expand description
Eigenvalues and eigenvectors of a general (non-symmetric) linear
operator given as a Rust closure, with ARPACK’s implicitly restarted
Arnoldi method (igraph_arpack_rnsolve).
matvec(x, y) stores A x into y, as in arpack_rssolve. The
eigenvalues may be complex: they are returned as Complex numbers,
with complex conjugate pairs next to each other, and the eigenvectors are
unpacked into complex vectors. Note that ARPACK requires nev <= n - 2
here; in regular mode 1 × 1 and 2 × 2 problems are solved exactly by
igraph (in closed form, without ARPACK).
As explained for arpack_rssolve, ARPACK starts from A v0 rather
than from the start vector v0, so eigenvectors of a singular operator
with eigenvalue 0 may be missed (shift the operator to A + s I and
subtract s afterwards), and ARPACK computations cannot be nested inside
matvec or inside handlers (a nested call fails with
ErrorKind::Failure).
Binds igraph_arpack_rnsolve.
See also SparseMat::arpack_rnsolve,
eigen_matrix for dense matrices, and
Graph::pagerank /
Graph::hub_and_authority_scores,
the classic non-symmetric eigenproblems on graphs.
§Errors
As arpack_rssolve: invalid options (see ArpackOptions; ARPACK
rejects nev > n - 2 for n > 2), a non-finite product, or an ARPACK
failure (ErrorKind::Arpack, see
ArpackError::from_error).
§Examples
A directed cycle is a permutation matrix: its eigenvalues are the n-th
roots of unity, all of magnitude 1.
use igraph::linalg::{arpack_rnsolve, ArpackOptions, ArpackWhich};
let n = 8;
let shift = |x: &[f64], y: &mut [f64]| {
for i in 0..n {
y[i] = x[(i + 1) % n];
}
};
let opts = ArpackOptions::default().with_nev(3).with_which(ArpackWhich::LargestReal);
let res = arpack_rnsolve(n, shift, &opts, None).unwrap();
assert!((res.values[0].re() - 1.0).abs() < 1e-8 && res.values[0].im().abs() < 1e-8);
for v in &res.values {
assert!(((v.re() * v.re() + v.im() * v.im()).sqrt() - 1.0).abs() < 1e-8);
}