Skip to main content

narust_158/inference/traits/
budget.rs

1//! 复刻OpenNARS的「预算」类型
2//! * 📄OpenNARS改版 `Budget`接口
3//! * 🎯只复刻外部读写方法,不限定内部数据字段
4//!   * ❌不迁移「具体类型」特征
5
6use crate::{entity::ShortFloat, global::Float, symbols::*, util::ToDisplayAndBrief};
7use nar_dev_utils::join;
8use narsese::lexical::Budget as LexicalBudget;
9
10/// 模拟`nars.inference.Budget`
11/// * 🎯实现最大程度的抽象与通用
12///   * 💭后续可以在底层用各种「证据值」替换,而不影响整个推理器逻辑
13/// * 🚩不直接使用「获取可变引用」的方式
14///   * 📌获取到的「证据值」可能另有一套「赋值」的方法:此时需要特殊定制
15///   * 🚩【2024-05-02 00:11:20】目前二者并行,`set_`复用`_mut`的逻辑(`_mut().set(..)`)
16/// * 🚩【2024-05-03 14:46:52】要求[`Sized`]是为了使用构造函数
17///
18/// # 📄OpenNARS
19///
20/// A triple of priority (current), durability (decay), and quality (long-term average).
21pub trait Budget: ToDisplayAndBrief {
22    /// 模拟`BudgetValue.getPriority`
23    /// * 🚩获取优先级
24    /// * 🚩【2024-05-02 18:21:38】现在统一获取值:对「实现了[`Copy`]的类型」直接复制
25    ///
26    /// # 📄OpenNARS
27    ///
28    /// Get priority value
29    ///
30    /// @return The current priority
31    fn priority(&self) -> ShortFloat;
32    /// 获取优先级(可变)
33    /// * 📌【2024-05-03 17:39:04】目前设置为内部方法
34    fn __priority_mut(&mut self) -> &mut ShortFloat;
35
36    /// 设置优先级
37    /// * 🚩现在统一输入值,[`Copy`]保证无需过于担心性能损失
38    #[inline(always)]
39    fn set_priority(&mut self, new_p: ShortFloat) {
40        self.__priority_mut().set(new_p)
41    }
42
43    /// 模拟`BudgetValue.getDurability`
44    /// * 🚩获取耐久度
45    /// * 🚩【2024-05-02 18:21:38】现在统一获取值:对「实现了[`Copy`]的类型」直接复制
46    ///
47    /// # 📄OpenNARS
48    ///
49    /// Get durability value
50    ///
51    /// @return The current durability
52    fn durability(&self) -> ShortFloat;
53    /// 获取耐久度(可变)
54    /// * 📌【2024-05-03 17:39:04】目前设置为内部方法
55    fn __durability_mut(&mut self) -> &mut ShortFloat;
56
57    /// 设置耐久度
58    /// * 🚩现在统一输入值,[`Copy`]保证无需过于担心性能损失
59    #[inline(always)]
60    fn set_durability(&mut self, new_d: ShortFloat) {
61        self.__durability_mut().set(new_d)
62    }
63
64    /// 模拟`BudgetValue.getQuality`
65    /// * 🚩获取质量
66    /// * 🚩【2024-05-02 18:21:38】现在统一获取值:对「实现了[`Copy`]的类型」直接复制
67    ///
68    /// # 📄OpenNARS
69    ///
70    /// Get quality value
71    ///
72    /// @return The current quality
73    fn quality(&self) -> ShortFloat;
74    /// 获取质量(可变)
75    /// * 📌【2024-05-03 17:39:04】目前设置为内部方法
76    fn __quality_mut(&mut self) -> &mut ShortFloat;
77
78    /// 设置质量
79    /// * 🚩现在统一输入值,[`Copy`]保证无需过于担心性能损失
80    #[inline(always)]
81    fn set_quality(&mut self, new_q: ShortFloat) {
82        self.__quality_mut().set(new_q)
83    }
84
85    /// 🆕获取「优先级,耐久度,质量」三元组
86    /// * 🎯方便获取符号
87    fn pdq(&self) -> [ShortFloat; 3] {
88        [self.priority(), self.durability(), self.quality()]
89    }
90
91    /// 🆕获取「优先级,耐久度,质量」三元组
92    /// * 🎯方便获取符号
93    fn pdq_float(&self) -> [Float; 3] {
94        [
95            self.priority().to_float(),
96            self.durability().to_float(),
97            self.quality().to_float(),
98        ]
99    }
100
101    /// 🆕从其它预算值处拷贝值
102    /// * 🚩拷贝优先级、耐久度与质量
103    fn copy_budget_from(&mut self, from: &impl Budget) {
104        self.set_priority(from.priority());
105        self.set_durability(from.durability());
106        self.set_quality(from.quality());
107    }
108
109    // * ✅【2024-06-28 00:58:16】目前无需使用:直接用「预算推理」中的方法`merge_from`
110    // fn merge_budget(&mut self, from: &impl Budget)
111
112    /// 模拟`BudgetValue.summary`
113    /// * 🚩📜统一采用「几何平均值」估计(默认)
114    ///
115    /// # 📄OpenNARS
116    ///
117    /// To summarize a BudgetValue into a single number in [0, 1]
118    #[inline(always)]
119    #[doc(alias = "summary")]
120    fn budget_summary(&self) -> ShortFloat {
121        // 🚩三者几何平均值
122        ShortFloat::geometrical_average([self.priority(), self.durability(), self.quality()])
123    }
124
125    /// 模拟 `BudgetValue.aboveThreshold`
126    /// * 🆕【2024-05-02 00:51:31】此处手动引入「阈值」,以避免使用「全局类の常量」
127    ///   * 🚩将「是否要用『全局类の常量』」交给调用方
128    /// * 📌常量`budget_threshold`对应OpenNARS`Parameters.BUDGET_THRESHOLD`
129    ///
130    /// # 📄OpenNARS
131    ///
132    /// Whether the budget should get any processing at all
133    ///
134    /// to be revised to depend on how busy the system is
135    ///
136    /// @return The decision on whether to process the Item
137    #[inline(always)]
138    fn budget_above_threshold(&self, budget_threshold: Float) -> bool {
139        self.budget_summary().to_float() >= budget_threshold
140    }
141
142    // ! ❌【2024-05-08 21:53:30】不进行「自动实现」而是「提供所需的默认实现」
143    //   * 📌情况:若直接使用「自动实现」则Rust无法分辨「既实现了『预算值』又实现了『真值』的类型所用的方法」
144    //   * 📝解决方案:提供一套`__`内部默认实现,后续在「结构」实现时可利用这俩「默认实现方法」通过方便的「宏」自动实现[`ToDisplayAndBrief`]
145
146    /// 模拟`toString`
147    /// * 🚩【2024-05-08 22:12:42】现在鉴于实际情况,仍然实现`toString`、`toStringBrief`方法
148    ///   * 🚩具体方案:实现一个统一的、内部的、默认的`__to_display(_brief)`,再通过「手动嫁接」完成最小成本实现
149    /// * 🚩【2024-06-21 19:29:46】目前方案:明确是「作为不同类型的『字符串呈现』方法」,并在具体类型中手动指定映射
150    ///   * 🎯一个是「明确具体的类型」一个是「避免使用混乱」
151    ///   * ❓【2024-06-21 19:31:12】或许后续将不再需要[`ToDisplayAndBrief`]
152    ///
153    /// # 📄OpenNARS
154    ///
155    /// Fully display the BudgetValue
156    ///
157    /// @return String representation of the value
158    fn budget_to_display(&self) -> String {
159        join!(
160            => MARK.to_string()
161            => &self.priority().to_display()
162            => SEPARATOR
163            => &self.durability().to_display()
164            => SEPARATOR
165            => &self.quality().to_display()
166            => MARK
167        )
168    }
169
170    /// 模拟`toStringBrief`
171    ///
172    /// # 📄OpenNARS
173    ///
174    /// Briefly display the BudgetValue
175    ///
176    /// @return String representation of the value with 2-digit accuracy
177    fn budget_to_display_brief(&self) -> String {
178        MARK.to_string()
179            + &self.priority().to_display_brief()
180            + SEPARATOR
181            + &self.durability().to_display_brief()
182            + SEPARATOR
183            + &self.quality().to_display_brief()
184            + MARK
185    }
186
187    /// 🆕转换为「词法真值」
188    /// * 🎯与词法Narsese的转换
189    /// * 🚩【2024-06-21 21:08:43】目前方法:真值和信度的字符串
190    fn budget_to_lexical(&self) -> LexicalBudget {
191        vec![
192            self.priority().to_string(),
193            self.durability().to_string(),
194            self.quality().to_string(),
195        ]
196    }
197}
198
199/// * 🚩【2024-05-09 00:56:52】改:统一为字符串
200/// # 📄OpenNARS
201///
202/// The character that marks the two ends of a budget value
203const MARK: &str = BUDGET_VALUE_MARK;
204
205/// * 🚩【2024-05-09 00:56:52】改:统一为字符串
206/// # 📄OpenNARS
207///
208/// The character that separates the factors in a budget value
209const SEPARATOR: &str = VALUE_SEPARATOR;