narust_158/entity/float_values/
truth_value.rs

1//! 🎯复刻OpenNARS `nars.entity.TruthValue`
2//! * 📌【2024-05-02 21:30:40】从「预算函数」来:一些地方必须用到「真值」及其方法
3//! * ✅【2024-05-03 16:21:02】所有方法基本复刻完毕
4
5use super::ShortFloat;
6use crate::{
7    __impl_to_display_and_display, global::Float, inference::Truth, util::ToDisplayAndBrief,
8};
9use anyhow::Result;
10use narsese::lexical::Truth as LexicalTruth;
11use std::{
12    fmt::Debug,
13    hash::{Hash, Hasher},
14};
15
16/// [`TruthValue`]初代实现
17/// * 🎯测试特征的效果
18/// * 📌[`PartialEq`]、[`Eq`]、[`Hash`]均特别实现
19///
20/// # 📄OpenNARS
21///
22/// Frequency and confidence.
23#[derive(Debug, Clone, Copy, Default, Eq)]
24pub struct TruthValue {
25    /// frequency
26    f: ShortFloat,
27    /// confidence
28    c: ShortFloat,
29    /// analytic
30    a: bool,
31}
32
33/// 定制的序列反序列化方法
34/// * 🎯节省序列化后的占用空间
35///   * 📄在JSON中不再需要是一个object,是一个`[f, c, a]`三元组就行
36mod serde {
37    use super::TruthValue;
38    use serde::{Deserialize, Deserializer, Serialize, Serializer};
39
40    impl Serialize for TruthValue {
41        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
42        where
43            S: Serializer,
44        {
45            // 构造[f,c,a]三元组
46            let v = (self.f, self.c, self.a);
47            // 直接委托到表示三元组
48            v.serialize(serializer)
49        }
50    }
51
52    impl<'de> Deserialize<'de> for TruthValue {
53        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
54        where
55            D: Deserializer<'de>,
56        {
57            // 先反序列化到内部整数值
58            let (f, c, a) = Deserialize::deserialize(deserializer)?;
59            // 然后尝试创建,并在其中转换Error类型
60            Ok(Self { f, c, a })
61        }
62    }
63}
64
65impl Truth for TruthValue {
66    #[inline(always)]
67    fn frequency(&self) -> ShortFloat {
68        self.f
69    }
70
71    #[inline(always)]
72    fn frequency_mut(&mut self) -> &mut ShortFloat {
73        &mut self.f
74    }
75
76    #[inline(always)]
77    fn confidence(&self) -> ShortFloat {
78        self.c
79    }
80
81    #[inline(always)]
82    fn confidence_mut(&mut self) -> &mut ShortFloat {
83        &mut self.c
84    }
85
86    #[inline(always)]
87    fn is_analytic(&self) -> bool {
88        self.a
89    }
90
91    #[inline(always)]
92    fn set_analytic(&mut self) {
93        self.a = true;
94    }
95}
96
97/* impl TruthValueConcrete for TruthV1 */
98impl TruthValue {
99    #[inline(always)]
100    pub fn new(frequency: ShortFloat, confidence: ShortFloat, is_analytic: bool) -> Self {
101        Self {
102            f: frequency,
103            c: confidence,
104            a: is_analytic,
105        }
106    }
107
108    pub fn from(truth: &impl Truth) -> Self {
109        Self::new(truth.frequency(), truth.confidence(), truth.is_analytic())
110    }
111
112    pub fn new_fc(frequency: ShortFloat, confidence: ShortFloat) -> Self {
113        Self::new(frequency, confidence, false)
114    }
115
116    pub fn from_floats(frequency: Float, confidence: Float, is_analytic: bool) -> Self {
117        Self::new(
118            ShortFloat::from_float(frequency),
119            ShortFloat::from_float(confidence),
120            is_analytic,
121        )
122    }
123
124    pub fn from_fc(frequency: Float, confidence: Float) -> Self {
125        Self::new_fc(
126            ShortFloat::from_float(frequency),
127            ShortFloat::from_float(confidence),
128        )
129    }
130
131    pub fn new_analytic_default() -> Self {
132        /* 📄OpenNARS源码 @ TruthFunctions:
133        new TruthValue(0.5f, 0f); */
134        Self::new(ShortFloat::HALF, ShortFloat::ZERO, false)
135    }
136
137    pub fn from_lexical(
138        lexical: LexicalTruth,
139        mut default_values: [ShortFloat; 2],
140        is_analytic: bool,
141    ) -> Result<Self> {
142        let truth_s = match lexical.len() {
143            0 => &[],
144            1 => &lexical[0..1],
145            _ => &lexical[0..2],
146        };
147        // 预先解析默认值
148        // ! ⚠️必须合法,否则panic
149        let float_s = &mut default_values;
150        for (i, s) in truth_s.iter().enumerate() {
151            // 浮点解析
152            let v = s.parse::<Float>()?;
153            // 短浮点解析
154            let sf = match ShortFloat::try_from(v) {
155                Ok(sf) => sf,
156                Err(_) => return Err(anyhow::anyhow!("无效短浮点值:{v}")),
157            };
158            float_s[i] = sf;
159        }
160        // 构造
161        let [f, c] = *float_s;
162        Ok(Self::new(f, c, is_analytic))
163    }
164
165    pub fn to_lexical(&self) -> LexicalTruth {
166        vec![
167            self.frequency().to_display_brief(),
168            self.confidence().to_display_brief(),
169        ]
170    }
171}
172
173/// 允许将所有[`Truth`]的引用转换为[`TruthValue`]
174/// * 🚩在其中创建新「真值」对象
175/// * 📝Rust对[`Into`]分派方法时,能实现「自身类型⇒直接传递自身⇒内联」的「零成本抽象」
176impl<T: Truth> From<&T> for TruthValue {
177    fn from(value: &T) -> Self {
178        Self::new(value.frequency(), value.confidence(), value.is_analytic())
179    }
180}
181
182__impl_to_display_and_display! {
183    @(truth_to_display; truth_to_display_brief;)
184    TruthValue as Truth
185}
186
187/// 模拟`equals`
188/// * ⚠️其中[`Self::a`]即`isAnalytic`不参与判等
189impl PartialEq for TruthValue {
190    #[inline(always)]
191    fn eq(&self, other: &Self) -> bool {
192        self.f == other.f && self.c == other.c
193    }
194}
195
196/// 手动实现[`Hash`]
197/// * ⚠️因为[`Self::a`]不参与判等,因此也不能参与到「散列化」中
198impl Hash for TruthValue {
199    fn hash<H: Hasher>(&self, state: &mut H) {
200        self.f.hash(state);
201        self.c.hash(state);
202        // self.a.hash(state);
203    }
204}
205
206/// 转换:涉及「词法Narsese」的解析
207/// * 🚩【2024-05-10 09:40:03】不实现「从字符串解析」
208///   * 无法仅通过「频率」「信度」确定一个「真值」
209///   * [`narsese`]包尚未有简单、直接地解析出「词法真值」的函数
210mod conversion {
211    // ! ❌【2024-05-10 09:35:35】难以仅通过`TryFrom`实现:需要更多参数
212    // ! ❌【2024-05-10 09:35:35】无法批量实现:孤儿规则
213
214    /// 快捷构造宏
215    #[macro_export]
216    macro_rules! truth {
217        // 二参数
218        ($f:expr; $c:expr) => {
219            TruthValue::from_fc($f, $c)
220        };
221        // 三参数
222        ($f:expr; $c:expr; $a:expr) => {
223            TruthValue::from_floats($f, $c, $a)
224        };
225    }
226}
227
228/// 单元测试
229#[cfg(test)]
230mod tests {
231    use super::*;
232    use crate::{ok, truth, util::AResult};
233    use nar_dev_utils::macro_once;
234
235    /// 定义要测试的「真值」类型
236    type TruthV = TruthValue;
237    type SF = ShortFloat;
238
239    // * ✅测试/new已在「快捷构造宏」中实现
240
241    // * ✅测试/from_fc已在「快捷构造宏」中实现
242
243    // * ✅测试/from_float已在「快捷构造宏」中实现
244
245    /// 测试/frequency
246    #[test]
247    fn frequency() -> AResult {
248        macro_once! {
249            /// * 🚩模式:[真值的构造方法] ⇒ 预期「短浮点」浮点值
250            macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
251                $(
252                    assert_eq!(
253                        truth!($($truth)*).frequency(),
254                        SF::from_float($expected)
255                    );
256                )*
257            }
258            [1.0; 0.9] => 1.0
259            [0.1; 0.9] => 0.1
260            [0.0001; 0.9] => 0.0001
261            [0.1024; 0.0] => 0.1024
262            [0.2; 0.1] => 0.2
263        }
264        ok!()
265    }
266
267    /// 测试/frequency_mut
268    #[test]
269    fn frequency_mut() -> AResult {
270        macro_once! {
271            /// * 🚩模式:[真值的构造方法] → 要被赋的值 ⇒ 预期「短浮点」浮点值
272            macro test($( [ $($truth:tt)* ] -> $new_float:tt => $expected:tt)*) {
273                $(
274                    let mut t = truth!($($truth)*);
275                    *t.frequency_mut() = SF::from_float($new_float);
276                    // 可变与不可变一致
277                    assert_eq!(t.frequency(), *t.frequency_mut());
278                    // 修改后与所读值一致
279                    assert_eq!(*t.frequency_mut(), SF::from_float($expected));
280                )*
281            }
282            [1.0; 0.9] -> 0.5 => 0.5
283            [0.1; 0.9] -> 0.2 => 0.2
284            [0.0001; 0.9] -> 0.8 => 0.8
285            [0.1024; 0.0] -> 0.0 => 0.0
286            [0.2; 0.1] -> 1.0 => 1.0
287        }
288        ok!()
289    }
290
291    /// 测试/confidence
292    #[test]
293    fn confidence() -> AResult {
294        macro_once! {
295            /// * 🚩模式:[真值的构造方法] ⇒ 预期「短浮点」浮点值
296            macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
297                $(
298                    assert_eq!(
299                        truth!($($truth)*).confidence(),
300                        SF::from_float($expected)
301                    );
302                )*
303            }
304            [1.0; 0.9] => 0.9
305            [0.1; 0.9] => 0.9
306            [0.0001; 0.9] => 0.9
307            [0.1024; 0.0] => 0.0
308            [0.2; 0.1] => 0.1
309        }
310        ok!()
311    }
312
313    /// 测试/confidence_mut
314    #[test]
315    fn confidence_mut() -> AResult {
316        macro_once! {
317            /// * 🚩模式:[真值的构造方法] → 要被赋的值 ⇒ 预期「短浮点」浮点值
318            macro test($( [ $($truth:tt)* ] -> $new_float:tt => $expected:tt)*) {
319                $(
320                    let mut t = truth!($($truth)*);
321                    *t.confidence_mut() = SF::from_float($new_float);
322                    // 可变与不可变一致
323                    assert_eq!(t.confidence(), *t.confidence_mut());
324                    // 修改后与所读值一致
325                    assert_eq!(*t.confidence_mut(), SF::from_float($expected));
326                )*
327            }
328            [1.0; 0.9] -> 0.5 => 0.5
329            [0.1; 0.9] -> 0.2 => 0.2
330            [0.0001; 0.9] -> 0.8 => 0.8
331            [0.1024; 0.0] -> 0.0 => 0.0
332            [0.2; 0.1] -> 1.0 => 1.0
333        }
334        ok!()
335    }
336
337    /// 测试/is_analytic
338    #[test]
339    fn is_analytic() -> AResult {
340        macro_once! {
341            /// * 🚩模式:[真值的构造方法] ⇒ 预期
342            macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
343                $(
344                    assert_eq!(
345                        truth!($($truth)*).is_analytic(),
346                        $expected
347                    );
348                )*
349            }
350            // 默认值`false`
351            [1.0; 0.9] => false
352            // 指定值
353            [1.0; 0.9; false] => false
354            [1.0; 0.9; true] => true
355        }
356        ok!()
357    }
358
359    // * ✅测试/__is_analytic_mut 已在`set_analytic`中测试过
360
361    /// 测试/set_analytic
362    #[test]
363    fn set_analytic() -> AResult {
364        fn test(mut truth: TruthV) {
365            truth.set_analytic();
366            assert!(truth.is_analytic());
367        }
368        macro_once! {
369            /// * 🚩模式:[真值的构造方法]
370            macro test($( [ $($truth:tt)* ])*) {
371                $(
372                    test(truth!($($truth)*));
373                )*
374            }
375            // 不管最开始是什么,均会变成`true`
376            [1.0; 0.9]
377            [1.0; 0.9; false]
378            [1.0; 0.9; true]
379        }
380        ok!()
381    }
382
383    /// 测试/expectation
384    #[test]
385    fn expectation() -> AResult {
386        fn test(truth: TruthV, expected: Float) {
387            assert_eq!(truth.expectation(), expected);
388        }
389        macro_once! {
390            /// * 🚩模式:[真值的构造方法] ⇒ 预期
391            macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
392                $(
393                    test(truth!($($truth)*), $expected);
394                )*
395            }
396            // * 特殊值矩阵
397            [0.0; 0.0] => 0.5   [0.0; 0.5] => 0.25   [0.0; 1.0] => 0.0
398            [0.5; 0.0] => 0.5   [0.5; 0.5] => 0.5    [0.5; 1.0] => 0.5
399            [1.0; 0.0] => 0.5   [1.0; 0.5] => 0.75   [1.0; 1.0] => 1.0
400            // * 📝公式:$c * (f - 0.5) + 0.5$
401            [1.0; 0.9] => ((0.9 * (1.0 - 0.5)) + 0.5)
402        }
403        ok!()
404    }
405
406    /// 测试/expectation_abs_dif
407    #[test]
408    fn expectation_abs_dif() -> AResult {
409        fn test(truth1: TruthV, truth2: TruthV, expected: Float) {
410            assert_eq!(truth1.expectation_abs_dif(&truth2), expected);
411        }
412        macro_once! {
413            /// * 🚩模式:| [真值的构造方法] - [真值的构造方法] | ⇒ 预期
414            macro test($( | [ $($truth1:tt)* ] - [ $($truth2:tt)* ] | => $expected:tt)*) {
415                $(
416                    test(
417                        truth!($($truth1)*),truth!($($truth2)*),
418                        $expected
419                    );
420                )*
421            }
422            // * 特殊值矩阵(上述矩阵的对边相差)
423            |[0.0; 0.0]-[1.0; 1.0]| => 0.5   |[0.0; 0.5]-[1.0; 0.5]| => 0.5   |[0.0; 1.0]-[1.0; 0.0]| => 0.5
424            |[0.5; 0.0]-[0.5; 1.0]| => 0.0   |[0.5; 0.5]-[0.5; 0.5]| => 0.0   |[0.5; 1.0]-[0.5; 0.0]| => 0.0
425            |[1.0; 0.0]-[0.0; 1.0]| => 0.5   |[1.0; 0.5]-[0.0; 0.5]| => 0.5   |[1.0; 1.0]-[0.0; 0.0]| => 0.5
426            // * 📝公式:
427            // *   | (c1 * (f1 - 0.5) + 0.5) - (c2 * (f2 - 0.5) + 0.5) |
428            // * = |  c1(f1 - 0.5) - c2(f2 - 0.5) |
429            // * = |  c1 f1 - c2 f2 - 0.5(c1 - c2) |
430            |[1.0; 0.9] - [0.8; 0.3]| => ((1.0*0.9 - 0.8*0.3 - 0.5*(0.9 - 0.3) as Float).abs())
431        }
432        ok!()
433    }
434
435    /// 测试/is_negative
436    #[test]
437    fn is_negative() -> AResult {
438        fn test(truth: TruthV, expected: bool) {
439            assert_eq!(truth.is_negative(), expected);
440        }
441        macro_once! {
442            /// * 🚩模式:[真值的构造方法] ⇒ 预期
443            macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
444                $(
445                    test(truth!($($truth)*), $expected);
446                )*
447            }
448            [1.0; 0.9] => false
449            [0.9; 0.9] => false
450            [0.8; 0.9] => false
451            [0.7; 0.9] => false
452            [0.6; 0.9] => false
453            [0.5; 0.9] => false
454            // [0.49995; 0.9] => false // 这个舍入到了0.5 | ❓边缘情况是否真的要纳入「单元测试」
455            // 0.5以下均为「负面」
456            // [0.49994; 0.9] => true
457            [0.4; 0.9] => true
458            [0.3; 0.9] => true
459            [0.2; 0.9] => true
460            [0.1; 0.9] => true
461            [0.0; 0.9] => true
462        }
463        ok!()
464    }
465
466    /// 测试/to_display
467    #[test]
468    fn to_display() -> AResult {
469        macro_once! {
470            /// * 🚩模式:[真值的构造方法] ⇒ 预期
471            macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
472                $(
473                    assert_eq!(
474                        truth!($($truth)*).to_display(),
475                        $expected
476                    );
477                )*
478            }
479            // ! 注意:OpenNARS中格式化出的「真值」没有空格
480            // 0
481            [0.0   ; 0.0   ] => "%0.0000;0.0000%"
482            // 1与非1
483            [1.0   ; 1.0   ] => "%1.0000;1.0000%"
484            [1.0   ; 0.9   ] => "%1.0000;0.9000%"
485            [0.9   ; 1.0   ] => "%0.9000;1.0000%"
486            [0.9   ; 0.9   ] => "%0.9000;0.9000%"
487            // 各个位数
488            [0.1   ; 0.42  ] => "%0.1000;0.4200%"
489            [0.137 ; 0.442 ] => "%0.1370;0.4420%"
490            [0.1024; 0.2185] => "%0.1024;0.2185%"
491        }
492        ok!()
493    }
494
495    /// 测试/to_display_brief
496    #[test]
497    fn to_display_brief() -> AResult {
498        macro_once! {
499            /// * 🚩模式:[真值的构造方法] ⇒ 预期
500            macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
501                $(
502                    assert_eq!(
503                        truth!($($truth)*).to_display_brief(),
504                        $expected
505                    );
506                )*
507            }
508            // ! 注意:OpenNARS中格式化出的「真值」没有空格
509            // 0
510            [0.0   ; 0.0   ] => "%0.00;0.00%"
511            // 1与非1
512            [1.0   ; 1.0   ] => "%1.00;1.00%"
513            [1.0   ; 0.9   ] => "%1.00;0.90%"
514            [0.9   ; 1.0   ] => "%0.90;1.00%"
515            [0.9   ; 0.9   ] => "%0.90;0.90%"
516            // 各个位数
517            [0.1   ; 0.42  ] => "%0.10;0.42%"
518            [0.137 ; 0.442 ] => "%0.14;0.44%" // ! 五入四舍
519            [0.1024; 0.2185] => "%0.10;0.22%" // ! 四舍五入
520            [0.999 ; 0.9999] => "%1.00;1.00%" // ! 五入到`1`
521        }
522        ok!()
523    }
524
525    /// 测试/from_lexical
526    #[test]
527    fn from_lexical() -> AResult {
528        fn test(lexical: LexicalTruth, truth: TruthV, fc: [Float; 2], is_analytic: bool) {
529            // 解析
530            let [f, c] = fc;
531            let parsed = TruthV::from_lexical(
532                lexical,
533                [
534                    // 默认值(完全限定语法)
535                    ShortFloat::from_float(f),
536                    ShortFloat::from_float(c),
537                ],
538                is_analytic,
539            )
540            .unwrap();
541            // 判等
542            assert_eq!(parsed, truth);
543        }
544        macro_once! {
545            /// * 🚩模式:[词法真值构造方法] ⇒ 预期[真值的构造方法]
546            macro test($(
547                [ $($lexical:tt)* ] @ [$f:expr; $c:expr; $is_analytic:expr]
548                => [ $($truth:tt)* ] )*
549            ) {
550                $(
551                    test(
552                        narsese::lexical_truth!($($lexical)*),
553                        truth!($($truth)*),
554                        [$f, $c],
555                        $is_analytic
556                    );
557                )*
558            }
559            // 完全解析
560            ["1.0" "0.9"] @ [0.0; 0.0; false] => [1.0; 0.9; false]
561            ["1.0" "0.9"] @ [0.0; 0.0; true] => [1.0; 0.9; true]
562            ["0.0" "0.0"] @ [1.0; 0.9; false] => [0.0; 0.0; false]
563            ["0.0" "0.0"] @ [1.0; 0.9; true] => [0.0; 0.0; true]
564            // 缺省
565            ["0.0"] @ [1.0; 0.9; true] => [0.0; 0.9; true]
566            [] @ [1.0; 0.9; true] => [1.0; 0.9; true]
567            // 多余
568            ["0.0" "0.1" "0.2"] @ [1.0; 0.9; true] => [0.0; 0.1; true]
569            ["0.0" "0.1" "0.2" "0.3"] @ [1.0; 0.9; true] => [0.0; 0.1; true]
570            ["0.0" "0.1" "ARCJ" "137442"] @ [1.0; 0.9; true] => [0.0; 0.1; true]
571        }
572        ok!()
573    }
574}