capability_grower_configuration/
level_skipping_configuration.rs

1// ---------------- [ File: capability-grower-configuration/src/level_skipping_configuration.rs ]
2crate::ix!();
3
4/// This struct should define how you skip certain levels early, turning them into leaves based on probabilities.
5#[derive(
6    SaveLoad,
7    Debug, 
8    Clone, 
9    PartialEq, 
10    Getters, 
11    Builder, 
12    Default, 
13    Serialize, 
14    Deserialize, 
15    AiJsonTemplate,
16    AiJsonTemplateWithJustification,
17)]
18#[builder(pattern="owned", setter(into))]
19#[getset(get="pub")]
20pub struct LevelSkippingConfiguration {
21    /// This array of fractions [0..1] should specify the chance that a node at level i is a leaf.
22    /// e.g. `[0.0, 0.2, 0.4]` → level 2 has 20% chance of skipping deeper expansion, etc.
23    leaf_probability_per_level: Vec<f32>,
24}
25
26impl LevelSkippingConfiguration {
27    pub fn validate(&self, depth: u8) -> Result<(), GrowerTreeConfigurationError> {
28        if self.leaf_probability_per_level.len() as u8 > depth {
29            return Err(GrowerTreeConfigurationError::LeafProbabilityLenExceedsDepth);
30        }
31        for &p in &self.leaf_probability_per_level {
32            if !(0.0..=1.0).contains(&p) {
33                return Err(GrowerTreeConfigurationError::LeafProbabilityOutOfRange);
34            }
35        }
36        Ok(())
37    }
38}
39
40impl FuzzyFromJsonValue for JustifiedLevelSkippingConfiguration {
41    fn fuzzy_from_json_value(value: &JsonValue)
42        -> Result<Self, FuzzyFromJsonValueError>
43    {
44        trace!("(JustifiedLevelSkippingConfiguration) Entering fuzzy_from_json_value");
45
46        // 1) If null => default
47        if value.is_null() {
48            debug!("(JustifiedLevelSkippingConfiguration) Null => returning empty config.");
49            return Ok(Self {
50                leaf_probability_per_level: vec![],
51                leaf_probability_per_level_confidence: 0.0,
52                leaf_probability_per_level_justification: String::new(),
53            });
54        }
55
56        // 2) Must be object => parse
57        let mut obj = match value.as_object() {
58            Some(m) => {
59                trace!("(JustifiedLevelSkippingConfiguration) Found object => flattening if needed.");
60                m.clone()
61            }
62            None => {
63                error!("(JustifiedLevelSkippingConfiguration) Not an object => fail!");
64                return Err(FuzzyFromJsonValueError::NotAnObject {
65                    target_type: "JustifiedLevelSkippingConfiguration",
66                    actual: value.clone(),
67                });
68            }
69        };
70
71        flatten_all_fields(&mut obj);
72
73        // leaf_probability_per_level => parse array of f32
74        trace!("(JustifiedLevelSkippingConfiguration) Parsing 'leaf_probability_per_level' => array of f32");
75        let leaf_prob_val = match obj.get("leaf_probability_per_level") {
76            Some(JsonValue::Array(arr)) => {
77                let mut out = Vec::with_capacity(arr.len());
78                for e in arr {
79                    match e.as_f64() {
80                        Some(f) => {
81                            let f32_val = f as f32;
82                            trace!("(JustifiedLevelSkippingConfiguration) leaf_probability item => {}", f32_val);
83                            out.push(f32_val);
84                        }
85                        None => {
86                            warn!("(JustifiedLevelSkippingConfiguration) leaf_probability item was non-numeric => skipping");
87                        }
88                    }
89                }
90                out
91            }
92            _ => {
93                debug!("(JustifiedLevelSkippingConfiguration) 'leaf_probability_per_level' missing => default empty");
94                vec![]
95            }
96        };
97        let lp_conf = get_f64_field(&obj, "leaf_probability_per_level_confidence", "JustifiedLevelSkippingConfiguration")
98            .unwrap_or(0.0);
99        let lp_just = get_string_field(&obj, "leaf_probability_per_level_justification", "JustifiedLevelSkippingConfiguration")
100            .unwrap_or_default();
101
102        trace!("(JustifiedLevelSkippingConfiguration) Successfully parsed => returning final struct.");
103        Ok(Self {
104            leaf_probability_per_level: leaf_prob_val,
105            leaf_probability_per_level_confidence: lp_conf,
106            leaf_probability_per_level_justification: lp_just,
107        })
108    }
109}