Modelarea şi analiza sistemelor multiagent Laboratorul 2

Crearea agenţilor direct din cod, comportamente simple, comunicare inter-agent
1. Prezentarea modalităţilor de creare dinamică a agenţilor 2. Comportamente şi comunicare inter-agent 2.1. Comportamente 2.2. Comunicarea inter-agent 2.3. Exemplificare printr-o aplicaţie 3. Aplicaţii

1. Prezentarea modalităţilor de creare dinamică a agenţilor
La crearea dinamică nu mai este necesară folosirea fişierului de configurare ca în laboratorul anterior, agenţii fiind creaţi şi lansaţi din cod. [C#]
static void Main(string[] args) { Profile p = new ProfileImpl(); Runtime rt = Runtime.instance(); jade.wrapper.AgentContainer mc = rt.createMainContainer(p); mc.start(); AgentController actrl = mc.createNewAgent("Agent1", "Lab2Example1.SimpleAgent", null); actrl.start(); }

[JAVA]
public static void main (String args[]) { try { Runtime rt = Runtime.instance(); Profile pMain = new ProfileImpl(); AgentContainer mc = rt.createMainContainer(pMain); AgentController actrl = mc.createNewAgent("Agent1", "lab2example1.SimpleAgent", args); actrl.start(); } catch(Exception e) { e.printStackTrace(); } }

Portul implicit folosit de JADE este 1099, dacă dintr-un anumit motiv nu putem folosi acest port se defineşte profilul specificând toate argumentele (hostul, portul şi id-ul platformei):

1

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

[C#] & [JAVA]
Profile p = new ProfileImpl ("192.168.123.147", 10000, "192.168.123.147:10000/JADE");

Pentru a crea agenţi în containere diferite putem proceda astfel: [C#]
static void Main(string[] args) { Runtime rt = Runtime.instance(); Profile pMain = new ProfileImpl(); jade.wrapper.AgentContainer mc1 = rt.createMainContainer(pMain); Profile p = new ProfileImpl(); jade.wrapper.AgentContainer mc2 = rt.createAgentContainer(p); Profile p2 = new ProfileImpl(); jade.wrapper.AgentContainer mc3 = rt.createAgentContainer(p2); AgentController ac1 = mc1.createNewAgent("Agent1", "Lab2Example2.SimpleAgent", args); ac1.start(); AgentController ac2 = mc2.createNewAgent("Agent2", "Lab2Example2.SimpleAgent", args); ac2.start(); AgentController ac3 = mc3.createNewAgent("Agent3", "Lab2Example2.SimpleAgent2", args); ac3.start(); }

[JAVA]
public static void main (String args[]) { try { Runtime rt = Runtime.instance(); Profile pMain = new ProfileImpl(); AgentContainer mc1 = rt.createMainContainer(pMain); Profile p = new ProfileImpl(); AgentContainer mc2 = rt.createAgentContainer(p); Profile p2 = new ProfileImpl(); AgentContainer mc3 = rt.createAgentContainer(p2); AgentController ac1 = mc1.createNewAgent("Agent1", "lab2example2.SimpleAgent", args); ac1.start(); AgentController ac2 = mc2.createNewAgent("Agent2", "lab2example2.SimpleAgent", args); ac2.start(); AgentController ac3 = mc3.createNewAgent("Agent3", "lab2example2.SimpleAgent2", args); ac3.start(); } catch(Exception e) { e.printStackTrace(); } }

2

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

Exemplul de mai sus creează un agent în containerul principal (main container), creează alte 2 containere (Container1 şi Container2) şi câte un agent în fiecare dintre acestea. De asemenea, un agent lansat poate crea la rândul său alţi agenţi: [C#]
class SimpleAgent2 : Agent { public override void setup() { Console.WriteLine("Hello, I'm " + getLocalName() + " and I'm living in " + this.getContainerController().getContainerName() + "\n"); PlatformController pc = getContainerController(); String nume_fiu = getLocalName() + "’s Child_1"; AgentController actrl = pc.createNewAgent(nume_fiu, "Lab2Example2.ChildAgent", null); actrl.start(); } }

[JAVA]
public class SimpleAgent2 extends Agent { @Override public void setup() { try { System.out.println("Hello, I'm " + this.getLocalName() + " and I'm living in " + this.getContainerController().getContainerName()); PlatformController pc = getContainerController(); String nume_fiu = getLocalName() + "’s Child_1"; AgentController actrl = pc.createNewAgent(nume_fiu, "lab2example2.ChildAgent", null); actrl.start(); } catch (ControllerException ex) {} }

După lansare, agentul de tip SimpleAgent2 creează un alt agent care va implementa clasa ChildAgent. Numele agentului fiu va fi dat în funcţie de numele agentului părinte.

2. Comportamente şi comunicare inter-agent
2.1 Comportamente
Sarcina sau sarcinile concrete pe care un agent le are de îndeplinit sunt realizate prin comportamente. Un comportament reprezintă o sarcină pe care un agent trebuie să o îndeplinească şi este implementat ca un obiect al unei clase ce extinde jade.core.behaviours.Behaviour. Pentru a face un agent să execute o sarcină implementată de un obiect Behaviour, acesta trebuie să fie adăugat la clasa agentului prin metoda addBehaviour().
3

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

[C#]
class Agent1 : Agent { public override void setup() { addBehaviour(new Looper(this, 300)); addBehaviour(new Looper(this, 500)); } }

[JAVA]
public class Agent1 extends Agent { @Override public void setup() { addBehaviour(new Looper(this, 300)); addBehaviour(new Looper(this, 500)); } }

Fiecare clasă Behaviour trebuie să implementeze două metode abstracte. Metoda action() defineşte operaţiile ce trebuie efectuate atunci când agentul se află în execuţie. Metoda done() returnează un boolean pentru a indica dacă s-a terminat comportamentul respectiv sau nu. [C#]
class Looper : SimpleBehaviour { static string offset = ""; static DateTime t0 = DateTime.Now; string tab = ""; int n = 1; long dt; public Looper(Agent a, long dt) : base(a) { this.dt = dt; offset += " "; tab = offset; } public override void action() { System.Console.WriteLine(tab + (int)(DateTime.Now - t0).TotalMilliseconds + ": " + myAgent.getLocalName()); block(dt); n++; } public override bool done() { return n > 6; } }

4

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

[JAVA]
public class Looper extends SimpleBehaviour { static String offset = ""; long lDateTime = new Date().getTime(); String tab = ""; int n = 1; long dt; public Looper(Agent a, long dt) { this.dt = dt; offset += " "; tab = offset; } @Override public void action() { long l2 = new Date().getTime(); System.out.println(l2-lDateTime + ":" + myAgent.getLocalName()); block(dt); n++; } @Override public boolean done() { return n > 6; } }

Comportamentul Looper afisează, în metoda sa action(), intervalul scurs de la începutul execuţiei aplicaţiei. Utilitatea funcţiei block() este de a trece comportamentul curent în aşteptare, agentul trecând la un alt comportament care necesită sa fie executat. Funcţia block(dt) de mai sus pune comportamentul Looper în aşteptare pentru perioada specificată de parametrul dt. Agentul de tip Agent1 implementează două comportamente de tip Looper. Initial, primul comportament executa metoda action(), realizează afişarea informaţiilor, apoi se blocchează pe durata intervalului dt (care, în cazul său, este de 300 ms). În urma acestui blocaj, se trece la următorul comportament, cel de-al doilea Looper. La rândul său, acesta afişează un mesaj şi apoi se blochează temporar, revenindu-se la primul comportament. Situaţia se repetă până când, pentru ambele comportamente, se îndeplineste condiţia din done(). Astfel, fiecare comportament va rula de 6 ori. Datorită impreciziei timerelor asociate, poate apărea situaţia în care comportamentele nu se execută alternativ. Iată rezultatul rulării Exemplului 3:
1: Agent1 3: Agent1 303: Agent1 505: Agent1 604: Agent1 907: Agent1 1006: Agent1 1208: Agent1 1507: Agent1 1509: Agent1 2009: Agent1 2511: Agent1

Liniile aliniate la un tab aparţin primului comportament, iar cele aliniate la două tab-uri sunt emise de cel de-al doilea. Spaţierea diferită se realizează în virtutea faptului că, la instanţierea celui
5

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

de-al doilea comportament, constructorul din Looper se va fi apelat deja o dată (la adăugarea primului comportament). Astfel, variabila offset va conţine de două ori mai multe spaţii decât în momentul instanţierii primului comportament. Când nu sunt comportamente disponibile pentru execuţie, agentul trece în starea sleep pentru a nu consuma timp CPU, şi este trezit atunci când un comportament devine disponibil pentru execuţie. Pentru a defini un comportament, trebuie mostenită una din clasele de bază disponibile în acest sens. Aceste clase definesc mai multe tipuri de comportamente, dupa cum urmează: SimpleBehaviour: comportamente atomice care implică un singur task. Acestea nu prezintă particularităţi sau cazuri aparte, fiind cele mai flexibile comportamente. OneShotBehavior: comportamente care se execută o singura dată şi care nu pot fi blocate. Metoda done() returnează întotdeauna true. CyclicBehavior: comportamente care se execută în mod repetat. Metoda done() returnează întotdeauna false. În acest caz, funcţia block() pune comportamentul pe pauză până la recepţia următorului mesaj. La recepţie, toate comportamentele for fi activate, iar funcţiile lor action() vor fi executate pe rând. block() nu opreşte execuţia, ci face tranziţia spre următoarea execuţie. Dacă nu se apelează block(), comportamentele de tip CyclicBehavior vor rula într-o buclă. În general, se recomandă ca toate metodele action() să se încheie cu un apel block(). TickerBehavior: comportament care se execută periodic, la un interval specificat (de exemplu, în constructor). Operaţiile executate se specifică suprascriind metoda onTick(). Execuţia thread-ului unui agent este ilustrată în figura următoare:

6

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

Pentru a ilustra mai bine ordinea în care se execută comportamentele, prezentăm următorul exemplu: se definesc trei comportamente, Behavior1, Behavior2, Behavior3, primul de tipul SimpleBehavior, iar ultimele două de tipul OneShotBehavior. Acestea se adaugă în ordine unui agent care le execută. Primul comportament este la un moment dat blocat pe o perioad ă determinată. Problema care se pune este: ce se întâmplă la sfarşitul execuţiei comportamentului al doilea, presupunînd ca între timp primul s-a deblocat? [C#]
class Agent1 : Agent { public override void setup() { addBehaviour(new Behaviour1(this)); addBehaviour(new Behaviour2(this)); addBehaviour(new Behaviour3(this)); } } class Behaviour1 : SimpleBehaviour { int n = 0; public Behaviour1(Agent a) { } public override void action() { Console.WriteLine("Start B1"); Console.WriteLine("Block B1"); block(500); Console.WriteLine("Unblock B1"); n++; } public override bool done() { return n > 3; } } class Behaviour2 : OneShotBehaviour { public Behaviour2(Agent a) { } public override void action() { Console.WriteLine("Start B2"); Thread.Sleep(1000); } } class Behaviour3 : OneShotBehaviour { public Behaviour3(Agent a) { } public override void action() { Thread.Sleep(1000); Console.WriteLine("Start B3"); } }

7

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

[JAVA]
class Behaviour1 extends SimpleBehaviour { int n = 0; public Behaviour1(Agent a) { } @Override public void action() { System.out.println("Start B1"); System.out.println("Block B1"); block(500); System.out.println("Unblock B1"); n++; } @Override public boolean done() { return n > 3; } } class Behaviour2 extends OneShotBehaviour { public Behaviour2(Agent a) { } @Override public void action() { System.out.println("Start B2"); try { Thread.sleep(1000); }catch(InterruptedException e){} } } class Behaviour3 extends OneShotBehaviour { public Behaviour3(Agent a) { } @Override public void action() { System.out.println("Start B3"); try { Thread.sleep(1000); }catch(InterruptedException e){} } }

Rezultatul execuţiei este următorul:
Start B1 Block B1 Unblock B1 Start B2 Start B3 Start B1 Block B1 Unblock B1 Start B1 Block B1

8

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

Unblock B1 Start B1 Block B1 Unblock B1

Aşadar, comportamentele se execută în ordinea în care au fost adăugate agentului. Dupa execuţia celui de-al doilea comportament se trece la al treilea, chiar dacă primul s-a deblocat între timp. La acesta se revine ulterior, el executându-se de trei ori, conform condiţiei din metoda sa done(). Observaţie! Fiecare clasă de bază care defineşte comportamente are un câmp myAgent de tip Agent. În momentul în care creăm propriul comportament, el moşteneste implicit acest câmp. Problema apare în momentul în care atribuim comportamentul unui agent definit explicit, de exemplu de tip Agent1, care moşteneşte Agent. Deoarece câmpul myAgent al comportamentului este în continuare de tip Agent, comportamentul nu va avea acces la proprietăţile specifice agentului de tip Agent1, chiar daca este asociat acestuia. Prin urmare, câmpul myAgent trebuie redefinit astfel încât tipul său să coincidă cu cel al agentului căruia îi este asignat comportamentul. În exemplele din laborator se poate observa cum, în momentul specificării clasei aferente unui comportament, câmpul myAgent este redefinit: [C#] private new Agent1 myAgent; [JAVA] private Agent1 myAgent; Noul câmp de tip Agent1 îl ascunde pe cel implicit, de tip Agent.

2.2 Comunicare inter-agent
Comunicarea şi interacţiunea dintre agenţi sunt caracteristici fundamentale ale sistemelor multiagent. Acestea sunt realizate prin intermediul schimbului de mesaje. Este deci foarte important ca agenţii să folosească pentru aceste mesaje un format şi o semantică compatibile. Deoarece JADE foloseşte standardele FIPA, în mod normal agenţii JADE ar trebui să poată comunica cu alţi agenţi care rulează pe alte platforme. Pe lângă conţinut, un mesaj trebuie sa aibă o listă cu destinatari, un expeditor, un format, un tip de mesaj etc. În JADE mesajele folosesc standardul ACL (Agent Communication Language), standard ce permite mai multe tipuri de codare a conţinutului mesajului. De asemenea permite conţinutului mesajului să reprezinte un obiect serializat. Comunicarea dintre agenţi se bazează pe trimiterea de mesaje asincrone. Fiecare agent are o „căsuţă poştală” (coada de mesaje), unde JADE plasează mesaje trimise de alţi agenti şi agentul care a primit mesajul este notificat. Trimiterea de mesaje spre alţi agenţi se realizează completând câmpurile unui obiect de tip ACLMessage şi apoi apelând metoda send() a agentului cu parametrul reprezentat de mesajul completat. Un agent poate selecta mesaje din coada sa de mesaje executând metoda receive() care returnează primul mesaj din coada sau null dacă nu sunt mesaje. [C#] & [JAVA]
//trimiterea unui mesaj: creează mesajul ACL şi setează destinatar, conţinut ACLMessage message = new ACLMessage(); AID receiverAID = new AID("Agent1", AID.ISLOCALNAME); // în acelaşi container message.addReceiver(receiverAID); message.setContent("Hello"); myAgent.send(message); //recepţionarea unui mesaj: cere un mesaj din coada sa internă 9

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

ACLMessage message = myAgent.receive(); //afiseaza conţinut la consola if (message != null) { string s = message.getContent() + " from " + message.getSender().getLocalName(); System.Console.WriteLine(s); }

2.3 Exemplificare printr-o aplicaţie
Dorim să realizăm o aplicaţie care să creeze 3 agenţi (Agent1, Agent2 şi Agent3) care să fie reprezentaţi printr-o fereastră windows (ce conţine un text box pe întreaga suprafaţă). Aceşti agenţi vor schimba mesaje între ei, textul mesajelor fiind vizibil în controlul de tip text box. Agentul 1 si 2 vor fi în containerul principal iar agentul 3 in alt container. Agent 1 şi Agent 3 vor implementa următoarele comportamente:   Refresh la controlul de tip text box periodic la 100 ms Aşteaptă primirea de mesaje şi răspunde la ele

Agent 2 va implementa următoarele comportamente:    Refresh la controlul de tip text box periodic la 100 ms Trimite mesaje la Agent 1 si 3 Aşteaptă răspunsuri

Fiecare agent va avea asociată câte o fereastra WindowsForm (C#), respectiv jFrame (Java), care conţine un textBox (C#) / textArea (Java) unde se vor afişa diferitele informaţii trimise/primite. Implementăm fereastra care va reprezenta vizual agentul. Metoda AddTextLine() va fi utilizată pentru a scrie diversele mesaje primite/recepţionate în textboxurile agenţilor corespunzători : [C#]
public partial class FormAgent : Form { public FormAgent() { InitializeComponent(); } public void DoEvents() { Application.DoEvents(); } public void AddTextLine(string s) { textBoxMessages.AppendText(s + Environment.NewLine); } private void FormAgent_FormClosed(object sender, FormClosedEventArgs e) { Environment.Exit(0); // inchide TOATE ferestrele si aplicatia Jade } }

10

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

[JAVA]
public class AgentFrame extends javax.swing.JFrame { public AgentFrame() { initComponents(); //inchiderea unei ferestre determina inchiderea intregii aplicatii setDefaultCloseOperation(EXIT_ON_CLOSE); } //cod generat automat ... public static void main(String args[]) { //cod generat automat ... public void AddTextLine(String s) { String newline = System.getProperty("line.separator"); textAreaMessages.append(s + newline); } } }

Construim clasa pentru agenţii 1 şi 3: [C#]
public class ReceiveMessageAndSendAnswer : Agent { private FormAgent windowsForm; public override void setup() { object[] args = this.getArguments(); if (args != null) windowsForm = (FormAgent)args[0]; windowsForm.Text = this.getName(); windowsForm.Show(); addBehaviour(new WinFormRefreshBehaviour(this, 100)); addBehaviour(new ReceiveBehaviour(this)); } }

[JAVA]
public class Agent1 extends Agent { private AgentFrame frame; @Override public void setup() { Object[] args = this.getArguments(); if(args != null) { frame = (AgentFrame)args[0]; } 11

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

frame.setTitle(this.getName()); frame.setVisible(true); addBehaviour(new FrameRefreshBehaviour(this, 100)); addBehaviour(new ReceiveBehaviour(this)); } }

Agentilor astfel definiţi li se asociază două comportamente: primul reactualizează textbox-ul unde se vor afişa mesajele, iar cel de-al doilea intră în asteptare, trimiţând un răspuns la primirea unui mesaj de la alt agent. [C#]
internal class ReceiveBehaviour : CyclicBehaviour { private new Agent1 myAgent; // "myAgent" implicit este de tip "Agent" public ReceiveBehaviour(Agent1 a) : base(a) { myAgent = a; } public override void action() { ACLMessage message = myAgent.receive(); if (message != null) { string s = message.getContent() + " from " + message.getSender().getLocalName(); myAgent.windowsForm.AddTextLine(s); ACLMessage answer = new ACLMessage(); answer.addReceiver(message.getSender()); answer.setContent("(Message :id 1)"); //cu ID-ul permis - mesajele sunt receptionate de Agent2 answer.setConversationId("ID1"); myAgent.send(answer); answer.setContent("(Message :id 2)"); answer.setConversationId("ID2"); // cu alt ID - mesajele sunt ignorate myAgent.send(answer); } else block(); // foarte important } }

[JAVA]
private class ReceiveBehaviour extends CyclicBehaviour { private Agent1 myAgent; public ReceiveBehaviour(Agent1 a) { super(a); myAgent = a; } @Override public void action() 12

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

{ ACLMessage message = myAgent.receive(); if(message != null) { String s = message.getContent() + " from " + message.getSender().getLocalName(); myAgent.frame.AddTextLine(s); ACLMessage answer = new ACLMessage(); answer.addReceiver(message.getSender()); answer.setContent("(Message :id 1)"); answer.setConversationId("ID1"); myAgent.send(answer); answer.setContent("(Message :id 2)"); answer.setConversationId("ID2"); myAgent.send(answer); } else { block(); } } }

Comportamentul de tipul ReceiveBehavior este derivat din clasa CyclicBehavior. Astfel, funcţia action() se va relua în mod repetat, aşteptînd un mesaj. În situaţia în care nu se primeşte mesaj (adică metoda receive() returnează null), comportamentul este blocat, lasând loc următoarelor comportamente asociate. Când mesajul primit are un conţinut concret, informaţiile primite se obţin cu ajutorul metodei getContent(). Apoi, se pregateşte un mesaj de răspuns answer care este trimis agentului sender de la care s-a primit mesajul iniţial. Se observă cum căile de comunicaţie între agenţi se pot stabili si restricţiona prin utilizarea metodei setConversationID() de către agentul care trimite. Agentul care ar trebui să primească mesajul trimis va utiliza MatchConversationID() pentru a stabili acelaşi ID al comunicaţiei. Construim clasa pentru comportamentul de refresh a ferestrei agentului: [C#]
internal class WinFormRefreshBehaviour : TickerBehaviour { new Agent1 myAgent; public WinFormRefreshBehaviour(Agent1 a, long period) : base(a, period) { myAgent = a; } public override void onTick() { myAgent.windowsForm.DoEvents(); } }

[JAVA]
private class FrameRefreshBehaviour extends TickerBehaviour 13

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

{ private Agent1 myAgent; public FrameRefreshBehaviour(Agent1 a, long period) { super(a, period); myAgent = a; } @Override public void onTick() { myAgent.frame.repaint(); } }

Observăm cum acest comportament moşteneşte clasa TickerBehaviour. Prin urmare, metoda sa onTick() (echivalentă cu metoda action() a altor comportamente) se va repeta la un anumit interval stabilit prin variabila period. Astfel conţinutul ferestrei aferente agentului se va reactualiza periodic. Construim clasa pentru agentul 2: [C#]
public class SendAndReceiveMessages: Agent { private FormAgent windowsForm; private int info; public override void setup() { object[] args = this.getArguments(); if (args != null) { windowsForm = (FormAgent)args[0]; if (args.Length > 1) info = (int)args[1]; } windowsForm.Text = this.getName(); windowsForm.Show(); addBehaviour(new WinFormRefreshBehaviour(this, 100)); addBehaviour(new ListSendBehaviour(this)); addBehaviour(new ReceiveBehaviour(this)); } }

[JAVA]
public class Agent2 extends Agent { private AgentFrame frame; private int info; @Override public void setup() { info = 3; Object[] args = this.getArguments(); 14

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

if(args != null) { frame = (AgentFrame)args[0]; if(args.length > 1) { info = (int)args[1]; } } frame.setTitle(this.getName()); frame.setVisible(true); addBehaviour(new FrameRefreshBehaviour(this, 100)); addBehaviour(new ListSendBehaviour(this)); addBehaviour(new ReceiveBehaviour(this)); } }

Agent2 va avea trei tipuri de comportamente: reactualizarea ferestrei, trimiterea de mesaje celorlaltor agenţi, şi recepţionarea răspunsurilor acestora. Implementăm comportamentul de trimitere a mesajelor către agent 1 şi 3. [C#]
internal class ListSendBehaviour : OneShotBehaviour { private new Agent2 myAgent; // "myAgent" implicit este de tip "Agent" public ListSendBehaviour(Agent2 a) : base(a) { myAgent = a; } public override void action() { // foloseşte câmpul "info" for (int i = 0; i < myAgent.info; i++) { myAgent.windowsForm.AddTextLine((i+1).ToString()); // trimite 2 mesaje lui Agent1 ACLMessage message = new ACLMessage(); AID receiverAID = new AID("Agent1", AID.ISLOCALNAME); // in acelasi container message.addReceiver(receiverAID); message.setContent("(Message :type start :value " + (i+1) + ")"); myAgent.send(message); message.setContent("(Message :type continue :value " + (i + 1) + ")"); myAgent.send(message); // trimite un mesaj lui Agent3 in alt container, este necesar IP-ul message = new ACLMessage(); receiverAID = new AID("Agent3@192.168.1.100:1090/JADE", AID.ISGUID); message.addReceiver(receiverAID); message.setContent("(Message :container second :value " + (i + 1) + ")"); myAgent.send(message); } } }

15

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

[JAVA]
private class ListSendBehaviour extends OneShotBehaviour { private Agent2 myAgent; public ListSendBehaviour(Agent2 a) { super(a); myAgent = a; } @Override public void action() { for(int i = 0; i < myAgent.info; i++) { myAgent.frame.AddTextLine("Displaying private info: " + (i+1)); ACLMessage message = new ACLMessage(); AID receiverID = new AID("Agent1", AID.ISLOCALNAME); // in acelasi container message.addReceiver(receiverID); message.setContent("(Message :container main :type continue :value" + (i + 1) + ")"); myAgent.send(message); //trimite un mesaj lui Agent3 in alt container, este necesar IP-ul String ip = ""; try { BufferedReader in = new BufferedReader(new FileReader("ip.txt")); ip = in.readLine(); in.close(); } catch (IOException e) { System.out.println("Could not read ip file..."); } message = new ACLMessage(); receiverID = new AID("Agent3@" + ip + ":1090/JADE", AID.ISGUID); message.addReceiver(receiverID); message.setContent("Message :container second :value " + (i + 1) + ")"); myAgent.send(message); } } }

Comportamentul implementat este de tip OneShotBehaviour, ceea ce înseamnă ca metoda sa action() se execută o singură dată. Identificarea agenţilor cărora li se trimite mesajul se realizează diferit, existând cazurile în care agentul care primeşte se află sau nu în acelaşi container. În prima situaţie, agentul este indentificat ca fiind în acelaşi container (AID.ISLOCALNAME), nefiind nevoie de informaţii suplimentare. Dacă însă agentul-destinaţie se află în alt container, este necesar si IPul, întrucât container-ul poate exista pe o alta maşină decât cea pe care rulează agentul care trimite.

16

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

Implementăm comportamentul de primire a mesajelor de la alţi agenţi. [C#]
internal class ReceiveBehaviour : CyclicBehaviour { private new Agent2 myAgent; public ReceiveBehaviour(Agent2 a) : base(a) { myAgent = a; } public override void action() { ACLMessage mDessage = null; MessageTemplate pattern = MessageTemplate.MatchConversationId("ID1"); message = myAgent.receive(pattern); if (message != null) { string s = message.getContent() + " from " + message.getSender().getLocalName(); myAgent.windowsForm.AddTextLine(s); } else { block(); // foarte important } } }

[JAVA]
private class ReceiveBehaviour extends CyclicBehaviour { private Agent2 myAgent; public ReceiveBehaviour(Agent2 a) { super(a); myAgent = a; } @Override public void action() { ACLMessage message = null; MessageTemplate pattern = MessageTemplate.MatchConversationId("ID1"); message = myAgent.receive(pattern); if (message != null) { String s = message.getContent() + " from " + message.getSender().getLocalName(); myAgent.frame.AddTextLine(s); } else { block(); } } } 17

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

Ca şi în cazul precedent, acest comportament este ciclic, aşteptându-se răspuns în mod repetat. Se doreşte primirea de mesaje doar pe anumite căi de comunicaţie (MatchConversationID()), cele cu un anumit ID definit în prealabil de agentul care trimite mesajele. Odată primit un mesaj, el este afişat în textbox-ul aferent. În final construim clasa MASInit care va adauga cele 2 containere şi agenţii Agent1 şi Agent2 în containerul principal; Agent3 va aparţine unui alt container. [C#]
public class MASInit { public static void DoInitialization() { jade.wrapper.AgentContainer mainContainer = CreateContainer("Container1M", true, "localhost", null, "1090"); mainContainer.start(); FormAgent ag1Form = new FormAgent(); ag1Form.Location = new Point(50, 50); FormAgent ag2Form = new FormAgent(); ag2Form.Location = new Point(500, 50); FormAgent ag3Form = new FormAgent(); ag3Form.Location = new Point(50, 350); jade.wrapper.AgentController agent1 = CreateAgent(mainContainer, "Agent1", "Messages. ReceiveMessageAndSendAnswer", new object[] { ag1Form }); jade.wrapper.AgentController agent2 = CreateAgent(mainContainer, "Agent2", "Messages. SendAndReceiveMessages", new object[] { ag2Form, 3 }); //agent3 este tot de tipul Agent 1, dar in alt container jade.wrapper.AgentContainer secondContainer = CreateContainer("Container2", false, "localhost", "1090", "1091"); secondContainer.start(); jade.wrapper.AgentController agent3 = CreateAgent(secondContainer, "Agent3","Messages.ReceiveMessageAndSendAnswer", new object[] { ag3Form }); agent1.start(); agent2.start(); agent3.start(); } /// <summary> /// Initializeaza un container /// </summary> /// <param name="ContainerName">Numele containerului</param> /// <param name="IsMainContainer">Containerul este sau nu MainContainer pentru platforma curenta</param> /// <param name="HostAddress">Adresa IP a host-ului</param> /// <param name="HostPort">Portul prin care comunica host-ul</param> /// <param name="LocalPort">Portul local prin care va comunica cu ceilalti agenti</param> 18

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

private static jade.wrapper.AgentContainer CreateContainer(string containerName, bool isMainContainer, string hostAddress, string hostPort, string localPort) { // Creem un nou profil de configurare pentru container ProfileImpl p = new ProfileImpl(); // Numele containerului if (containerName != String.Empty) p.setParameter(Profile.CONTAINER_NAME, containerName); // Containerul este sau nu MainContainer pentru platforma curenta p.setParameter(Profile.MAIN, isMainContainer.ToString()); // Portul local prin care va comunica cu ceilalti agenti if (localPort != null) p.setParameter(Profile.LOCAL_PORT, localPort); // Adresa IP a host-ului if (hostAddress != String.Empty) p.setParameter(Profile.MAIN_HOST, hostAddress); // Portul prin care comunicam cu host-ul if (hostPort != String.Empty) p.setParameter(Profile.MAIN_PORT, hostPort); if (isMainContainer == true) { // Cerem crearea containerului principal return Runtime.instance().createMainContainer(p); } else { // Cerem crearea containerului return Runtime.instance().createAgentContainer(p); } } private static jade.wrapper.AgentController CreateateAgent(jade.wrapper.AgentContainer container, string agentName, string agentClass, object[] args) { return container.createNewAgent(agentName, agentClass, args); } }

[JAVA]
public class MASInit { public static void DoInitialization() { AgentContainer mainContainer = CreateContainer("Container1M", true, "localhost", "", "1090"); try { mainContainer.start(); } catch (ControllerException e){}

19

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

AgentFrame ag1Frame = new AgentFrame(); ag1Frame.setLocation(50, 50); AgentFrame ag2Frame = new AgentFrame(); ag2Frame.setLocation(500, 50); AgentFrame ag3Frame = new AgentFrame(); ag3Frame.setLocation(50, 350); AgentController agent1 = CreateAgent(mainContainer, "Agent1", "messages.Agent1", new Object[] { ag1Frame }); AgentController agent2 = CreateAgent(mainContainer, "Agent2", "messages.Agent2", new Object[] { ag2Frame }); // agent3 este tot de tipul Agent 1, dar in alt container AgentContainer secondContainer = CreateContainer("Container2", false, "localhost", "1090", "1091"); try { secondContainer.start(); } catch (ControllerException e){} AgentController agent3 = CreateAgent(secondContainer, "Agent3", "messages.Agent1", new Object[] { ag3Frame }); try { agent1.start(); agent2.start(); agent3.start(); } catch (ControllerException e){} } private static AgentContainer CreateContainer(String containerName, boolean isMainContainer, String hostAddress, String hostPort, String localPort) { // Creem un nou profil de configurare pentru container ProfileImpl p = new ProfileImpl(); // Numele containerului if (!containerName.isEmpty()) { p.setParameter(Profile.CONTAINER_NAME, containerName); } // Containerul este sau nu MainContainer pentru platforma curenta p.setParameter(Profile.MAIN, String.valueOf(isMainContainer)); // Portul local prin care va comunica cu ceilalti agenti if (localPort != null) { p.setParameter(Profile.LOCAL_PORT, localPort); } // Adresa IP a host-ului if (!hostAddress.isEmpty()) 20

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

{ p.setParameter(Profile.MAIN_HOST, hostAddress); } // Portul prin care comunicam cu host-ul if (!hostPort.isEmpty()) { p.setParameter(Profile.MAIN_PORT, hostPort); } if (isMainContainer == true) { // Cerem crearea containerului principal return Runtime.instance().createMainContainer(p); } else { // Cerem crearea containerului return Runtime.instance().createAgentContainer(p); } } private static AgentController CreateAgent(AgentContainer container, String agentName, String agentClass, Object[] args) { AgentController a = null; try { a = container.createNewAgent(agentName, agentClass, args); } catch (StaleProxyException e){} return a; } }

3. Aplicaţii
3.1. Să se creeze un chat automat la care să participe 5 agenţi: Agent1, Agent2, ..., Agent5. Fiecare agent va trimite periodic câte un mesaj către un agent ales aleatoriu de genul „[AgentX intreaba] Ce ora este acum?”. Agentul intrebat va raspunde printr-un mesaj de tipul: „[AgentY raspunde]: Ora este 08:24” unde AgentX, AgentY reprezintă numele agenţilor. 3.2. Se consideră trei tipuri de agenţi: 1. agenţi Ping-Pong care ştiu  să raspundă la mesaje PING cu PONG  să se închidă la primirea unui mesaj STOP Mesajul primit va avea urmatorul format: [AgentX->PING] sau [AgentX->STOP] 2. agenţi care ştiu să oprească agenţi PING-PONG aleşi aleatoriu la intervale regulate 3. un agent Manager care va raporta periodic care agenţi PING-PONG sunt in viaţă prin efectuarea unui PING către aceştia. Implementaţi o aplicaţie care să conţină un agent manager, un număr de agenţi PING-PONG şi un număr de agenţi care ştiu să oprească un agent PING-PONG.
21

Modelarea si analiza sistemelor multi-agent - Laborator http://florinleon.byethost24.com/lab_masma.htm

Sign up to vote on this title
UsefulNot useful