narust_158/entity/float_values/
truth_value.rs1use 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#[derive(Debug, Clone, Copy, Default, Eq)]
24pub struct TruthValue {
25 f: ShortFloat,
27 c: ShortFloat,
29 a: bool,
31}
32
33mod 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 let v = (self.f, self.c, self.a);
47 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 let (f, c, a) = Deserialize::deserialize(deserializer)?;
59 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
97impl 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 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 let float_s = &mut default_values;
150 for (i, s) in truth_s.iter().enumerate() {
151 let v = s.parse::<Float>()?;
153 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 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
173impl<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
187impl 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
196impl Hash for TruthValue {
199 fn hash<H: Hasher>(&self, state: &mut H) {
200 self.f.hash(state);
201 self.c.hash(state);
202 }
204}
205
206mod conversion {
211 #[macro_export]
216 macro_rules! truth {
217 ($f:expr; $c:expr) => {
219 TruthValue::from_fc($f, $c)
220 };
221 ($f:expr; $c:expr; $a:expr) => {
223 TruthValue::from_floats($f, $c, $a)
224 };
225 }
226}
227
228#[cfg(test)]
230mod tests {
231 use super::*;
232 use crate::{ok, truth, util::AResult};
233 use nar_dev_utils::macro_once;
234
235 type TruthV = TruthValue;
237 type SF = ShortFloat;
238
239 #[test]
247 fn frequency() -> AResult {
248 macro_once! {
249 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 #[test]
269 fn frequency_mut() -> AResult {
270 macro_once! {
271 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 assert_eq!(t.frequency(), *t.frequency_mut());
278 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 #[test]
293 fn confidence() -> AResult {
294 macro_once! {
295 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 #[test]
315 fn confidence_mut() -> AResult {
316 macro_once! {
317 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 assert_eq!(t.confidence(), *t.confidence_mut());
324 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 #[test]
339 fn is_analytic() -> AResult {
340 macro_once! {
341 macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
343 $(
344 assert_eq!(
345 truth!($($truth)*).is_analytic(),
346 $expected
347 );
348 )*
349 }
350 [1.0; 0.9] => false
352 [1.0; 0.9; false] => false
354 [1.0; 0.9; true] => true
355 }
356 ok!()
357 }
358
359 #[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 macro test($( [ $($truth:tt)* ])*) {
371 $(
372 test(truth!($($truth)*));
373 )*
374 }
375 [1.0; 0.9]
377 [1.0; 0.9; false]
378 [1.0; 0.9; true]
379 }
380 ok!()
381 }
382
383 #[test]
385 fn expectation() -> AResult {
386 fn test(truth: TruthV, expected: Float) {
387 assert_eq!(truth.expectation(), expected);
388 }
389 macro_once! {
390 macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
392 $(
393 test(truth!($($truth)*), $expected);
394 )*
395 }
396 [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 [1.0; 0.9] => ((0.9 * (1.0 - 0.5)) + 0.5)
402 }
403 ok!()
404 }
405
406 #[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 macro test($( | [ $($truth1:tt)* ] - [ $($truth2:tt)* ] | => $expected:tt)*) {
415 $(
416 test(
417 truth!($($truth1)*),truth!($($truth2)*),
418 $expected
419 );
420 )*
421 }
422 |[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 |[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 #[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 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.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 #[test]
468 fn to_display() -> AResult {
469 macro_once! {
470 macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
472 $(
473 assert_eq!(
474 truth!($($truth)*).to_display(),
475 $expected
476 );
477 )*
478 }
479 [0.0 ; 0.0 ] => "%0.0000;0.0000%"
482 [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 [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 #[test]
497 fn to_display_brief() -> AResult {
498 macro_once! {
499 macro test($( [ $($truth:tt)* ] => $expected:tt)*) {
501 $(
502 assert_eq!(
503 truth!($($truth)*).to_display_brief(),
504 $expected
505 );
506 )*
507 }
508 [0.0 ; 0.0 ] => "%0.00;0.00%"
511 [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 [0.1 ; 0.42 ] => "%0.10;0.42%"
518 [0.137 ; 0.442 ] => "%0.14;0.44%" [0.1024; 0.2185] => "%0.10;0.22%" [0.999 ; 0.9999] => "%1.00;1.00%" }
522 ok!()
523 }
524
525 #[test]
527 fn from_lexical() -> AResult {
528 fn test(lexical: LexicalTruth, truth: TruthV, fc: [Float; 2], is_analytic: bool) {
529 let [f, c] = fc;
531 let parsed = TruthV::from_lexical(
532 lexical,
533 [
534 ShortFloat::from_float(f),
536 ShortFloat::from_float(c),
537 ],
538 is_analytic,
539 )
540 .unwrap();
541 assert_eq!(parsed, truth);
543 }
544 macro_once! {
545 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 ["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 ["0.0"] @ [1.0; 0.9; true] => [0.0; 0.9; true]
566 [] @ [1.0; 0.9; true] => [1.0; 0.9; true]
567 ["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}