use crate::{
control::{
ContextDerivationConcept, ReasonContext, ReasonContextConcept, ReasonContextWithLinks,
},
entity::{Judgement, PunctuatedSentenceRef, Sentence, Stamp, TruthValue},
inference::{
try_solution_apply_context, try_solution_apply_task, try_solution_calculate,
BudgetInferenceContext, TruthFunctions,
},
language::{variable_process, Term},
};
use nar_dev_utils::{unwrap_or_return, RefCount};
pub fn match_task_and_belief(context: &mut ReasonContextConcept) {
let shuffle_rng_seed = context.shuffle_rng_seeds(); let current_belief = unwrap_or_return!(?context.current_belief());
let current_task_rc = context.current_task();
let current_task = current_task_rc.get_();
let current_task_punctuation = current_task.as_punctuated_ref();
use PunctuatedSentenceRef::*;
match current_task_punctuation {
Judgement(judgement) => {
if judgement.revisable_to(current_belief) {
let (content, truth, stamp) = revision(judgement, current_belief, context);
let [current_task_truth, current_belief_truth] = [
TruthValue::from(judgement),
TruthValue::from(current_belief),
]; drop(current_task);
drop(current_task_rc);
let budget =
context.revise_matching(¤t_task_truth, ¤t_belief_truth, &truth);
context.double_premise_task_full(None, content, Some((truth, true)), budget, stamp);
}
}
Question(question) => {
let has_unified = variable_process::has_unification_q(
question.content(),
current_belief.content(),
shuffle_rng_seed,
);
if has_unified {
let result = try_solution_calculate(
current_belief,
¤t_task,
context.parameters().budget_threshold,
);
drop(current_task);
drop(current_task_rc);
let current_belief = current_belief.clone(); let mut current_task_rc = context.current_task_mut();
let mut current_task = current_task_rc.mut_();
try_solution_apply_task(&result, &mut current_task, ¤t_belief);
drop(current_task);
drop(current_task_rc);
try_solution_apply_context(result, ¤t_belief, context);
}
}
}
}
fn revision(
new_belief: &impl Judgement,
old_belief: &impl Judgement,
context: &ReasonContextConcept,
) -> (Term, TruthValue, Stamp) {
let content = new_belief.content().clone();
let revised_truth = new_belief.revision(old_belief);
let new_stamp = Stamp::from_merge_unchecked(
new_belief,
old_belief,
context.time(),
context.max_evidence_base_length(),
);
(content, revised_truth, new_stamp)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{
expect_narsese_term,
inference::{process_direct, tools::*, InferenceEngine},
};
const ENGINE: InferenceEngine = InferenceEngine::new(
process_direct, InferenceEngine::ECHO.transform_f(),
match_task_and_belief,
InferenceEngine::ECHO.reason_f(),
);
#[test]
fn revise_after_direct() {
let mut vm = create_reasoner_from_engine(ENGINE);
vm.input_fetch_print_expect(
"
nse Sentence. %1.0;0.5%
cyc 5
nse Sentence. %0.0;0.5%
cyc 5
",
expect_narsese_term!(OUT "Sentence" in outputs),
);
}
#[test]
fn answer_after_revise() {
let mut vm = create_reasoner_from_engine(ENGINE);
vm.input_fetch_print_expect(
"
nse Sentence. %1.0;0.5%
cyc 2
nse Sentence?
cyc 2
",
expect_narsese_term!(ANSWER "Sentence" in outputs),
);
vm.input_fetch_print_expect(
"
nse Sentence. %0.0;0.5%
cyc 2
",
expect_narsese_term!(ANSWER "Sentence" in outputs),
);
vm.input_fetch_print_expect(
"
nse Sentence. %0.5;0.5%
cyc 2
",
expect_narsese_term!(ANSWER "Sentence" in outputs),
);
}
#[test]
fn answer_question_with_variables() {
let mut vm = create_reasoner_from_engine(ENGINE);
vm.input_fetch_print_expect(
"
nse <A --> B>.
cyc 5
nse <?1 --> B>?
cyc 50
",
expect_narsese_term!(ANSWER "<A --> B>" in outputs),
);
vm.input_fetch_print_expect(
"
res
nse <A --> B>.
cyc 5
nse <A --> ?1>?
cyc 50
",
expect_narsese_term!(ANSWER "<A --> B>" in outputs),
);
}
#[test]
fn stability() {
let mut vm = create_reasoner_from_engine(ENGINE);
for i in 0..0x10 {
let _outs = vm.input_cmds_and_fetch_out(&format!(
"
nse <A{i} --> B>. %1.0;0.9%
cyc 5
nse <A{i} --> B>. %0.0;0.9%
cyc 5
nse <A{i} --> B>?
cyc 5
"
));
}
vm.input_cmds("cyc 1000");
}
}