// https://github.com/opennars/opennars/blob/master/nars_core/nars/inference/TemporalRules.java#L502 /** * Evaluate the quality of the judgment as a solution to a problem * * \param problem A goal or question * \param solution The solution to be evaluated * \return The quality of the judgment as the solution */ public static float solutionQuality(EnumRateByConfidence rateByConfidence, ClassicalTask problemTask, ClassicalSentence solution, Memory memory, CompoundAndTermContext compoundAndTermContext) { ClassicalSentence problem = problemTask.sentence; /* TODO< implement TEMPORAL * if (!matchingOrder(problem.temporalOrder, solution.temporalOrder)) { * return 0.0F; * } */ TruthValue truth = solution.truth; if (problem.stamp.occurrenceTime != solution.stamp.occurrenceTime) { truth = solution.projectionTruth(problem.stamp.occurrenceTime, memory.time); } //when the solutions are comparable, we have to use confidence!! else truth expectation. //this way negative evidence can update the solution instead of getting ignored due to lower truth expectation. //so the previous handling to let whether the problem has query vars decide was wrong. if (rateByConfidence == EnumRateByConfidence.NO) { return((float)(truth.expectation / Math.Sqrt(Math.Sqrt(Math.Sqrt(compoundAndTermContext.getTermComplexityOfAndByTermReferer(solution.term) * Parameters.COMPLEXITY_UNIT))))); } else { return(truth.confidence); } }
// does the emotion part of the trySolution function private static void trySolution_emotion(ClassicalSentence belief, ClassicalTask task, DerivationContext ctx) { ClassicalSentence problem = task.sentence; Memory memory = ctx.memory; ClassicalSentence oldBest = task.bestSolution; if (oldBest != null) { TemporalRules.EnumRateByConfidence rateByConfidence = oldBest.term == belief.term ? TemporalRules.EnumRateByConfidence.YES : TemporalRules.EnumRateByConfidence.NO; float newQ = TemporalRules.solutionQuality(rateByConfidence, task, belief, memory, ctx.compoundAndTermContext); float oldQ = TemporalRules.solutionQuality(rateByConfidence, task, oldBest, memory, ctx.compoundAndTermContext); if (oldQ >= newQ) { if (problem.isGoal) { memory.emotion.adjustHappy(oldQ, task.budget.priority, ctx); } //System.out.println("Unsolved: Solution of lesser quality"); //java memory.emit(Unsolved.class, task, belief, "Lower quality"); return; } } }
// https://github.com/opennars/opennars/blob/master/nars_core/nars/entity/Concept.java#L233 /** * To accept a new judgment as belief, and check for revisions and solutions * * \param judg The judgment to be accepted * \param task The task to be processed * \return Whether to continue the processing of the task */ private void processJudgment(DerivationContext ctx, ClassicalConcept @this, ClassicalTask task) { ClassicalSentence judgement = task.sentence; ClassicalTask oldBeliefTask = selectCandidate(task, @this.beliefs, EnumForRevision.REVISION);// only revise with the strongest // QUESTION< how about projection? > ClassicalSentence oldBelief = null; if (oldBeliefTask != null) { oldBelief = oldBeliefTask.sentence; Stamp newStamp = judgement.stamp; Stamp oldStamp = oldBelief.stamp; // when table is full, the latter check is especially important, too if ( Stamp.checkEquals( newStamp, oldStamp, Stamp.EnumCompareCreationTime.NO, Stamp.EnumCompareOccurrenceTime.YES, Stamp.EnumCompareEvidentialBaseTime.YES) && task.sentence.truth == oldBelief.truth ) { memory.removeTask(task, "Duplicated"); return; } else if (LocalRules.revisible(judgement, oldBelief)) { // commented because we have to implement revision like in the legacy system // projection can occur either with the NARS default or the new exponential decay model // QUESTION< which one is better ? > ctx.setTheNewStamp(newStamp, oldStamp, memory.time); ClassicalSentence projectedBelief = oldBelief.projection(memory.time, newStamp.occurrenceTime); if (projectedBelief != null) { if (projectedBelief.stamp.occurrenceTime != oldBelief.stamp.occurrenceTime) { // nal.singlePremiseTask(projectedBelief, task.budget); } ctx.currentBelief = projectedBelief; LocalRules.revision(ctx, judgement, projectedBelief, false); } } } if (task.isAboveThreshold) { foreach (var iQuestion in @this.questions) { LocalRules.trySolution(judgement, iQuestion, ctx, true, memory); } TableMaintenance.addToTable(task, false, @this.beliefs, Parameters.CONCEPT_BELIEFS_MAX, null /*ConceptBeliefAdd.class*/, null /*ConceptBeliefRemove.class*/); // if taskLink predicts this concept then add to predictive // TODO } }
/* -------------------- same contents -------------------- */ /** * The task and belief have the same content * <p> * called in RuleTables.reason * * @param task The task * @param belief The belief * @param memory Reference to the memory */ public static bool match(ClassicalTask task, ClassicalSentence belief, DerivationContext ctx) { ClassicalSentence sentence = task.sentence; if (sentence.isJudgment) { if (revisible(sentence, belief)) { return(revision(ctx, sentence, belief, true)); } } else { // TODO /* commented because variables and order are not implemented * if (matchingOrder(sentence, belief)) { * Term[] u = new Term[] { sentence.term, belief.term }; * if (Variables.unify(Symbols.VAR_QUERY, u)) { * trySolution(belief, task, nal, true); * } * } */ } return(false); }
// see https://github.com/opennars/opennars/blob/master/nars_core/nars/entity/Concept.java#L779 /** * Select a belief value or desire value for a given query * * @param query The query to be processed * @param list The list of beliefs or desires to be used * @return The best candidate selected */ ClassicalTask selectCandidate(ClassicalTask query, IList <ClassicalTask> list, EnumForRevision forRevision) { var rateByConfidence = TemporalRules.EnumRateByConfidence.YES; //table vote, yes/no question / local processing // TODO< paralelize somehow > float currentBest = 0; float beliefQuality; ClassicalTask candidate = null; //synchronized(list) { for (int i = 0; i < list.Count; i++) { ClassicalTask judgT = list[i]; ClassicalSentence judg = judgT.sentence; beliefQuality = TemporalRules.solutionQuality(rateByConfidence, query, judg, memory, compoundAndTermContext); // makes revision explicitly search for if (beliefQuality > currentBest /*&& (!forRevision || judgT.sentence.equalsContent(query)) */ /*&& (!forRevision || !Stamp.baseOverlap(query.stamp.evidentialBase, judg.stamp.evidentialBase)) */) { currentBest = beliefQuality; candidate = judgT; } } //} return(candidate); }
/** * Determine the rank of a judgment by its quality and originality (stamp baseLength), called from Concept * * \param judg The judgment to be ranked * \return The rank of the judgment, according to truth value only */ public static float rankBelief(ClassicalSentence judg, bool rankTruthExpectation) { if (rankTruthExpectation) { return(judg.truth.expectation); } float confidence = judg.truth.confidence; // float originality = judg.stamp.getOriginality(); return(confidence); //or(confidence, originality); }
/** * 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"); }
/** * Check whether two sentences can be used in revision * * @param s1 The first sentence * @param s2 The second sentence * @return If revision is possible between the two sentences */ public static bool revisible(ClassicalSentence s1, ClassicalSentence s2) { /* TODO TODO * if (!s1.isEternal() && !s2.isEternal() && Math.abs(s1.getOccurenceTime() - s2.getOccurenceTime()) > Parameters.REVISION_MAX_OCCURRENCE_DISTANCE) { * return false; * } * return (s1.getRevisible() && * matchingOrder(s1.getTemporalOrder(), s2.getTemporalOrder()) && * CompoundTerm.cloneDeepReplaceIntervals(s1.term).equals(CompoundTerm.cloneDeepReplaceIntervals(s2.term)) && * !Stamp.baseOverlap(s1.stamp.evidentialBase, s2.stamp.evidentialBase)); */ return(true); // HACK TODO }
static void testNars() { CompoundAndTermContext compoundAndTermContext = new CompoundAndTermContext(); RuleDispatcher.compoundAndTermContext = compoundAndTermContext; // for debugging PrototypingInput prototypingInput = new PrototypingInput(compoundAndTermContext); Nar nar = Nar.make(compoundAndTermContext, new MetaNix.nars.config.RuntimeParameters()); CompoundIndex compoundIndex1 = prototypingInput.makeInheritance("a", "b"); ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters task1SentenceParameters = new ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters(); task1SentenceParameters.term = compoundAndTermContext.accessCompoundByIndex(compoundIndex1).thisTermReferer; task1SentenceParameters.truth = TruthValue.make(1.0f, 0.5f); task1SentenceParameters.stamp = Stamp.makeWithPresentTense(nar.memory); task1SentenceParameters.punctation = ClassicalSentence.EnumPunctation.JUDGMENT; ClassicalSentence task1Sentence = ClassicalSentence.makeByTermPunctuationTruthStampNormalize(task1SentenceParameters); ClassicalTask.MakeParameters task1MakeParameters = new ClassicalTask.MakeParameters(); task1MakeParameters.sentence = task1Sentence; task1MakeParameters.budget = new ClassicalBudgetValue(0.5f, 0.5f, 0.5f); nar.inputTask(ClassicalTask.make(task1MakeParameters)); CompoundIndex compoundIndex2 = prototypingInput.makeInheritance("b", "c"); ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters task2SentenceParameters = new ClassicalSentence.MakeByTermPunctuationTruthStampNormalizeParameters(); task2SentenceParameters.term = compoundAndTermContext.accessCompoundByIndex(compoundIndex2).thisTermReferer; task2SentenceParameters.truth = TruthValue.make(1.0f, 0.5f); task2SentenceParameters.stamp = Stamp.makeWithPresentTense(nar.memory); task2SentenceParameters.punctation = ClassicalSentence.EnumPunctation.JUDGMENT; ClassicalSentence task2Sentence = ClassicalSentence.makeByTermPunctuationTruthStampNormalize(task2SentenceParameters); ClassicalTask.MakeParameters task2MakeParameters = new ClassicalTask.MakeParameters(); task2MakeParameters.sentence = task2Sentence; task2MakeParameters.budget = new ClassicalBudgetValue(0.5f, 0.5f, 0.5f); nar.inputTask(ClassicalTask.make(task2MakeParameters)); for (;;) { nar.cycle(); } int here = 5; }
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)); }
/** * 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); }
// 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); }
/* --------------- 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 }
// https://github.com/opennars/opennars/blob/4515f1d8e191a1f097859decc65153287d5979c5/nars_core/nars/entity/Concept.java#L648 /** * To answer a question by existing beliefs * * \param task The task to be processed * \return Whether to continue the processing of the task */ private void processQuestion(DerivationContext ctx, ClassicalConcept @this, ClassicalTask task) { ClassicalTask quesTask = task; bool newQuestion = true; foreach (ClassicalTask t in @this.questions) { if (t.sentence.equalsContent(quesTask.sentence)) { quesTask = t; newQuestion = false; break; } } if (newQuestion) { if (@this.questions.Count + 1 > Parameters.CONCEPT_QUESTIONS_MAX) { ClassicalTask removed = @this.questions[0]; @this.questions.RemoveAt(0); // FIFO //memory.event.emit(ConceptQuestionRemove.class, this, removed); } @this.questions.Add(task); // memory.event.emit(ConceptQuestionAdd.class, this, task); } ClassicalSentence ques = quesTask.sentence; ClassicalTask newAnswerT = (ques.isQuestion) ? selectCandidate(quesTask, @this.beliefs, EnumForRevision.NOREVISION) : selectCandidate(quesTask, @this.desires, EnumForRevision.NOREVISION); if (newAnswerT != null) { LocalRules.trySolution(newAnswerT.sentence, task, ctx, true, memory); } // commented because memory events are not implemented //else if(task.isInput() && !quesTask.getTerm().hasVarQuery() && quesTask.getBestSolution() != null) { //show previously found solution anyway in case of input //memory.emit(Events.Answer.class, quesTask, quesTask.getBestSolution()); //} }
// see https://github.com/opennars/opennars/blob/4515f1d8e191a1f097859decc65153287d5979c5/nars_core/nars/storage/Memory.java#L417 void processNewTasks() { while (newTasks.Count != 0) { ClassicalTask task = newTasks.Dequeue(); if ( // new input or existing concept task.isInput || task.sentence.isQuest || task.sentence.isQuestion /*|| concept(task.sentence.term) != null*/ ) { localInference(task); } else { ClassicalSentence sentence = task.sentence; if (sentence.isJudgment || sentence.isGoal) { double expectation = sentence.truth.expectation; // new concept formation if ( (sentence.isJudgment && expectation > Parameters.DEFAULT_CREATION_EXPECTATION) || (sentence.isGoal && expectation > Parameters.DEFAULT_CREATION_EXPECTATION_GOAL) ) { attention.addNovelTask(task); } else { removeTask(task, "Neglected"); } } } } }
/** * 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); }
// 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); }
// https://github.com/opennars/opennars/blob/62c814fb0f3e474a176515103394049b2887ec29/nars_core/nars/entity/Concept.java#L440 /** * To accept a new goal, and check for revisions and realization, then * decide whether to actively pursue it * * \param judg The judgment to be accepted * \param task The task to be processed * \return Whether to continue the processing of the task */ private bool processGoal(DerivationContext ctx, ClassicalConcept @this, ClassicalTask task) { ClassicalSentence goal = task.sentence; ClassicalTask oldGoalT = selectCandidate(task, @this.desires, EnumForRevision.REVISION); // revise with the existing desire values ClassicalSentence oldGoal = null; if (oldGoalT != null) { oldGoal = oldGoalT.sentence; Stamp newStamp = goal.stamp; Stamp oldStamp = oldGoal.stamp; bool isStampEqual = Stamp.checkEquals( newStamp, oldStamp, Stamp.EnumCompareCreationTime.NO, Stamp.EnumCompareOccurrenceTime.NO, Stamp.EnumCompareEvidentialBaseTime.YES); if (isStampEqual) { return(false); // duplicate } if (LocalRules.revisible(goal, oldGoal)) { ctx.setTheNewStamp(newStamp, oldStamp, memory.time); ClassicalSentence projectedGoal = oldGoal.projection(task.sentence.stamp.occurrenceTime, newStamp.occurrenceTime); if (projectedGoal != null) { // if (goal.after(oldGoal, nal.memory.param.duration.get())) { //no need to project the old goal, it will be projected if selected anyway now // nal.singlePremiseTask(projectedGoal, task.budget); //return; // } ctx.currentBelief = projectedGoal; if (true /* TODO< check if not operation > !(task.sentence.term instanceof Operation)*/) { bool successOfRevision = LocalRules.revision(ctx, task.sentence, projectedGoal, false); if (successOfRevision) // it is revised, so there is a new task for which this function will be called { return(false); // with higher/lower desire } // it is not allowed to go on directly due to decision making https://groups.google.com/forum/#!topic/open-nars/lQD0no2ovx4 } } } } Stamp s2 = goal.stamp.clone(); s2.occurrenceTime = memory.time; if (s2.after(task.sentence.stamp, ctx.memory.param.duration.value)) // this task is not up to date we have to project it first { ClassicalSentence projGoal = task.sentence.projection(memory.time, ctx.memory.param.duration.value); if (projGoal != null && projGoal.truth.expectation > ctx.memory.param.decisionThreshold) { ctx.singlePremiseTask(projGoal, task.budget.clone()); // keep goal updated // return false; //outcommented, allowing "roundtrips now", relevant for executing multiple steps of learned implication chains } } if (task.isAboveThreshold) { ClassicalTask beliefT = selectCandidate(task, @this.beliefs, EnumForRevision.NOREVISION); // check if the Goal is already satisfied double antiSatisfaction = 0.5; // we dont know anything about that goal yet, so we pursue it to remember it because its maximally unsatisfied if (beliefT != null) { ClassicalSentence belief = beliefT.sentence; ClassicalSentence projectedBelief = belief.projection(task.sentence.stamp.occurrenceTime, ctx.memory.param.duration.value); LocalRules.trySolution(projectedBelief, task, ctx, true, memory); // check if the Goal is already satisfied (manipulate budget) antiSatisfaction = task.sentence.truth.getExpDifAbs(belief.truth); } double satisfaction = 1.0 - antiSatisfaction; TruthValue t = goal.truth.clone(); t.frequency = (float)(t.frequency - satisfaction); // decrease frequency according to satisfaction value bool fullfilled = antiSatisfaction < Parameters.SATISFACTION_TRESHOLD; ClassicalSentence projectedGoal = goal.projection(ctx.memory.time, ctx.memory.time); // NOTE< this projection is fine > /* commented because we stil have to implement operations * if (projectedGoal != null && task.isAboveThreshold && !fullfilled && projectedGoal.truth.expectation > nal.memory.param.decisionThreshold.get()) { * * try { * Operation bestop = null; * float bestop_truthexp = 0.0f; * TruthValue bestop_truth = null; * Task executable_precond = null; * //long distance = -1; * long mintime = -1; * long maxtime = -1; * for (Task t: this.executable_preconditions) { * Term[] prec = ((Conjunction)((Implication)t.getTerm()).getSubject()).term; * Term[] newprec = new Term[prec.length - 3]; * for (int i = 0; i < prec.length - 3; i++) { //skip the last part: interval, operator, interval * newprec[i] = prec[i]; * } * * //distance = Interval.magnitudeToTime(((Interval)prec[prec.length-1]).magnitude, nal.memory.param.duration); * mintime = nal.memory.time() + Interval.magnitudeToTime(((Interval)prec[prec.length - 1]).magnitude - 1, nal.memory.param.duration); * maxtime = nal.memory.time() + Interval.magnitudeToTime(((Interval)prec[prec.length - 1]).magnitude + 2, nal.memory.param.duration); * * Operation op = (Operation)prec[prec.length - 2]; * Term precondition = Conjunction.make(newprec, TemporalRules.ORDER_FORWARD); * * Concept preconc = nal.memory.concept(precondition); * long newesttime = -1; * Task bestsofar = null; * if (preconc != null) { //ok we can look now how much it is fullfilled * * //check recent events in event bag * for (Task p : this.memory.sequenceTasks) { * if (p.sentence.term.equals(preconc.term) && p.sentence.isJudgment() && !p.sentence.isEternal() && p.sentence.getOccurenceTime() > newesttime && p.sentence.getOccurenceTime() <= memory.time()) { * newesttime = p.sentence.getOccurenceTime(); * bestsofar = p; //we use the newest for now * } * } * if (bestsofar == null) { * continue; * } * //ok now we can take the desire value: * TruthValue A = projectedGoal.getTruth(); * //and the truth of the hypothesis: * TruthValue Hyp = t.sentence.truth; * //and the truth of the precondition: * Sentence projectedPrecon = bestsofar.sentence.projection(memory.time() comment*- distance comment*, memory.time()); * * if (projectedPrecon.isEternal()) { * continue; //projection wasn't better than eternalization, too long in the past * } * //debug start * //long timeA = memory.time(); * //long timeOLD = bestsofar.sentence.stamp.getOccurrenceTime(); * //long timeNEW = projectedPrecon.stamp.getOccurrenceTime(); * //debug end * TruthValue precon = projectedPrecon.truth; * //and derive the conjunction of the left side: * TruthValue leftside = TruthFunctions.desireDed(A, Hyp); * //in order to derive the operator desire value: * TruthValue opdesire = TruthFunctions.desireDed(precon, leftside); * * float expecdesire = opdesire.getExpectation(); * if (expecdesire > bestop_truthexp) { * bestop = op; * bestop_truthexp = expecdesire; * bestop_truth = opdesire; * executable_precond = t; * } * } * } * * if (bestop != null && bestop_truthexp > memory.param.decisionThreshold.get()) { * Task t = new Task(new Sentence(bestop, Symbols.JUDGMENT_MARK, bestop_truth, projectedGoal.stamp), new BudgetValue(1.0f, 1.0f, 1.0f)); * //System.out.println("used " +t.getTerm().toString() + String.valueOf(memory.randomNumber.nextInt())); * if (!task.sentence.stamp.evidenceIsCyclic()) { * if (!executeDecision(t)) { //this task is just used as dummy * memory.emit(UnexecutableGoal.class, task, this, nal); * } else { * memory.decisionBlock = memory.time() + Parameters.AUTOMATIC_DECISION_USUAL_DECISION_BLOCK_CYCLES; * SyllogisticRules.generatePotentialNegConfirmation(nal, executable_precond.sentence, executable_precond.budget, mintime, maxtime, 2); * } * } * } * } * catch(Exception ex) { * System.out.println("Failure in operation choice rule, analyze!"); * } * * * * questionFromGoal(task, ctx); * * * addToTable(task, false, desires, Parameters.CONCEPT_GOALS_MAX, ConceptGoalAdd.class, ConceptGoalRemove.class); * * InternalExperience.InternalExperienceFromTask(memory, task,false); * * if(nal.memory.time >= memory.decisionBlock && !executeDecision(task)) { * // commented because we haven't implemented the observer until now memory.emit(UnexecutableGoal.class, task, this, nal); * return true; // it was made true by itself * } * return false; * } // big if */ return(fullfilled); } return(false); }
// 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 ); } } }
/** * Derived task comes from the inference rules. * * \param task the derived task * \param overlapAllowed //https://groups.google.com/forum/#!topic/open-nars/FVbbKq5En-M */ public bool derivedTask( ClassicalTask task, bool revised, bool single, ClassicalTask parent, ClassicalSentence occurence2, bool overlapAllowed ) { if (derivationFilters != null) { foreach (DerivationFilter iDerivationFilter in derivationFilters) { string rejectionReason = iDerivationFilter.reject(this, task, revised, single, parent, occurence2); if (rejectionReason != null) { memory.removeTask(task, rejectionReason); return(false); } } } ClassicalSentence occurence = parent != null ? parent.sentence : null; if (!task.budget.isAboveThreshold) { memory.removeTask(task, "Insufficient Budget"); return(false); } if (task.sentence != null && task.sentence.truth != null) { float conf = task.sentence.truth.confidence; if (conf == 0) { //no confidence - we can delete the wrongs out that way. memory.removeTask(task, "Ignored (zero confidence)"); return(false); } } /* uncommented because operations are not jet implemented * TODO< translate to C# if operations are implemented */ /* * if (task.sentence.term instanceof Operation) { * Operation op = (Operation)task.sentence.term; * if (op.getSubject() instanceof Variable || op.getPredicate() instanceof Variable) { * memory.removeTask(task, "Operation with variable as subject or predicate"); * return false; * } * } */ Stamp stamp = task.sentence.stamp; if (occurence != null && !occurence.stamp.isEternal) { stamp.occurrenceTime = occurence.stamp.occurrenceTime; } if (occurence2 != null && !occurence2.stamp.isEternal) { stamp.occurrenceTime = occurence2.stamp.occurrenceTime; } // it is revision, of course its cyclic, apply evidental base policy // TODO< reconsider > if ( !overlapAllowed && this.evidentalOverlap && Stamp.checkOverlap(stamp) ) { memory.removeTask(task, "Overlapping Evidenctal Base"); //"(i=" + i + ",j=" + j +')' return(false); } task.setElementOfSequenceBuffer(false); if (!revised) { task.budget.durability = (task.budget.durability * Parameters.DERIVATION_DURABILITY_LEAK); task.budget.priority = (task.budget.priority * Parameters.DERIVATION_PRIORITY_LEAK); } //memory.event.emit(Events.TaskDerive.class, task, revised, single, occurence, occurence2); //memory.logic.TASK_DERIVED.commit(task.budget.getPriority()); addTask(task, "Derived"); return(true); }