/* * BudgetFunctions.java * * Copyright (C) 2008 Pei Wang * * This file is part of Open-NARS. * * Open-NARS is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * Open-NARS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Open-NARS. If not, see <http://www.gnu.org/licenses/>. */ package nars.inference; import static java.lang.Math.max; import static java.lang.Math.pow; import static java.lang.Math.sqrt; import nars.storage.Memory; import nars.config.Parameters; import nars.entity.BudgetValue; import nars.entity.Concept; import nars.entity.Item; import nars.entity.Sentence; import nars.entity.Task; import nars.entity.TaskLink; import nars.entity.TermLink; import nars.entity.TruthValue; import nars.language.Term; import static java.lang.Math.max; /** * Budget functions for resources allocation */ public final class BudgetFunctions extends UtilityFunctions { /* ----------------------- Belief evaluation ----------------------- */ /** * Determine the quality of a judgment by its truth value alone * <p> * Mainly decided by confidence, though binary judgment is also preferred * * @param t The truth value of a judgment * @return The quality of the judgment, according to truth value only */ public final static float truthToQuality(final TruthValue t) { final float exp = t.getExpectation(); return (float) max(exp, (1 - exp)*0.75); } /** * 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 final static float rankBelief(final Sentence judg, final boolean rankTruthExpectation) { if(rankTruthExpectation) { return judg.getTruth().getExpectation(); } final float confidence = judg.truth.getConfidence(); //final float originality = judg.stamp.getOriginality(); return confidence; //or(confidence, originality); } /** * Evaluate the quality of a revision, then de-prioritize the premises * * @param tTruth The truth value of the judgment in the task * @param bTruth The truth value of the belief * @param truth The truth value of the conclusion of revision * @return The budget for the new task */ static BudgetValue revise(final TruthValue tTruth, final TruthValue bTruth, final TruthValue truth, final boolean feedbackToLinks, final nars.control.DerivationContext nal) { final float difT = truth.getExpDifAbs(tTruth); final Task task = nal.getCurrentTask(); task.decPriority(1 - difT); task.decDurability(1 - difT); if (feedbackToLinks) { TaskLink tLink = nal.getCurrentTaskLink(); tLink.decPriority(1 - difT); tLink.decDurability(1 - difT); TermLink bLink = nal.getCurrentBeliefLink(); final float difB = truth.getExpDifAbs(bTruth); bLink.decPriority(1 - difB); bLink.decDurability(1 - difB); } float dif = truth.getConfidence() - max(tTruth.getConfidence(), bTruth.getConfidence()); float priority = or(dif, task.getPriority()); float durability = aveAri(dif, task.getDurability()); float quality = truthToQuality(truth); /* if (priority < 0) { memory.nar.output(ERR.class, new RuntimeException("BudgetValue.revise resulted in negative priority; set to 0")); priority = 0; } if (durability < 0) { memory.nar.output(ERR.class, new RuntimeException("BudgetValue.revise resulted in negative durability; set to 0; aveAri(dif=" + dif + ", task.getDurability=" + task.getDurability() +") = " + durability)); durability = 0; } if (quality < 0) { memory.nar.output(ERR.class, new RuntimeException("BudgetValue.revise resulted in negative quality; set to 0")); quality = 0; } */ return new BudgetValue(priority, durability, quality); } /** * Update a belief * * @param task The task containing new belief * @param bTruth Truth value of the previous belief * @return Budget value of the updating task */ static BudgetValue update(final Task task, final TruthValue bTruth) { final TruthValue tTruth = task.sentence.truth; final float dif = tTruth.getExpDifAbs(bTruth); final float priority = or(dif, task.getPriority()); final float durability = aveAri(dif, task.getDurability()); final float quality = truthToQuality(bTruth); return new BudgetValue(priority, durability, 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 BudgetValue distributeAmongLinks(final BudgetValue b, final int n) { final float priority = (float) (b.getPriority() / sqrt(n)); return new BudgetValue(priority, b.getDurability(), b.getQuality()); } public enum Activating { Max, TaskLink } /* ----------------------- Concept ----------------------- */ /** * Activate a concept by an incoming TaskLink * * @param receiver The budget receiving the activation * @param amount The budget for the new item */ public static void activate(final BudgetValue receiver, final BudgetValue amount, Activating mode) { switch (mode) { case Max: BudgetFunctions.merge(receiver, amount); break; case TaskLink: final float oldPri = receiver.getPriority(); receiver.setPriority( or(oldPri, amount.getPriority()) ); receiver.setDurability( aveAri(receiver.getDurability(), amount.getDurability()) ); receiver.setQuality( receiver.getQuality() ); break; } } /* ---------------- Bag functions, on all Items ------------------- */ /** * 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(final BudgetValue budget, final float forgetCycles, final float relativeThreshold) { float quality = budget.getQuality() * relativeThreshold; // re-scaled quality final float p = budget.getPriority() - quality; // priority above quality if (p > 0) { quality += p * pow(budget.getDurability(), 1.0 / (forgetCycles * p)); } // priority Durability budget.setPriority(quality); return quality; } /** * 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(final BudgetValue b, final BudgetValue a) { b.setPriority(max(b.getPriority(), a.getPriority())); b.setDurability(max(b.getDurability(), a.getDurability())); b.setQuality(max(b.getQuality(), a.getQuality())); } /* ----- Task derivation in LocalRules and SyllogisticRules ----- */ /** * Forward inference result and adjustment * * @param truth The truth value of the conclusion * @return The budget value of the conclusion */ public static BudgetValue forward(final TruthValue truth, final nars.control.DerivationContext nal) { return budgetInference(truthToQuality(truth), 1, nal); } /** * Backward inference result and adjustment, stronger case * * @param truth The truth value of the belief deriving the conclusion * @param nal Reference to the memory * @return The budget value of the conclusion */ public static BudgetValue backward(final TruthValue truth, final nars.control.DerivationContext nal) { return budgetInference(truthToQuality(truth), 1, nal); } /** * Backward inference result and adjustment, weaker case * * @param truth The truth value of the belief deriving the conclusion * @param nal Reference to the memory * @return The budget value of the conclusion */ public static BudgetValue backwardWeak(final TruthValue truth, final nars.control.DerivationContext nal) { return budgetInference(w2c(1) * truthToQuality(truth), 1, nal); } /* ----- Task derivation in CompositionalRules and StructuralRules ----- */ /** * Forward inference with CompoundTerm conclusion * * @param truth The truth value of the conclusion * @param content The content of the conclusion * @param nal Reference to the memory * @return The budget of the conclusion */ public static BudgetValue compoundForward(final TruthValue truth, final Term content, final nars.control.DerivationContext nal) { final float complexity = (content == null) ? Parameters.COMPLEXITY_UNIT : Parameters.COMPLEXITY_UNIT*content.getComplexity(); return budgetInference(truthToQuality(truth), complexity, nal); } /** * Backward inference with CompoundTerm conclusion, stronger case * * @param content The content of the conclusion * @param memory Reference to the memory * @return The budget of the conclusion */ public static BudgetValue compoundBackward(final Term content, final nars.control.DerivationContext nal) { return budgetInference(1, content.getComplexity()*Parameters.COMPLEXITY_UNIT, nal); } /** * Backward inference with CompoundTerm conclusion, weaker case * * @param content The content of the conclusion * @param nal Reference to the memory * @return The budget of the conclusion */ public static BudgetValue compoundBackwardWeak(final Term content, final nars.control.DerivationContext nal) { return budgetInference(w2c(1), content.getComplexity()*Parameters.COMPLEXITY_UNIT, nal); } /** * Get the current activation level of a concept. * * @param t The Term naming a concept * @return the priority value of the concept */ public static float conceptActivation(Memory mem, final Term t) { final Concept c = mem.concept(t); return (c == null) ? 0f : c.getPriority(); } /** * Common processing for all inference step * * @param qual Quality of the inference * @param complexity Syntactic complexity of the conclusion * @param nal Reference to the memory * @return Budget of the conclusion task */ private static BudgetValue budgetInference(final float qual, final float complexity, final nars.control.DerivationContext nal) { Item t = nal.getCurrentTaskLink(); if (t == null) { t = nal.getCurrentTask(); } float priority = t.getPriority(); float durability = t.getDurability() / complexity; final float quality = qual / complexity; final TermLink bLink = nal.getCurrentBeliefLink(); if (bLink != null) { priority = or(priority, bLink.getPriority()); durability = and(durability, bLink.getDurability()); final float targetActivation = conceptActivation(nal.memory, bLink.target); bLink.incPriority(or(quality, targetActivation)); bLink.incDurability(quality); } return new BudgetValue(priority, durability, quality); } @Deprecated static BudgetValue solutionEval(final Sentence problem, final Sentence solution, Task task, final Memory memory) { throw new RuntimeException("Moved to TemporalRules.java"); } public static BudgetValue budgetTermLinkConcept(Concept c, BudgetValue taskBudget, TermLink termLink) { return taskBudget.clone(); } }