narust_158/entity/linkages/
term_link.rs

1//! 词项链
2
3use super::{TLink, TLinkType, TLinkage, TermLinkTemplate};
4use crate::{
5    entity::{BudgetValue, Item, ShortFloat, Token},
6    inference::Budget,
7    language::Term,
8    util::ToDisplayAndBrief,
9};
10use nar_dev_utils::join;
11use serde::{Deserialize, Serialize};
12use std::ops::{Deref, DerefMut};
13
14/// 词项链
15///
16/// # 📄OpenNARS
17///
18/// A link between a compound term and a component term
19///
20/// A TermLink links the current Term to a target Term, which is either a component of, or compound made from, the current term.///
21///
22/// Neither of the two terms contain variable shared with other terms.///
23///
24/// The index value(s) indicates the location of the component in the compound.///
25///
26/// This class is mainly used in inference.RuleTable to dispatch premises to inference rules
27#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
28pub struct TermLink {
29    /// 🆕纯粹的T链接类型
30    inner: TLinkage<Term>,
31    /// 🆕Item令牌
32    token: Token,
33}
34
35impl TermLink {
36    fn new(
37        target: Term,
38        budget: BudgetValue,
39        link_type: TLinkType,
40        indexes: impl Into<Box<[usize]>>,
41    ) -> Self {
42        let indexes = indexes.into();
43        let key = Self::generate_key_for_term_link(&target, link_type, &indexes);
44        let inner = TLinkage::new_direct(target, link_type, indexes);
45        Self {
46            token: Token::new(key, budget),
47            inner,
48        }
49    }
50
51    pub fn from_template(target: Term, template: &TermLinkTemplate, budget: BudgetValue) -> Self {
52        // * 🚩生成类型与索引
53        let link_type = Self::generate_type_from_template(&target, template);
54        let indexes = template.indexes().to_vec().into_boxed_slice();
55        // * 🚩构造
56        Self::new(target, budget, link_type, indexes)
57    }
58
59    /// 不同于默认方法,但要调用默认方法
60    /// * 🎯从「目标」、已生成的「类型」「索引」生成「键」
61    fn generate_key_for_term_link(
62        target: &Term,
63        link_type: TLinkType,
64        indexes: &[usize],
65    ) -> String {
66        // * 🚩标准T链接子串 + 词项的字符串形式
67        Self::generate_key_base(link_type, indexes) + &target.to_string()
68    }
69
70    fn generate_type_from_template(target: &Term, template: &TermLinkTemplate) -> TLinkType {
71        let template_type = template.link_type();
72        // * 🚩断言此时「链接模板」的链接类型:必定是「从元素链接到整体」
73        debug_assert!(
74            template_type.is_to_compound(),
75            "模板必定是「从元素链接到整体」"
76        );
77        // * 🚩开始计算类型
78        match template.will_from_self_to() == target {
79            // * 🚩自「元素→整体」来(复合词项的「模板链接」指向自身)
80            // * 🚩到「整体→元素」去
81            // * 📄【2024-06-04 20:35:22】
82            // * Concept@48 "<{tim} --> (/,livingIn,_,{graz})>" ~> target="{tim}"
83            // * + template: willFromSelfTo="{tim}"
84            // * 📄【2024-06-04 20:35:32】
85            // * Concept@52 "<{tim} --> (/,livingIn,_,{graz})>" ~> target="tim"
86            // * + template: willFromSelfTo="tim"
87            true => template_type.try_point_to_component(),
88            false => template_type,
89        }
90    }
91}
92
93// 委托[`Token`]实现
94impl Budget for TermLink {
95    fn priority(&self) -> ShortFloat {
96        self.token.priority()
97    }
98
99    fn __priority_mut(&mut self) -> &mut ShortFloat {
100        self.token.__priority_mut()
101    }
102
103    fn durability(&self) -> ShortFloat {
104        self.token.durability()
105    }
106
107    fn __durability_mut(&mut self) -> &mut ShortFloat {
108        self.token.__durability_mut()
109    }
110
111    fn quality(&self) -> ShortFloat {
112        self.token.quality()
113    }
114
115    fn __quality_mut(&mut self) -> &mut ShortFloat {
116        self.token.__quality_mut()
117    }
118}
119
120// 委托[`Token`]实现
121impl Item for TermLink {
122    fn key(&self) -> &String {
123        self.token.key()
124    }
125}
126
127// 委托[`TLinkage`]实现
128impl TLink<Term> for TermLink {
129    fn target<'r, 's: 'r>(&'s self) -> impl Deref<Target = Term> + 'r {
130        self.inner.target()
131    }
132
133    fn target_mut<'r, 's: 'r>(&'s mut self) -> impl DerefMut<Target = Term> + 'r {
134        self.inner.target_mut()
135    }
136
137    fn link_type(&self) -> super::TLinkType {
138        self.inner.link_type()
139    }
140
141    fn indexes(&self) -> &[usize] {
142        self.inner.indexes()
143    }
144}
145
146impl ToDisplayAndBrief for TermLink {
147    fn to_display(&self) -> String {
148        join! {
149            => self.token.budget_to_display()
150            => " "
151            => self.key()
152        }
153    }
154
155    fn to_display_brief(&self) -> String {
156        join! {
157            => self.token.budget_to_display_brief()
158            => " "
159            => self.key()
160        }
161    }
162}