Click here to Skip to main content
15,949,741 members
Articles / Programming Languages / C#

Multi-Agent Software Design on Windows

Rate me:
Please Sign up or sign in to vote.
2.64/5 (7 votes)
9 Nov 2007CPOL5 min read 39K   756   19   1
Multi-Agent Software Design example on Windows, using .NET Framework

Introduction

In this article, I would like to give an example of a multi-agent solution on Windows platform using .NET Framework. I was working on a multi agent system where each agent was composed of C++ data processor application and a Java GUI application. This is a typical approach where some requirements have to be done very fast and there is a need for a GUI for human machine interface. This was a C2 (Command and Control System). Inter Agent and Intra Agent communication was through Corba. Now I am working on a new multi agent system where each agent is composed of a Windows service application (data processor application which has to be managed and fast) and a GUI Windows forms application. Now Inter Agent and Intra Agent communication is through .NET remoting. I would like to share my basic design behind the completely Windows based multi agent system.

Background

Taken from: Agent Technology Green Paper – Agent Working Group – OMG Document ec/99-12-02 Version 0.9

"A software agent is an autonomous software entity that can interact with its environment. Environment can be other agents, hardware, etc. Multiagents systems, then, are systems that are composed of coordinated agents together with the relationships that exist between them. For example in a kitchen, the toaster "knows" when the toast is done, and the coffeemaker "knows" when the coffee is ready. However, there is no cooperative environment here—only an environment with single agents. In a multiagent environment, the kitchen becomes more than just a collection of processors. Here, the appliances would be interconnected in such a way that the coffeemaker and the toaster would know that the coffee and toast be ready at the same time.

Some of the rationale for multiagent systems are as follows:

  • One agent could be constructed that does everything, but fat agents represent a bottleneck for speed, reliability, maintainability, and so on (i.e., there are no omnipotent agents). Dividing functionality among many agents provides modularity, flexibility, modifiability, and extensibility.
  • Specialized knowledge is not often available from a single agent (i.e., there are no omniscient agents). Knowledge that is spread over various sources (agents) can be integrated for a more complete view when needed.
  • Applications requiring distributed computing are better supported by MAS. Here, agents can be designed as fine-grained autonomous components that act in parallel. Concurrent processing and problem solving can provide solutions to many problems that, up until now, we handled in a more linear manner. Agent technology, then, provides the ultimate in distributed component technology.

To support multiagent systems, an appropriate environment needs to be established. MAS environments:

  • provide an infrastructure specifying communication and interaction protocols.
  • are typically open and have no centralized designer or top-down control function.
  • contain agents that are autonomous, adaptive, and coordinative.

Clearly, single-agent environments are much simpler because designers do not have to deal with issues such as cooperation, negotiation, and so on. However, the large-scale requirements of industry necessitates approaches requiring coordination and distribution."

Using the Code

My multi agent design is quite simple. There are multiple agents, they communicate with each other through .NET remoting and a global database. Each agent consists of a service application and a forms application. The Windows Form application part is optional. Sometimes there is no need for a human interface. I preferred service applications because services can be automatically started when the computer boots, can be paused and restarted, and do not show any user interface. These features make services ideal for use on a server or whenever you need long-running functionality that does not interfere with other users who are working on the same computer. And they are watched by the system, if they crash they can be restarted automatically.

Now let's talk about the example multi-agent system. System has 2 agents - temperature agent and time agent. Screenshot - GeneralDesignSmaller.gif

Temperature agent gets the temperature from a virtual sensor (a random number generator) and gets the current time from the time agent and records it every 30 seconds. The user interface part of the temperature agent shows recorded temperatures in a table and shows the instant temperature.

Time management agent only publishes the current time. Nothing is recorded to the database. The user interface shows the current time.

Here is the design of the example multi-agent system.

Let's start with agent-agent communication. We only need a common DateTime class. This class will be used between 2 agents and inside the time agent.

(Please refer to MSDN .NET Framework Remoting Overview, the examples are just great.)

Here we only create the datetime class which is remotable:

C#
public class ClassDateTime : MarshalByRefObject
{
    private DateTime _dateTime;
    public ClassDateTime()
    {
        _dateTime = DateTime.Now;
    }
    public void setDateTime(DateTime now)
    {
        _dateTime = now;
    }
    public DateTime getDateTime()
    {
        return _dateTime;
    }
}

Let's continue with service application – Windows Forms application communication. We only need a common Temperature class. This class will be used inside the temperature agent.

C#
public class ClassTemperature  : MarshalByRefObject
{
    private int _temperature;
    public void setTemperature(int temperature)
    {
        _temperature = temperature;
    }
    public int getTemperature()
    {
        return _temperature;
    }
}

Now we can create the time agent service application. Please refer to the MSDN, Windows Service Applications section. We handle the remote object registration in the service constructor. When the time agent service application is started, it starts the timer which updates the remotable object every second.

C#
public partial class ServiceTime : ServiceBase
{
    private ClassDateTime _dateTime;
    private System.Timers.Timer _timer;
    public ServiceTime()
    {
        InitializeComponent();
        // Create the server channel.
        TcpChannel serverChannel = new TcpChannel(9090);
        // Register the server channel.
        ChannelServices.RegisterChannel(serverChannel);
        // Expose an object for remote calls.
        RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(ClassDateTime), "RemoteObject.rem",
            WellKnownObjectMode.Singleton);
        _dateTime = (ClassDateTime)Activator.GetObject(
                    typeof(ClassDateTime),
                        "tcp://localhost:9090/RemoteObject.rem");
    }
    protected override void OnStart(string[] args)
    {
        // start the timer            
        _timer = new System.Timers.Timer();
        _timer.Interval = 1000;
        _timer.AutoReset = true;
        _timer.Elapsed += new ElapsedEventHandler(PublishDateTime);
        _timer.Start();
    }
    private void PublishDateTime(object sender, ElapsedEventArgs e)
    {
        _dateTime.setDateTime(DateTime.Now);
    }
    protected override void OnStop()
    {
        // stop the timer
        _timer.Stop();
    }

Let's continue with the Temperature Agent service application. This agent is a client for the ClassDateTime but server for the ClassTemperature objects. We are initializing these objects in the constructor. This agent publishes the temperature every 2 seconds and records it in the database (XML file) every 10 seconds. These are done through 2 timer objects _timerPublishTemperature and _timerWriteToXml. Random temperature value is generated by a Random object.

C#
public partial class ServiceTemperature : ServiceBase
{
    private ClassDateTime _dateTime;
    private ClassTemperature _temperature;
    private DataTable _globalDB;
    private Random _autoRand;
    private System.Timers.Timer _timerPublishTemperature;
    private System.Timers.Timer _timerWriteToXml;
    
        public ServiceTemperature()
    {
        InitializeComponent();
        //server for the ClassTemperature
        TcpChannel serverChannel = new TcpChannel(8080);
        
        // Register the server channel.
        ChannelServices.RegisterChannel(serverChannel);            
        
        // Expose an object for remote calls.
        RemotingConfiguration.RegisterWellKnownServiceType(
            typeof(ClassTemperature), "RemoteObject2.rem",
            WellKnownObjectMode.Singleton);
        _temperature = (ClassTemperature)Activator.GetObject(
                    typeof(ClassTemperature),
                        "tcp://localhost:8080/RemoteObject2.rem");
        
        //client for the ClassDateTime
        _dateTime = (ClassDateTime)Activator.GetObject(
        typeof(ClassDateTime),
            "tcp://localhost:9090/RemoteObject.rem");
        
        //dbCreation
        _globalDB = new DataTable();
        _globalDB.TableName = "RecordTable";
        _globalDB.Columns.Add("Record DateTime", typeof(DateTime));
        _globalDB.Columns.Add("Temperature", typeof(Double));
        //random number generator
        _autoRand = new Random();
        
    }
    protected override void OnStart(string[] args)
    {            
        _timerPublishTemperature = new System.Timers.Timer();
        _timerWriteToXml = new System.Timers.Timer();
        _timerPublishTemperature.Interval = 2000;
        _timerWriteToXml.Interval = 10000;
        _timerPublishTemperature.AutoReset = true;
        _timerWriteToXml.AutoReset = true;
        _timerPublishTemperature.Elapsed += new ElapsedEventHandler(PublishTemperature);
        _timerWriteToXml.Elapsed += new ElapsedEventHandler(WriteToXml);
        _timerPublishTemperature.Start();
        _timerWriteToXml.Start();
    }
    protected override void OnStop()
    {
        _timerWriteToXml.Stop();
        _timerPublishTemperature.Stop();
        
    }
    private void PublishTemperature(object sender, ElapsedEventArgs e)
    {
        int tmp;
        tmp = Convert.ToInt32(_autoRand.NextDouble() * 10);
        _temperature.setTemperature(tmp);
    }
    private void WriteToXml(object sender, ElapsedEventArgs e)
    {
        int tmp;
        tmp = Convert.ToInt32(_autoRand.NextDouble() * 10);
        //add to the db
        DataRow rowToAdd = _globalDB.NewRow();
        rowToAdd[0] = _dateTime.getDateTime();
        rowToAdd[1] = tmp;
        _globalDB.Rows.Add(rowToAdd);
        _globalDB.AcceptChanges();
        _globalDB.WriteXml("C:\\globalDB.xml");
    }
}

Now we can continue with the user interface part of the agents. The UI part of the Time Agent is quite simple. There is a button to start the timer which gets the current time from the service application part every 2 seconds.

C#
public partial class FormMain : Form
{
    private ClassDateTime _dateTime;        
    public FormMain()
    {
        InitializeComponent();            
    }
    private void button1_Click(object sender, EventArgs e)
    {
        _dateTime = (ClassDateTime)Activator.GetObject(
                    typeof(ClassDateTime),
                        "tcp://localhost:9090/RemoteObject.rem");
        timer1.Enabled = true;
    }
    private void timer1_Tick(object sender, EventArgs e)
    {
        labelCurDateTimeValue.Text = 
		Convert.ToString(_dateTime.getDateTime().ToString());
    }
}

Temperature Agent user interface has a datagridview to show the recorded data by the service application part. It also shows the instant temperature value gathered through .NET remoting. Start button starts the timer which gets the temperature value from the service application, and reads the recorded values from the database (XML file) and displays it in the datagridview. In the solution, there is setup project which installs the service application parts of the agents.

C#
public partial class FormMain : Form
{        
    ClassTemperature _temperature;        
    public FormMain()
    {
        InitializeComponent();                        
    }
    private void button1_Click(object sender, EventArgs e)
    {
        dataSet1.ReadXml("C:\\globalDB.xml");
        dataGridView1.DataSource = dataSet1.Tables[0];
            
        _temperature = (ClassTemperature)Activator.GetObject(
                    typeof(ClassTemperature),
                        "tcp://localhost:8080/RemoteObject2.rem");
            
        timerMain.Enabled = true;            
    }
    private void timerMain_Tick(object sender, EventArgs e)
    {
        labelTempValue.Text = _temperature.getTemperature().ToString();
    }
}

After installing the service parts, you can start the services from Services control panel located in the Administrative Tools folder. Please start the WindowsServiceTimeAgent first and then WindowsServiceTemperatureAgent. Then you can run the user interface parts of the agents.

History

  • 9th November, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) NEC
Turkey Turkey
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Dzmoumou15-Apr-11 8:42
Dzmoumou15-Apr-11 8:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.