/* * Believe.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.operator.mental; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import nars.util.EventEmitter.EventObserver; import nars.util.Events; import nars.util.Events.CycleEnd; import nars.storage.Memory; import nars.NAR; import nars.config.Parameters; import nars.control.DerivationContext; import nars.entity.BudgetValue; import nars.entity.Sentence; import nars.entity.Stamp; import nars.entity.Task; import nars.entity.TruthValue; import nars.inference.BudgetFunctions; import nars.io.Output.ANTICIPATE; import nars.io.Output.CONFIRM; import nars.io.Output.DISAPPOINT; import nars.io.Symbols; import nars.language.Interval; import nars.language.Product; import nars.language.Term; import nars.operator.Operation; import nars.operator.Operator; import nars.plugin.mental.InternalExperience; //** //* Operator that creates a judgment with a given statement //* public class Anticipate extends Operator implements EventObserver { public final Map<Vector2Int,LinkedHashSet<Term>> anticipations = new LinkedHashMap(); final Set<Term> newTasks = new LinkedHashSet(); DerivationContext nal; final static TruthValue expiredTruth = new TruthValue(0.0f, Parameters.ANTICIPATION_CONFIDENCE); final static BudgetValue expiredBudget = new BudgetValue(Parameters.DEFAULT_JUDGMENT_PRIORITY, Parameters.DEFAULT_JUDGMENT_DURABILITY, BudgetFunctions.truthToQuality(expiredTruth)); public Anticipate() { super("^anticipate"); } @Override public boolean setEnabled(NAR n, boolean enabled) { n.memory.event.set(this, enabled, Events.InduceSucceedingEvent.class, Events.CycleEnd.class); return true; } class Vector2Int { public long predictionCreationTime; //2014 and this is still the best way to define a data structure that simple? public long predictedOccurenceTime; public Vector2Int(long predictionCreationTime, long predictedOccurenceTime) { //rest of the crap: this.predictionCreationTime=predictionCreationTime; //when the prediction happened this.predictedOccurenceTime=predictedOccurenceTime; //when the event is expected } } public void updateAnticipations() { if (anticipations.isEmpty()) return; long now=nal.memory.time(); //share stamps created by tasks in this cycle boolean hasNewTasks = !newTasks.isEmpty(); Iterator<Map.Entry<Vector2Int, LinkedHashSet<Term>>> aei = anticipations.entrySet().iterator(); while (aei.hasNext()) { Map.Entry<Vector2Int, LinkedHashSet<Term>> ae = aei.next(); long aTime = ae.getKey().predictedOccurenceTime; long predictionstarted=ae.getKey().predictionCreationTime; if(aTime < predictionstarted) { //its about the past.. return; } //lets say a and <(&/,a,+4) =/> b> leaded to prediction of b with specific occurence time //this indicates that this interval can be reconstructed by looking by when the prediction //happened and for what time it predicted, Only when the happening would already lead to <(&/,a,+5) =/> b> //we are allowed to apply CWA already, i think this is the perfect time to do this //since there is no way anymore that the observation would support <(&/,a,+4) =/> b> at this time, //also this way it is not applied to early, it seems to be the perfect time to me, //making hopeExpirationWindow parameter entirely osbolete Interval Int=Interval.interval(aTime-predictionstarted, nal.memory); //ok we know the magnitude now, let's now construct a interval with magnitude one higher //(this we can skip because magnitudeToTime allows it without being explicitly constructed) //ok, and what predicted occurence time would that be? because only if now is bigger or equal, didnt happen is true double expiredate=predictionstarted+Interval.magnitudeToTime(Int.magnitude+2, nal.memory.param.duration); // boolean didntHappen = (now>=expiredate); boolean maybeHappened = hasNewTasks && !didntHappen; if ((!didntHappen) && (!maybeHappened)) continue; LinkedHashSet<Term> terms = ae.getValue(); Iterator<Term> ii = terms.iterator(); while (ii.hasNext()) { Term aTerm = ii.next(); boolean remove = false; if (didntHappen) { deriveDidntHappen(aTerm,aTime); remove = true; } if (maybeHappened) { if (newTasks.remove(aTerm)) { //in case it happened, temporal induction will do the rest, else deriveDidntHappen occurred if(!remove) { nal.memory.emit(CONFIRM.class, aTerm); } remove = true; hasNewTasks = !newTasks.isEmpty(); } } if (remove) ii.remove(); } if (terms.isEmpty()) { //remove this time entry because its terms have been emptied aei.remove(); } } newTasks.clear(); } @Override public void event(Class event, Object[] args) { if (event == Events.InduceSucceedingEvent.class || event == Events.TaskDerive.class) { Task newEvent = (Task)args[0]; this.nal= (DerivationContext)args[1]; if (newEvent.sentence.truth != null && newEvent.sentence.isJudgment() && newEvent.sentence.truth.getExpectation() > Parameters.DEFAULT_CONFIRMATION_EXPECTATION && !newEvent.sentence.isEternal()) { newTasks.add(newEvent.getTerm()); //new: always add but keep truth value in mind } } if (nal!=null && event == CycleEnd.class) { updateAnticipations(); } } //* // * To create a judgment with a given statement // * @param args Arguments, a Statement followed by an optional tense // * @param memory The memory in which the operation is executed // * @return Immediate results as Tasks // * @Override protected ArrayList<Task> execute(Operation operation, Term[] args, Memory memory) { if(operation==null) { return null; //not as mental operator but as fundamental principle } anticipate(args[0],memory,memory.time()+memory.param.duration.get(), null); return null; } boolean anticipationOperator=false; //a parameter which tells whether NARS should know if it anticipated or not //in one case its the base functionality needed for NAL8 and in the other its a mental NAL9 operator public boolean isAnticipationAsOperator() { return anticipationOperator; } public void setAnticipationAsOperator(boolean val) { anticipationOperator=val; } public void anticipate(Term content, Memory memory, long occurenceTime, Task t) { //if(true) // return; /*if(content instanceof Conjunction && ((Conjunction)content).getTemporalOrder()!=TemporalRules.ORDER_NONE) { return; }*/ if(t!=null && t.sentence.truth.getExpectation() < Parameters.DEFAULT_CONFIRMATION_EXPECTATION) { return; } // Concept c = memory.concept(t.getTerm()); /* if(!c.observable) { return; }*/ if(t != null) { memory.emit(ANTICIPATE.class, t); } else { memory.emit(ANTICIPATE.class, content); } LinkedHashSet<Term> ae = new LinkedHashSet(); anticipations.put(new Vector2Int(memory.time(),occurenceTime), ae); ae.add(content); if(anticipationOperator) { Operation op=(Operation) Operation.make(Product.make(content), this); TruthValue truth=new TruthValue(1.0f,0.90f); Stamp st; if(t==null) { st=new Stamp(memory); } else { st=t.sentence.stamp.clone(); st.setOccurrenceTime(memory.time()); } Sentence s=new Sentence(op,Symbols.JUDGMENT_MARK,truth,st); Task newTask=new Task(s,new BudgetValue( Parameters.DEFAULT_JUDGMENT_PRIORITY*InternalExperience.INTERNAL_EXPERIENCE_PRIORITY_MUL, Parameters.DEFAULT_JUDGMENT_DURABILITY*InternalExperience.INTERNAL_EXPERIENCE_DURABILITY_MUL, BudgetFunctions.truthToQuality(truth))); memory.addNewTask(newTask, "Perceived (Internal Experience: Anticipation)"); } } protected void deriveDidntHappen(Term aTerm, long expectedOccurenceTime) { TruthValue truth = expiredTruth; BudgetValue budget = expiredBudget; Stamp stamp = new Stamp(nal.memory); //stamp.setOccurrenceTime(nal.memory.time()); stamp.setOccurrenceTime(expectedOccurenceTime); //it did not happen, so the time of when it did not //happen is exactly the time it was expected Sentence S = new Sentence(aTerm, Symbols.JUDGMENT_MARK, truth, stamp); Task task = new Task(S, budget); nal.derivedTask(task, false, true, null, null, false); task.setElemOfSequenceBuffer(true); nal.memory.emit(DISAPPOINT.class, task); } }