diff --git a/pynars/Config.py b/pynars/Config.py index 22cb8f78..93ac5a44 100644 --- a/pynars/Config.py +++ b/pynars/Config.py @@ -71,6 +71,12 @@ class Config: rate_discount_p_internal_exp = 0.1 rate_discount_d_internal_exp = 0.1 + # parameters for updating the Budget of Concept. + # Lower values means it is harder to change the budget, higher values means it is easier to change the budget + concept_update_durability_weight = 0.1 + concept_update_quality_weight = 0.1 + + # temporal parameters temporal_duration = 5 n_sequence_attempts = 10 n_op_condition_attempts = 10 diff --git a/pynars/NARS/DataStructures/_py/Concept.py b/pynars/NARS/DataStructures/_py/Concept.py index 05dc1051..948f19bb 100644 --- a/pynars/NARS/DataStructures/_py/Concept.py +++ b/pynars/NARS/DataStructures/_py/Concept.py @@ -1,4 +1,6 @@ from typing import Tuple, Type, List, Union + +from pynars.NAL.Functions import Or from pynars.NAL.Functions.Tools import calculate_solution_quality, distribute_budget_among_links from pynars.NAL.Functions.BudgetFunctions import Budget_merge from pynars.Narsese import Belief, Task, Item, Budget, Sentence, Term, Task, Judgement, Goal @@ -138,12 +140,29 @@ def accept(self, task: Task, concepts: Bag=None, conceptualize: bool=True): if concept is None: return # The memroy is full, and the concept fails to get into the memory. self._build_task_links(concepts, task) self._build_term_links(concepts, task, budget) + + def update_priority(self, p, concepts: Bag): + concepts.take_by_key(key=self,remove=True) + self.budget.priority = Or(self.budget.priority, p) + concepts.put(item=self) + + def update_durability(self, d, concepts: Bag): + concepts.take_by_key(key=self, remove=True) + self.budget.durability = (Config.concept_update_durability_weight * d + + (1-Config.concept_update_durability_weight)*self.budget.durability) + concepts.put(item=self) + + def update_quality(self, q, concepts: Bag): + concepts.take_by_key(key=self, remove=True) + self.budget.quality = (Config.concept_update_quality_weight * q + + (1-Config.concept_update_quality_weight)*self.budget.quality) + concepts.put(item=self) def _build_task_links(self, concepts: Bag, task: Task): '''''' budget = task.budget task_link = TaskLink(self, task, budget, True, index=[]) - self._insert_task_link(task_link) + self._insert_task_link(task_link, concepts) if self.term.is_atom: return sub_budget = budget.distribute(self.term.count()-1) # TODO: It seems that the budget is not the same with that in OpenNARS 3.0.4/3.1.0. Check here. for term in self.term.components: @@ -154,7 +173,7 @@ def _build_task_links(self, concepts: Bag, task: Task): indices = Link.get_index(self.term, term) for index in indices: task_link = TaskLink(concept, task, sub_budget, index=index) - concept._insert_task_link(task_link) + concept._insert_task_link(task_link, concepts) def _build_term_links(self, concepts: Bag, task: Task, budget: Budget): ''' @@ -181,18 +200,24 @@ def _build_term_links(self, concepts: Bag, task: Task, budget: Budget): indices = Link.get_index(self.term, term) for index in indices: - self._insert_term_link(TermLink(self, sub_concept, sub_budget, False, index=index)) - sub_concept._insert_term_link(TermLink(sub_concept, self, sub_budget, True, index=index)) + self._insert_term_link(TermLink(self, sub_concept, sub_budget, False, index=index), concepts) + sub_concept._insert_term_link(TermLink(sub_concept, self, sub_budget, True, index=index), concepts) sub_concept._build_term_links(concepts, task, sub_budget) - def _insert_task_link(self, task_link: TaskLink): + def _insert_task_link(self, task_link: TaskLink, concepts: Bag): self.task_links.put(task_link) + # update the concept's budget using the link's budget + self.update_priority(task_link.budget.priority, concepts) + self.update_durability(task_link.budget.durability, concepts) # TODO: more handling. see OpenNARS 3.1.0 Concept.java line 318~366. - def _insert_term_link(self, term_link: TermLink): + def _insert_term_link(self, term_link: TermLink, concepts: Bag): self.term_links.put(term_link) + # update the concept's budget using the link's budget + self.update_priority(term_link.budget.priority, concepts) + self.update_durability(term_link.budget.durability, concepts) # TODO: more handling. see OpenNARS 3.1.0 Concept.java line 318~366. @classmethod diff --git a/pynars/NARS/DataStructures/_py/Memory.py b/pynars/NARS/DataStructures/_py/Memory.py index 32d87b1d..1e348c99 100644 --- a/pynars/NARS/DataStructures/_py/Memory.py +++ b/pynars/NARS/DataStructures/_py/Memory.py @@ -96,7 +96,7 @@ def accept(self, task: Task): def _accept_judgement(self, task: Task, concept: Concept): '''''' - belief_revised = None + belief_revised_task = None answers = { Question: [], Goal: [] } if Enable.operation: raise # InternalExperienceBuffer.handleOperationFeedback(task, nal); if Enable.anticipation: raise # ProcessAnticipation.confirmAnticipation(task, concept, nal); @@ -118,7 +118,7 @@ def _accept_judgement(self, task: Task, concept: Concept): } ''' raise - belief_revised = local__revision(task, belief) # TODO: handling the stamps + belief_revised_task: Task = local__revision(task, belief) # TODO: handling the stamps # reduce priority by achieving level task.reduce_budget_by_achieving_level(belief) @@ -140,7 +140,10 @@ def _accept_judgement(self, task: Task, concept: Concept): _, goal_answer = self._solve_goal(task_goal, concept, None, task) if goal_answer is not None: answers[Goal] = [goal_answer] - return belief_revised, answers + # Modify the concept's Budget using the belief + if belief_revised_task is not None: concept.update_quality(belief_revised_task.sentence.sharpness, concepts=self.concepts) + + return belief_revised_task, answers def _accept_question(self, task: Task, concept: Concept): '''''' diff --git a/pynars/Narsese/_py/Sentence.py b/pynars/Narsese/_py/Sentence.py index 79147545..979fc8cf 100644 --- a/pynars/Narsese/_py/Sentence.py +++ b/pynars/Narsese/_py/Sentence.py @@ -106,8 +106,8 @@ def directness(self): @property def sharpness(self): - if self.truth_value is None: return None - else: return 2 * abs(self.truth_value.e - 0.5) + if self.truth is None: return None + else: return 2 * abs(self.truth.e - 0.5) # @property # def temporal_order(self):