User Guide
Introduction
The aim of this document is to describe in detail the Artificial Life framework, which is a mutli-agent system designed to run within the same Operating System process. The agents run in the same OS process mainly for speed and also to avoid implementing a complex system to share information between agents.
Artificial Life uses threads to run the concurrent agents. Developing and debuging applications using lots of threads is known to be difficult. The framework addresses those difficulties by implementing mechanisms using messaging systems (Messenger, MethodInvocation and Event).
The framework defines two types of agents: The services and the processes. The processes are agents that perform tasks and the services are agents that provide services to the processes.
The agents are organized in a tree structure called Instance. Within an Instance, the services and the processes are grouped together and an unlimited number of groups can be defined. Each node of the Instance tree can have a collection of views used to monitor the activity of the node or interact with the node.
Each Instance has an Instance Model; Instance Models are basically lists of Class Definitions organized in a tree structure where Class Definitions record paths to classes (Java classes). Instance Models are used in Instance Manager to define the list of classes (Java classes) that can be added to Instances (Service, Process or Views). Instance Models can be seen as libraries.
Please note that a good understanding of Java programming is a prerequisite.
Content
I. Architecture
1. Tools
a. Instance Server
b. Model Composer
c. Instance Manager
2. API
II. How To:
- Create a service
- Create a process
- Create a view
- Store a property
- Settings
- Logging
- Method Invocation
- Event
- Find a service
- Reference and de-reference a service
- Use referenced service
I. Architecture
Artificial Life can be decomposed in two parts: The tools used to manage and run the Instances and the API.
1. Tools
a. Instance Server
Instance Server runs Instances and can be remotely managed by using Telnet (Port 4000).
b. Model Composer
Model Composer is used to manipulate the Instance Models: Add, update or delete Class Definitions.
c. Instance Manager
Instance Manager is used to create, modify, delete, run, import or export Instances. You will use this tool to add or delete classes (Service, Process or Views) in Instances.
Instance Manager uses Instance Server to run Instances.
Artificial Life provides two ways to run your agent code:
- By coping your compiled agent code in the ext sub folder (for extensions) of Artificial Life and then by running directly Instance Manager
- By launching Instance Manager from your project (This technique will give you the possibility to debug your code with your favorite Java IDE). Here is an example of a class that you can add to your project:
import org.artificialLife.tools.common.*;
public class InstanceManager extends ALTool
{
public InstanceManager()
{
super(new org.artificialLife.tools.instanceManager.InstanceManagerFrame());
}
public static void main(String args[])
{
new InstanceManager().run();
}
}
2. API
The API defines the interfaces that the agents and the views implement and provide all the necessary services that you will need to run Instances.
II. How To:
- Create a service
package myproject; import org.artificialLife.kernel.*; public class MyService extends Service { public MyService() { super("My Service"); } protected void run() { while (!this.stopRequested()) { // Do something... } } } - Create a process
package myproject; import org.artificialLife.kernel.*; public class MyAgent extends ALProcess { public MyAgent() { super("My Agent"); } protected void run() { while (!this.stopRequested()) { // Do something... } } } - Create a view
package myproject; import org.artificialLife.system.*; public class MyServiceView extends View { public MyServiceView() { super("My Service"); } public void setContext(ALComponent context) { Service s; if (context != null) { if (context instanceof MyService) { service = (MyService) context; // Initialize the view... } } } } - Store a property
package myproject; import org.artificialLife.kernel.*; public class MyService extends Service { private String myProperty; public MyService() { super("My Service"); } protected void run() { while (!this.stopRequested()) { // Do something... } } @ALProperty (displayName = "My Property") public String getMyProperty() { return myProperty; } public void setMyProperty(String myProperty) { this.myProperty = myProperty; } } - Settings
import org.artificialLife.system.*; public MyClass { public MyClass() { } public void MyMethod() { Setting setting; String value; setting = ALSystem.settings.get("MY_SETTING"); if (setting == null) { value = "Setting value"; ALSystem.settings.setDefault("MY_SETTING", value); } else { value = (String)setting.getValue(); } ALSystem.settings.delete("MY_SETTING"); } } - Logging
import org.artificialLife.system.*; public MyClass { public MyClass() { } public void MyMethod() { ALSystem.logs.log(new InformationLog("My Project", "Information")); ALSystem.logs.log(new DebugLog("My Project", "Debug information")); ALSystem.logs.log(new ErrorLog("My Project", "Error")); } } - Method Invocation
// A service package myproject; import org.artificialLife.kernel.*; public class MyService extends Service { public MyService() { super("My Service"); } protected void run() { while (!this.stopRequested()) { // Do something... } } public void myMethod() { } } // Invocation from an agent package myproject; import org.artificialLife.kernel.*; import org.artificialLife.mi.*; public class MyAgent extends ALProcess { public MyAgent() { super("My Agent"); } protected void run() { MyService service; ... while (!this.stopRequested()) { ... // Method invocation using the method invocation handler of the service new MethodInvocator(service.getMethodInvocationHandler()).invoke(service, "myMethod", new Class[] {}, new Object[] {}); ... } } } - Event
// An event package myproject; import org.artificialLife.events.*; public class MyEvent extends Event { public MyEvent() { } } // A service dispatching and receiving events package myproject; import org.artificialLife.kernel.*; import org.artificialLife.events.*; import org.artificialLife.system.*; public class MyService extends Service { private EventDispatcher eventDispatcher; private QueuedEventListener eventListener; public MyService() { super("My Service"); eventDispatcher = new EventDispatcher(); eventListener = new QueuedEventListener() { public void takeEvent(Event event) { try { if (event instanceof MyEvent) { // Do something... } } catch (Exception e) { ALSystem.logs.log(new ErrorLog("My Project", e)); } } }; } protected void run() { while (!this.stopRequested()) { // Do something... } } @Override public void start() { if (!this.isRunning()) { eventDispatcher.start(); eventListener.start(); eventDispatcher.addListener(eventListener); super.start(); } } @Override public void stop() { if (this.isRunning()) { eventDispatcher.stop(); eventDispatcher.removeListener(eventListener); eventListener.stop(); super.stop(); } } public EventDispatcher getEventDispatcher() { return eventDispatcher; } } // Send events from an agent package myproject; import org.artificialLife.kernel.*; import org.artificialLife.events.*; public class MyAgent extends ALProcess { public MyAgent() { super("My Agent"); } protected void run() { MyService service; MyEvent event; ... while (!this.stopRequested()) { ... event = new MyEvent(); service.getEventDispatcher.fireEvent(event); ... } } } - Find a service
package myproject; import org.artificialLife.system.*; import org.artificialLife.kernel.*; public class MyAgent extends ALProcess { public MyAgent() { super("My Agent"); } @Override public void start() { Service service; if (!this.isRunning()) { // Find a service ascending in the Instance tree service = new AscServiceLocator(this).findFirst(MyService.class); if (service == null) { throw new SystemException("Service not found."); } // Find a service descending in the Instance tree service = new DescServiceLocator(this).findFirst(MyService.class); if (service == null) { throw new SystemException("Service not found."); } super.start(); } } protected void run() { while (!this.stopRequested()) { // Do something... } } } - Reference and de-reference a service
package myproject; import org.artificialLife.system.*; import org.artificialLife.kernel.*; public class MyAgent extends ALProcess { public MyAgent() { super("My Agent"); } @Override public void start() { Service service; if (!this.isRunning()) { service = new AscServiceLocator(this).findFirst(MyService.class); if (service == null) { throw new SystemException("Service not found."); } // Reference the service this.getReferencedServices().referenceService("MyService", service); super.start(); } } @Override public void stop() { if (this.isRunning()) { super.stop(); // De-reference the service this.getReferencedServices().dereferenceService("MyService"); } } protected void run() { while (!this.stopRequested()) { // Do something... } } } - Use referenced service
package myproject; import org.artificialLife.system.*; import org.artificialLife.kernel.*; public class MyAgent extends ALProcess { public MyAgent() { super("My Agent"); } @Override public void start() { Service service; if (!this.isRunning()) { service = new AscServiceLocator(this).findFirst(MyService.class); if (service == null) { throw new SystemException("Service not found."); } this.getReferencedServices().referenceService("MyService", service); super.start(); } } @Override public void stop() { if (this.isRunning()) { super.stop(); this.getReferencedServices().dereferenceService("MyService"); } } protected void run() { MyService service; // Use the referenced service service = (MyService)this.getReferencedServices().getService("MyService"); while (!this.stopRequested()) { // Do something... } } }
