Skip to main content

narust_158/inference/
budget_inference.rs

1//! 预算推理
2//! * 📄跟从改版OpenNARS的代码安排
3//! * 🎯存储【非纯函数式】【与控制机制直接相关】的预算函数
4
5use super::{BudgetInferenceFunction, BudgetInferenceResult, Truth};
6use crate::{
7    control::ReasonContextWithLinks,
8    entity::{BudgetValue, ShortFloat, TLink, TruthValue},
9    inference::{Budget, BudgetFunctions, ReviseResult},
10    language::Term,
11};
12use nar_dev_utils::{OrSomeRef, RefCount};
13
14/// 预算推理
15pub trait BudgetInference: Budget {
16    /// 🆕模拟`BudgetValue.merge`,亦与`BudgetInference.merge`相同
17    /// * 📌此处承载「预算函数」的修改语义
18    /// * 📝若不限定`Self: Sized`,则对`new_budget`的赋值有问题
19    fn merge_from(&mut self, other: &impl Budget)
20    where
21        Self: Sized,
22    {
23        let this = &*self;
24        let new_budget = this.merge(other);
25        self.copy_budget_from(&new_budget);
26    }
27
28    /// 修正@直接推理
29    /// * 🚩【2024-05-21 10:30:50】现在仅用于直接推理,但逻辑可以共用:「反馈到链接」与「具体任务计算」并不矛盾
30    ///
31    /// # 📄OpenNARS
32    ///
33    /// Evaluate the quality of a revision, then de-prioritize the premises
34    fn revise_direct(
35        new_belief_truth: &impl Truth,
36        old_belief_truth: &impl Truth,
37        revised_truth: &impl Truth,
38        current_task_budget: &mut impl Budget,
39    ) -> BudgetValue {
40        // * 🚩计算
41        let ReviseResult {
42            new_budget,
43            new_task_budget,
44            ..
45        } = BudgetValue::revise(
46            new_belief_truth,
47            old_belief_truth,
48            revised_truth,
49            current_task_budget,
50            None::<(&BudgetValue, &BudgetValue)>,
51        );
52        // * 🚩应用修改
53        current_task_budget.copy_budget_from(&new_task_budget);
54        // * 🚩返回
55        new_budget
56    }
57}
58
59/// 自动实现「预算推理」
60/// * 🎯直接在「预算值」上加功能
61impl<B: Budget> BudgetInference for B {}
62
63use BudgetInferenceFunction::*;
64/// 🆕为「推理上下文」实现的「预算推理」系列方法
65pub trait BudgetInferenceContext: ReasonContextWithLinks {
66    /// 🆕同{@link BudgetInference#revise},但是「概念推理」专用
67    /// * 🚩在「共用逻辑」后,将预算值反馈回「词项链」「任务链」
68    fn revise_matching(
69        &mut self,
70        new_belief_truth: &impl Truth,
71        old_belief_truth: &impl Truth,
72        revised_truth: &impl Truth,
73    ) -> BudgetValue {
74        // * 🚩计算
75        let current_task = self.current_task();
76        let current_task_link = self.current_task_link();
77        let current_belief_link = self.belief_link_for_budget_inference();
78        let current_links_budget = current_belief_link.map(|b_link| (current_task_link, b_link));
79        let result = BudgetValue::revise(
80            new_belief_truth,
81            old_belief_truth,
82            revised_truth,
83            &*current_task.get_(),
84            current_links_budget,
85        );
86        // * 🚩应用修改
87        // 任务更新
88        drop(current_task);
89        self.current_task_mut()
90            .mut_()
91            .copy_budget_from(&result.new_task_budget);
92        // 链接更新
93        if let Some([new_t_budget, new_b_budget]) = result.new_links_budget {
94            let current_task_link = self.current_task_link_mut();
95            current_task_link.copy_budget_from(&new_t_budget);
96            if let Some(current_belief_link) = self.belief_link_for_budget_inference_mut() {
97                current_belief_link.copy_budget_from(&new_b_budget);
98            }
99        }
100        // * 🚩返回
101        result.new_budget
102    }
103
104    /// # 📄OpenNARS
105    ///
106    /// Forward inference result and adjustment
107    fn budget_forward<T: Truth>(&mut self, truth: impl OrSomeRef<T>) -> BudgetValue {
108        self.budget_inference(Forward, truth.or_some_ref(), None)
109    }
110
111    /// # 📄OpenNARS
112    ///
113    /// Backward inference result and adjustment, stronger case
114    fn budget_backward<T: Truth>(&mut self, truth: impl OrSomeRef<T>) -> BudgetValue {
115        self.budget_inference(Backward, truth.or_some_ref(), None)
116    }
117
118    /// # 📄OpenNARS
119    ///
120    /// Backward inference result and adjustment, weaker case
121    fn budget_backward_weak<T: Truth>(&mut self, truth: impl OrSomeRef<T>) -> BudgetValue {
122        self.budget_inference(BackwardWeak, truth.or_some_ref(), None)
123    }
124
125    /// # 📄OpenNARS
126    ///
127    /// Forward inference with CompoundTerm conclusion
128    fn budget_compound_forward<T: Truth>(
129        &mut self,
130        truth: impl OrSomeRef<T>,
131        content: impl OrSomeRef<Term>,
132    ) -> BudgetValue {
133        self.budget_inference(CompoundForward, truth.or_some_ref(), content.or_some_ref())
134    }
135
136    /// # 📄OpenNARS
137    ///
138    /// Backward inference with CompoundTerm conclusion, stronger case
139    fn budget_compound_backward(&mut self, content: impl OrSomeRef<Term>) -> BudgetValue {
140        self.budget_inference(CompoundBackward, None::<&TruthValue>, content.or_some_ref())
141    }
142
143    /// # 📄OpenNARS
144    ///
145    /// Backward inference with CompoundTerm conclusion, weaker case
146    fn budget_compound_backward_weak(&mut self, content: impl OrSomeRef<Term>) -> BudgetValue {
147        self.budget_inference(
148            CompoundBackwardWeak,
149            None::<&TruthValue>,
150            content.or_some_ref(),
151        )
152    }
153
154    /// # 📄OpenNARS
155    ///
156    /// Common processing for all inference step
157    fn budget_inference(
158        &mut self,
159        function: BudgetInferenceFunction,
160        truth: Option<&impl Truth>,
161        content: Option<&Term>,
162    ) -> BudgetValue {
163        // * 🚩获取有关「词项链」「任务链」的有关参数
164        let t_link = self.current_task_link();
165        let b_link = self.belief_link_for_budget_inference();
166        // * 🚩非空时计算,其它默认为0(转换推理不会用到)
167        let target_activation = b_link.map_or(ShortFloat::ZERO, |b_link| {
168            self.concept_activation(&b_link.target())
169        });
170        // * 🚩计算新结果
171        let result = BudgetValue::budget_inference(
172            function,
173            truth,
174            content,
175            t_link,
176            b_link,
177            target_activation,
178        );
179        // * 🚩应用新结果
180        let b_link = self.belief_link_for_budget_inference_mut();
181        Self::budget_inference_apply(result, b_link)
182    }
183
184    /// Get the current activation level of a concept.
185    /// * 🚩从「概念」中来
186    /// * 🚩【2024-06-22 16:59:34】因涉及控制机制(推理上下文),故放入此中
187    fn concept_activation(&self, term: &Term) -> ShortFloat {
188        self.term_to_concept(term)
189            .map_or(ShortFloat::ZERO, |c| c.priority())
190    }
191
192    /// 🆕根据计算出的「预算函数」应用其中的结果
193    /// * 🚩覆盖各处预算值,并以此更新
194    /// * 🚩返回得出的「新预算值」
195    fn budget_inference_apply(
196        result: BudgetInferenceResult,
197        belief_link_budget: Option<&mut impl Budget>,
198    ) -> BudgetValue {
199        // * 🚩拿出「新信念链预算」并更新
200        if let (Some(b_budget), Some(ref new_budget)) =
201            (belief_link_budget, result.new_belief_link_budget)
202        {
203            b_budget.copy_budget_from(new_budget);
204        }
205        // * 🚩拿出「新预算」并返回
206        result.new_budget
207    }
208}
209impl<C: ReasonContextWithLinks> BudgetInferenceContext for C {}
210
211/// TODO: 单元测试
212#[cfg(test)]
213mod tests {
214    // * merge_from
215    // * revise_direct
216    // * revise_matching
217    // * budget_forward
218    // * budget_backward
219    // * budget_backward_weak
220    // * budget_compound_forward
221    // * budget_compound_backward
222    // * budget_compound_backward_weak
223    // * budget_inference
224    // * concept_activation
225    // * budget_inference_apply
226}