Skip to content

Commit e5ca9c9

Browse files
Add comprehensive tests and doc examples for partial cycle-finding
Co-authored-by: samueltardieu <44656+samueltardieu@users.noreply.github.com>
1 parent 4891c38 commit e5ca9c9

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

src/directed/cycle_detection.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@
99
/// μ̃ satisfies μ ≤ μ̃ < μ + λ, where μ is the minimal index.
1010
///
1111
/// This is faster than [`floyd`] as it skips the computation of the minimal μ.
12+
/// The upper bound μ̃ is sufficient for many applications, such as computing f^n(x) for
13+
/// large n, where knowing the exact starting point of the cycle is not necessary.
14+
///
15+
/// # Example
16+
///
17+
/// ```
18+
/// use pathfinding::prelude::floyd_partial;
19+
///
20+
/// let (lam, _elem, mu_tilde) = floyd_partial(1, |x| (x * 2) % 7);
21+
/// assert_eq!(lam, 3); // Cycle length
22+
/// assert!(mu_tilde >= 1); // Upper bound on mu
23+
/// ```
1224
///
1325
/// # Warning
1426
///
@@ -74,6 +86,18 @@ where
7486
/// μ̃ satisfies μ ≤ μ̃ < μ + λ, where μ is the minimal index.
7587
///
7688
/// This is faster than [`brent`] as it skips the computation of the minimal μ.
89+
/// The upper bound μ̃ is sufficient for many applications, such as computing f^n(x) for
90+
/// large n, where knowing the exact starting point of the cycle is not necessary.
91+
///
92+
/// # Example
93+
///
94+
/// ```
95+
/// use pathfinding::prelude::brent_partial;
96+
///
97+
/// let (lam, _elem, mu_tilde) = brent_partial(1, |x| (x * 2) % 7);
98+
/// assert_eq!(lam, 3); // Cycle length
99+
/// assert!(mu_tilde >= 1); // Upper bound on mu
100+
/// ```
77101
///
78102
/// # Warning
79103
///

tests/cycle_detection.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,35 @@ fn brent_partial_works() {
3535
assert!(2 <= mu_tilde);
3636
assert!(mu_tilde < 2 + 3);
3737
}
38+
39+
#[test]
40+
fn partial_functions_match_full_functions() {
41+
// Test that partial functions return the same lambda as full functions
42+
let f = |x| (x + 5) % 6 + 3;
43+
44+
let (lam_floyd, elem_floyd, mu_floyd) = floyd(-10, f);
45+
let (lam_floyd_partial, elem_floyd_partial, mu_tilde_floyd) = floyd_partial(-10, f);
46+
47+
let (lam_brent, elem_brent, mu_brent) = brent(-10, f);
48+
let (lam_brent_partial, elem_brent_partial, mu_tilde_brent) = brent_partial(-10, f);
49+
50+
// Lambda should be the same
51+
assert_eq!(lam_floyd, lam_floyd_partial);
52+
assert_eq!(lam_brent, lam_brent_partial);
53+
assert_eq!(lam_floyd, lam_brent);
54+
55+
// Elements should be in the cycle
56+
assert!([4, 6, 8].contains(&elem_floyd));
57+
assert!([4, 6, 8].contains(&elem_floyd_partial));
58+
assert!([4, 6, 8].contains(&elem_brent));
59+
assert!([4, 6, 8].contains(&elem_brent_partial));
60+
61+
// Mu values from full algorithms should be the same
62+
assert_eq!(mu_floyd, mu_brent);
63+
64+
// Mu_tilde should be valid upper bounds
65+
assert!(mu_floyd <= mu_tilde_floyd);
66+
assert!(mu_tilde_floyd < mu_floyd + lam_floyd);
67+
assert!(mu_brent <= mu_tilde_brent);
68+
assert!(mu_tilde_brent < mu_brent + lam_brent);
69+
}

0 commit comments

Comments
 (0)