Skip to main content

arpack_rnsolve

Function arpack_rnsolve 

Source
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);
}