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