/** * Link to a new task from all relevant concepts for continued processing in * the near future for unspecified time. * <p> * The only method that calls the TaskLink constructor. * * /param task The task to be linked * /param content The content of the task */ private static void linkToTask(DerivationContext ctx, ClassicalConcept @this, ClassicalTask task) { ClassicalBudgetValue taskBudget = task.budget; @this.insertTaskLink( new ClassicalTaskLink( task, null, taskBudget, Parameters.TERM_LINK_RECORD_LENGTH), ctx); // link type: SELF if (!TermUtilities.isTermCompoundTerm(@this.term)) { return; } if (@this.termLinkTemplates.isEmpty()) { return; } ClassicalBudgetValue subBudget = BudgetFunctions.distributeAmongLinks(taskBudget, @this.termLinkTemplates.Count); if (!subBudget.isAboveThreshold) { return; } // else here for (int t = 0; t < @this.termLinkTemplates.Count; t++) { ClassicalTermLink termLink = @this.termLinkTemplates[t]; if (termLink.type == ClassicalTermLink.EnumType.TEMPORAL) { continue; } TermOrCompoundTermOrVariableReferer componentTerm = termLink.target; ClassicalConcept componentConcept = @this.memory.conceptualize(subBudget, componentTerm); if (componentConcept != null) { componentConcept.insertTaskLink( new ClassicalTaskLink( task, termLink, subBudget, Parameters.TERM_LINK_RECORD_LENGTH), ctx); } } @this.buildTermLinks(taskBudget); // recursively insert TermLink }
/** * Activated task called in MatchingRules.trySolution and * Concept.processGoal * * @param budget The budget value of the new Task * @param sentence The content of the new Task * @param candidateBelief The belief to be used in future inference, for * forward/backward correspondence */ public void addTask(ClassicalTask currentTask, ClassicalBudgetValue budget, ClassicalSentence sentence, ClassicalSentence candidateBelief) { ClassicalTask.MakeParameters taskParameters = new ClassicalTask.MakeParameters(); taskParameters.sentence = sentence; taskParameters.budget = budget; taskParameters.parentTask = currentTask; taskParameters.parentBelief = sentence; taskParameters.bestSolution = candidateBelief; addTask(ClassicalTask.make(taskParameters), "Activated"); }
// see https://github.com/opennars/opennars/blob/4515f1d8e191a1f097859decc65153287d5979c5/nars_core/nars/inference/BudgetFunctions.java#L192 // ATTENTION RELATED /** * Decrease Priority after an item is used, called in Bag. * After a constant time, p should become d*p. Since in this period, the * item is accessed c*p times, each time p-q should multiple d^(1/(c*p)). * The intuitive meaning of the parameter "forgetRate" is: after this number * of times of access, priority 1 will become d, it is a system parameter * adjustable in run time. * * /param budget The previous budget value * /param forgetCycles The budget for the new item * /param relativeThreshold The relative threshold of the bag */ public static float applyForgetting(ClassicalBudgetValue budget, float forgetCycles, float relativeThreshold) { float rescaledQuality = budget.quality * relativeThreshold; float p = budget.priority - rescaledQuality; // priority above quality if (p > 0) { rescaledQuality += p * (float)Math.Pow(budget.durability, 1.0 / (forgetCycles * p)); } // priority Durability budget.priority = rescaledQuality; return(rescaledQuality); }
public bool singlePremiseTask(ClassicalSentence newSentence, ClassicalBudgetValue newBudget) { if (!newBudget.isAboveThreshold) { return(false); } ClassicalTask.MakeParameters newTaskParameters = new ClassicalTask.MakeParameters(); newTaskParameters.sentence = newSentence; newTaskParameters.budget = newBudget; newTaskParameters.parentTask = currentTask; ClassicalTask newTask = ClassicalTask.make(newTaskParameters); return(derivedTask(newTask, false, true, null, null, false)); }
// TODO< rename to evaluateQualityOfBeliefAsASolutionToProblemAndReward and refactor into functions > // https://github.com/opennars/opennars/blob/master/nars_core/nars/inference/TemporalRules.java#L537 /* ----- Functions used both in direct and indirect processing of tasks ----- */ /** * Evaluate the quality of a belief as a solution to a problem, then reward * the belief and de-prioritize the problem * * \param problem The problem (question or goal) to be solved * \param solution The belief as solution * \param task The task to be immediately processed, or null for continued process * \return The budget for the new task which is the belief activated, if * necessary */ public static ClassicalBudgetValue solutionEval( ClassicalTask problem, ClassicalSentence solution, ClassicalTask task, DerivationContext ctx ) { ClassicalBudgetValue budget = null; bool feedbackToLinks = false; if (task == null) { task = ctx.currentTask; feedbackToLinks = true; } bool taskSentenceIsjudgment = task.sentence.isJudgment; EnumRateByConfidence rateByConfidence = problem.sentence.term.hasVarQuery() ? EnumRateByConfidence.YES : EnumRateByConfidence.NO; // here its whether its a what or where question for budget adjustment float quality = TemporalRules.solutionQuality(rateByConfidence, problem, solution, ctx.memory, ctx.compoundAndTermContext); if (problem.sentence.isGoal) { ctx.memory.emotion.adjustHappy(quality, task.budget.priority, ctx); } if (taskSentenceIsjudgment) { task.budget.incPriority(quality); } else { float taskPriority = task.budget.priority; // +goal satisfication is a matter of degree - https://groups.google.com/forum/#!topic/open-nars/ZfCM416Dx1M budget = new ClassicalBudgetValue(UtilityFunctions.or(taskPriority, quality), task.budget.durability, BudgetFunctions.truthToQuality(solution.truth)); task.budget.priority = Math.Min(1 - quality, taskPriority); } // TODO< implement links > /* LINKS commented because links are not implemented * if (feedbackToLinks) { * TaskLink tLink = ctx.currentTaskLink; * tLink.setPriority(Math.Min(1 - quality, tLink.getPriority())); * TermLink bLink = ctx.currentBeliefLink; * bLink.incPriority(quality); * }*/ return(budget); }
/** * Check if a Sentence provide a better answer to a Question or Goal * * \param belief The proposed answer * \param task The task to be processed */ public static bool trySolution(ClassicalSentence belief, ClassicalTask task, DerivationContext ctx, bool report, Memory memory) { trySolution_emotion(belief, task, ctx); task.setBestSolution(memory, belief); //memory.logic.SOLUTION_BEST.commit(task.getPriority()); ClassicalBudgetValue budget = TemporalRules.solutionEval(task, belief, task, ctx); if (budget == null || !budget.isAboveThreshold) { //memory.emit(Unsolved.class, task, belief, "Insufficient budget"); return(false); } // Solution was Activated // report if (task.sentence.isQuestion || task.sentence.isQuest) { if (task.isInput && report) //only show input tasks as solutions //memory.emit(Answer.class, task, belief); { } else { //memory.emit(Output.class, task, belief); //solution to quests and questions can be always showed } } else { //memory.emit(Output.class, task, belief); //goal things only show silence related } /*memory.output(task); * * //only questions and quests get here because else output is spammed * if(task.sentence.isQuestion() || task.sentence.isQuest()) { * memory.emit(Solved.class, task, belief); * } else { * memory.emit(Output.class, task, belief); * }*/ ctx.addTask(ctx.currentTask, budget, belief, task.getParentBelief()); return(true); }
// see https://github.com/opennars/opennars/blob/4515f1d8e191a1f097859decc65153287d5979c5/nars_core/nars/storage/Memory.java#L187 /** * Get the Concept associated to a Term, or create it. * * Doesn't take it from the bag and put it back to save some cycles and to allow better concurrency * Doesn't adjust budget * * if it fails with an soft error (can't take it from the bag etc) it returns null * * doesn't displace concepts * * @param term indicating the concept * @return an existing Concept, or a new one, or null */ public ClassicalConcept conceptualize(ClassicalBudgetValue budget, TermOrCompoundTermOrVariableReferer term) { ClassicalConcept concept = workingCyclish.concepts.referenceByKey(term); if (concept == null) { // CONCURRENCY< lock and put back > // create new concept, with the applied budget concept = new ClassicalConcept(compoundAndTermContext, term, bagBuilder, budget, this); workingCyclish.concepts.putIn(concept); // from java code base // TODO ASK< implement //emit(Events.ConceptNew.class, concept); } else { // legacy java code applies budget here, we don't } return(concept); }
/** * Belief revision * <p> * called from Concept.reviseTable and match * * @param newBelief The new belief in task * @param oldBelief The previous belief with the same content * @param feedbackToLinks Whether to send feedback to the links * @param memory Reference to the memory */ public static bool revision(DerivationContext ctx, ClassicalSentence newBelief, ClassicalSentence oldBelief, bool feedbackToLinks) { if (newBelief.term == null) { return(false); } newBelief.stamp.alreadyAnticipatedNegConfirmation = oldBelief.stamp.alreadyAnticipatedNegConfirmation; TruthValue newTruth = newBelief.truth; TruthValue oldTruth = oldBelief.truth; TruthValue truth = TruthFunctions.revision(newTruth, oldTruth); ClassicalBudgetValue budget = BudgetFunctions.revise(newTruth, oldTruth, truth, feedbackToLinks, ctx); if (budget.isAboveThreshold) { if (ctx.doublePremiseTaskRevised(newBelief.term, truth, budget)) { //nal.mem().logic.BELIEF_REVISION.commit(); return(true); } } return(false); }
/** * Merge an item into another one in a bag, when the two are identical * except in budget values * * \param b The budget baseValue to be modified * \param a The budget adjustValue doing the adjusting */ public static void merge(ClassicalBudgetValue b, ClassicalBudgetValue a) { b.priority = Math.Max(b.priority, a.priority); b.durability = Math.Max(b.durability, a.durability); b.quality = Math.Max(b.quality, a.quality); }
/* ----------------------- Links ----------------------- */ /** * Distribute the budget of a task among the links to it * * /param b The original budget * /param n Number of links * /return Budget value for each link */ public static ClassicalBudgetValue distributeAmongLinks(ClassicalBudgetValue b, int n) { float priority = (float)(b.priority / Math.Sqrt(n)); return(new ClassicalBudgetValue(priority, b.durability, b.quality)); }
// function prototype and some of the methode is like https://github.com/opennars/opennars/blob/4515f1d8e191a1f097859decc65153287d5979c5/nars_core/nars/inference/RuleTables.java#L73 internal static void reason( ClassicalTaskLink taskLink, ClassicalTermLink beliefLink, DerivationContext ctx ) { { // debugging int taskId = taskLink.targetTask.name.term.getAtomicOrTerm; int beliefId = beliefLink.target.getAtomicOrTerm; if (taskId == 300002 && beliefId == 300004) { int breakpointHere2 = 1; } else if (taskId == 300004 && beliefId == 300002) { int breakpointHere2 = 1; } int breakpointHere1 = 1; } Memory memory = ctx.memory; memory.emotion.manageBusy(ctx); ClassicalTask task = ctx.currentTask; ClassicalSentence taskSentence = task.sentence; TermOrCompoundTermOrVariableReferer taskTerm = taskSentence.term; TermOrCompoundTermOrVariableReferer beliefTerm = beliefLink.target; // commented because not jet translated //if (equalSubTermsInRespectToImageAndProduct(taskTerm, beliefTerm)) // return; ClassicalConcept beliefConcept = memory.translateTermToConcept(beliefTerm); ClassicalSentence belief = (beliefConcept != null) ? beliefConcept.getBelief(ctx, task) : null; ctx.currentBelief = belief; if (belief != null) { beliefTerm = belief.term; //because interval handling that differs on conceptual level // too restrictive, its checked for non-deductive inference rules in derivedTask (also for single prem) if (Stamp.checkBaseOverlap(task.sentence.stamp, belief.stamp)) { ctx.evidentalOverlap = true; if (!task.sentence.stamp.isEternal || !belief.stamp.isEternal) { return; // only allow for eternal reasoning for now to prevent derived event floods } //return; // preparisons are made now to support this nicely } // comment out for recursive examples, this is for the future, it generates a lot of potentially useless tasks //ctx.emit(Events.BeliefReason.class, belief, beliefTerm, taskTerm, nal); if (LocalRules.match(task, belief, ctx)) // new tasks resulted from the match, so return { return; } } // current belief and task may have changed, so set again: ctx.currentBelief = belief; ctx.currentTask = task; // HACK< derivation must be made by combining compounds > if (!TermUtilities.isTermCompoundTerm(taskTerm) || !TermUtilities.isTermCompoundTerm(beliefTerm)) { return; } // derive and create new tasks for the results { IList <TemporaryDerivedCompoundWithDecorationAndTruth> derivedCompoundTermsWithDecorationAndTruth = new List <TemporaryDerivedCompoundWithDecorationAndTruth>(); bool insert = true; DeriverCaller.deriverCaller( ctx.compoundAndTermContext, ctx.compoundAndTermContext.translateToCompoundChecked(taskTerm), ctx.compoundAndTermContext.translateToCompoundChecked(beliefTerm), out derivedCompoundTermsWithDecorationAndTruth, insert); // translate derivedCompoundTermsWithDecorationAndTruth to tasks and add them // for this we have to call DerivationContext.doublePremiseTask() to generate the tasks foreach (var iDerivedWithDecorationAndTruth in derivedCompoundTermsWithDecorationAndTruth) { TermOrCompoundTermOrVariableReferer content = iDerivedWithDecorationAndTruth.derivedCompoundWithDecoration.termReferer; bool temporalInduction = false; // TODO< decide by rule? from the deriver? > bool overlapAllowed = false; // TODO< decide by rule? from the deriver? > TruthValue truth = null; truth = RuleTable.calcTruthDoublePremise(task.sentence.truth, belief.truth, iDerivedWithDecorationAndTruth.truthfunction); ClassicalBudgetValue budget = new ClassicalBudgetValue(0.5f, 0.5f, 0.5f); // TODO< calculate budget by table > ctx.doublePremiseTask(content, truth, budget, temporalInduction, overlapAllowed ); } } }
// see https://github.com/opennars/opennars/blob/4515f1d8e191a1f097859decc65153287d5979c5/nars_core/nars/control/DerivationContext.java#L217 /** * Shared final operations by all double-premise rules, called from the * rules except StructuralRules * * /param newContent The content of the sentence in task * /param newTruth The truth value of the sentence in task * /param newBudget The budget value in task * /param temporalInduction * /param overlapAllowed // https://groups.google.com/forum/#!topic/open-nars/FVbbKq5En-M */ public IList <ClassicalTask> doublePremiseTask( TermOrCompoundTermOrVariableReferer newContent, TruthValue newTruth, ClassicalBudgetValue newBudget, bool temporalInduction, bool overlapAllowed ) { IList <ClassicalTask> ret = new List <ClassicalTask>(); if (newContent == null) { return(null); } if (!newBudget.isAboveThreshold) { return(null); } if ( newContent == null /* commented because not implemented || * ((newContent instanceof Interval)) || * ((newContent instanceof Variable))*/ ) { return(null); } /* commented because not implemented * if (newContent.subjectOrPredicateIsIndependentVar()) { * return null; * }*/ ClassicalSentence newSentence; ClassicalTask newTask; ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters makeSentenceParameters = new ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters(); makeSentenceParameters.term = newContent; makeSentenceParameters.punctation = currentTask.sentence.punctation; makeSentenceParameters.truth = newTruth; makeSentenceParameters.stamp = returnTheNewStamp(); newSentence = ClassicalSentence.makeByTermPunctuationTruthStampNormalize(makeSentenceParameters); newSentence.producedByTemporalInduction = temporalInduction; ClassicalTask.MakeParameters taskMakeParameters = new ClassicalTask.MakeParameters(); taskMakeParameters.sentence = newSentence; taskMakeParameters.budget = newBudget; taskMakeParameters.parentTask = currentTask; taskMakeParameters.parentBelief = currentBelief; newTask = ClassicalTask.make(taskMakeParameters); if (newTask != null) { bool added = derivedTask(newTask, false, false, null, null, overlapAllowed); if (added) { ret.Add(newTask); } } // "Since in principle it is always valid to eternalize a tensed belief" if (temporalInduction && Parameters.IMMEDIATE_ETERNALIZATION) // temporal induction generated ones get eternalized directly { TruthValue truthEternalized = TruthFunctions.eternalize(newTruth); Stamp st = returnTheNewStamp().clone(); st.isEternal = true; makeSentenceParameters = new ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters(); makeSentenceParameters.term = newContent; makeSentenceParameters.punctation = currentTask.sentence.punctation; makeSentenceParameters.truth = truthEternalized; makeSentenceParameters.stamp = st; newSentence = ClassicalSentence.makeByTermPunctuationTruthStampNormalize(makeSentenceParameters); newSentence.producedByTemporalInduction = temporalInduction; taskMakeParameters = new ClassicalTask.MakeParameters(); taskMakeParameters.sentence = newSentence; taskMakeParameters.budget = newBudget; taskMakeParameters.parentTask = currentTask; taskMakeParameters.parentBelief = currentBelief; newTask = ClassicalTask.make(taskMakeParameters); if (newTask != null) { bool added = derivedTask(newTask, false, false, null, null, overlapAllowed); if (added) { ret.Add(newTask); } } } return(ret); }
/* --------------- new task building --------------- */ /** * Shared final operations by all double-premise rules, called from the * rules except StructuralRules * * \param newContent The content of the sentence in task * \param newTruth The truth value of the sentence in task * \param newBudget The budget value in task */ public bool doublePremiseTaskRevised(TermOrCompoundTermOrVariableReferer newContent, TruthValue newTruth, ClassicalBudgetValue newBudget) { ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters makeSentenceParameters = new ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters(); makeSentenceParameters.term = newContent; makeSentenceParameters.punctation = currentTask.sentence.punctation; makeSentenceParameters.truth = newTruth; makeSentenceParameters.stamp = returnTheNewStamp(); ClassicalSentence newSentence = ClassicalSentence.makeByTermPunctuationTruthStampNormalize(makeSentenceParameters); ClassicalTask.MakeParameters makeTaskParameters = new ClassicalTask.MakeParameters(); makeTaskParameters.sentence = newSentence; makeTaskParameters.budget = newBudget; makeTaskParameters.parentTask = currentTask; makeTaskParameters.parentBelief = currentBelief; ClassicalTask newTask = ClassicalTask.make(makeTaskParameters); return(derivedTask(newTask, true, false, null, null, true)); // allows overlap since overlap was already checked on revisable( function // which is not the case for other single premise tasks }