package nars.plugin.mental;
import nars.util.Plugin;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import nars.util.EventEmitter.EventObserver;
import nars.util.Events.TaskDerive;
import nars.storage.Memory;
import nars.NAR;
import nars.config.Parameters;
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.Symbols;
import static nars.language.CompoundTerm.termArray;
import nars.language.Similarity;
import nars.language.Term;
import nars.operator.Operation;
import nars.operator.Operator;
import com.google.common.util.concurrent.AtomicDouble;
/**
* 1-step abbreviation, which calls ^abbreviate directly and not through an added Task.
* Experimental alternative to Abbreviation plugin.
*/
public class Abbreviation implements Plugin {
private double abbreviationProbability = InternalExperience.INTERNAL_EXPERIENCE_PROBABILITY;
/**
* Operator that give a CompoundTerm an atomic name
*/
public static class Abbreviate extends Operator {
public Abbreviate() {
super("^abbreviate");
}
private static AtomicInteger currentTermSerial = new AtomicInteger(1);
public Term newSerialTerm(char prefix) {
return new Term(prefix + String.valueOf(currentTermSerial.incrementAndGet()));
}
/**
* 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) {
Term compound = args[0];
Term atomic = newSerialTerm(Symbols.TERM_PREFIX);
Sentence sentence = new Sentence(
Similarity.make(compound, atomic),
Symbols.JUDGMENT_MARK,
new TruthValue(1, Parameters.DEFAULT_JUDGMENT_CONFIDENCE), // a naming convension
new Stamp(memory));
float quality = BudgetFunctions.truthToQuality(sentence.truth);
BudgetValue budget = new BudgetValue(
Parameters.DEFAULT_JUDGMENT_PRIORITY,
Parameters.DEFAULT_JUDGMENT_DURABILITY,
quality);
return Lists.newArrayList( new Task(sentence, budget) );
}
}
public AtomicInteger abbreviationComplexityMin = new AtomicInteger(20);
public AtomicDouble abbreviationQualityMin = new AtomicDouble(0.95f);
public EventObserver obs;
//TODO different parameters for priorities and budgets of both the abbreviation process and the resulting abbreviation judgment
//public AtomicDouble priorityFactor = new AtomicDouble(1.0);
public boolean canAbbreviate(Task task) {
return !(task.sentence.term instanceof Operation) &&
(task.sentence.term.getComplexity() > abbreviationComplexityMin.get()) &&
(task.budget.getQuality() > abbreviationQualityMin.get());
}
@Override
public boolean setEnabled(final NAR n, final boolean enabled) {
final Memory memory = n.memory;
Operator _abbreviate = memory.getOperator("^abbreviate");
if (_abbreviate == null) {
_abbreviate = memory.addOperator(new Abbreviate());
}
final Operator abbreviate = _abbreviate;
if(obs==null) {
obs=new EventObserver() {
@Override public void event(Class event, Object[] a) {
if (event != TaskDerive.class)
return;
if ((abbreviationProbability < 1.0) && (Memory.randomNumber.nextDouble() > abbreviationProbability))
return;
Task task = (Task)a[0];
//is it complex and also important? then give it a name:
if (canAbbreviate(task)) {
Operation operation = Operation.make(
abbreviate, termArray(task.sentence.term ),
false);
operation.setTask(task);
abbreviate.call(operation, memory);
}
}
};
}
memory.event.set(obs, enabled, TaskDerive.class);
return true;
}
}