Function nekolib::algo::cycle_mu_lambda

source ·
pub fn cycle_mu_lambda<T, F>(x0: T, f: F) -> (usize, usize)where
    T: Eq + Clone,
    F: Fn(T) -> T,
Expand description

周期検出を行う。

与えられた x0x_0ff を用いて xi=f(xi1)x_i = f(x_{i-1}) (i>0i > 0) として 定義される列 {xi}i=0\{x_i\}_{i=0}^\infty の周期検出を行う。 xμ=xμ+λx_{\mu} = x_{\mu+\lambda} なる最小の (μ,λ)(\mu, \lambda) を返す。

Requirements

ff は参照透過である。

Notes

共通の ff に対して、異なる複数の x0x_0 から周期検出を行いたい場合は、 この関数を複数回呼ぶよりも高速なアルゴリズムがあると思われる。 ある x0x_0 での出力が (μ,λ)(\mu, \lambda) であれば、 xix_i (1i<μ1\le i< \mu) での出力は (μi,λ)(\mu-i, \lambda)xix_i (μi<μ+λ\mu\le i<\mu+\lambda) での出力は (0,λ)(0, \lambda) とわかる。 さらに、これら μ+λ\mu+\lambda 個以外の xx' についても、 fi(x)f^i(x') がこれらのいずれかと等しくなる ii が存在すれば、 Θ(μ)\Theta(\mu) 回の ff の呼び出しで x,f(x),,fi1(x)x', f(x'), \dots, f^{i-1}(x') の出力もわかるはず。

Complexity

Θ(μ+λ)\Theta(\mu+\lambda) 回の ff の呼び出しを行う。

Examples

use nekolib::algo::cycle_mu_lambda;

// 3, 9, 11, 9, 11, ...
assert_eq!(cycle_mu_lambda(3, |x| x * x % 14), (1, 2));
// 2, 6, 4, 5, 1, 3, 2, ...
assert_eq!(cycle_mu_lambda(2, |x| x * 3 % 7), (0, 6));
use nekolib::algo::cycle_mu_lambda;

assert_eq!(cycle_mu_lambda(0, |x| x), (0, 1));