-
Notifications
You must be signed in to change notification settings - Fork 1
Architecture
The framework provides infrastructure to create agents, agent behaviour, messaging, output and logging broadly forming the:
- Agent Definition Mechanism
- Communication Layer
- Visualisation or Output Module
The main components of Phoenix are:
- Agent Controller
- Agents
- Message Queues
- Output Module
- Logging
AgentController (AC) is a container within which agents live and execute their behaviours. ACs communicate using AMQP protocol. An AC is responsible for the following:
- Agent creation
- Inter agent messaging
- Inter AC messaging.
- Writing simulation output.
- Gracefully shutting-down the simulation locally.
An agent represents a real world or abstract entity which is a vital actor in the simulation. Agents have a list of attributes which define the agent and their uniqueness with respect to other agents of the same type.
Agent attributes is a abstract class. For a particular type of Agent (e.g. Person) the class has to extended and required set of attributes defined. The values of the attributes could be stored in a database or in a XML file.
Agents have objectives, beliefs and preferences or biases by which they exist in the system. To achieve its objective an agent has to undertake certain actions to manipulate its data, interact with other agents etc, this is done through actions calls behaviours. An agent may have one or more behaviours which are executed in a defined order.
The messaging subsystem (or communication channel) is a vital component in a distributed system which facilitates information sharing and synchronisation. In Phoenix the communication is entirely confined to ACs. Our messaging system had to satisfy the following requirements:
- High throughput - A few thousand messages should be delivered, end-to-end, in a second.
- High availability - The system should not crash under high load.
- Asynchronous messaging - Synchronous messaging will slow down a large system. A asynchronous technique which works like mail boxes is desired.
- Platform independence - It should not be tied to a particular programming language or a operating system, this will enable us to build heterogeneous ACs.
RabbitMQ is our choice of the message queuing system. It is based on the Advanced Message Queuing Messaging Protocol (AMQP) standard and is open source under Mozilla Public License. RabbitMQ has interfaces in languages such as Java, .Net, Python and others and supports multiple schemes of communication including 1-to-1, 1-to-many, Store-and-forward, file-streaming and others. Messages are transmitted in the form of binary data and hence any form of encryption/decryption has to be implemented at the client side.
This is work in progress. Currently only log4j logs are available for output analysis. We plan to include a graphing system.
The framework uses log4j, a java based logging utility under Apache License, Version 2.0 to provide detailed logging of all system level actions by the various entities.
The framework is implemented in Java. Java provides ease of programming and has a wide range of helpful libraries. In this section the code is explained to some extent.
AgentController is an abstract class. The AgentController is responsible for running agents, writing the output, communicating with other ACs and so on.
Agents are implemented as Java threads. Agent is an abstract class with at least the following attributes:
- AID - a unique identifier for the agent.
- objectiveFlag - indicates whether the agent has achieved its objective.
- statusFlag - a true value indicates that the agent has finished his task for the current tick, and a false value indicates that the agent hasn't finished execution.
- compositeBehaviour - one or more behaviours which the agent will run depending on the agents preferences and objectives.
The framework enables the definition of several types of agents, and the creation of a large number of agents of each type.
Every agent will have a set of behaviours, and choose to exhibit(run) a particular behaviour based on its internal logic. Behaviours are implemented using the composite design pattern. Behaviour is an abstract class with a method called 'run', which receives all the parameters of the agent in an object of type //AgentAttributes//. Every agent type will have its specific behaviour implementation, for example PersonMoveBehaviour (to move a person agent), VehicleMoveBehaviour etc.
The parameter (AgentAttributes) defines the current state of the agent. For example, a person agent will have attributes like health, speed, curiosity etc. AgentAttributes is itself an abstract class, and each agent type will have its own implementation of this class. Person agent type will have personAttributes, //Vehicle// will have VehicleAttributes and so on.
Every agent contains a 'run' method. While the implementation of this method, other attributes of the agent, its preferences and behaviours depend on the simulation to be run, the logic of the agent will be internalised within this method.
Each AC runs in its own JVM and inter AC communication is through the RabbitMQ message queue. Every AC has an input queue, which is identified by the host IP address and a queue name. To communicate with another AC, a AC has to write the message to the recipients message queue. The AC is notified as and when a new message is received through a listener implemented in a method called receivedMessage(Message).
A message is a has the following fields:
- type - is an integer and identifies the type of message
- content - is an Integer to indicate the status of the sending AC
- sender - is a string and identifies the sender (is the host name of the sender)
Manages the delivery of a message to the recipient and listening to incoming messages.
- queueUser - the AC using this queue.
- queueParameters - parameters of the input queue for the AC
This is an interface using which any class can receive messages on an input queue. Any class which wants to receive and send messages should implement this interface. QueueUser enforces the 'Observer' design pattern on the implementing class. Every AC (which implements QueueUser) registers with a QueueManager, and whenever a message is received QueueManager notifies the AC by calling the receivedMessage(Message) method of the AC.
This defines the parameters of the input queue.
- queueName - name of the queue.
- username - username for RabbitMQ
- password - password for RabbitMQ





