From 1b2ec1dd313edcd43abfb7d3d85126575aadd43f Mon Sep 17 00:00:00 2001 From: ARCJ137442 <61109168+ARCJ137442@users.noreply.github.com> Date: Mon, 23 Oct 2023 12:50:17 +0800 Subject: [PATCH 1/3] fix: :bug: Functional Bug fix - duplicated prefix of `^^op` in cmd Fixed: In the call of cmd `register-operation`, parameter `name_operation` in `Reasoner`'s method `register_operation` was incorrectly encapsulated with an `Operation` resulting in `^^op` --- pynars/ConsolePlus.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pynars/ConsolePlus.py b/pynars/ConsolePlus.py index 015ec3b..46dcbfb 100644 --- a/pynars/ConsolePlus.py +++ b/pynars/ConsolePlus.py @@ -300,6 +300,7 @@ def register_operation(*args: List[str]) -> None: ! Unsupported: register mental operations ''' name = args[0] + "The operator's name without `^` as prefix" eType = args[1] code = " ".join(args[2:]) if code == '': @@ -316,8 +317,7 @@ def execution_F(arguments: Iterable[Term], task: Task=None, memory: Memory=None) execution_F.__doc__ = f''' The execution is auto generated from operator {name} in {eType} mode with code={code} ''' - from pynars.NARS.Operation import Operation - current_NARS_interface.reasoner.register_operation(Operation(name), execution_F) + current_NARS_interface.reasoner.register_operation(name, execution_F) print(f'Operation {name} was successfully registered in mode "{eType}" with code={code}') From 8cbd17f55b32b273b518ed77be7f4dae0201aa1c Mon Sep 17 00:00:00 2001 From: ARCJ137442 <61109168+ARCJ137442@users.noreply.github.com> Date: Wed, 25 Oct 2023 13:21:18 +0800 Subject: [PATCH 2/3] feat: :sparkles: Port the "volume" mechanism from OpenNARS A simple "volume" mechanism, ported from OpenNARS, allows the use of cmd `volume` to set values as OpenNARS does and thus limit the production of `OUT` type output. --- pynars/ConsolePlus.py | 13 +++++++++++++ pynars/Interface.py | 36 ++++++++++++++++++++++++++++-------- pynars/Narsese/_py/Budget.py | 16 +++++++++++++++- 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/pynars/ConsolePlus.py b/pynars/ConsolePlus.py index 015ec3b..186ee3f 100644 --- a/pynars/ConsolePlus.py +++ b/pynars/ConsolePlus.py @@ -221,6 +221,19 @@ def toggle_silent() -> None: }.''') +@cmd_register(('volume'), (int, 100)) +def volume(vol:int) -> None: + '''Format: volume [volume:int 0~100] + Set the Output Volume of the console to control its output (same as OpenNARS)''' + if 0 <= vol <= 100: + current_NARS_interface.silence_value = 1 - vol * 0.01 # same as `(100-vol)/100` + current_NARS_interface.print_output( + type=PrintType.INFO, content=f'''Volume is set to "*volume={vol}".''') + else: + current_NARS_interface.print_output( + type=PrintType.INFO, content=f'''Volume {vol} is out of range 0~100!''') + + @cmd_register(('toggle-color', 'color')) def toggle_color() -> None: '''Toggle the color display of cmds (for terminals that do not support custom foreground/background colors)''' diff --git a/pynars/Interface.py b/pynars/Interface.py index 81d9ded..797418a 100644 --- a/pynars/Interface.py +++ b/pynars/Interface.py @@ -204,6 +204,10 @@ def change_random_seed(seed: int) -> None: f'Changing random seed={seed}...', comment_title='Setup') silent_output: bool = False + 'determines whether the output is hidden or not' + + silence_value: float = 0.5 + 'determines the level (min threshold of total budget) of output (NARSOutput) generate, only affects the narsese output' # reasoner _NARS: Reasoner = None # ! internal @@ -231,6 +235,7 @@ def __init__(self, seed=-1, NARS: reasoner = None, silent: bool = False) -> None # config self.silent_output: bool = silent + self.silence_value = 0 # reasoner self.print_output( @@ -375,18 +380,33 @@ def _handle_lines(self, lines: str) -> List[NARSOutput]: for task_line in task_list: tasks_derived, judgement_revised, goal_revised, answers_question, answers_quest,\ (task_operation_return, task_executed) = task_line + # * only the 'OUT' will be affected by silence level for derived_task in tasks_derived: - outs.append( - NARSOutput( - PrintType.OUT, derived_task.sentence.repr(), *derived_task.budget) - ) + ''' + Ref. OpenNARS 3.1.2 Memory.java line 291~294 + ``` + float s = task.getBudget().totalBudget(); + float minSilent = reasoner.getSilenceValue().get() / 100.0f; + if (s > minSilent) { // only report significant derived Tasks + //generalInfoReport("4"); + report(task.getSentence(), false, false); + } + ``` + ''' + if derived_task.budget.total > self.silence_value: + outs.append( + NARSOutput( + PrintType.OUT, derived_task.sentence.repr(), *derived_task.budget) + ) if judgement_revised is not None: - outs.append(NARSOutput(PrintType.OUT, judgement_revised.sentence.repr( - ), *judgement_revised.budget)) + if judgement_revised.budget.total > self.silence_value: + outs.append(NARSOutput( + PrintType.OUT, judgement_revised.sentence.repr(), *judgement_revised.budget)) if goal_revised is not None: - outs.append(NARSOutput( - PrintType.OUT, goal_revised.sentence.repr(), *goal_revised.budget)) + if judgement_revised.budget.total > self.silence_value: + outs.append(NARSOutput( + PrintType.OUT, goal_revised.sentence.repr(), *goal_revised.budget)) if answers_question is not None: for answer in answers_question: outs.append( diff --git a/pynars/Narsese/_py/Budget.py b/pynars/Narsese/_py/Budget.py index fce8d01..cde4bd1 100644 --- a/pynars/Narsese/_py/Budget.py +++ b/pynars/Narsese/_py/Budget.py @@ -51,4 +51,18 @@ def distribute(self, n: int): return new BudgetValue(priority, b.getDurability(), b.getQuality(), narParameters); ``` ''' - return Budget(self.priority/sqrt((n if n > 0 else 1)), self.durability, self.quality) \ No newline at end of file + return Budget(self.priority/sqrt((n if n > 0 else 1)), self.durability, self.quality) + + @property + def total(self) -> float: + ''' + To summarize a BudgetValue into a single number in [0, 1] + It's used for introduce the 'volume' by comparing with the number of silence level + Ref. OpenNARS 3.1.2 BudgetValue.java line 194~200: + ``` + public float totalBudget() { + return UtilityFunctions.aveGeo(priority.getValue(), durability.getValue(), quality.getValue()); + } + ``` + ''' + return (self.priority * self.durability * self.quality)**(1/3) \ No newline at end of file From 46c91ce6d4f7380abde4da558d9524d8f88a0c8c Mon Sep 17 00:00:00 2001 From: ARCJ137442 <61109168+ARCJ137442@users.noreply.github.com> Date: Thu, 26 Oct 2023 00:26:55 +0800 Subject: [PATCH 3/3] revert: :rewind: Revert the following OpenNARS version to 3.1.0 totalBudget -> summary; `(self.priority * self.durability * self.quality)**(1/3)` -> `self.durability*(self.priority+self.quality)/2.0` --- pynars/ConsolePlus.py | 2 +- pynars/Interface.py | 26 +++++++++++++++----------- pynars/Narsese/_py/Budget.py | 16 +--------------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/pynars/ConsolePlus.py b/pynars/ConsolePlus.py index 186ee3f..ce69b58 100644 --- a/pynars/ConsolePlus.py +++ b/pynars/ConsolePlus.py @@ -226,7 +226,7 @@ def volume(vol:int) -> None: '''Format: volume [volume:int 0~100] Set the Output Volume of the console to control its output (same as OpenNARS)''' if 0 <= vol <= 100: - current_NARS_interface.silence_value = 1 - vol * 0.01 # same as `(100-vol)/100` + current_NARS_interface.volume_threshold = 1 - vol * 0.01 # same as `(100-vol)/100` current_NARS_interface.print_output( type=PrintType.INFO, content=f'''Volume is set to "*volume={vol}".''') else: diff --git a/pynars/Interface.py b/pynars/Interface.py index 797418a..0a39f8d 100644 --- a/pynars/Interface.py +++ b/pynars/Interface.py @@ -206,7 +206,7 @@ def change_random_seed(seed: int) -> None: silent_output: bool = False 'determines whether the output is hidden or not' - silence_value: float = 0.5 + volume_threshold: float = 0.5 'determines the level (min threshold of total budget) of output (NARSOutput) generate, only affects the narsese output' # reasoner @@ -235,7 +235,7 @@ def __init__(self, seed=-1, NARS: reasoner = None, silent: bool = False) -> None # config self.silent_output: bool = silent - self.silence_value = 0 + self.volume_threshold = 0 # reasoner self.print_output( @@ -383,28 +383,32 @@ def _handle_lines(self, lines: str) -> List[NARSOutput]: # * only the 'OUT' will be affected by silence level for derived_task in tasks_derived: ''' - Ref. OpenNARS 3.1.2 Memory.java line 291~294 + Ref. OpenNARS 3.1.0 Memory.java line 344~352 ``` - float s = task.getBudget().totalBudget(); - float minSilent = reasoner.getSilenceValue().get() / 100.0f; - if (s > minSilent) { // only report significant derived Tasks - //generalInfoReport("4"); - report(task.getSentence(), false, false); + final float budget = t.budget.summary(); + final float noiseLevel = 1.0f - (narParameters.VOLUME / 100.0f); + + if (budget >= noiseLevel) { // only report significant derived Tasks + emit(OUT.class, t); + if (Debug.PARENTS) { + emit(DEBUG.class, "Parent Belief\t" + t.parentBelief); + emit(DEBUG.class, "Parent Task\t" + t.parentTask + "\n\n"); + } } ``` ''' - if derived_task.budget.total > self.silence_value: + if derived_task.budget.summary > self.volume_threshold: outs.append( NARSOutput( PrintType.OUT, derived_task.sentence.repr(), *derived_task.budget) ) if judgement_revised is not None: - if judgement_revised.budget.total > self.silence_value: + if judgement_revised.budget.summary > self.volume_threshold: outs.append(NARSOutput( PrintType.OUT, judgement_revised.sentence.repr(), *judgement_revised.budget)) if goal_revised is not None: - if judgement_revised.budget.total > self.silence_value: + if judgement_revised.budget.summary > self.volume_threshold: outs.append(NARSOutput( PrintType.OUT, goal_revised.sentence.repr(), *goal_revised.budget)) if answers_question is not None: diff --git a/pynars/Narsese/_py/Budget.py b/pynars/Narsese/_py/Budget.py index cde4bd1..fce8d01 100644 --- a/pynars/Narsese/_py/Budget.py +++ b/pynars/Narsese/_py/Budget.py @@ -51,18 +51,4 @@ def distribute(self, n: int): return new BudgetValue(priority, b.getDurability(), b.getQuality(), narParameters); ``` ''' - return Budget(self.priority/sqrt((n if n > 0 else 1)), self.durability, self.quality) - - @property - def total(self) -> float: - ''' - To summarize a BudgetValue into a single number in [0, 1] - It's used for introduce the 'volume' by comparing with the number of silence level - Ref. OpenNARS 3.1.2 BudgetValue.java line 194~200: - ``` - public float totalBudget() { - return UtilityFunctions.aveGeo(priority.getValue(), durability.getValue(), quality.getValue()); - } - ``` - ''' - return (self.priority * self.durability * self.quality)**(1/3) \ No newline at end of file + return Budget(self.priority/sqrt((n if n > 0 else 1)), self.durability, self.quality) \ No newline at end of file