Skip to main content

_diffctx/config/
category_weights.rs

1//! Per-`EdgeCategory` weight multipliers — the calibratable `w_τ` from the
2//! paper.
3//!
4//! Each fine-grained edge type (130+ in `weights.rs`) carries a default
5//! domain-prior weight. On top, every edge is scaled by a per-category
6//! multiplier `w_τ ∈ R_{≥0}`, one per `EdgeCategory` variant (10 total).
7//! These ten scalars are the parameters intended for offline calibration
8//! (Bayesian opt / grid search) against a labeled corpus, as described in
9//! paper Section 4.3 (Edge-Type Weight Calibration).
10//!
11//! Default for every variant is 1.0 (no scaling — the fine-grained
12//! prior weights from `weights.rs` apply unchanged).
13
14use once_cell::sync::Lazy;
15
16use crate::graph::EdgeCategory;
17
18#[derive(Debug, Clone, Copy)]
19pub struct CategoryWeights {
20    pub semantic: f64,
21    pub structural: f64,
22    pub sibling: f64,
23    pub config: f64,
24    pub config_generic: f64,
25    pub document: f64,
26    pub similarity: f64,
27    pub history: f64,
28    pub test_edge: f64,
29    pub generic: f64,
30}
31
32impl Default for CategoryWeights {
33    fn default() -> Self {
34        Self {
35            semantic: 1.0,
36            structural: 1.0,
37            sibling: 1.0,
38            config: 1.0,
39            config_generic: 1.0,
40            document: 1.0,
41            similarity: 1.0,
42            history: 1.0,
43            test_edge: 1.0,
44            generic: 1.0,
45        }
46    }
47}
48
49impl CategoryWeights {
50    /// Multiplier applied to every edge of the given category before scoring.
51    pub fn multiplier(&self, category: EdgeCategory) -> f64 {
52        match category {
53            EdgeCategory::Semantic => self.semantic,
54            EdgeCategory::Structural => self.structural,
55            EdgeCategory::Sibling => self.sibling,
56            EdgeCategory::Config => self.config,
57            EdgeCategory::ConfigGeneric => self.config_generic,
58            EdgeCategory::Document => self.document,
59            EdgeCategory::Similarity => self.similarity,
60            EdgeCategory::History => self.history,
61            EdgeCategory::TestEdge => self.test_edge,
62            EdgeCategory::Generic => self.generic,
63        }
64    }
65}
66
67pub static CATEGORY_WEIGHTS: Lazy<CategoryWeights> = Lazy::new(CategoryWeights::default);
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn defaults_are_unity() {
75        let w = CategoryWeights::default();
76        for cat in [
77            EdgeCategory::Semantic,
78            EdgeCategory::Structural,
79            EdgeCategory::Sibling,
80            EdgeCategory::Config,
81            EdgeCategory::ConfigGeneric,
82            EdgeCategory::Document,
83            EdgeCategory::Similarity,
84            EdgeCategory::History,
85            EdgeCategory::TestEdge,
86            EdgeCategory::Generic,
87        ] {
88            assert_eq!(w.multiplier(cat), 1.0);
89        }
90    }
91
92    #[test]
93    fn multiplier_reaches_each_variant() {
94        let w = CategoryWeights {
95            semantic: 0.1,
96            structural: 0.2,
97            sibling: 0.3,
98            config: 0.4,
99            config_generic: 0.5,
100            document: 0.6,
101            similarity: 0.7,
102            history: 0.8,
103            test_edge: 0.9,
104            generic: 0.05,
105        };
106        assert_eq!(w.multiplier(EdgeCategory::Semantic), 0.1);
107        assert_eq!(w.multiplier(EdgeCategory::Structural), 0.2);
108        assert_eq!(w.multiplier(EdgeCategory::Sibling), 0.3);
109        assert_eq!(w.multiplier(EdgeCategory::Config), 0.4);
110        assert_eq!(w.multiplier(EdgeCategory::ConfigGeneric), 0.5);
111        assert_eq!(w.multiplier(EdgeCategory::Document), 0.6);
112        assert_eq!(w.multiplier(EdgeCategory::Similarity), 0.7);
113        assert_eq!(w.multiplier(EdgeCategory::History), 0.8);
114        assert_eq!(w.multiplier(EdgeCategory::TestEdge), 0.9);
115        assert_eq!(w.multiplier(EdgeCategory::Generic), 0.05);
116    }
117}