ibdgen/lib.rs
1mod ibd;
2mod random_type;
3
4
5pub mod coincidence_matrix;
6pub mod block_array;
7pub mod block_result;
8
9use ibd::*;
10
11use block_result::BlockResult;
12
13use anyhow::Error;
14
15
16/// Finds the best incomplete block design (IBD) by running multiple iterations of the IBD generation algorithm.
17///
18/// # Arguments
19///
20/// * `v` - Number of treatments
21/// * `n_b` - Number of blocks
22/// * `block_size` - Number of treatments per block
23/// * `n_repeats` - Number of optimization repeats within each iteration
24/// * `iter` - Number of iterations to run
25/// * `prohibited_pairs` - Vector of tuples containing pairs of treatments that cannot appear together in any block (0-based indices)
26/// * `on_update` - Callback function called after each iteration with the current iteration number and best D-optimality value
27///
28/// # Returns
29///
30/// Returns a tuple containing:
31/// * The best block design solution found (`BlockResult`)
32/// * The iteration number where the best solution was found
33/// * The D-optimality value of the best solution
34///
35/// # Errors
36///
37/// Returns an error if the IBD generation fails
38pub fn find_best_ibd<F>(v: u8, n_b: usize, block_size: usize, n_repeats: usize, iter: usize, prohibited_pairs: Vec<(usize, usize)>, mut on_update: F) -> Result<(BlockResult, usize, f64), Error>
39 where
40 F: FnMut(usize, f64),
41 {
42 let mut best_d = 0.0;
43 let mut best_solution = BlockResult::default();
44 let mut best_iter = 0;
45 for i in 1..=iter {
46 let result = ibdgen(
47 v,
48 n_b,
49 block_size,
50 n_repeats,
51 prohibited_pairs.clone()
52 ).unwrap();
53
54 if result.best_d > best_d {
55 best_d = result.best_d;
56 best_solution = result;
57 best_iter = i;
58 }
59
60 on_update(i, best_d);
61 }
62 Ok((best_solution, best_iter, best_d))
63}
64
65