capability_grower_configuration/
weighted_branching_configuration.rs

1// ---------------- [ File: capability-grower-configuration/src/weighted_branching_configuration.rs ]
2crate::ix!();
3
4/// This struct should define a **mean ± variance** approach for branching factor,
5/// letting you generate more **natural/organic** trees rather than uniform child counts.
6#[derive(
7    SaveLoad,
8    Debug, 
9    Clone, 
10    PartialEq, 
11    Getters, 
12    Builder, 
13    Default, 
14    Serialize, 
15    Deserialize, 
16    AiJsonTemplate,
17    AiJsonTemplateWithJustification,
18)]
19#[builder(pattern="owned", setter(into))]
20#[getset(get="pub")]
21pub struct WeightedBranchingConfiguration {
22    /// This integer should be > 0, specifying the **average** number of children for each node.
23    /// Setting it higher → more siblings, good for broader coverage.
24    #[serde(deserialize_with = "fuzzy_u8")]
25    mean: u8,
26
27    /// This integer should be ≤ `mean`, specifying how much random variation is allowed.
28    /// E.g. variance=2 means the actual child count might be [mean-2..mean+2].
29    #[serde(deserialize_with = "fuzzy_u8")]
30    variance: u8,
31}
32
33impl WeightedBranchingConfiguration {
34    pub fn validate(&self) -> Result<(), GrowerTreeConfigurationError> {
35        if self.mean == 0 {
36            return Err(GrowerTreeConfigurationError::WeightedBranchMeanCannotBeZero);
37        }
38        if self.variance > self.mean {
39            return Err(GrowerTreeConfigurationError::WeightedBranchMeanLessThanVariance);
40        }
41        Ok(())
42    }
43}
44
45impl FuzzyFromJsonValue for JustifiedWeightedBranchingConfiguration {
46    fn fuzzy_from_json_value(value: &JsonValue)
47        -> Result<Self, FuzzyFromJsonValueError>
48    {
49        trace!("(JustifiedWeightedBranchingConfiguration) Entering fuzzy_from_json_value");
50
51        // 1) If null => default
52        if value.is_null() {
53            debug!("(JustifiedWeightedBranchingConfiguration) Null => returning default (mean=0,variance=0).");
54            return Ok(Self {
55                mean: 0,
56                mean_confidence: 0.0,
57                mean_justification: String::new(),
58                variance: 0,
59                variance_confidence: 0.0,
60                variance_justification: String::new(),
61            });
62        }
63
64        // 2) Must be object => parse
65        let mut obj = match value.as_object() {
66            Some(m) => {
67                trace!("(JustifiedWeightedBranchingConfiguration) Found object => flattening if needed.");
68                m.clone()
69            }
70            None => {
71                error!("(JustifiedWeightedBranchingConfiguration) Not an object => fail!");
72                return Err(FuzzyFromJsonValueError::NotAnObject {
73                    target_type: "JustifiedWeightedBranchingConfiguration",
74                    actual: value.clone(),
75                });
76            }
77        };
78
79        flatten_all_fields(&mut obj);
80
81        // mean => fuzzy_u8
82        trace!("(JustifiedWeightedBranchingConfiguration) Parsing 'mean' => fuzzy_u8");
83        let mean_val = match obj.get("mean") {
84            Some(x) => {
85                match fuzzy_u8(x) {
86                    Ok(u) => {
87                        trace!("(JustifiedWeightedBranchingConfiguration) mean => {}", u);
88                        u
89                    }
90                    Err(e) => {
91                        error!("(JustifiedWeightedBranchingConfiguration) mean parse error => {:?}", e);
92                        return Err(FuzzyFromJsonValueError::Other {
93                            target_type: "JustifiedWeightedBranchingConfiguration",
94                            detail: format!("mean parse error: {:?}", e),
95                        });
96                    }
97                }
98            }
99            None => 0,
100        };
101        let mean_conf = get_f64_field(&obj, "mean_confidence", "JustifiedWeightedBranchingConfiguration")
102            .unwrap_or(0.0);
103        let mean_just = get_string_field(&obj, "mean_justification", "JustifiedWeightedBranchingConfiguration")
104            .unwrap_or_default();
105
106        // variance => fuzzy_u8
107        trace!("(JustifiedWeightedBranchingConfiguration) Parsing 'variance' => fuzzy_u8");
108        let var_val = match obj.get("variance") {
109            Some(x) => {
110                match fuzzy_u8(x) {
111                    Ok(u) => {
112                        trace!("(JustifiedWeightedBranchingConfiguration) variance => {}", u);
113                        u
114                    }
115                    Err(e) => {
116                        error!("(JustifiedWeightedBranchingConfiguration) variance parse error => {:?}", e);
117                        return Err(FuzzyFromJsonValueError::Other {
118                            target_type: "JustifiedWeightedBranchingConfiguration",
119                            detail: format!("variance parse error: {:?}", e),
120                        });
121                    }
122                }
123            }
124            None => 0,
125        };
126        let var_conf = get_f64_field(&obj, "variance_confidence", "JustifiedWeightedBranchingConfiguration")
127            .unwrap_or(0.0);
128        let var_just = get_string_field(&obj, "variance_justification", "JustifiedWeightedBranchingConfiguration")
129            .unwrap_or_default();
130
131        trace!("(JustifiedWeightedBranchingConfiguration) Successfully parsed => returning final struct.");
132        Ok(Self {
133            mean: mean_val,
134            mean_confidence: mean_conf,
135            mean_justification: mean_just,
136            variance: var_val,
137            variance_confidence: var_conf,
138            variance_justification: var_just,
139        })
140    }
141}