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;