sorting_race/services/fairness/
comparison.rs

1//! Comparison-budget fairness model implementation
2
3use crate::models::traits::{FairnessModel, Sorter};
4
5/// Fairness model that allocates equal comparison budgets to all algorithms
6#[derive(Debug)]
7pub struct ComparisonFairness {
8    budget_per_step: usize,
9}
10
11impl ComparisonFairness {
12    /// Create a new comparison fairness model
13    pub fn new(budget: usize) -> Self {
14        Self {
15            budget_per_step: budget.max(1),
16        }
17    }
18
19    /// Get the current budget per step
20    pub fn get_budget(&self) -> usize {
21        self.budget_per_step
22    }
23
24    /// Set a new budget per step
25    pub fn set_budget(&mut self, budget: usize) {
26        self.budget_per_step = budget.max(1);
27    }
28}
29
30impl Default for ComparisonFairness {
31    fn default() -> Self {
32        Self::new(10)
33    }
34}
35
36impl FairnessModel for ComparisonFairness {
37    fn allocate_budget(&self, algorithms: &[Box<dyn Sorter>]) -> Vec<usize> {
38        // Allocate equal budget to all algorithms
39        algorithms
40            .iter()
41            .map(|algorithm| {
42                if algorithm.is_complete() {
43                    0 // No budget for completed algorithms
44                } else {
45                    self.budget_per_step
46                }
47            })
48            .collect()
49    }
50
51    fn name(&self) -> &str {
52        "Comparison Budget"
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use crate::services::sorters::bubble::BubbleSort;
60
61    #[test]
62    fn test_comparison_fairness_equal_allocation() {
63        let fairness = ComparisonFairness::new(5);
64        let algorithms: Vec<Box<dyn Sorter>> = vec![
65            Box::new(BubbleSort::new()),
66            Box::new(BubbleSort::new()),
67            Box::new(BubbleSort::new()),
68        ];
69
70        let budgets = fairness.allocate_budget(&algorithms);
71        assert_eq!(budgets, vec![5, 5, 5]);
72    }
73
74    #[test]
75    fn test_comparison_fairness_completed_algorithm() {
76        let fairness = ComparisonFairness::new(10);
77        let mut bubble1 = BubbleSort::new();
78        let mut bubble2 = BubbleSort::new();
79        
80        // Set up one completed algorithm
81        bubble1.reset(vec![]); // Empty array makes it complete
82        bubble2.reset(vec![3, 1, 2]); // Non-empty array
83
84        let algorithms: Vec<Box<dyn Sorter>> = vec![
85            Box::new(bubble1),
86            Box::new(bubble2),
87        ];
88
89        let budgets = fairness.allocate_budget(&algorithms);
90        assert_eq!(budgets[0], 0); // Completed algorithm gets 0
91        assert_eq!(budgets[1], 10); // Active algorithm gets full budget
92    }
93
94    #[test]
95    fn test_comparison_fairness_minimum_budget() {
96        let fairness = ComparisonFairness::new(0); // Should be clamped to 1
97        assert_eq!(fairness.get_budget(), 1);
98    }
99
100    #[test]
101    fn test_comparison_fairness_name() {
102        let fairness = ComparisonFairness::new(5);
103        assert_eq!(fairness.name(), "Comparison Budget");
104    }
105}