astra.core.ASTRAClass Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of astra-interpreter Show documentation
Show all versions of astra-interpreter Show documentation
Core interpreter artifact for the ASTRA Language
package astra.core;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Set;
import astra.event.Event;
import astra.event.GoalEvent;
import astra.formula.Formula;
import astra.formula.Goal;
import astra.formula.Inference;
import astra.formula.Predicate;
import astra.reasoner.Queryable;
import astra.term.ListTerm;
import astra.term.Term;
import astra.tr.Function;
public abstract class ASTRAClass implements Queryable {
Map> rules = new HashMap<>();
Map functions = new HashMap<>();
Map> inferences = new HashMap<>();
List ruleOrder = new LinkedList<>();
private Set filter = new HashSet<>();
private List linearization;
private Class[] parents;
private int distFromRoot = -1;
public void setParents(Class[] parents) {
this.parents = parents;
}
public boolean isRunnable() {
GoalEvent event = new GoalEvent('+', new Goal(new Predicate("main", new Term[] { new ListTerm()})));
for (ASTRAClass cls : linearization) {
if (cls.rules.containsKey(event.signature())) return true;
}
return false;
}
public synchronized Agent newInstance(String name) throws AgentCreationException, ASTRAClassNotFoundException {
if (Agent.hasAgent(name)) {
throw new AgentCreationException("An agent with name: \"" + name + "\" already exists.");
}
Agent agent = new Agent(name);
agent.setMainClass(this);
return agent;
}
public abstract void initialize(Agent agent);
public abstract Fragment createFragment(Agent agent) throws ASTRAClassNotFoundException;
public List getLinearization() throws ASTRAClassNotFoundException {
if (linearization==null) {
linearization = new LinkedList<>();
Queue queue = new PriorityQueue<>(1, (o1,o2) -> o1.getDistance()-o2.getDistance());
Queue queue2 = new LinkedList<>();
queue2.add(this);
while (!queue2.isEmpty()) {
ASTRAClass claz = queue2.poll();
if (claz.parents != null) {
for (int i=claz.parents.length-1; i>-1; i--) {
ASTRAClass c = ASTRAClassLoader.getDefaultClassLoader().loadClass(claz.parents[i]);
if (!queue.contains(c) && !queue2.contains(c)) {
queue2.add(c);
}
}
queue.add(claz);
}
}
while (!queue.isEmpty()) {
ASTRAClass claz = queue.poll();
if (!linearization.contains(claz))
linearization.add(0, claz);
}
}
return linearization;
}
public int getDistance() {
int maxDist;
int d;
if (distFromRoot==-1) {
maxDist=0;
if (parents != null) {
for (Class parent : this.parents) {
try {
ASTRAClass cls = ASTRAClassLoader.getDefaultClassLoader().loadClass(parent);
d = cls.getDistance();
if (d > maxDist) maxDist = d;
} catch (ASTRAClassNotFoundException e) {
e.printStackTrace();
}
}
}
distFromRoot = maxDist+1;
}
return distFromRoot;
}
public String toString() {
return "ASTRAClass:"+getClass().getCanonicalName();
}
public String getCanonicalName() {
return getClass().getCanonicalName();
}
public List getRuleOrder() {
return ruleOrder;
}
public void addRule(Rule rule) {
ruleOrder.add(rule);
List list = rules.get(rule.event.signature());
if (list == null) {
filter.add(rule.event.signature());
list = new LinkedList<>();
rules.put(rule.event.signature(), list);
}
list.add(rule);
}
public void addInference(Inference inference) {
List list = inferences.get(inference.head().id());
if (list == null) {
list = new LinkedList<>();
inferences.put(inference.head().id(), list);
}
list.add(inference);
}
public void addFunction(Function function) {
if (functions.containsKey(function.identifier.id())) {
System.out.println("Attempt to add duplicate function :" + function.identifier);
return;
}
functions.put(function.identifier.id(), function);
}
public Set filter() {
return filter;
}
public boolean handleEvent(Event event, Agent agent) {
// System.out.println("["+agent.name()+"] Checking class: " + getClass().getCanonicalName());
if (agent.trace()) System.out.println("["+agent.name()+"] Checking class: " + getClass().getCanonicalName());
List list = rules.get(event.signature());
// System.out.println("["+agent.name()+"] List: " + list);
if (list == null) return false;
for (Rule rule : list) {
if (agent.trace()) System.out.println("["+agent.name()+"] \tChecking rule: " + rule.event);
Map bindings = Helper.evaluateRule(agent, rule, event);
if (bindings != null) {
Object source = event.getSource();
if (source != null) {
Intention intention = null;
if (Intention.class.isInstance(source)) {
intention = (Intention) source;
intention.addSubGoal(event, rule, bindings, null);
if (agent.trace()) System.out.println("["+agent.name()+"] \tADDING SUBGOAL: " + rule.event + "\n\tbindings: " + bindings);
} else if (RuleExecutor.class.isInstance(source)) {
RuleExecutor executor = (RuleExecutor) source;
intention = executor.intention();
intention.addSubGoal(event, rule, bindings, executor);
if (agent.trace()) System.out.println("["+agent.name()+"] \tADDING RULE SUBGOAL: " + rule.event + "\n\tbindings: " + bindings);
}
intention.resume();
} else {
// Intention i = null;
// System.out.println("["+agent.name()+"] \tCREATING NEW INTENTION: " + rule.event + "\n\tbindings: " + bindings);
agent.addIntention(new Intention(agent, event, rule, bindings));
// System.out.println(i.toString());
}
return true;
}
}
if (agent.trace()) System.out.println("[" + agent.name() + "] FAILED to match event...");
return false;
}
public static ASTRAClass forName(String url) throws ASTRAClassNotFoundException {
return ASTRAClassLoader.getDefaultClassLoader().loadClass(url);
}
public static ASTRAClass forName(String _package, String url) throws ASTRAClassNotFoundException {
if (_package == null) return forName(url);
return ASTRAClassLoader.getDefaultClassLoader().loadClass(_package+"."+url);
}
public Function getFunction(Predicate predicate) {
return functions.get(predicate.id());
}
public boolean hasFunctions() {
return !functions.isEmpty();
}
public void addMatchingFormulae(Queue queue, Formula predicate) {
if (predicate instanceof Predicate) {
List list = inferences.get(((Predicate) predicate).id());
if (list != null) queue.addAll(list);
}
}
public Iterator iterator(Formula formula) {
if (formula instanceof Predicate) {
List list = inferences.get(((Predicate) formula).id());
return list == null ? Queryable.EMPTY_LIST.iterator():list.iterator();
}
return Queryable.EMPTY_LIST.iterator();
}
public boolean isSubclass(ASTRAClass cl) {
try {
for (ASTRAClass cls : cl.getLinearization()) {
if (cls.getCanonicalName().equals(this.getCanonicalName())) return true;
}
} catch (ASTRAClassNotFoundException e) {
e.printStackTrace();
}
return false;
}
public Map> rules() {
return this.rules;
}
public Class[] getParents() {
return parents;
}
}