All Downloads are FREE. Search and download functionalities are using the official Maven repository.

astra.lang.System Maven / Gradle / Ivy

There is a newer version: 1.4.3
Show newest version
package astra.lang;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import astra.core.ASTRAClass;
import astra.core.ASTRAClassNotFoundException;
import astra.core.Agent;
import astra.core.AgentCreationException;
import astra.core.Module;
import astra.core.ModuleException;
import astra.core.Scheduler;
import astra.event.GoalEvent;
import astra.execution.SchedulerStrategy;
import astra.formula.Formula;
import astra.formula.Goal;
import astra.formula.Predicate;
import astra.messaging.Utilities;
import astra.messaging.Utilities.PredicateState;
import astra.term.ListTerm;
import astra.term.Primitive;
import astra.term.Term;

/**
 * The System API contains a number of actions, terms and formulae that help you to 
 * manage the operation of the overall multi-agent system.
 */
public class System extends Module {
	private static class AgentEntry {
		String owner;
		Agent agent;
		
		public AgentEntry(String owner, Agent agent) {
			this.owner = owner;
			this.agent = agent;
		}
	}
	
	@ACTION
	public boolean skip() {
		return true;
	}
	
	// Static map of agents on the platform.
	private static Map agents = new HashMap();
	
	/**
	 * This internal method associates the agent with the module - this is overridden 
	 * to store a reference to the agent in the agents map
	 */
	@Override
	public void setAgent(Agent agent) {
		super.setAgent(agent);
		agents.put(agent.name(), new AgentEntry(null, agent));
	}
	
	/**
	 * Action that fails.
	 * 
	 * @return false
	 */
	@ACTION
	public boolean fail() {
		return false;
	}
	
	/**
	 * Action that allows the agent to terminate itself.
	 * 
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION
	public boolean terminate() {
		agent.terminate();
		agents.remove(agent.name());
		return true;
	}
	
	/**
	 * Action that allows the agent to create another agent.
	 * 
	 * @param name the name of the agent to be created
	 * @param clazz the class of the agent (an ASTRA class)
	 * 
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION
	public boolean createAgent(String name, String clazz) {
		if (agents.containsKey(name)) {
			throw new ModuleException("[System Module] Error: An agent with this name already exists on this platform: " + name);
		}
		
		try {
			ASTRAClass cl = ASTRAClass.forName(clazz);
			
			final Agent agt = cl.newInstance(name);
			agents.put(name, new AgentEntry(agent.name(), agt));
			Scheduler.schedule(agt);
		} catch (AgentCreationException e) {
			throw new ModuleException(e);
		} catch (ASTRAClassNotFoundException e) {
			throw new ModuleException(e);
		}
		return true;
	}

	/**
	 * This method can be used to set the main goal of an agent. It has been added
	 * to support the basic debugger...
	 * @param name the name of the agent
	 * @param args the list of arguments to be passed with the goal
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION
	public boolean setMainGoal(String name, ListTerm args) {
		agents.get(name).agent.addEvent(new GoalEvent(GoalEvent.ADDITION, new Goal(new Predicate("main", new Term[] {args}))));
		return true;
	}
	
	/**
	 * Action to terminate another agent (if it exists and the invoking agent 
	 * is the owner of that agent).
	 * 
	 * @param name the name of the agent to be terminated
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION
	public boolean terminateAgent(String name) {
		AgentEntry entry = agents.get(name);
		if (entry == null) {
			java.lang.System.err.println("[System Module] No such agent: " + name);
			return false;
		}
		
		// Only the owner (the creator) or the agent itself can call terminate
		if (agent.name().equals(entry.owner) || name.equals(agent.name())) {
			entry.agent.terminate();
			agents.remove(name);
			java.lang.System.out.println("[System Module] Agent '" + name + "' terminated");
		} else {
			java.lang.System.err.println("[System Module] Access Denied: Agent: " + agent.name() + " cannot terminate agent: " + name);
			return false;
		}
		return true;
	}

	/**
	 * Term that returns a list of all the agents on the platform.
	 * 
	 * @return an ASTRA list containing the names of all agents on the platform 
	 */
	@TERM 
	public ListTerm getAgents() {
		ListTerm term = new ListTerm();
		for (String name : agents.keySet()) {
			term.add(Primitive.newPrimitive(name));
		}
		return term;
	}
	
	/**
	 * Term that returns the type of the agent.
	 * 
	 * @return the type of the agent
	 */
	@TERM
	public String getType() {
		return agent.getASTRAClass().getCanonicalName();
	}
	
	@TERM
	public String env(String variable) {
		return java.lang.System.getenv(variable);
	}
	
	/**
	 * Term that returns the type of the agent with the given name.
	 * 
	 * @param name the name of the agent
	 * @return the type of the agent with the given name
	 */
	@TERM
	public String getType(String name) {
		AgentEntry entry = agents.get(name);
		if (entry == null) {
			java.lang.System.out.println("[System Module] There is no agent with name: " + name);
			return "none";
		}
		return entry.agent.getASTRAClass().getCanonicalName();
	}
	
	/**
	 * Term that returns a list of all the agents on the platform
	 * 
	 * @param type the agent type
	 * @return an ASTRA list containing the names of all agents on the platform 
	 */
	@TERM 
	public ListTerm getAgentsOfType(String type) {
		ListTerm term = new ListTerm();

		ASTRAClass cl;
		try {
			cl = ASTRAClass.forName(type);
		} catch (ASTRAClassNotFoundException e) {
			e.printStackTrace();
			java.lang.System.err.println("[System Module] Error: Type: " + type + " is not an ASTRA Class");
			return term;
		}
		
		for (String name : agents.keySet()) {
			AgentEntry entry = agents.get(name);
			if (entry.agent.getASTRAClass().isSubclass(cl)) term.add(Primitive.newPrimitive(name));
		}
		return term;
	}

	/**
	 * Term that returns a list of all the agents on that are children of the invoking agent
	 * 
	 * @return an ASTRA list containing the names of all agents on the platform 
	 */
	@TERM 
	public ListTerm getChildren() {
		ListTerm term = new ListTerm();

		for (AgentEntry entry : agents.values()) {
			if (agent.name().equals(entry.owner)) term.add(Primitive.newPrimitive(entry.agent.name()));
		}
		return term;
	}

	/**
	 * Term that returns a list of all the agents on that are children of the invoking agent
	 * 
	 * @return an ASTRA list containing the names of all agents on the platform 
	 */
	@TERM 
	public String getOwner() {
		AgentEntry entry = agents.get(agent.name());
		if (entry.owner == null) return "none";
		return entry.owner;
	}

	/**
	 * Formula thet returns true if the given type is available on the agent platform
	 * 
	 * @param type the agent type
	 * @return the formula TRUE if the type exists on the agent platform, the formula FALSE otherwise
	 */
	@FORMULA
	public Formula hasType(String type) {
		try {
			ASTRAClass.forName(type);
		} catch (ASTRAClassNotFoundException e) {
			return Predicate.FALSE;
		}
		return Predicate.TRUE;
	}
	
	/**
	 * Formula that returns true if the agent has children (i.e. it has created other 
	 * agents), false otherwise.
	 * 
	 * @return the formula TRUE if the agent has children, the formula FALSE otherwise
	 */
	@FORMULA
	public Formula hasChildren() {
		for(AgentEntry entry : agents.values()) {
			if (entry.owner.equals(agent.name())) return Predicate.TRUE;
		}
		return Predicate.FALSE;
	}
	
	/**
	 * Formula that returns true if the agent has an owner, false otherwise (this will 
	 * only return false for the "main" agent.
	 * 
	 * @return the formula TRUE if the agent has an owner, the formula FALSE otherwise
	 */
	@FORMULA
	public Formula hasOwner() {
		return agents.get(agent.name()).owner != null ? Predicate.TRUE:Predicate.FALSE;
	}
	
	/**
	 * Action that causes the platform to stop
	 * 
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION
	public boolean exit() {
		Scheduler.shutdown();
		Scheduler.displayStats();
		java.lang.System.exit(0);
		return true;
	}
	
	/**
	 * Action that causes the agent to sleep for a specified period of time
	 * 
	 * @param time the sleep time in milliseconds
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION(inline=false)
	public boolean sleep(int time) {
//		java.lang.System.out.println("[" + getClass().getCanonicalName()+"] sleeping...");
		try {
			Thread.sleep(time);
		} catch (InterruptedException e) {
			return false;
		}
//		java.lang.System.out.println("[" + getClass().getCanonicalName()+"] slept...");
		return true;
	}
	
	/**
	 * Term that returns the name of the agent.
	 * 
	 * @return the name of the agent
	 */
	@TERM
	public String name() {
		return agent.name();
	}
	
	@ACTION
	public boolean setSchedulePoolSize(int size) {
		Scheduler.setThreadPoolSize(size);
		return true;
	}
	
	/**
	 * Action that allows you to set the scheduling strategy used by the agents...
	 * @param strategy a fully qualified {@link SchedulerStrategy} class name
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION
	public boolean setSchedulingStrategy(String strategy) {
		try {
			Scheduler.setStrategy((SchedulerStrategy) Class.forName(strategy).getDeclaredConstructor(new Class[0]).newInstance(new Object[0]));
			java.lang.System.out.println("Scheduling Strategy set to: "+strategy);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * Term that returns the current time in millisecond (delegates to the 
	 * {@link java.lang.System} class)
	 * 
	 * @return the current time in milliseconds
	 */
	@TERM
	public long currentTimeMillis() {
		return java.lang.System.currentTimeMillis();
	}

	/**
	 * Formula that returns true if the agent exists, false otherwise.
	 * 
	 * @param name the name of the agent being checked
	 * @return the formula TRUE if the agent exists, FALSE otherwise
	 */
	@FORMULA
	public Formula agentExists(String name) {
		return agents.containsKey(name) ? Predicate.TRUE:Predicate.FALSE;
	}
	
	/**************************************************************************************************************
	 * VERY BASIC STATE CAPTURE AND RECONSTRUCTION CODE
	 **************************************************************************************************************/
	
	/**
	 * Term that captures the current state of the specified agent through 
	 * serialisation of its beliefs and stores that state in an 
	 * {@link AgentState} object.
	 * 
	 * @param name the name of the agent whose state is to be captured.
	 * @return an object representing the state of the agent
	 */
	@TERM
	public AgentState deconstruct(String name) {
		Agent agt = Agent.getAgent(name);
		
		// Transform to basic form to ensure there is no issue with the internal string mappers
		List l2 = new LinkedList();
		for (Formula formula : agt.beliefs().beliefs()) {
			l2.add(Utilities.toPredicateState(formula));
		}
		
		ByteArrayOutputStream baout = new ByteArrayOutputStream();
		try {
			ObjectOutputStream out = new ObjectOutputStream(baout);
			out.writeObject(l2);
			out.close();
			
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}
		return new AgentState(name, agt.getASTRAClass().getCanonicalName(), baout.toByteArray());
	}

	/**
	 * Action that recreates an agent based on the given state, which is 
	 * passed in as an instance of the {@link AgentState} class.
	 * 
	 * @param state the state of the agent to be recreated.
	 * @return true if the action succeeeds, false otherwise
	 */
	@SuppressWarnings("unchecked")
	@ACTION
	public boolean reconstruct(AgentState state) {
		try {
			Agent agt = ASTRAClass.forName(state.type).newInstance(state.name);
			System.agents.put(state.name, new AgentEntry(agent.name(), agt));
			ByteArrayInputStream bain = new ByteArrayInputStream(state.beliefs);
			ObjectInputStream in = new ObjectInputStream(bain);
			
			for (PredicateState pstate : (List) in.readObject()) {
				agt.beliefs().store().addBelief((Predicate) Utilities.fromPredicateState(pstate));
			}

			Scheduler.schedule(agt);
		} catch (ASTRAClassNotFoundException e) {
			e.printStackTrace();
			return false;
		} catch (AgentCreationException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	/**
	 * Term that extracts the name of the agent from an {@link AgentState}
	 * object.
	 * 
	 * @param state an agent state
	 * @return the name of the agent as recorded in the state representation
	 */
	@TERM
	public String getNameFromState(AgentState state) {
		return state.name;
	}
	/**
	 * Sets the sleep time for the scheduler.
	 * @param time a duration in milliseconds (ms)
	 * @return true if the action succeeeds, false otherwise
	 */
	@ACTION
	public boolean setSleepTime(long time) {
		Scheduler.setSleepTime(time);
		return true;
	}
	
	/**
	 * Displays the agent timings table
	 * 
	 * @return true if the action succeeds, false otherwise
	 */
	@ACTION
	public boolean displayTimings() {
		for (Entry entry : Agent.timings.entrySet()) {
			java.lang.System.out.println(entry.getKey() + "," + (((double) entry.getValue())/Agent.iterations.get(entry.getKey())) + ","+Agent.iterations.get(entry.getKey()));
		}
		return true;
	}
	
	@ACTION
	public boolean trace(boolean trace) {
		agent.setTrace(trace);
		return true;
	}

	@ACTION
	public boolean step() {
		agent.setState(Agent.STEP);
		return true;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy