#![doc(alias = "derivation_context")]
use crate::{
control::{util_outputs, Reasoner},
entity::{
Concept, JudgementV1, Punctuation, RCTask, Sentence, ShortFloat, Task, TaskLink, TermLink,
},
global::{ClockTime, Float},
language::Term,
parameters::Parameters,
storage::Memory,
};
use nar_dev_utils::RefCount;
use navm::output::Output;
use rand::RngCore;
use std::ops::{Deref, DerefMut};
pub trait ReasonContext {
fn reasoner(&self) -> &Reasoner;
fn reasoner_mut(&mut self) -> &mut Reasoner;
fn memory(&self) -> &Memory;
fn time(&self) -> ClockTime;
fn parameters(&self) -> &Parameters;
fn max_evidence_base_length(&self) -> usize {
self.parameters().maximum_stamp_length
}
#[doc(alias = "reliance")]
fn reasoning_reliance(&self) -> ShortFloat {
ShortFloat::from_float(self.parameters().reliance)
}
fn volume_percent(&self) -> Float;
fn silence_percent(&self) -> Float {
1.0 - self.volume_percent()
}
#[inline]
fn shuffle_rng_seeds<T: ContextRngSeedGen>(&mut self) -> T {
let rng = &mut self.reasoner_mut().shuffle_rng;
let generate = || rng.next_u64();
T::generate_seed_from_context(generate)
}
fn has_result(&self) -> bool {
self.num_new_tasks() > 0
}
fn num_new_tasks(&self) -> usize;
fn add_new_task(&mut self, task: Task);
#[doc(alias = "add_export_string")]
#[doc(alias = "add_string_to_record")]
#[doc(alias = "add_output")]
fn report(&mut self, output: Output);
fn report_comment(&mut self, message: impl ToString) {
if self.volume_percent() >= util_outputs::COMMENT_VOLUME_THRESHOLD_PERCENT {
self.report(util_outputs::output_comment(message));
}
}
fn report_out(&mut self, narsese: &Task) {
self.report(util_outputs::output_out(narsese))
}
fn report_error(&mut self, description: impl ToString) {
self.report(util_outputs::output_error(description))
}
fn current_concept(&self) -> &Concept;
fn current_concept_mut(&mut self) -> &mut Concept;
fn current_term(&self) -> &Term {
self.current_concept().term()
}
fn term_to_concept(&self, term: &Term) -> Option<&Concept> {
match term == self.current_term() {
true => Some(self.current_concept()),
false => self.memory().term_to_concept(term),
}
}
fn key_to_concept(&self, key: &str) -> Option<&Concept> {
match key == Memory::term_to_key(self.current_term()) {
true => Some(self.current_concept()),
false => self.memory().key_to_concept(key),
}
}
fn current_task<'r, 's: 'r>(&'s self) -> impl Deref<Target = RCTask> + 'r;
fn current_task_mut<'r, 's: 'r>(&'s mut self) -> impl DerefMut<Target = RCTask> + 'r;
fn reason_direction(&self) -> ReasonDirection {
use Punctuation::*;
use ReasonDirection::*;
match self.current_task().get_().punctuation() {
Judgement => Forward,
Question => Backward,
}
}
fn absorbed_by_reasoner(self);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ReasonDirection {
Forward,
Backward,
}
pub trait ReasonContextWithLinks: ReasonContext {
fn current_belief(&self) -> Option<&JudgementV1>;
fn has_current_belief(&self) -> bool {
self.current_belief().is_some()
}
fn belief_link_for_budget_inference(&self) -> Option<&TermLink>;
fn belief_link_for_budget_inference_mut(&mut self) -> Option<&mut TermLink>;
fn current_task_link(&self) -> &TaskLink;
fn current_task_link_mut(&mut self) -> &mut TaskLink;
}
#[derive(Debug)]
pub struct ReasonContextCore<'this> {
pub(in crate::control) reasoner: &'this mut Reasoner,
time: ClockTime,
volume: usize,
pub(in crate::control) current_concept: Concept,
}
impl<'this> ReasonContextCore<'this> {
pub fn new<'p: 'this>(reasoner: &'p mut Reasoner, current_concept: Concept) -> Self {
Self {
time: reasoner.time(),
volume: reasoner.volume(),
current_concept,
reasoner,
}
}
}
impl ReasonContextCore<'_> {
pub fn reasoner_mut(&mut self) -> &mut Reasoner {
self.reasoner
}
pub fn memory(&self) -> &Memory {
&self.reasoner.memory
}
pub fn memory_mut(&mut self) -> &mut Memory {
&mut self.reasoner.memory
}
pub fn time(&self) -> ClockTime {
self.time
}
pub fn parameters(&self) -> &Parameters {
&self.reasoner.parameters
}
pub fn volume_percent(&self) -> Float {
self.volume as Float / 100.0
}
pub fn current_concept(&self) -> &Concept {
&self.current_concept
}
pub fn current_concept_mut(&mut self) -> &mut Concept {
&mut self.current_concept
}
pub fn absorbed_by_reasoner(self, outs: ReasonContextCoreOut) {
let reasoner = self.reasoner;
let memory = reasoner.memory_mut();
memory.put_back_concept(self.current_concept);
outs.absorbed_by_reasoner(reasoner);
}
}
#[derive(Debug, Clone, Default)]
pub struct ReasonContextCoreOut {
pub(in crate::control) new_tasks: Vec<Task>,
pub(in crate::control) outputs: Vec<Output>,
}
impl ReasonContextCoreOut {
pub fn new() -> Self {
Self::default()
}
pub fn absorbed_by_reasoner(self, reasoner: &mut Reasoner) {
for new_task in self.new_tasks {
reasoner.task_buffer.add_task(new_task);
}
for output in self.outputs {
reasoner.report(output);
}
}
pub fn num_new_tasks(&self) -> usize {
self.new_tasks.len()
}
pub fn add_new_task(&mut self, task: Task) {
self.new_tasks.push(task);
}
pub fn add_output(&mut self, output: Output) {
self.outputs.push(output);
}
}
#[macro_export]
macro_rules! __delegate_from_core {
() => {
fn reasoner(&self) -> &Reasoner {
&self.core.reasoner
}
fn reasoner_mut(&mut self) -> &mut Reasoner {
&mut self.core.reasoner
}
fn memory(&self) -> &Memory {
self.core.memory()
}
fn time(&self) -> ClockTime {
self.core.time()
}
fn parameters(&self) -> &Parameters {
self.core.parameters()
}
fn volume_percent(&self) -> Float {
self.core.volume_percent()
}
fn num_new_tasks(&self) -> usize {
self.outs.num_new_tasks()
}
fn add_new_task(&mut self, task: Task) {
self.outs.add_new_task(task)
}
fn report(&mut self, output: Output) {
self.outs.add_output(output);
}
fn current_concept(&self) -> &Concept {
self.core.current_concept()
}
fn current_concept_mut(&mut self) -> &mut Concept {
self.core.current_concept_mut()
}
};
}
pub type RngSeed = u64;
pub trait ContextRngSeedGen: Sized {
fn generate_seed_from_context(generate: impl FnMut() -> RngSeed) -> Self;
}
impl ContextRngSeedGen for RngSeed {
#[inline(always)]
fn generate_seed_from_context(mut generate: impl FnMut() -> RngSeed) -> Self {
generate()
}
}
impl<const N: usize> ContextRngSeedGen for [u64; N] {
#[inline]
fn generate_seed_from_context(mut generate: impl FnMut() -> u64) -> Self {
let mut result = [0; N];
for value_ref in result.iter_mut() {
*value_ref = generate();
}
result
}
}