Controlul Distribuit al Proceselor de Fabricatie cu Ajutorul Mediului Multi Agent Jade
Cuprins
Capitolul 1. Introducere
Capitolul 2. Sisteme multi-agent
2.1 Domeniul de utilizare al sistemelor multi-agent
2.2 Arhitectura sistemelor multi-agent
Capitolul 3. Noțiuni teoretice JADE
3.1 Platforma JADE
3.1.1 Instalarea platformei
3.1.2 Standardul FIPA
3.2 Agentul JADE
3.2.1 Managementul agenților
3.2.2 Crearea unui agent
3.2.3 Comunicarea între agenți
3.2.4 Comportamentul agenților
3.3 Protocoale de comunicație
Capitolul 4 Implementarea sistenului software
4.1Alegerea mediului de dezvoltare a aplicației
4.2 Configurare Eclipse pentru rularea aplicațiilor JADE
Capitolul 5 Studiu de caz
5.1 Prezentarea aplicației
5.2 Soluția de implementare
5.3 Detalierea claselor si a funcțiilor folosite
5.4 Execuția aplicației
5.4.1 Negocierea sub CNP
Capitolul 6. Concluzii
Capitoul 7 Bibliografie
ANEXE
Capitolul 1. Introducere
Sistemele multi-agent urmăresc simularea unor aspecte ale comportamenului uman prin tratarea noțiunilor de scop, cooperare, competiție. În ultima perioadă aceste sisteme au cunoscut o evoluție în toate domeniile, în special cele care se ocupă de controlul și monitorizarea sistemelor de fabricație.
Aceste sisteme permit alocarea dinamică a unui număr finit de resurse de fabricație pentru a derula optim procesul de producție, indiferent de structura unui ordin de fabricație sau de dinamica acestuia.
Aplicația implementată în această lucrare, permite ca procesul de programare (scheduling) a job-urilor de fabricație să fie controlat într-o manieră distribuită, cu respectarea restricțiilor legate de procesarea ordinului de fabricație curent. Acesta este motivul pentru care s-a adoptat tehnologia multi-agent cu agenți inteligenți și folosirea protocolului de contractare în rețea (CNP) pentru alocarea descentralizată a resurselor de fabricație.
Agenții acestei aplicații sunt de tip proactiv, social și vor reprezenta resursele de fabricație, ordinele de fabricație precum și coordonatorul procesului de producție la nivelul tuturor celulelor .
Aplicația prezentată în această lucrare presupune un sistem de fabricație cu 5 celule de fabricație P1-P5, fiecare dintre acestea fiind specializată pe un anume pas de fabricație. Acestea primesc piesele în formă brută/semifabricată si le procesează printr-un număr de mașini de procesare de același tip în cadrul fiecărei celule. Incărcarea și descărcarea pieselor de pe mașinile de procesat din cadrul unei celule se realizează cu ajutorul unui robot fix, iar trasferul între celule se realizează cu ajutorul agenților transportori ai căror rol este de a muta piesele din depozit într-o celulă, dintr-o celulă în altă celulă, sau dintr-o celulă în depozitul de ieșire.
În cadrul acestei aplicații este prezentat modul în care comunică agenții între ei utilizând atât protocolul de comunicare în rețea (CNP) pentru coordonarea între agenții ordin și agenții resursă aferenți, dar și comunicarea directă interagent prin intermediul mesajelor ce respectă standardul FIPA.
Rularea aplicației a presupus urmărirea unor scenarii:
Procesarea unui ordin de fabricație pentru un singur produs de un anumit tip, având la dispoziție câte un agent din fiecare celulă;
Procesarea unui ordin de fabricație pentru două produse de același tip, având la dispoziție câte un agent din fiecare celulă;
Procesarea a două ordine de fabricație diferite, având la dispoziție câte un agent din fiecare celulă.
Capitolul 2. Sisteme multi-agent
2.1 Domeniul de utilizare al sistemelor multi-agent
Un agent este o entitate software sau hardware situată într-un mediu de execuție și care este capabilă de acțiuni autonome pentru a-și îndeplini obiectivele proiectate.
Un sistem multi-agent( SMA) este compus din agenți care interacționează între ei prin: comunicare, coodronare, cooperare sau negociere, fiecare având cunoștințe, capacități de acțiune și scopuri proprii. Agenții individuali angajați într-un sistem multi-agent au diferite țeluri sau motivații. Aceste sisteme pot rezolva probleme care pentru un agent individual sunt prea dificile. Prin construcția aplicațiilor utilizând tehnologia sistemelor multi-agent, se îmbunătățește flexibilitatea și capacitatea acestora de a rezolva situațiile neprevăzute apărute în cadrul sistemului. Aceste sisteme se folosesc îndeosebi atunci când se vorbește despre sisteme de o mare complexitate, fie despre viteză de procesare mare, fie de întinderea sistemului pe o arie largă.
În ultimii ani, sistemele multi-agent au cunoscut o răspândire mare, fiind utilizate în aplicații din diferite domenii. Acestea sunt utilizate într-o gamă foarte largă de aplicații, variind de la sisteme relativ mici, de asistență personală, până la sisteme complexe, de misiuni critice pentru aplicații industriale.
Aplicațiile industriale sunt foarte importante pentru acest tip de sistem, deoarece în acest domeniu s-au testat pentru prima dată tehnicile sistemelor multi-agent.
Domeniul transporturilor și al traficului este de asemenea o arie importantă, în care natura distribuită a traficului și a porcesului de transport face ca sistemele multi-agent să fie soluția comercială cea mai eficientă.
Sistemele de telecomunicații reprezintă o altă arie de aplicare a sistemelor multi-agent, și în care acestea au fost folosite cu foarte mare succes. Defapt, sistemele de telecomunicații sunt mari, alcătuite din rețele distribuite și componente interconectate ce necesită monitorizare și management în timp real, ceea ce un sistem multi-agent poate oferi.
Sistemele multi-robot folosesc de asemenea acest tip de sistem bazat pe mai mulți agenți.
Aceste sisteme se pot găsi chiar și în domeniul sănătății, unde s-a propus deja înfruntarea cu diferite domenii de înrijire medicală, și anume programarea pacienților și management, accesul la informații medicale și management.
2.2 Arhitectura sistemelor multi-agent
Un aspect important al arhitecturii unui sistem multi-agent este facilitatea cu care se pot adăuga sau elimina agenți din respectivul sistem.
Există două tipuri de arhitecturi: statică si dinamică. Arhitectura în care toate componentele sistemului, intrările și ieșirile sale sunt definite în specificația proiectului, se numește arhitectură statică.În acest tip de arhitectură trebuie să fie prezentate toate elementele pentru ca sistemul să funcționeze. Într-o arhitectură dinamică, componentele nu sunt toate cunoscute, iar proveniența și specificația intrărilor cât și destinația ieșirilor, nu sunt fixe. În acest tip de arhitectură, unii agenți pot participa sau nu o anumită perioadă de timp, și pot intra sau abandona participarea la sistem.
Capitolul 3. Noțiuni teoretice JADE
3.1 Platforma JADE
JADE este o platformă ce oferă funcționalități de baza ce sunt independente față de aplicația specificată, și care simplifică realizarea aplicațiilor distribuite care exploatează abstracția agentului software. Aceasta conține un Main-Container cu 2 agenți: AMS(Agent Management System) si DF( Directory Facilitator). Mai există un agent special, RMA( Remote Monitoring Agent), care oferă o interfață pentru această platformă. Meritul cel mai mare al acestei platforme este acela că implementează această abstracție într-un foarte bine cunoscut limbaj de programare orientat pe obiect, Java, oferind o interfață ușor de utilizat.
3.1.1 Instalarea platformei
Instalarea platformei JADE contsă în dezarhivarea fișierului descărcat de pe http://jade.tilab.com . Tot aici se găsește și distribuția JADE care conține 5 arhive cu urmatoarele informații:
jadeBin.zip( conține toate variantele precompilate ale librăriilor JADE gata de a fi utilizate);
jadeDoc.zip(contine documentația disponibilă);
jadeExamples.zip(conține codul sursă pentru diferite exemple);
jadeSrc.zip(conține sursele platformei);
jadeAll.zip(conține toate cele 4 arhive menționate mai sus);
Pentru compilarea și execuția unui program JADE, variabila de sistem classpath trebuie să conțină fișierele .jar aflate in jadeBin.zip .Acest lucru se realizează dezarhivând fisierele menționate mai sus, creând un folder în partiția c:// cu următoarea structură:
3.1.2 Standardul FIPA
FIPA( Foundation for Intelligent Physical Agents) este folosit îndeosebi în comunicarea între agenți și urmărește următorul set de principii:
Tehnologiile agenților oferă un nou paradigm pentru a rezolva atât problemele noi cât și cele deja cunoscute;
Tehnologi ile unor agenți au atins un grad considerabil de maturitate;
Pentru a fi de folos, tehnologiile unor agenți necesită standardizare;
Standardizarea tehnologiilor generice s-a dovedit a fi posibilă și pentru a oferi rezultate eficiente către alte foruri de standardizare;
Standardizarea mecanicii interne a agenților nu este principala înghijorare, ci mai degrabă infrastructura și limbajul necesar pentru interoperarea deschisă.
În cazul platformei JADE, caracteristicile agenților sunt in conformitate cu specificațiile FIPA, putând fi integrate module de raționare în cadrul unul agent.
3.2 Agentul JADE
Programarea orientată pe agenți( POA) este o paradigmă software ce reunește idei din domeniile sistemelor distribuite, programare orientată pe obiect și inteligență artificială.
Un agent JADE este un sistem de calcul situat într-un mediu și care este capabil de acțiuni autonome în acest mediu, cu scopul realizării unor obiective. În ciclul lor de viață, aceștia trec prin diferite etape precum:
Inițiere: Agentul este creat, dar nu este înregistrat în AMS(serviciun de evidență a numelor agenților);
Activare: Agentul a fost înregistrat și are un nume. În această etapă, el poate comunica cu ceilalți agenți;
Suspendare: Agentul este oprit din cauza întrerupeii firului sau de execuție;
Așteptare: Agentul este blocat așteptând apariția unui eveniment;
Ștergere: Agentul și-a terminat firul de execuție, și se șterge din AMS;
Tranzitare: Agentul își schimbă locația.
3.2.1 Managementul agenților
Platforma agentilor( AP) generează o infrastructură fizică în care agenții sunt partajați. Aceasta este formată din mașini de lucru, sisteme de operare, componente FIPA de management ale agenților, agenții îșiși si orice suport software adițional.
Agentul este un proces computațional care populează o AP și oferă unul sau mai multe servicii computaționale ce pot fi publicate ca un descriptor de servicii. Un agent trebuie să aibă cel puțin un deținător și trebuie să fie identificat de cel puțin o noțiune care să poată fi descrisă utilizând FIPA Agent Identifier( AID).
Directory Facilitator( DF) este o componentă opțională a AP, ce oferă serviciul de pagini aurii altor agenți. Acesta reține o listă de agenți completă și precisă și oferă cele mai recente informații despre agenți. Fiecare agent care dorește să își publice serviciile trebuie să găsească un DF adecvat și să solicite înregistrarea descrierii sale. Agenții pot solicita și deregistrarea din DF, moment în care nu mai sunt disponibili in comunicarea cu alți agenți. În orice moment, un agent poate solicita DF pentru modificarea descrierii proprii. O altă acțiune pentru care un agent poate solicita DF este aceea de căutare a unor șabloane care să coincidă cu descrierea sa (Figura 3.2.1.a).
Figura 3.2.1.1 Agentul DF
Agent Management System( AMS) este o componentă obligatorie a unei AP si este responsabilă pentru managementul operațiilor ce au loc pe acea platformă, precum crarea si ștergerea agenților. Acesta reprezintă autoritatea principală a platformei deoarece are control asupra folosirii resurselor existente, reține informații despre ceilalți agenți. Pe o platformă există un singur astfel de agent. Fiecare agent trebuie să se înregistreze cu un AMS pentru a obține un agent identificator( valoare unică) (Figura 3.2.1.b).
Figura 3.2.1.2 Agentul AMS
Serviciul de Transportare a Mesajelor( MTS) este un serviciu care oferit de AP ce transporta mesaje de tip FIPA-ACL între doi agenți pe o anumită AP, sau între agenți de pe AP-uri diferite. Mesajele conțin difeăutare a unor șabloane care să coincidă cu descrierea sa (Figura 3.2.1.a).
Figura 3.2.1.1 Agentul DF
Agent Management System( AMS) este o componentă obligatorie a unei AP si este responsabilă pentru managementul operațiilor ce au loc pe acea platformă, precum crarea si ștergerea agenților. Acesta reprezintă autoritatea principală a platformei deoarece are control asupra folosirii resurselor existente, reține informații despre ceilalți agenți. Pe o platformă există un singur astfel de agent. Fiecare agent trebuie să se înregistreze cu un AMS pentru a obține un agent identificator( valoare unică) (Figura 3.2.1.b).
Figura 3.2.1.2 Agentul AMS
Serviciul de Transportare a Mesajelor( MTS) este un serviciu care oferit de AP ce transporta mesaje de tip FIPA-ACL între doi agenți pe o anumită AP, sau între agenți de pe AP-uri diferite. Mesajele conțin diferite informații precum: destinatarul, conținutul mesajului, limbajul folosit, ș.a. .
Dacă lansarea conține opțiunea “-gui”, atunci va fi funcțional și agentul RMA( Remote Monitoring Agent), care este un serviciu de urmările a agenților (Figura 3.2.1.c).
Figura 3.2.1.3 Agentul RMA
3.2.1.1 Clasa DFService – asigurarea interoperabilității bazate pe servicii
Această clasă conține un set de metode statice de comunicare bazată pe servicii ce respectă specificațiile FIPA. Include metode pentru înregistrare, ștergere a înregistrării, modificare și căutare ce formează un serviciu de tip „pagini aurii”, implementat cu ajutorul clasei Directory Facilitator (DF). Toate aceste metode blochează activitatea agenților până când își termină activitatea sau până când apare o excepție ce le întrerupe activitatea.
Mod de înregistrare a unui agent prin DF:
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
…
DFAgentDescription DFD = new DFAgentDescription();
Dfd.setName(getAID());
ServiceDescription sd = new ServiceDescriptiom();
sd.setName(getLocalName());//
sd.setType(“tipul serviciului”);
dfd.addServices(sd);
try
{
DFService.register(this,dfd);
}
catch(FIPAException fe)
{
fe.printStackTrace();
}
Secvență de cod 3.2.1.1.1 Înregistrare în DF
Mod de căutare a unui agent prin DF:
DFAgentDescription mt = new DFAgentDescription();
ServiceDescription sd = new ServiceDescription();
Sd.setType(“tipul serviciului cautat”);
mt.addServices(sd);
try
{
DFAgentDescription[] result= DFService.search(agentulMeu,mt);
}
catch(FIPAException fe)
{
Fe.printStackTrace();
}
Secvență de cod 3.2.1.1.2 Căutare în DF
Ștergerea înregistrării unui agent se realizează cu ajutorul funcției “deregister()”:
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
…
DFAgentDescription DFD = new DFAgentDescription();
Dfd.setName(getAID());
ServiceDescription sd = new ServiceDescriptiom();
sd.setName(getLocalName());//
sd.setType(“tipul serviciului”);
dfd.addServices(sd);
try
{
DFService.deregister(this,dfd);
}
catch(FIPAException fe)
{
fe.printStackTrace();
}
Secvență de cod 3.2.1.1.3 Ștergere din DF
Modificarea unei înregistrări se realizează cu ajutorul funcției “modify()”.
3.2.2 Crearea unui agent
Un agent Jade este un program Java având o structură specială și care lansat în execuție, realizează una sau mai multe acțiuni, putând interacționa cu alți agenți. Crearea unui agent înseamnă o simplă definire a unei clase care să extindă clasa “Agent” din „jade.core.Agent”, și implementarea metodei setup().
Să luăm drept exemplu un agent care tot ce face este să afișeze un mesaj:
import jade.core.Agent;
public class HelloWorldAgent extends Agent
{
protected void setup(){
System.out.println(“Hello world. I am an agent!”);
}
}
Secvență de cod 3.2.2.1 Creare Agent
3.2.3 Comunicarea între agenți
Comunicarea agenților este probabil cea mai importantă caracteristică a platformei JADE și este implementată în conformitate cu standardul FIPA. Acest lucru se realizează prin schimburi de mesaje ce au la bază un șablon comun ce respectă atât standardul SL-FIPA( FIPA Static Language) cât și standardul ACL( Agent Communication Language).
Un mesaj JADE, pe lângă conținutul propriu-zis, mai are o serie de atribute ce se accesează cu ajutorul metodelor de tip set și get.
Conținutul unui mesaj JADE presupune:
Tipul mesajului – Performative (mesaje de tip: INFORM, PROPOSE, ACCEPT_PROPOSAL, ș.a.);
Lista cu destinatarii mesajului(Receiver) – poate exista unul sau mai mulți destinatari;
Expeditorul mesajului ( Sender);
Conținutul mesajului ( Content);
Id-ul conversației (ConversationId) – leagă mesajele dintr-o conversație;
Limba (Language) – limba în care este scris conținutul;
Ontologia (Ontology);
Protocolul (Protocol);
RaspundeCu (ReplyWith) – utilizat pentru specificitatea răspunsului, un câmp care ne ajută să distingem răspunsurile;
CaRăspunsLa (InReplyTo) – expeditorul ajută fixarea specificității răspunsului( distinge mesajele);
RaspundÎnTimpDe (ReplyByDate) – folosit pentru a indica o limită de timp pentru răspuns;
Atunci când dorim să generăm un mesaj, trebuie să specificăm tipul acestuia:
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
Msg.setContent(“conținut”);
Există mai multe tipuri de mesaje. Acestea sunt prezentate în Tabel 3.2.3:
Tabel 3.2.3 Tipuri de mesaje în JADE
Expedierea unui mesaj către un alt agent se realizează completând câmpurile unui obiect de tip ACL, urmat de apelul metodei send() din clasa Agent. Codul de mai jos crează un mesaj de informare a unui agent cu numele “Peter” , prin care îi comunică acestuia că azi va ploua:
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.addReceiver(new AID(“Peter”, AID.ISLOCALNAME));
msg.setContent(„Today it’s raining”);
send(msg);
Secvență de cod 3.2.3.1 Trimitere mesaj
Atunci când se trimite un mesaj, acesta este pus într-o coadă de mesaje. Un agent primește un mesaj apelând metoda receive(). Această metodă returnează primul mesaj din coada de mesaje, sau null dacă nu există niciun mesaj în coadă.
ACLMessage msg = receive();
If(msg != null)
{ se procesează mesajul;
}
Secvență de cod 3.2.3.2 Recepție mesaj
3.2.4 Comportamentul agenților
Un agent poate executa mai multe comportamente simultam. Este important de știut că programarea comportamentelor într-un agent nu este preemtivă, dar este cooperativă. Asta înseamnă că atunci când un comportament este programat pentru execuție, este apelată metoda proprie action() a cărei execuție nu poate fi întreruptă de niciun alt comportament. Cu alte cuvinte în momentul în care un comportament începe să ruleze nu va fi întrerupt până când nu eliberează de bună voie thread-ul invocând metoda block(). Programatorul definește momentul în care un agent își schimbă execuția de la un comportament la altul. Această abordare adeseori le crează dificultăți utilizatorilor JADE fără experiență. Cu toate că necesită atenție și efort în implementare, aceste comportamente au o serie de avataje:
Permite un singur fir Java pentru un agent, ceea ce este foarte important pentru mediile cu resurse limitate cum ar fi telefoanele mobile;
Oferă performanțe îmbunătățite având în vedere faptul că schimbarea comportamentelor se realizează mult mai rapid decât schimbarea firelor de execuție Java;
Elimină problemele de sincronizare dintre comportamentele concurente accesând aceleasi resurse, din moment ce toate comportamentele sunt executate de acelasi fir de execuție Java;
Tipurile de comportamente JADE sunt ilustrate în Tabel 3.2.4
Tabel 3.2.4 Tipuri de comportamente JADE
Metode ale claselor comportamentale:
abstract void action() – definește acțiunea realizată de agent;
abstract boolean done() – metoda action() se executa cât timp metoda done() retureanză false.
block() – suspendă execuția metodei action();
block(long dt) – planifică următoarea execuție a metodei action() dupa dt milisecunde;
protected void onTick() – se folosește la comportamentele de tip TickerBehaviour și este un înlocuitor al metodei action() cu observația că se execută odată la o perioadă dată de utilizator. Conține acțiunea care trebuie întreprinsă.
3.3 Protocoale de comunicație
Într-un sistem multi-agent, este nevoie de coordonare și de colaborare pentru a se realiza o sarcină complexă. Contract Net Protocolul (CNP) este un mecanism de coordonare întâlnit de foarte multe ori în acest tip de sistem deoarece împarte sarcinile fiecărui agent în parte.
Pentru CNP există două tipuri de agenți: Inițiator și Participant. În orice moment, un agent poate fi atât Inițiator cât și Participant, sau chiar ambele. CNP crează un mijloc de contractare, precum și sarcini de subcontractare. Astfel, Inițiatorul este manager iar Participanții sunt contractori. Inițiatorul poate fi un agent care dorește să cumpere ceva sau care așteaptă să își vândă dreptul de a furniza ceva. Participanții, în oricare din cazurile de mai sus, sunt agenți care așteaptă sa vândă ceva sau care doresc să cumpere dreptul de a furniza ceva.
Protocolul de interacțiune este compus dintr-o sesiune cu patru pași importanți. Agenții trebuie să treacă prin toți acești pași pentru a negocia fiecare contract:
Inițiatorul trimite Call For Proposal (CFP), adică îi propune fiecărui participant să realizeze un anumit job;
Fiecare participant îi trimite Inițiatorului un răspuns cu jobul pe care știe el să îl facă;
Inițiatorul alege cea mai bună ofertă și contractează agentul care a trimis acea ofertă, trimițându-i un mesaj de tip ACCEPT_PROPOSAL;
Inițiatorul trimite un mesaj de tip REJECT_PROPOSAL către restul agenților participanți.
FIPA are specificațiile CNP pentru comunicare între agenți. Modul în care lucrează un FIPA-CNP este ilustrat în Figura 3.2.5.
Figura 3.2.5 Protocolul de conumicație FIPA-Contract-Net-Protocol
Capitolul 4 Implementarea sistenului software
4.1Alegerea mediului de dezvoltare a aplicației
Pentru a putea elabora acet proiect de licență a fost necesară alegerea unui IDE pentru Java care să ofere facilități de programare ușoară a uneia sau a mai multor implementări JADE. Întrucât am avut de ales între Eclipse și NetBeans, deoarece ambele medii de dezvoltare orefă posibilitatea înțelegerii limbajului JADE, am ales Eclipse datorită faptului că în timpul facultății am studiat acest mediu de dezvoltare open-source.
Am folosit Eclipse IDE for Java Developers versiunea Juno care se poate descărca de pe pagina oficială a mediului de dezvoltare Eclipse (www.eclipse.org).
Java este un limbaj de programare de nivel înalt ce are ca și caracteristici principale: simplitate, robustețe, securitate, portabilitate, permite programarea cu fire de execuție, este modelat după C si C++, este neutru din punct de vedere arhitectural, se folosește ușor pentru programarea în rețea, este complet orientat pe obiect.
Pentru partea de programare Java am descărcat ultima versiune de JDK (Java Developer’s Kit) pentru Windows, fisierul executabil fiind numit jdk-7u25-i586.exe.
Pe partea de programare multi-agent JADE s-a descărcat pachetul JADE-all-4.3.0 de pe site-ul oficial Telecom Italia http://jade.tilab.com/.
4.2 Configurare Eclipse pentru rularea aplicațiilor JADE
Pentru a putea rula aplicații multi-agent în Eclipse, avem nevoie de librăriile: jade.jar, common-codes-1.3.jar, http.jar, iiop.jar, jadeTools.jar.
Captură ecran 4.2.1. Introducerea librăriilor în mediul de dezvoltare Eclipse
Pentru a putea exemplifica toată configurația corectă a mediului de dezvoltare, vom lua un prim exemplu de lucru cu agenți. Acest exemplu este foarte simplu dar și foarte sugestiv. Avem un agent la pornirea căruia se va afișa în consolă mesajul: “Salut! Numele meu este Anca și sunt un agent.”.
package PrimulAgent;
import jade.core.*;
public class PrimAgent extends Agent{
protected void setup(){
System.out.println(“Salut.Numele meu este ”+getLocalName()+” si sunt un agent”);
Object[] args= getArguments();
if(args != null){
for(int i=0;i<args.length;i++)
{ String s= args[i].toString();
System.out.println(s);
}}
doDelete();
}
Protected void takeDown(){
System.out.println(“Finishing! “+getAID().getName());
System.exit(0);
}}
Secvență de cod 4.2.1 Agentul Anca
Pentru a putea executa programe folosind platforma JADE, trebuie configurat mediul de dezvoltare Eclipse, urmând pașii descriși în capturile de ecran de mai jos:
Captură ecran 4.2.2 Configurare Eclipse
Captură ecran 4.2.3 Configurare Eclipse
Pentru a putea lansa în execuție agentul nostru, primul pas care trebuie făcut, este de a adauga instrucțiunea jade.Boot în “Main class”. Aceasta este instrucțiunea care pronește aplicația.
Captură ecran 4.2.4 Configurare Eclipse
Cu ajutorul instrucțiunii “-gui”, se pornește interfața grafică a containerului de bază RMA(RemoteAgent Management).
Argumentele liniei de comandă se completează astfel:
[nume_agent]:[nume_pachet].[nume_clasă]
De aceea în exemplul nostru am introdus în linia de comandă:” Anca:PrimulAgent.PrimAgent”.
La apasarea butonului Run se va porni interfața grafică RMA și bineînțeles că în containerul principal se va afla agentul creat.
Captură ecran 4.2.5 Lansarea în execuție a interfeței grafice RMA
Capitolul 5 Studiu de caz
5.1 Prezentarea aplicației
Scenariul de fabricație propus:
Se presupune un sistem de fabricație format din 5 celule de fabricație P1-P5, fiecare fiind specializată într-un anume proces de fabricație.
În fiecare celulă de fabricație există instalat un robot la punctul de I/E ce preia piesele brute de la roboții de transport/ magazia de piese brute S1 și plasează la finalul procesării produsele semifabricate/finite pe roboți transport/ magazia cu produse finale S2.
De exemplu pentru P2 există următoare componență:
Figura 5.1.1 Componența echipamentului din celula 2
Pentru transport se folosesc 4 echipamente de transport T1-T4 (roboți mobili/banzi transportoare) ce vor asigura transportul pieselor brute/semifabricatelor/produselor finite.
S1 este depozitul cu piese brute, iar S2 depozit de produse finale.
Scenariul ne prezintî 3 tipuri de produse: “Produs-1”, ”Produs-2”, “Prous-3”.Fiecare dintre aceste produse urmărește un anumit flux de fabricație, astfel încât traseul prin sistemul de fabricație este diferit pentru cele 3 tipuri de produse.
Schema fluxului de fabricație pentru cele 3 produse posibil a fi obținute este:
Figura 5.1.2 Fluxul de fabricație a celor 3 tipuri de produse ce pot fi fabricate
Pentru a înțelege mai bine această figură, pașii de fabricație ai fiecărui produs sunt prezentați și în tabelul timpilor aferenți fiecărui pas:
Tabel 5.1.3 Timpii aferenți fiecărui pas de fabricație (exprimat în minute)
5.2 Soluția de implementare
Pentru a putea realiza sistemul, avem nevoie de mai mulți agenți, și anume:
Agentul TAC( este agentul coordinator al tuturor ordinelor de fabricație);
Agent task TA;
Agent resursă RA;
Intermediar director servicii SDF.
Agentul TAC:
Reprezintă componenta de interfață între sistemul de management al alocării dinamice de resurse și sistemul de planificare a resurselor la nivel de întreprindere;
Primește ordinele de fabricație;
Raportează starea ordinelor de fabricație( pasul la care se află procesul de fabricație, iar dacă un ordin s-a terminat, raportează acest lucru și numărul produselor care au fost fabricate, sistemului de planificare a resurselor de fabricație);
Crează un TA pentru fiecare ordin de fabricație;
Comunică cu TA transmițându-i informații legate de ordinul de fabricație;
Distruge TA la terminarea ordinului de fabricație;
Agentul TA:
Fiecare TA reprezintă un singur ordin de fabricație;
TAprimește de la TAC următoarele informații:
Identificatorul ordinului de fabricație( adică tipul produsului);
Cantitatea de produse care trebuie obținută;
Lista cu pașii de procesare;
Lista cu timpii de procesare;
După creare, TA va trimite o cerere de realizare a primului pas de fabricație din lista pașilor, necesar în obținerea unui produs solicitat, către SDF;
Cererile de contractare sunt evaluate și contractual va fi acordat Ra ce a depus cererea cea mai avantajoasă, conform unui mecanism de acordare de tip CNP.
Agentul SDF:
SDF este un agent folosit drept director de servicii, acceptând publicarea cererilor de servicii solicitate de către TA-uri. Furnizorii de servicii( RA) subscriu la SDF pentru a obține:
Notificări când apare o nouă cerere de serviciu;
Specificațiile unei cereri de serviciu.
Agentul RA:
Agenți rezidenți pe echipamentele de procesare;
Asigură execuția unui pas de procesare din procesul de fabricație al unui produs;
Sunt creați pe calculatorul aferent echipamentului, la pornirea acestuia;
După ce vor primi specificațiile de la SDF, RA-urile vor evalua dacă pot gestiona job-ul curent, și în caz afirmativ, vor transmite direct către TA cererea proprie de contractare;
În cazul operării normale, RA-urile verifică periodic SDF pentru a găsi ultimul serviciu publicat și solicit specificații pentru a evalua dacă pot să solicite o cerere de contractare;
În mod real, job-ul asumat de către RA este transmis controllerului propriu sub formă de instrucțiuni executabile; controllerul va trimite înapoi informații despre starea de execuție a job-ului și despre starea echipamentului( aici lucrurile vor trebui simulate).
5.3 Detalierea claselor si a funcțiilor folosite
După cum spuneam în capitolele anterioare, fiecare agent reprezintă o clasă careia i se alocă un anumit tip de comportament. În această lucrare avem două clase principale: TA, ce reprezină agenții inițiatori, RA, ce reprezină agenții de tip participant. Pe lângă acestea, mai există și clasele ce implementează interfațele grafice ale acestora, și anume: TAC, implementează interfața grafică a unui agent de tip inițiator și în același timp îl și crează la apăsarea butonului “send”, și RaguiImpl care implementeayă interfața grafică a unui agent de tip participant.
Implementarea claselor TAC și RaguiImpl diferă deoarece TA trebuie să cunoască informații despre ordinul de fabricație pe când RA trebuie să cunoască numai pasul de producție pe care îl poate realiza și celula din care face parte.
Clasa TAC:
Extinde o clasă de tip JFrame( folosit în Java pentru interfețe grafice).
Prezintă 4 câmpuri de text și anume: Tipul produsului, Numărul de produse, lista pașilor de procesare si lista timpilor de procesare. În funcție de fiecare tip de produs în parte și de cantitatea introdusă, TAC va ști singur lista de procese și timpi aferenți acestora.
Valorile introduse în aceste câmpuri vor fi trimise ca și parametri către TA și în funcție de aceștia se va realiza procesul de negociere. În cazul în care utilizatorul nu completează unul din câmpurile de text, se va afișa un mesaj de avertizare.
Datorită acestor două tipuri de agenți prezentați în această lucrare, interfețele grafice le vom numi sugestiv astfel, TAC va creând agentul inițiator, va purta numele “Inițiator”.
Captură de ecran 5.3.1 Introducere parametri penru TA
Pe lângă aceste 4 câmpuri de text, TAC mai prezintă și o zonă de text în care se vor afișa toate mesajele agentului creat, TA, cât și mesajele primite de către TA de la agenții participanți RA.
Captură de ecran 5.3.2 Zonă de text TAC
În partea de jos a acestei interfețe se găsesc 3 butoane: Send, Reset și Exit.
Captură de ecran 5.3.3 Butoane TAC
După cum menționam anterior, prin apăsarea butonului “ Send” se crează agentul inițiator TA prin trimiterea parametrilor completați în câmpurile de text, numai dacă acestea există.
Prin apăsarea butonului “Reset”, toate câmpurile de text devin vide, chiar dacă înainte erau completate.
Apăsarea butonului “Exit”generează distrugerea ordinului de fabricație.
Clasa TA:
Extinde clasa Agent. În metoda setup() se afișează un mesaj precum că agentul este pregătit, se salvează numele agentului ce a fost introdus în linia de comandă, se deschide interfața grafică TAC, iar apoi este setat agentul TA. În metoda takeDown() se afișează un mesaj precum că agentul a fost distrus, și dacă interfața grafică nu a fost închisă anterior, se apelează metoda dispose() pentru a realiza acest lucru.
În metoda createTA() vom adăuga două clase comporamentale: una de cerere de realizare a primului pas de fabricație necesar pentru obținerea unui produs( JobToRA), iar cea de-a doua de acordare a jobului către RA care a depus oferta cea mai avantajoasă, conform unui mecanism de acordare de tip Contract Net Protocol (UpdateManager). Ambele comportamente sunt de tip TickerBehaviour, adică se execută odată la o anumită perioadă de timp.
În clasa JobToRA, TA trimite o cerere de realizare a primului pas de fabricație necesar pentru realizarea unui produs solicitat către SDF. TA se va axa numai pe agenții care participă la procesul de negociere.
În metoda onTick() a clasei comportamentale UpdateManager contorizăm fiecare execuție a acestei funcții, și dacă lista pașilor ce trebuiesc realizați nu este vidă și contorul nu ajunge să fie egal cu numărul pașilor ce trebuiesc executați, atunci se actualizează lista pașilor și lista timpilor, și se adaugă comportamenul de negociere de tip CFP( handleService). Fiind un comportament de tip TickerBehaviour, acesta se execută odată la o anumită perioadă specificată în cod. După ce se execută fiecare pas din procesul de fabricație, se va afișa un mesaj de tipul: ”Produsul a fost realizat.”.
Clasa comportamentală handleService extinde un comportament de tipul Behaviour, ceea ce înseamnă ca se execută ori de câte ori este apelată. În metoda action() am implementat, pe pași, un comportament de negociere de tip CFP. În primul rând, extragem din lista pașilor de executat, doar primul pas, iar din lista timpilor doar primul timp, deoarece de fiecare dată vom contracta RA-uri care să execute primul pas din listă. Apoi trimitem către toți agenții RA o propunere de realizare a pasului creând un șablon în care specificăm un identificator al conversației, si conținutul propriu-yis al mesajului. Așteptăm să primim răspunsuri de la toți agenții RA, iar dacă pasul trimis de TA coincide cu pasul pe care îl poate realiza RA, acesta devine bestOffer( agentul care a venit cu oferta cea mai bună). Dacă există un bestOffer, TA îi trimite un mesaj de tipul ACCEPT_PROPOSAL având drept conținut identificatorul produslui de fabricat. Toți ceilalți agenți de tip RA primesc un mesaj de tipul REJECT_PROPOSAL. Înainte ca agentul RA sa înceapă să execute pasul, TA îi trimite cantitatea de produse care să fie realizate.
CLASA RaguiImpl:
Extinde o clasă de tip JFrame( folosit în Java pentru interfețe grafice).
Prezintă 2 câmpuri de text și anume: Pasul de fabricație pe care îl poate realiza și celula din care face parte agentul.
Valorile introduse în aceste câmpuri vor fi trimise ca și parametri către RA și în funcție de aceștia se va realiza procesul de negociere. În cazul în care utilizatorul nu completează unul din câmpurile de text, se va afișa un mesaj de avertizare.
Datorită acestor două tipuri de agenți prezentați în această lucrare, interfețele grafice le vom numi sugestiv astfel, RA fiind agentul participant, va purta numele “Participant”, urmat de un număr care reprezintă al câtelea agent este.
Captură de ecran 5.3.4 Introducere parametri RA
Pe lângă aceste 2 câmpuri de text, RA mai prezintă și o zonă de text în care se vor afișa toate mesajele agentului creat, atât mesaje din timpul procesului de negociere cât și mesaje din timpul execuției pasului alocat.
Captură de ecran 5.3.5 Zonă de text RA
La fel ca și la TAC, în partea de jos a acestei interfețe se găsesc 3 butoane: Send, Reset și Exit.
Captură de ecran 5.3.6 Butoane RA
Prin apăsarea butonului “ Send” se crează agentul Participant RA prin trimiterea parametrilor completați în câmpurile de text, numai dacă acestea există.
Prin apăsarea butonului “Reset”, toate câmpurile de text devin vide, chiar dacă înainte erau completate.
Apăsarea butonului “Exit”generează distrugerea ordinului de fabricație.
Clasa RA:
Exinde o clasă de tip Agent. În metoda setup() se crează un așa-zis catalog, în care voi salva datele tuturor agenților de tip RA, se deschide interfața grafică RAguiImpl, este setat agentul RA. Fiecare agent în parte se înscrie în Paginile aurii cu un anumit șablon în care este specificat tipul serviciului oferit. Tot în această metodă se adaugă două comportamente: primul este handleBidCFP care administrează cererile de contractare primate de la TA, iar al doilea comportament administrează agenții care primesc de la TA un mesaj de tip ACCEPT_PROPOSAL. Această clasă invocă adăugarea unui nou comportament de tip ProcesarePas care realizează execuția propriu-zisă a task-urilor unui agent. Aceasta este responsabilă de:
Transportul pieselor de la depozit la o celulă, dintre două celule, sau de la o celulă la depozit( Transport());
Calculul duratei de procesare al unui pas de execuție( DurataDeProcesare());
Primirea mesajului de la TA ce conține cantitatea produselor ce trebuiesc fabricate( PrimireMesaj());
Transmiterea către TA a mesajelor de terminare a procesării pașilor de execuție( TrimiteMesaj()).
În metoda action() a acestei clase comportamentale, în funcție de tipul produsului de procesat și în funcție de pasul de procesare la care ne aflăm, sunt apelate funcții care ajută la execuția propriu-zisă a task-ului.
5.4 Execuția aplicației
În această lucrare am abordat trei scenarii diferite și anume:
Execuția unui ordin de fabricație cu un produs de orice tip și cu câte un agent din fiecare celulă;
Execuția unui ordin de fabricație cu două produse de orice tip și câte un agent din fiecare celulă;
Execuția a două ordine de fabricație diferite, cu un produs de orice tip și câte un agent din fiecare celulă.
Fiecare agent RA creat în linia de comandă, după cum specificam și în subcapitolul anterior, trebuie să se înscrie în paginile aurii cu un anumit șablon care să specifice tipul serviciului pe care acesta îl oferă, deoarece căutarea unui serviciu de procesare a unui pas de fabricație se realizează numai în cadrul acestor pagini aurii, iar atâta timp cât agenții RA nu sunt înscriși, TA nu v-a găsi niciun agent care să poată efectua ordinul de fabricație curent.
Modalitatea prin care agenții RA se înscriu în paginile aurii o voi exemplifica prin secvența de cod care se găsește în clasa RA în cadrul metodei setup() :
DFAgentDescription dfd =new DFAgentDescription();
dfd.setName(getAID());
ServiceDescription sd= new ServiceDescription();
sd.setType("Procesare_pas");
sd.setName(getLocalName()+"Procesare_pas");
dfd.addServices(sd);
try {
DFService.register(this,dfd);
}
catch (FIPAException fe)
{
fe.printStackTrace();
}
Secvență de cod 5.4.1 Înregistrare în paginile aurii
După ce un agent se înregistrează în paginile aurii, este pregătit pentru comunicația cu TA. Agenții RA nu vor fi distruși după ce au realizat un pas din procesul de fabricație, întrucât în momentul în care își termină de făcut treaba, ei devin disponibili pentru alte ordine de fabricație ce pot apărea.
Agenții TA nu se înscriu în paginile aurii, deoarece ei caută un furnizor al unui serviciu ce respectă un anumit șablon. Acest lucru se realizează conform următoarei secvențe de cod:
if(idf != null)
{
DFAgentDescription template = new DFAgentDescription();
SDF = new ServiceDescription[2];
ServiceDescription tempSDF = new ServiceDescription();
tempSDF.setType("Procesare_pas");
SDF[0] = tempSDF;
template.addServices(SDF[0]);
try {
DFAgentDescription[] result = DFService.search(myAgent, template);
/*dupa ce primeste prima cerere de contractare legata de serviciul publicat Ta va cere SDF stergerea serviciului*/
RAAgents.clear();
for (int i = 0; i < result.length; ++i) {
RAAgents.addElement(result[i].getName());
}
}
catch (FIPAException fe) {
fe.printStackTrace();
}
}
Secvență de cod 5.4.2 Căutare servicii în SDF
Când dorim să simulăm execuția procesului de fabricație, se va lansa în execuție platforma JADE cu agenții pe care noi îi creăm în linia de comandă a mediului de dezvoltare Eclipse, împreună cu cei trei agenți impliciți pe care îi prezintă această platformă ( ams,df,rma), prezentați in subcapitolele anterioare.
Având câte un agent RA din fiecare tip de celulă și un agent inițiator TA, în linia de comandă vom crea 6 agenți: 5 participanți și un inițiator.
Captură de ecran 5.4.1 Argumentele liniei de comandă
După aplicarea și lansarea în execuție a acestor argumente, se va deschide interfața grafică a platformei JADE.
Captură de ecran 5.4.2 Agenții creați în urma lansării în execuție a argumentelor
În acest moment, agenții creați sunt pregătiți să comunice și să interacționeze între ei, așteptând să primească date de la utilizator pe interfețele grafice corespunzătoare fiecărui tip de agent în parte care pornesc împreună cu interfața RMA.
Captură de ecran 5.4.3 Grafică propusă de utilizator
Prin această interfață grafică propusă de utilizator, se va monitoriza întregul proces de fabricație: procesul de contractare a pasului de fabricație dorit, procesul de negociere dintre agentul TA și agenții RA, și precesarea sistemului în funcție de studiul de caz propus.
Vom considera primul scenariu propus și anume: agentul TA are rol de inițiator, lansează o cerere de contractare ce are drept scop realizarea unui produs de un anumit tip. Agenții RA au rolul de participanți la licitație și doresc să li se ofere dreptul de a realiza la un moment-dat, pasul de fabricație propus de TA.
Captură de ecran 5.4.4 Trimiterea cererii de contractare(Inițiator) și publicarea ofertelor(Participanți)
În captura de ecran 5.4.4 am surprins crearea unui ordin de fabricație de realizare a unui produs de tip “Produs-2”, cu lista pașilor procesului: P2, P1, P4, P2, P4, P3, P5 și cu lista timpilor de execuție a pașilor: 15, 30, 40, 10, 40, 30, 60. De asemenea am surprins și agenții RA, fiecare din câte o celulă de fabricație. Astfel cererile de contractare oferite de către TA vor fi oferite în cazul nostru, pe rând, fiecăruia dintre agenții RA după cum urmează: prima cerere de contractare îi va fi oferită agentului “Participant2”, a doua cerere de contractare agentului “Participant1”, a treia agentului “Participant4” și așa mai departe.
Modalitatea prin care agentul TA realizează comunicarea cu agenții RA este următoarea: agenții RA se înscriu în paginile aurii cu un șablon care conține tipul serviciului pe care acesta îl oferă și numele pasului pe care îl poate realiza, agentul TA caută un serviciu cu un anumit șablon care conține tipul serviciului pe care îl dorește, și numele pasului pe care dorește să fie realizat. Dacă tipurile serviciillor și pasul oferite de RA se potrivesc cu tipul serviciului și pasul de procesare dorite de TA, se continuă cu procesul de negociere, dacă nu, agentul primește un mesaj de tipul REJECT_PROPOSAL.
5.4.1 Negocierea sub CNP
Cel mai simplu este să utilizăm mesaje de tip Call For Proposal (CFP) pentru ca agentul inițiator să transmită agentului participant o cerere de procesare. Mesajele de tip PROPOSE vor fi utilizate de către agenții participanți, atunci când oferta lor coincide cu cererea agentului inițiator. Mesajele de tip REFUSE vor fi utilizate tot de către agenții participanți atunci când oferta lor nu coincide cu cererea agentului inițiator. Agentul inițiator după ce primește de la RA un mesaj de tip PROPOSE, și termină de analizat dacă aceasta este oferta cea mai bună, trimite către RA mesaj de tip ACCEPT_PROPOSAL pentru a prelua cererea de procesare a pasului specificat.
Trimiterea unui mesaj de tip CFP se realizează după urmatorul șablon:
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
for (int i = 0; i < RAAgents.size(); ++i) {
cfp.addReceiver((AID)RAAgents.elementAt(i));
}
cfp.setContent(rez); //Ne intereseaza doar un anumit pas de fabricatie
cfp.setConversationId("Procesare_pas");
cfp.setReplyWith("cfp"+System.currentTimeMillis()); // Valoare unica
myAgent.send(cfp);
myGui.notifyUser("Se doreste efectuarea pasului "+rez+" cu timpul de executie "+tmp);
myGui.notifyUser("Am trimis propunerea de tip CFP catre "+RAAgents.size()+" agenti RA");
//Pregatim sablonul in care vom selecta doar ofertele ce ne intereseaza
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("Procesare_pas"),MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
Secvență de cod 5.4.1.1 Trimitere mesaj CFP
Pentru a trimite un mesaj de tip PROPOSE/REFUSE se folosește următoarea secvență de cod:
String name = msg.getContent();
ACLMessage reply= msg.createReply();
String step = (String) catalogue.get(name);
pas=step;
if(step != null)
{
reply.setPerformative(ACLMessage.PROPOSE);
reply.setContent(step);
}
myAgent.send(reply);
Secvență de cod 5.4.1.2 Trimitere mesaj de tip PROPOSE
În cazul mesajelor de tip REFUSE, în locul cuvântului PROPOSE ar fi fost REFUSE.
Pentru transmiterea mesajelor de tip ACCEPT_PROPOSAL se folosește următoarea secvență de cod:
if (bestOffer != null ) {
ACLMessage order = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
String e="";
order.addReceiver(bestOffer);
order.setContent(id);
order.setConversationId("Procesare_pas");
order.setReplyWith("order"+System.currentTimeMillis());
myAgent.send(order);
ReceptieMesaj();
ReceptieMesaj();
myGui.notifyUser("Trimitem: Accept Proposal catre: "+ bestOffer.getLocalName());
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("Procesare_pas"),MessageTemplate.MatchInReplyTo(order.getReplyWith()));
}
Secvență de cod 5.4.1.3 Trimitere mesaj de tip ACCEPT_PROPOSAL
În urma negocierii scenariului propus, avem următoarele rezultate:
După primul pas al negocierii, agentul Participant2 primește jobul de realizare a pasului P2, care este primul din lista pașilor, ceilalți agenți au primit REFUSE;
Captură de ecran 5.4.1.1 P2 a primit ACCEPT_PROPOSAL
Captură de ecran 5.4.1.2 P1 a fost refuzat, le fel ca toti ceilalți agenți
După al doilea pas al procesării, agentul Participan1 primește jobul de realizare al pasului P1, iar ceilalți agenți primesc REFUSE, și așa mai departe.
Urmărind lista pașilor ce trebuiesc realizați, putem să ne dăm seama ușor ce participant și când primește jobul de realizare al unui pas, întrucât numele sunt foarte sugestive.
Un al doilea scenariu propus, este acela al execuției unui ordin de fabricație cu două produse de orice tip și câte un agent din fiecare celulă. Aplicația funcționează dupa același principiu prezentat anterior, tot ceea ce se schimbă este lista pașilor de fabricație necesari și lista timpilor aferenți pașilor. Datorită faptului că sunt foarte greu de urmărit toți agenții, am surprins câteva momente din procesul de fabricație care urmează un astfel de scenariu.
Pentru un produs de tipul “Produs-1”:
Captură de ecran 5.4.1.3 Două produse de tipul “Produs-1”
Pentru un produs de tipul “Produs-2”:
Captură de ecran 5.4.1.4 Două produse de tipul “Produs-2”
Pentru un produs de tipul “Produs-2”:
Captură de ecran 5.4.1.5 Două produse de tipul “Produs-3”
Un al treilea scenariu propus, este acela în care se dorește execuția a două ordine de fabricație diferite, cu un produs de orice tip și câte un agent din fiecare celulă. Un astfel de scenariu, este de asemenea foarte greu de urmărit datorită numărului mare de interfețe grafice și al mesajelor ce trebuiesc urmărite cu atenție. De aceea, am surprins în următoarea captură de ecran, lucrul în paralel a doi agenți RA ce lucrează pentru două ordine de fabricație diferite. Primul ordin este de realizare a unui produs de tipul “Produs-1” și al doilea de realizare a unui produs de tipul “Produs-3”, agenții RA, P1 și P3, lucrează în paralel, P1 pentru “Produs-3”, iar P3 pentru “Produs-1”.
Captură de ecran 5.4.1.6 Două produse de tipuri diferite
În anii anteriori, a mai existat o abordare a acestei teme. Exista un agent inițiator TA și trei agenți participanți RA. Negocierea se realiza o singură dată, întrucât un agent RA însemna defapt un agent care știe să fabrice un anumit produs cap-coadă, și își manevra singur acea lista a pașilor care trebuiesc efectuați. Întrucât enunțul aplicației specifică faptul că fiecare RA reprezintă un anumit pas de fabricație, am implementat un cod care să realizeze acest lucru, fiecare agent în parte fiind capabil să își gestioneze singur execuția.
Capitolul 6. Concluzii
În cadrul acestei lucrări am reușit să realizez comunicarea între mai mulți agenți ce respectă standardul FIPA și negocierea între agentul inițiator TA și agenții participanți RA. Deși atunci când este creat, agentul TA primește întregul ordin de fabricație de la TAC, acesta știe cum să trimită cererea de contractare pentru fiecare pas de fabricație ce este necesar în procesarea acelui ordin de fabricație.
Platforma JADE prezintă atât avantaje cât și dezavantaje. Unul din marele avantaje este acela că poate executa sarcini complexe și paralele, întrucât se poate lucra cu fire de execuție. Agenții de asemenea pot avea comportamente complexe care să poată realiza diferite aplicații din domeniul industrial, și pot fi ușor de manevrat datorită lucrului cu interfețe grafice. Faptul că platforma JADE folosește standardul FIPA, oferă portabilitate și interoperabilitate, dar și simplitate în implementarea aplicațiilor, deoarece agenții platformei pot să comunice cu orice alt agent care se bazează pe acest standard.
Dezavantajul principal este acela că, în cazul în care în cadrul platformei sunt integrați un număr mare de agenți, simularea aplicației se realizează într-un timp mare din cauza numărului mare de mesaje transmise în cadrul rețelei.
Această lucrare permite îmbunătațiri în ceea ce privește reactivitatea sistemului de control multi-agent la căderea unui echipament (resursă). În caz de avarie sau de cădere a unei resurse, sistemul să țină evidența stării curente a procesării și poată gestiona replanificarea întregului process pe echipamentele disponibile prin realocarea dinamică a resurselor.
Capitoul 7 Bibliografie
F Bellifemine, G caire, D Greenwood, “ Developing Multi-Agent System with JADE”;
Java Agent Development Framework, http://www.jade.tulab.com/ ;
Agenți JADE , http://software.ucv.ro/~epopescu/teaching/DNAD/Tutorial%20agenti.pdf ;
Z Alibhai, B.A.Sc., “What is Contract Net Interaction Protocol?”, http://www2.ensc.sfu.ca/research/iDEA/courses/files/Contract%20Net%20Protocol1.pdf ;
Introducere in Java, http://thor.info.uaic.ro/~acf/java/curs/1/introducere.html ;
TEHNOLOGII JAVA PETRNU DEZVOLTAREA APLICAȚIILOR , http://inf.ucv.ro/~popirlan/java/laborator13.pdf ;
Buldum Alexandru, 2013, “Aplicație multi-agent, bazată pe servicii pentru alocarea dinamică a resurselor în procesele de fabricație. Implementare în platform JADE”.
ANEXE
Pachetul “DirectorServicii”
SDF.java
package DirectorServicii;
import java.util.Vector;
import jade.core.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import jade.wrapper.*;
import javax.swing.JOptionPane;
import ProceseFabricatie.AgentTask.*;
import ProceseFabricatie.AgentResursa.*;
// Contains methods to work with services
public class SDF
{
// Returns the AID of a service provider
// Registers a service on behalf of an agent
public static void requiring(String serviceName, Agent myAgent) throws FIPAException
{
// Register the service in the yellow pages
DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(myAgent.getAID());
ServiceDescription sd = new ServiceDescription();
sd.setType(serviceName);
sd.setName(serviceName);
dfd.addServices(sd);
DFService.register(myAgent, dfd);
}
// Deregisters a service on behalf of an agent
public static void removeJob(Agent myAgent)
{
try
{
DFService.deregister(myAgent);
}catch(FIPAException e){}
}
}
Pachetul “ProceseFabricatie.AgentResursa”
RAgui.java
package ProceseFabricatie.AgentResursa;
public interface RAgui {
void setAgent(RA a);
void show();
void hide();
void notifyUser(String message);
void notifyUserInt(int x);
void dispose();
}
RAguiImpl.java
package ProceseFabricatie.AgentResursa;
import jade.gui.TimeChooser;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.Date;
/**
This is the GUI of the agent that tries to sell books on behalf of its user
*/
public class RAguiImpl extends JFrame implements RAgui {
private RA myAgent;
//private JTextField titleTF, desiredPriceTF,minPriceTF;
private JTextField step, celula,timpProcesare;
private JButton sendB, resetB, exitB;
private JTextArea TextTA;
private JComboBox combo;
public void setAgent(RA a) {
myAgent = a;
setTitle(myAgent.getName());//setam titlul ferestrei
}
public RAguiImpl() {
super();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
myAgent.doDelete();
}
} );
JPanel containerPrincipal = new JPanel();
containerPrincipal.setLayout(new GridBagLayout());
containerPrincipal.setMinimumSize(new Dimension(330, 125));
containerPrincipal.setPreferredSize(new Dimension(330, 125));
JLabel l = new JLabel("pas-de-fabricatie");
l.setHorizontalAlignment(SwingConstants.LEFT);
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;//randul 0
gridBagConstraints.gridy = 0;//coloana 0
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;//textul aliniat in partea stanga
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
String ID[] = {"","P1","P2","P3","P4","P5"};
combo= new JComboBox(ID);
GridBagConstraints gridsBagConstraints = new GridBagConstraints();
gridsBagConstraints.gridx = 1;
gridsBagConstraints.gridy = 0;
gridsBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridsBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
combo.setBackground(Color.gray);
combo.setForeground(Color.black);
combo.setMinimumSize(new Dimension(100, 20));
containerPrincipal.add(combo,gridsBagConstraints);
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String str = (String)combo.getSelectedItem();
step.setText(str);
if(step.getText().equalsIgnoreCase("p1"))
{
celula.setText("celula 1");
}
else{
if(step.getText().equalsIgnoreCase("p2"))
{
celula.setText("celula 2");
}
else{
if(step.getText().equalsIgnoreCase("p3"))
{
celula.setText("celula 3");
}
else {
if(step.getText().equalsIgnoreCase("p4"))
{
celula.setText("celula 4");
}
else
{
celula.setText("celula 5");
}
}
}
}
}
});
step= new JTextField(7);
step.setMinimumSize(new Dimension(270, 20));
step.setPreferredSize(new Dimension(270, 20));//setam dimensiunea casutei in care introducem informatiile
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(step, gridBagConstraints);
l = new JLabel("celula-de-fabricatie: ");
l.setHorizontalAlignment(SwingConstants.LEFT);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
containerPrincipal.add(combo,gridsBagConstraints);
celula = new JTextField(7);
celula.setMinimumSize(new Dimension(100, 20));
celula.setPreferredSize(new Dimension(100, 20));
// idTF.setEnabled(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(celula, gridBagConstraints);
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
TextTA = new JTextArea();
TextTA.setEnabled(false);
TextTA.setDisabledTextColor(Color.RED);
TextTA.setFont(new Font("",Font.BOLD,12));
JScrollPane jsp = new JScrollPane(TextTA);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jsp.setMinimumSize(new Dimension(400, 270));
jsp.setPreferredSize(new Dimension(400, 280));
//jsp.setMininum
TextTA.setLineWrap(true);
TextTA.getCaret().setDot( TextTA.getText().length() );
jsp.scrollRectToVisible(TextTA.getVisibleRect() );
JPanel p = new JPanel();
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
p.add(jsp);
getContentPane().add(p, BorderLayout.CENTER);
setResizable(true);
p = new JPanel();
Font fontS = new Font("", Font.BOLD,13);
sendB = new JButton("Send");
sendB.setBackground(Color.GREEN);
sendB.setForeground(Color.DARK_GRAY);
sendB.setFont(fontS);
//la apasarea butonului "Send"
sendB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
//id ia valoarea trecuta in casuta
String id = step.getText();
String cell=celula.getText();
//cat timp id are o valoare
if (id != null && id.length() > 0) {
try {
notifyUser("Publicam oferta :\n Agentul realizeaza "+id+" si se afla in "+cell+"\n ");
myAgent.updateCatalogue(id,cell);
}
catch (Exception ex2) {
// Date invalide
JOptionPane.showMessageDialog(RAguiImpl.this, "Invalid values", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
else {
// No deadline specified
JOptionPane.showMessageDialog(RAguiImpl.this, "Nu s-a introdus pasul de fabricatie", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
}
);
resetB = new JButton("Reset");
resetB.setBackground(Color.ORANGE);
resetB.setForeground(Color.DARK_GRAY);
Font fontR = new Font("", Font.BOLD,13);
resetB.setFont(fontR);
resetB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
step.setText("");
celula.setText("");
}
} );
exitB = new JButton("Exit");
exitB.setForeground(Color.DARK_GRAY);
exitB.setBackground(Color.RED);
Font fontE = new Font("", Font.BOLD,13);
exitB.setFont(fontE);
exitB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
myAgent.doDelete();
}
} );
sendB.setPreferredSize(resetB.getPreferredSize());
exitB.setPreferredSize(resetB.getPreferredSize());
p.add(sendB);
p.add(resetB);
p.add(exitB);
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(p, BorderLayout.SOUTH); ////
// p.setBorder(new TitledBorder(""));
pack();
setResizable(true);
}
public void notifyUser(String message) {
TextTA.append(message+"\n");
}
@Override
public void notifyUserInt(int x) {
TextTA.append(x+"\n");
}
}
RA.java
package ProceseFabricatie.AgentResursa;
import ProceseFabricatie.AgentTask.TA;
import DirectorServicii.SDF;
import jade.content.ContentElement;
import jade.content.onto.basic.Action;
import jade.content.onto.basic.Result;
import java.lang.Thread.*;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.*;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.util.leap.ArrayList;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import java.text.NumberFormat;
import java.util.*;
@SuppressWarnings("all")
public class RA extends Agent
{
private Hashtable catalogue;
private Vector RAAgent=new Vector();
private RAgui myGui;
public int startTime=0;
public String listProcess,timeProcess;
private AID TAAgent;
protected ServiceDescription[] SDF;
public static String q_ty;
static long timpProces;
public String pas,produs;
String Initiator;
public String tip_produs;
public int contor1=0,contor2=0,contor3=0,contor4=0;
public String pas_propriu;
boolean sfarsit=false;
int VarTempProdCel=0;
long moment_disponibilitate=0;//cand Ra devine liber, trebuie trimis catre TA
int timp_procesare_curent=0;
int cantitate;
String Cantitate;
int timp;
public void setQty(String qty){
this.q_ty=qty;
}
/* initializam agentul
* */
protected void setup()
{ //opening the user interface
catalogue=new Hashtable();
myGui =new RAguiImpl();
myGui.setAgent(this);
myGui.show();
//we register the agent in the yellow pages
DFAgentDescription dfd =new DFAgentDescription();
dfd.setName(getAID());
ServiceDescription sd= new ServiceDescription();
sd.setType("Procesare_pas");
sd.setName(getLocalName()+"Procesare_pas");
dfd.addServices(sd);
try {
DFService.register(this,dfd);
}
catch (FIPAException fe)
{
fe.printStackTrace();
}
//Add the behaviour serving queries from RA agents
addBehaviour(new handleBidCFP());
//add the behaviour serving purchase orders from TA agents
addBehaviour(new handleBidProposal());
System.out.println("Agent RA: " + getAID().getName()+ " is ready.");
//primim numele agentilor ca si argument
Object[] args = getArguments();
if(args != null && args.length > 0)
{
for( int i=0; i<args.length; ++i)
{
AID procesare_pas = new AID((String) args[i], AID.ISLOCALNAME);
RAAgent.addElement(procesare_pas);
}
}
}
protected void takeDown()
{
//we don't deregister from yellow pages because we need all the time the agents, and if an agent finished
//his work, he can start to do a step from another fabrication system
//we are not closing either, because of the same reason
System.out.println(getAID().getName()+" terminated his work");
}
public void updateCatalogue(final String name, final String cell)
{
addBehaviour(new OneShotBehaviour() {
public void action()
{
catalogue.put(name,cell);
System.out.println(name+" Inserted into catalogue. He is from "+cell);
}
});
}
private class handleBidCFP extends CyclicBehaviour {
public void action()
{
MessageTemplate mt= MessageTemplate.MatchPerformative(ACLMessage.CFP);
ACLMessage msg = myAgent.receive(mt);
if(msg != null)
{ //ACCEPT_PROPOSAL Message received. Process it
String name = msg.getContent();
ACLMessage reply= msg.createReply();
String step = (String) catalogue.get(name);
pas=step;
if(step != null)
{
reply.setPerformative(ACLMessage.PROPOSE);
reply.setContent(step);
}
myAgent.send(reply);
myGui.notifyUser(step != null ? "\nCererea de contractare "+name+" coincide cu oferta lansata de de "+getName()+"\nPropunem (PROPOSE) oferta proprie de contractare a pasului: "+ "\n\t"+name+"\n": " \nCererea de contractare "+name+" nu coincide cu propunerea"+"\n de contractare a "+getName()+"\nCererea de contractare a fost refuzata: "+"\tREFUSE");
}
else{
block();
}
}
}
private class handleBidProposal extends CyclicBehaviour{
public void action()
{MessageTemplate mt=MessageTemplate.MatchPerformative(ACLMessage.ACCEPT_PROPOSAL);
ACLMessage msg=myAgent.receive(mt);
if(msg != null)
{ //ACCEPT_PROPOSAL
String name = msg.getContent();
produs=name;
ACLMessage reply = msg.createReply();
switch (pas){
case "celula 1": pas="P1";
break;
case "celula 2": pas="P2";
break;
case "celula 3": pas="P3";
break;
case "celula 4": pas="P4”;
break;
case "celula 5": pas="P5";
break;
}
reply.setContent(pas);
reply.setPerformative(ACLMessage.INFORM);
TAAgent=msg.getSender();
myGui.notifyUser("Am primit mesaj de tip: ACCEPT_PROPOSAL");
myGui.notifyUser(pas+ " va fi procesat pentru : "+ msg.getSender().getName());
myAgent.send(reply);
addBehaviour(new ProcesarePas(myAgent,name));
}
else {
block();
}
}
}
private class ProcesarePas extends Behaviour{
public String name;
public String Cantitate1;
ProcesarePas(Agent a,String nume)
{
super(a);
this.name=nume;
}
public void PrimireMesaj()
{
ACLMessage qty= myAgent.receive();
if(qty!=null)
{
Cantitate=qty.getContent();
cantitate=Integer.parseInt(Cantitate);
myGui.notifyUser("cantitatea dorita "+cantitate);
}
}
public void Transport(int timp1,String celula_trecuta,String celula_proprie)
{ long start1=System.currentTimeMillis();
int timp2=timp1*200;
try{
myGui.notifyUser("Se transporta piesa de la "+celula_trecuta+" la "+celula_proprie);
Thread.sleep(timp2);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end1= System.currentTimeMillis();
long timp_transport=(end1-start1)/200;
myGui.notifyUser("S-a transportat piesa la "+celula_proprie);
}
public void DurataDeProcesare(int timp1,String tip_produs,String pas_propriu)//cum fac sa primesc Timp precum parametru de la TA?
{
// cantitate=cnt;
//timp=cnt*timp1*1000;
timp=timp1*200;
long start = System.currentTimeMillis();
moment_disponibilitate=start+timp1;
System.out.println("valoare de start: "+start);
try {
myGui.notifyUser("Incepe procesarea pasului "+pas_propriu+" al produsului "+tip_produs+" pentru +cnt+ produse pentru un timp de "+timp/200+" secunde/5");
Thread.sleep(timp);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("valoare de sfarsit: "+end);
long timp_procesare=(end-start)/200;
System.out.println("timp procesare= "+(end-start)/200);
myGui.notifyUser("Procesarea pasului "+pas_propriu+" pentru "+tip_produs+" pentru +cnt+ produse terminata dupa "+timp_procesare+" secunde.");
}
public void TrimiteMesaj(String inform)
{
ACLMessage done= new ACLMessage(ACLMessage.INFORM);
done.addReceiver(TAAgent);
done.setContent(inform);
myAgent.send(done);
}
public void action()
{
tip_produs=produs;
pas_propriu=pas;
switch(tip_produs){
case "Produs-1": switch(pas_propriu){
case "P1": PrimireMesaj(); timp_procesare_curent=45; Transport(3,"depozit","celula1"); DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu); TrimiteMesaj("Procesare Terminata in celula 1") TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P2": PrimireMesaj(); timp_procesare_curent=10; Transport(3,"celula1","celula2"); DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 2");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P3": PrimireMesaj(); timp_procesare_curent=80; Transport(3,"celula2","celula3"); DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 3");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P4": PrimireMesaj();
timp_procesare_curent=20;
Transport(3,"celula3","celula4");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 4");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P5": PrimireMesaj();
timp_procesare_curent=60;
Transport(3,"celula4","celula5");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 5");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Transport(3,"celula5","depozit2");
break;
}
sfarsit=true;
break;
case "Produs-2": switch(pas_propriu){
case "P1": PrimireMesaj();
timp_procesare_curent=30;
Transport(3,"celula2","celula1");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 1");
TrimiteMesaj("rezultatul dorit a fost obtinut ");
break;
case "P2": contor2++;
myGui.notifyUser("contor2 are valoarea: "+contor2);
PrimireMesaj();
if(cantitate==0)
{
timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
if(cantitate==1)
{if(contor2==1)
{timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
else
{ timp_procesare_curent=10;
Transport(3,"celula4","celula2");
}}
if(cantitate==2)
{
if(contor2==1 || contor2==2)
{
timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
else {
timp_procesare_curent=10;
Transport(3,"celula4","celula2");
}
}
if(cantitate==3)
{
if(contor2==1 || contor2==2 || contor2==3)
{timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
else {
timp_procesare_curent=10;
Transport(3,"celula4","celula2");
}
}
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 2");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P3": PrimireMesaj();
timp_procesare_curent=30;
Transport(3,"celula4","celula3");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 3");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Break;
case "P4": PrimireMesaj();
contor4++;
timp_procesare_curent=40;
if(cantitate==1)
{
if(contor4==1)
{
Transport(3,"celula1","celula4");
}
else
{
Transport(3,"celula2","celula4");
}
}
if(cantitate==2)
{
if(contor4==1 || contor4==2)
{Transport(3,"celula1","celula4");
}
else
{Transport(3,"celula2","celula4");
}
}
if(cantitate==3)
{
if(contor4==1 || contor4==2 || contor4==3)
{
Transport(3,"celula1","celula4");
}
else
{
Transport(3,"celula2","celula4");
}
}
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 4");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P5": PrimireMesaj();
timp_procesare_curent=60;
Transport(3,"celula3","celula5");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 5");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Transport(3,"celula5","depozit");
break;
}
sfarsit=true;
break;
case "Produs-3": switch(pas_propriu){
case "P1": PrimireMesaj();
contor1++;
if (cantitate==0)
timp_procesare_curent=10;
if(cantitate==1)
{
if(contor1==1)
timp_procesare_curent=10;
else
timp_procesare_curent=30;
}
if(cantitate==2)
{ if(contor1==1|| contor1==2)
timp_procesare_curent=10;
else
timp_procesare_curent=30;
}
if(cantitate==3)
{if(contor1==1 || contor1==2 || contor1==3)
timp_procesare_curent=10;
else
timp_procesare_curent=30;
}
Transport(3,"celula3","celula1");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 1");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P3": PrimireMesaj();
contor3++;
if(cantitate==0)
{
timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
if(cantitate==1)
{if(contor3==1)
{ timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
else
{ timp_procesare_curent=20;
Transport(3,"celula4","celula3");
}
}
if(cantitate==2)
{if(contor3==1 || contor3==2)
{ timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
else
{ timp_procesare_curent=20;
Transport(3,"celula4","celula3");
}
}
if(cantitate==3)
{if(contor3==1 ||contor3==2 || contor3==3)
{ timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
else
{ timp_procesare_curent=20;
Transport(3,"celula4","celula3");
}
}
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 3");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P4": PrimireMesaj();
timp_procesare_curent=70;
Transport(3,"celula1","celula4");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 4");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P5": PrimireMesaj();
timp_procesare_curent=30;
Transport(3,"celula1","celula5");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 5");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Transport(3,"celula5","depozit");
break;
}
sfarsit=true;
break;
}
}
public boolean done()
{
return sfarsit;
}
}
}
Pachetul “ProceseFabricatie.AgentTask”
TACgui.java
package ProceseFabricatie.AgentTask;
import ProceseFabricatie.AgentResursa.RA;
public interface TACgui {
void setAgent(TA a);
// void setAgent(TA1 a);
void show();
void hide();
void notifyUser(String message);
void notifyUserInt(int x);
void dispose();
}
TAC.java
package ProceseFabricatie.AgentTask;
import jade.gui.TimeChooser;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.Date;
@SuppressWarnings("all")
public class TAC extends JFrame implements TACgui {
private TA agentulMeu;
//private TA1 agentulMeu1;
private JTextField idTF, cantitateDoritaTF, dataLimitaTF,deadlineTF,lista_proceselor, lista_timpilor,maxDelayTF;
private JButton sendB, resetB, exitB, allertB;
private JTextArea logTA;
private JComboBox combo,combo1;
int contorTA=0;
public TAC() {
super();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
agentulMeu.doDelete();
}
} );
JPanel containerPrincipal = new JPanel();
//containerPrincipal.setBackground(Color.white);
containerPrincipal.setLayout(new GridBagLayout());
containerPrincipal.setPreferredSize(new Dimension(100, 140));
JLabel l = new JLabel("Produs");
// l.setHorizontalAlignment(SwingConstants.LEFT);
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
///
String ID[] = {"","Produs-1","Produs-2","Produs-3"};
combo = new JComboBox(ID);
GridBagConstraints gridsBagConstraints = new GridBagConstraints();
gridsBagConstraints.gridx = 1;
gridsBagConstraints.gridy = 0;
gridsBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridsBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
combo.setBackground(Color.gray);
combo.setForeground(Color.black);
combo.setMinimumSize(new Dimension(100, 20));
containerPrincipal.add(combo,gridsBagConstraints);
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String str = (String)combo.getSelectedItem();
idTF.setText(str);
}
});
idTF = new JTextField(15);
idTF.setMinimumSize(new Dimension(100, 20));
idTF.setPreferredSize(new Dimension(100, 20));
// idTF.setEnabled(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(idTF, gridBagConstraints);
l = new JLabel("Numar produse");
l.setHorizontalAlignment(SwingConstants.LEFT);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
String ID1[] = {"","1","2","3"};
combo1 = new JComboBox(ID1);
gridsBagConstraints = new GridBagConstraints();
gridsBagConstraints.gridx = 1;
gridsBagConstraints.gridy = 1;
gridsBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridsBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
combo1.setBackground(Color.gray);
combo1.setForeground(Color.black);
combo1.setMinimumSize(new Dimension(100, 20));
containerPrincipal.add(combo1,gridsBagConstraints);
combo1.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String cant = (String)combo1.getSelectedItem();
cantitateDoritaTF.setText(cant);
if(idTF.getText().equalsIgnoreCase("Produs-1"))
{if(cantitateDoritaTF.getText().equalsIgnoreCase("1"))
{lista_proceselor.setText("P1,P2,P3,P4,P5");
lista_timpilor.setText("45,10,80,20,60");
}
else
{
if(cantitateDoritaTF.getText().equalsIgnoreCase("2"))
{
lista_proceselor.setText("P1,P1,P2,P2,P3,P3,P4,P4,P5,P5");
lista_timpilor.setText("45,45,10,10,80,80,20,20,60,60");
}
else
{
lista_proceselor.setText("P1,P1,P1,P2,P2,P2,P3,P3,P3,P4,P4,P4,P5,P5,P5");
lista_timpilor.setText("45,45,45,10,10,10,80,80,80,20,20,20,60,60,60");
}
}
}
else{
if(idTF.getText().equalsIgnoreCase("Produs-2"))
{if(cantitateDoritaTF.getText().equalsIgnoreCase("1"))
{lista_proceselor.setText("P2,P1,P4,P2,P4,P3,P5");
lista_timpilor.setText("15,30,40,10,40,30,60");
}
else{ if(cantitateDoritaTF.getText().equalsIgnoreCase("2"))
{
lista_proceselor.setText("P2,P2,P1,P1,P4,P4,P2,P2,P4,P4,P3,P3,P5,P5");
lista_timpilor.setText("15,15,30,30,40,40,10,10,40,40,30,30,60,60");
}
else{
lista_proceselor.setText("P2,P2,P2,P1,P1,P1,P4,P4,P4,P2,P2,P2,P4,P4,P4,P3,P3,P3,P5,P5,P5"); lista_timpilor.setText("15,15,15,30,30,30,40,40,40,10,10,10,40,40,40,30,30,30,60,60,60");
}
}
}
else {
if(cantitateDoritaTF.getText().equalsIgnoreCase("1"))
{lista_proceselor.setText("P3,P1,P4,P3,P1,P5");
lista_timpilor.setText("30,10,70,20,30,40");
}
else
{ if(cantitateDoritaTF.getText().equalsIgnoreCase("2" {
lista_proceselor.setText("P3,P3,P1,P1,P4,P4,P3,P3,P1,P1,P5,P5"); lista_timpilor.setText("30,30,10,10,70,70,20,20,30,30,40,40");
} else{lista_proceselor.setText("P3,P3,P3,P1,P1,P1,P4,P4,P4,P3,P3,P3,P1,P1,P1,P5,P5,P5"); lista_timpilor.setText("30,30,30,10,10,10,70,70,70,20,20,20,30,30,30,40,40,30");
}
}
}
}
}
});
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
cantitateDoritaTF = new JTextField(15);
cantitateDoritaTF.setMinimumSize(new Dimension(100, 20));
cantitateDoritaTF.setPreferredSize(new Dimension(100, 20));
cantitateDoritaTF.setEnabled(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(cantitateDoritaTF, gridBagConstraints);
l = new JLabel(" Lista Proces:");
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setMinimumSize(new Dimension(100, 20));
l.setPreferredSize(new Dimension(100, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;//coloana 0
gridBagConstraints.gridy = 3;//randul 3
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
containerPrincipal.add(l, gridBagConstraints);
lista_proceselor = new JTextField(50);
lista_proceselor.setMinimumSize(new Dimension(120, 20));
lista_proceselor.setPreferredSize(new Dimension(120, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(lista_proceselor, gridBagConstraints);
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
l = new JLabel(" Lista Timpilor:");
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setMinimumSize(new Dimension(100, 20));
l.setPreferredSize(new Dimension(100, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;//coloana 0
gridBagConstraints.gridy = 5;//randul 5
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
containerPrincipal.add(l, gridBagConstraints);
lista_timpilor = new JTextField(50);
lista_timpilor.setMinimumSize(new Dimension(120, 20));
lista_timpilor.setPreferredSize(new Dimension(120, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 5;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(lista_timpilor, gridBagConstraints);
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
logTA = new JTextArea();
logTA.setEnabled(false);
logTA.setDisabledTextColor(Color.black);
logTA.setFont(new Font("",Font.BOLD,12));
JScrollPane jsp = new JScrollPane(logTA);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jsp.setMinimumSize(new Dimension(400, 270));
jsp.setPreferredSize(new Dimension(400, 280));
logTA.setLineWrap(true);
logTA.getCaret().setDot( logTA.getText().length() );
jsp.scrollRectToVisible(logTA.getVisibleRect() );
JPanel p = new JPanel();
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
p.add(jsp);
getContentPane().add(p, BorderLayout.CENTER);
p = new JPanel();
//Buton "SEND"
sendB = new JButton("Send");
sendB.setBackground(Color.green);
sendB.setForeground(Color.DARK_GRAY);
Font fontS = new Font("", Font.BOLD,13);
sendB.setFont(fontS);
sendB.addActionListener(new ActionListener(){
//la apasarea butonului SEND se vor salva datele din casute
public void actionPerformed(ActionEvent e) {
String id = idTF.getText();
int q_ty=-1;
String listTime ;
String listProcess;
//doar daca id-ul pentru ordinul de fabricatie a fost introdus
if (id != null && id.length() > 0) {
try {
//salvam datele din casute
q_ty=Integer.parseInt(cantitateDoritaTF.getText()); listProcess=(String)(lista_proceselor.getText());
listTime=(String)(lista_timpilor.getText());
agentulMeu.createTA(id,q_ty,listProcess,listTime);
notifyUser("Ordin de fabricatie: "+id+"\n se doreste efectuarea pasilor: "+listProcess+"\n cu lista timpilor de procesare: "+listTime+"\n cantitate: "+q_ty+" produs(e)\n");
}
catch (Exception ex1) {
// Eroare valori
JOptionPane.showMessageDialog(TAC.this, "Eroare!Utilizati valori numerice", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
else {
// Nu s-a completat casuta cu ordinul de fabricatie
JOptionPane.showMessageDialog(TAC.this, "Eroare: Introduceti ordinul de fabricatie", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
}
);
//Buton de RESET
resetB = new JButton("Reset");
resetB.setBackground(Color.orange);
resetB.setForeground(Color.DARK_GRAY);
Font fontR = new Font("", Font.BOLD,13);
resetB.setFont(fontR);
resetB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
idTF.setText("");
cantitateDoritaTF.setText("");
lista_proceselor.setText("");
lista_timpilor.setText("");
}
} );
//Buton "EXIT"
exitB = new JButton("Exit");
exitB.setBackground(Color.red);
exitB.setForeground(Color.DARK_GRAY);
Font fontE = new Font("", Font.BOLD,13);
exitB.setFont(fontE);
//la apasarea butonului agentul va fi sters
exitB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
agentulMeu.doDelete();
}
} );
//Buton "Alert"
ImageIcon redButton=new ImageIcon("images/red-button.jpg");
allertB=new JButton(redButton);
p.add(sendB);
p.add(resetB);
p.add(exitB);
//butoanele sunt aranjate in partea de jos
getContentPane().add(p, BorderLayout.SOUTH);
pack();
setResizable(true);
//fereastra nu va avea dimensiune fixa
}
public void setAgent(TA a) {
agentulMeu = a;
setTitle(agentulMeu.getName());
}
//
public void notifyUser(String message) {
logTA.append(message+"\n");
}
public void notifyUserInt(int x)
{
logTA.append(x+"\n");
}
}
TA.java
package ProceseFabricatie.AgentTask;
import DirectorServicii.SDF;
import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import java.util.Vector;
import java.util.Date;
import jade.content.lang.Codec.CodecException;
@SuppressWarnings("all")
/**
Clasa TA
**/
public class TA extends Agent{
//Lista cu agentii RA care asigura servicii de fabricatie
private Vector RAAgents = new Vector();
private Vector RATransport=new Vector();
public String idf;
private AID[] RA;
//Interfata GUI ce interactioneaza cu userul
private TAC myGui;
protected ServiceDescription[]SDF;
private MessageTemplate mt;
int contorPasi=0;
private UpdateManager manager;
String sirproces;
String sirtimp;
int lungime;
int contorL=0;
int j=0;
String ultimulMesaj1="";
/**
* Initializarea agentului
**/
protected void setup() {
// Printam un mesaj
System.out.println("Agent TA: "+getAID().getName()+" este pregatit.");
//Salvam numele agentilor ce au fost introdusi in linia de comanda
Object[] args = getArguments();
if (args != null && args.length > 0) {
for (int i = 0; i < args.length; ++i) {
AID mRA = new AID((String) args[i], AID.ISLOCALNAME);
RAAgents.addElement(mRA);
}
}
// Pornim interfata grafica
myGui = new TAC();
myGui.setAgent(this);
myGui.show();
// RegisterService();
}
/**
* Urmatorul cod ne va ajuta sa cautam la fiecare 20 de secunde, agentii disponibili
* fabricarii produselor.
* TA trimite o cerere de realizare a primului pas de fabricatie, necesar in
* obtinerea unui produs solicitat, catre SDF
**/
/**
* Distrugerea agentilor
**/
protected void takeDown() {
if (myGui != null) {
myGui.dispose();
}
System.out.println("Agentul TA "+getAID().getName()+" a fost distrus");
}
//porneste un agent task pentru un ordin fabricatie nou primit de la ERP
public void createTA(String id,int cantitate,String listProcess,String listTime)
{ idf=id;
/*trimitem o cerere de realizare a primului pas de fabricatie,
necesar in obtinerea unui produs solicitat, catre SDF*/
addBehaviour(new JobToRA(this));
/* contractul va fi acordat RA ce a depus cererea cea mai avantajoasa,
conform unui mecanism de acordare de tip CNP */
addBehaviour(new UpdateManager(this,id,cantitate,listProcess,listTime));
}
private class JobToRA extends TickerBehaviour{
double t1 = System.currentTimeMillis();
private JobToRA (Agent a){
super(a,1000); //timpul de asteptare
}
public void onTick() {
/* TA trimite o cerere de realizare a primului pas de fabricatie,necesar in obtinerea unui produs solicitat catre SDF.Agentul nostru se va axa doar pe agentii care sunt participanti la procesul de negociere*/
if(idf != null)
{
DFAgentDescription template = new DFAgentDescription();
SDF = new ServiceDescription[2];
ServiceDescription tempSDF = new ServiceDescription();
tempSDF.setType("Procesare_pas");
SDF[0] = tempSDF;
template.addServices(SDF[0]);
try {
DFAgentDescription[] result = DFService.search(myAgent, template);
/*dupa ce primeste prima cerere de contractare legata de serviciul publicat Ta va cere SDF stergerea serviciului*/
RAAgents.clear();
for (int i = 0; i < result.length; ++i) {
RAAgents.addElement(result[i].getName());
}
}
catch (FIPAException fe) {
fe.printStackTrace();
}
}
}//de la functia onTick
}//de la clasa JobToRA
public void publishJob(String sms){
DFAgentDescription template = new DFAgentDescription();
SDF = new ServiceDescription[5];
ServiceDescription tempSDF = new ServiceDescription();
tempSDF.setType(sms);
SDF[0] = tempSDF;
template.addServices(SDF[0]);
try {
DFAgentDescription[] result = DFService.search(this, template);
/*dupa ce primeste prima cerere de contractare legata de serviuciul publicat
Ta va cere SDF stergerea serviciului*/
RAAgents.clear();
for (int i = 0; i < result.length; ++i) {
RAAgents.addElement(result[i].getName());
}
}
catch (FIPAException fe) {
fe.printStackTrace();
}
}
public class UpdateManager extends TickerBehaviour {
public String id;
public int q_ty;
public String listProcess;
public String listTime;
int end=0;
private int period;
public void setFixedPeriod(boolean fixedPeriod)
{
fixedPeriod=false;
}
/*protected long getPeriod(String lTime)
{
perioadai= Integer.parseInt(lTime.substring(0,2));
return perioadai;
}*/
void setari(String lTime)
{
period= Integer.parseInt(lTime.substring(0,2));
setFixedPeriod(false);
}
public UpdateManager(Agent a, String ID, int cantitate,String lProcess,String lTime) {
super(a,12000);
id = ID;
q_ty = cantitate;
listProcess=lProcess;
listTime=lTime;
contorPasi++;
}
public void ReceptieMesaj1()
{
ACLMessage done4=myAgent.receive();
if(done4 != null)
{
ultimulMesaj1 = done4.getContent();
//System.out.println("mesajul ce a ajuns de la "+done3.getSender().getName()+" este "+ultimulMesaj);
myGui.notifyUser(ultimulMesaj1);
}
}
public void onTick() {
if(listProcess!=null){
if(contorL <= (listProcess.length())/3)
{
if(contorL==0)
{
sirproces=listProcess;
sirtimp=listTime;
System.out.println("lista proceselor: "+sirproces);
System.out.println("lista timpilor: "+sirtimp);
}
else
{ sirproces=sirproces.substring(3);
sirtimp=sirtimp.substring(3);
System.out.println("lista proceselor: "+sirproces);
System.out.println("lista timpilor: "+sirtimp);
}
myAgent.addBehaviour(new handleService(id,q_ty,sirproces,sirtimp,this));
contorL++;
}
else
{ myGui.notifyUser("Procesare terminata in celula 5");
myGui.notifyUser("rezultatul dorit a fost obtinut");
myGui.notifyUser("Produsul a fost fabricat");
end=1;
manager.stop();
}
}
}
}
/**
* Cererile de contractare sunt evaluate si contractul va fi acordat RA ce a depus
* cererea cea mai avantajoasa conform unui mecanism de acordare de tip CNP
* ce presupune urmatorul protocol(TA-initiator, RA-urile -participanti)
**/
private class handleService extends Behaviour {
private String id;
private String listTime;
private int q_ty;
private String listProcess;
private AID bestOffer; // Agentul ofertant care vine cu cea mai buna oferta
private int bestTimeProcess;// cea mai rentabila oferta va fi cu timpul de procesare mai redus
private int req_qty;// cantitatea ceruta
private int repliesCnt = 0; // un numarator pentru agentii RA
// un sablon pentru a primi doar mesajele ce ne intereseaza
private boolean sfarsit = false;
private int step=0;
public int contor=0;
String ultimulMesaj;
public handleService(String ID,int qty,String procese,String timpi,UpdateManager m)
{
super(null);
id = ID;
listTime = timpi;
q_ty=qty;
listProcess=procese;
manager = m;
}
public void ReceptieMesaj()
{
ACLMessage done3=myAgent.receive();
if(done3 != null)
{
ultimulMesaj = done3.getContent();
}
}
public void action() {
String rez=listProcess.substring(0,2);
String tmp=listTime.substring(0,2);
switch(step)
{
case 0:
// Trimitem catre agentii RA un call for proposal(CFP)
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
for (int i = 0; i < RAAgents.size(); ++i) {
cfp.addReceiver((AID)RAAgents.elementAt(i));
}
cfp.setContent(rez); //Ne intereseaza doar un anumit pas de fabricatie
cfp.setConversationId("Procesare_pas");
cfp.setReplyWith("cfp"+System.currentTimeMillis()); // Valoare unica
myAgent.send(cfp);
myGui.notifyUser("Se doreste efectuarea pasului "+rez+" cu timpul de executie "+tmp);
myGui.notifyUser("Am trimis propunerea de tip CFP catre "+RAAgents.size()+" agenti RA");
//Pregatim sablonul in care vom selecta doar ofertele ce ne intereseaza
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("Procesare_pas"),MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
step=1;
break;
case 1:
//Primim toate propunerile/refuzurile de la agentii RA
ACLMessage reply = myAgent.receive(mt);
if (reply != null) {
// Am primit raspunsul
if (reply.getPerformative() == ACLMessage.PROPOSE) {
// Avem oferta de la agentul RA
String PasProcesare = (String) (reply.getContent());
myGui.notifyUser("Am primit o cerere de contractare de la: " +reply.getSender().getLocalName()+"\n cu urmatoarele informatii aferente job-ului\n"+PasProcesare+" .\n");
if(bestOffer==null)
{
bestTimeProcess=Integer.parseInt(tmp);
//selectam cea mai buna oferta
bestOffer = reply.getSender();
}
}
repliesCnt++;
if (repliesCnt >= RAAgents.size()) {
// Am primit toate raspunsurile. Nu mai exista in acest moment agenti RA
step = 2;
}
}
else {
block();
}
break;
case 2:
//verificam daca cea mai buna oferta trimisa de participant
//se incadreaza in cerintele impuse ce catre initiator
if (bestOffer != null ) {
//Se trimite un mesaj de acceptare agentului care a venit cu cea mai buna oferta
ACLMessage order = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
String e="";
order.addReceiver(bestOffer);
order.setContent(id);
order.setConversationId("Procesare_pas");
order.setReplyWith("order"+System.currentTimeMillis());
myAgent.send(order);
ReceptieMesaj();
ReceptieMesaj();
myGui.notifyUser("Trimitem: Accept Proposal catre: "+ bestOffer.getLocalName());
//Se pregateste sablonul pentru a primi raspunul
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("Procesare_pas"),MessageTemplate.MatchInReplyTo(order.getReplyWith()));
step = 3;
}
else {
// Daca nu se primeste nicio propunere acceptata, agentii se distrug
step =7;
break;
}
myGui.notifyUser("\n Ceilalti agenti intrati la licitatie au primit"+" Reject-Proposal");
break;
case 3:
// Participantul care a primit de realizat task-ul trimite catre TA
// un mesaj de informare
reply = myAgent.receive(mt);
if (reply != null) {
// Ordinul de fabricatie a fost receptionat
if (reply.getPerformative() == ACLMessage.INFORM) {
myGui.notifyUser("Licitatia s-a incheiat.Avem urmatoarele informatii\n\tCastigatorul licitatiei este:"+reply.getSender().getLocalName()+"\n\tProdusul ce va fi fabricat: "+id+"\n\tPasul de fabricatie: "+reply.getContent()+"\n\tLot de productie: "+q_ty+" produse");
}
step = 4;
}
else {
block();
}
break;
case 4:
System.out.println("se doreste realizarea a "+q_ty+" produse");
ACLMessage request = new ACLMessage(ACLMessage.INFORM);
request.addReceiver(bestOffer);
request.setContent(Integer.toString(q_ty));
request.setConversationId("Pocesare_pas");
request.setReplyWith("prelucrare"+System.currentTimeMillis());
myAgent.send(request);
myGui.notifyUser("Cerem agentului "+bestOffer+" inceperea procesarii pasului "+rez);
step=5;
break;
case 5:
myGui.notifyUser("Incepe procesarea pasului "+rez+" cu timpul de executie "+tmp+".");
step=6;
break;
case 6:
step=7;
break;
} //sfarsit switch
}
public boolean done() {
return step==7;
}
}
}
Bibliografie
F Bellifemine, G caire, D Greenwood, “ Developing Multi-Agent System with JADE”;
Java Agent Development Framework, http://www.jade.tulab.com/ ;
Agenți JADE , http://software.ucv.ro/~epopescu/teaching/DNAD/Tutorial%20agenti.pdf ;
Z Alibhai, B.A.Sc., “What is Contract Net Interaction Protocol?”, http://www2.ensc.sfu.ca/research/iDEA/courses/files/Contract%20Net%20Protocol1.pdf ;
Introducere in Java, http://thor.info.uaic.ro/~acf/java/curs/1/introducere.html ;
TEHNOLOGII JAVA PETRNU DEZVOLTAREA APLICAȚIILOR , http://inf.ucv.ro/~popirlan/java/laborator13.pdf ;
Buldum Alexandru, 2013, “Aplicație multi-agent, bazată pe servicii pentru alocarea dinamică a resurselor în procesele de fabricație. Implementare în platform JADE”.
ANEXE
Pachetul “DirectorServicii”
SDF.java
package DirectorServicii;
import java.util.Vector;
import jade.core.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import jade.wrapper.*;
import javax.swing.JOptionPane;
import ProceseFabricatie.AgentTask.*;
import ProceseFabricatie.AgentResursa.*;
// Contains methods to work with services
public class SDF
{
// Returns the AID of a service provider
// Registers a service on behalf of an agent
public static void requiring(String serviceName, Agent myAgent) throws FIPAException
{
// Register the service in the yellow pages
DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(myAgent.getAID());
ServiceDescription sd = new ServiceDescription();
sd.setType(serviceName);
sd.setName(serviceName);
dfd.addServices(sd);
DFService.register(myAgent, dfd);
}
// Deregisters a service on behalf of an agent
public static void removeJob(Agent myAgent)
{
try
{
DFService.deregister(myAgent);
}catch(FIPAException e){}
}
}
Pachetul “ProceseFabricatie.AgentResursa”
RAgui.java
package ProceseFabricatie.AgentResursa;
public interface RAgui {
void setAgent(RA a);
void show();
void hide();
void notifyUser(String message);
void notifyUserInt(int x);
void dispose();
}
RAguiImpl.java
package ProceseFabricatie.AgentResursa;
import jade.gui.TimeChooser;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.Date;
/**
This is the GUI of the agent that tries to sell books on behalf of its user
*/
public class RAguiImpl extends JFrame implements RAgui {
private RA myAgent;
//private JTextField titleTF, desiredPriceTF,minPriceTF;
private JTextField step, celula,timpProcesare;
private JButton sendB, resetB, exitB;
private JTextArea TextTA;
private JComboBox combo;
public void setAgent(RA a) {
myAgent = a;
setTitle(myAgent.getName());//setam titlul ferestrei
}
public RAguiImpl() {
super();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
myAgent.doDelete();
}
} );
JPanel containerPrincipal = new JPanel();
containerPrincipal.setLayout(new GridBagLayout());
containerPrincipal.setMinimumSize(new Dimension(330, 125));
containerPrincipal.setPreferredSize(new Dimension(330, 125));
JLabel l = new JLabel("pas-de-fabricatie");
l.setHorizontalAlignment(SwingConstants.LEFT);
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;//randul 0
gridBagConstraints.gridy = 0;//coloana 0
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;//textul aliniat in partea stanga
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
String ID[] = {"","P1","P2","P3","P4","P5"};
combo= new JComboBox(ID);
GridBagConstraints gridsBagConstraints = new GridBagConstraints();
gridsBagConstraints.gridx = 1;
gridsBagConstraints.gridy = 0;
gridsBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridsBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
combo.setBackground(Color.gray);
combo.setForeground(Color.black);
combo.setMinimumSize(new Dimension(100, 20));
containerPrincipal.add(combo,gridsBagConstraints);
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String str = (String)combo.getSelectedItem();
step.setText(str);
if(step.getText().equalsIgnoreCase("p1"))
{
celula.setText("celula 1");
}
else{
if(step.getText().equalsIgnoreCase("p2"))
{
celula.setText("celula 2");
}
else{
if(step.getText().equalsIgnoreCase("p3"))
{
celula.setText("celula 3");
}
else {
if(step.getText().equalsIgnoreCase("p4"))
{
celula.setText("celula 4");
}
else
{
celula.setText("celula 5");
}
}
}
}
}
});
step= new JTextField(7);
step.setMinimumSize(new Dimension(270, 20));
step.setPreferredSize(new Dimension(270, 20));//setam dimensiunea casutei in care introducem informatiile
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(step, gridBagConstraints);
l = new JLabel("celula-de-fabricatie: ");
l.setHorizontalAlignment(SwingConstants.LEFT);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
containerPrincipal.add(combo,gridsBagConstraints);
celula = new JTextField(7);
celula.setMinimumSize(new Dimension(100, 20));
celula.setPreferredSize(new Dimension(100, 20));
// idTF.setEnabled(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(celula, gridBagConstraints);
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
TextTA = new JTextArea();
TextTA.setEnabled(false);
TextTA.setDisabledTextColor(Color.RED);
TextTA.setFont(new Font("",Font.BOLD,12));
JScrollPane jsp = new JScrollPane(TextTA);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jsp.setMinimumSize(new Dimension(400, 270));
jsp.setPreferredSize(new Dimension(400, 280));
//jsp.setMininum
TextTA.setLineWrap(true);
TextTA.getCaret().setDot( TextTA.getText().length() );
jsp.scrollRectToVisible(TextTA.getVisibleRect() );
JPanel p = new JPanel();
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
p.add(jsp);
getContentPane().add(p, BorderLayout.CENTER);
setResizable(true);
p = new JPanel();
Font fontS = new Font("", Font.BOLD,13);
sendB = new JButton("Send");
sendB.setBackground(Color.GREEN);
sendB.setForeground(Color.DARK_GRAY);
sendB.setFont(fontS);
//la apasarea butonului "Send"
sendB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
//id ia valoarea trecuta in casuta
String id = step.getText();
String cell=celula.getText();
//cat timp id are o valoare
if (id != null && id.length() > 0) {
try {
notifyUser("Publicam oferta :\n Agentul realizeaza "+id+" si se afla in "+cell+"\n ");
myAgent.updateCatalogue(id,cell);
}
catch (Exception ex2) {
// Date invalide
JOptionPane.showMessageDialog(RAguiImpl.this, "Invalid values", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
else {
// No deadline specified
JOptionPane.showMessageDialog(RAguiImpl.this, "Nu s-a introdus pasul de fabricatie", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
}
);
resetB = new JButton("Reset");
resetB.setBackground(Color.ORANGE);
resetB.setForeground(Color.DARK_GRAY);
Font fontR = new Font("", Font.BOLD,13);
resetB.setFont(fontR);
resetB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
step.setText("");
celula.setText("");
}
} );
exitB = new JButton("Exit");
exitB.setForeground(Color.DARK_GRAY);
exitB.setBackground(Color.RED);
Font fontE = new Font("", Font.BOLD,13);
exitB.setFont(fontE);
exitB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
myAgent.doDelete();
}
} );
sendB.setPreferredSize(resetB.getPreferredSize());
exitB.setPreferredSize(resetB.getPreferredSize());
p.add(sendB);
p.add(resetB);
p.add(exitB);
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(p, BorderLayout.SOUTH); ////
// p.setBorder(new TitledBorder(""));
pack();
setResizable(true);
}
public void notifyUser(String message) {
TextTA.append(message+"\n");
}
@Override
public void notifyUserInt(int x) {
TextTA.append(x+"\n");
}
}
RA.java
package ProceseFabricatie.AgentResursa;
import ProceseFabricatie.AgentTask.TA;
import DirectorServicii.SDF;
import jade.content.ContentElement;
import jade.content.onto.basic.Action;
import jade.content.onto.basic.Result;
import java.lang.Thread.*;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.*;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.util.leap.ArrayList;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import java.text.NumberFormat;
import java.util.*;
@SuppressWarnings("all")
public class RA extends Agent
{
private Hashtable catalogue;
private Vector RAAgent=new Vector();
private RAgui myGui;
public int startTime=0;
public String listProcess,timeProcess;
private AID TAAgent;
protected ServiceDescription[] SDF;
public static String q_ty;
static long timpProces;
public String pas,produs;
String Initiator;
public String tip_produs;
public int contor1=0,contor2=0,contor3=0,contor4=0;
public String pas_propriu;
boolean sfarsit=false;
int VarTempProdCel=0;
long moment_disponibilitate=0;//cand Ra devine liber, trebuie trimis catre TA
int timp_procesare_curent=0;
int cantitate;
String Cantitate;
int timp;
public void setQty(String qty){
this.q_ty=qty;
}
/* initializam agentul
* */
protected void setup()
{ //opening the user interface
catalogue=new Hashtable();
myGui =new RAguiImpl();
myGui.setAgent(this);
myGui.show();
//we register the agent in the yellow pages
DFAgentDescription dfd =new DFAgentDescription();
dfd.setName(getAID());
ServiceDescription sd= new ServiceDescription();
sd.setType("Procesare_pas");
sd.setName(getLocalName()+"Procesare_pas");
dfd.addServices(sd);
try {
DFService.register(this,dfd);
}
catch (FIPAException fe)
{
fe.printStackTrace();
}
//Add the behaviour serving queries from RA agents
addBehaviour(new handleBidCFP());
//add the behaviour serving purchase orders from TA agents
addBehaviour(new handleBidProposal());
System.out.println("Agent RA: " + getAID().getName()+ " is ready.");
//primim numele agentilor ca si argument
Object[] args = getArguments();
if(args != null && args.length > 0)
{
for( int i=0; i<args.length; ++i)
{
AID procesare_pas = new AID((String) args[i], AID.ISLOCALNAME);
RAAgent.addElement(procesare_pas);
}
}
}
protected void takeDown()
{
//we don't deregister from yellow pages because we need all the time the agents, and if an agent finished
//his work, he can start to do a step from another fabrication system
//we are not closing either, because of the same reason
System.out.println(getAID().getName()+" terminated his work");
}
public void updateCatalogue(final String name, final String cell)
{
addBehaviour(new OneShotBehaviour() {
public void action()
{
catalogue.put(name,cell);
System.out.println(name+" Inserted into catalogue. He is from "+cell);
}
});
}
private class handleBidCFP extends CyclicBehaviour {
public void action()
{
MessageTemplate mt= MessageTemplate.MatchPerformative(ACLMessage.CFP);
ACLMessage msg = myAgent.receive(mt);
if(msg != null)
{ //ACCEPT_PROPOSAL Message received. Process it
String name = msg.getContent();
ACLMessage reply= msg.createReply();
String step = (String) catalogue.get(name);
pas=step;
if(step != null)
{
reply.setPerformative(ACLMessage.PROPOSE);
reply.setContent(step);
}
myAgent.send(reply);
myGui.notifyUser(step != null ? "\nCererea de contractare "+name+" coincide cu oferta lansata de de "+getName()+"\nPropunem (PROPOSE) oferta proprie de contractare a pasului: "+ "\n\t"+name+"\n": " \nCererea de contractare "+name+" nu coincide cu propunerea"+"\n de contractare a "+getName()+"\nCererea de contractare a fost refuzata: "+"\tREFUSE");
}
else{
block();
}
}
}
private class handleBidProposal extends CyclicBehaviour{
public void action()
{MessageTemplate mt=MessageTemplate.MatchPerformative(ACLMessage.ACCEPT_PROPOSAL);
ACLMessage msg=myAgent.receive(mt);
if(msg != null)
{ //ACCEPT_PROPOSAL
String name = msg.getContent();
produs=name;
ACLMessage reply = msg.createReply();
switch (pas){
case "celula 1": pas="P1";
break;
case "celula 2": pas="P2";
break;
case "celula 3": pas="P3";
break;
case "celula 4": pas="P4”;
break;
case "celula 5": pas="P5";
break;
}
reply.setContent(pas);
reply.setPerformative(ACLMessage.INFORM);
TAAgent=msg.getSender();
myGui.notifyUser("Am primit mesaj de tip: ACCEPT_PROPOSAL");
myGui.notifyUser(pas+ " va fi procesat pentru : "+ msg.getSender().getName());
myAgent.send(reply);
addBehaviour(new ProcesarePas(myAgent,name));
}
else {
block();
}
}
}
private class ProcesarePas extends Behaviour{
public String name;
public String Cantitate1;
ProcesarePas(Agent a,String nume)
{
super(a);
this.name=nume;
}
public void PrimireMesaj()
{
ACLMessage qty= myAgent.receive();
if(qty!=null)
{
Cantitate=qty.getContent();
cantitate=Integer.parseInt(Cantitate);
myGui.notifyUser("cantitatea dorita "+cantitate);
}
}
public void Transport(int timp1,String celula_trecuta,String celula_proprie)
{ long start1=System.currentTimeMillis();
int timp2=timp1*200;
try{
myGui.notifyUser("Se transporta piesa de la "+celula_trecuta+" la "+celula_proprie);
Thread.sleep(timp2);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end1= System.currentTimeMillis();
long timp_transport=(end1-start1)/200;
myGui.notifyUser("S-a transportat piesa la "+celula_proprie);
}
public void DurataDeProcesare(int timp1,String tip_produs,String pas_propriu)//cum fac sa primesc Timp precum parametru de la TA?
{
// cantitate=cnt;
//timp=cnt*timp1*1000;
timp=timp1*200;
long start = System.currentTimeMillis();
moment_disponibilitate=start+timp1;
System.out.println("valoare de start: "+start);
try {
myGui.notifyUser("Incepe procesarea pasului "+pas_propriu+" al produsului "+tip_produs+" pentru +cnt+ produse pentru un timp de "+timp/200+" secunde/5");
Thread.sleep(timp);
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("valoare de sfarsit: "+end);
long timp_procesare=(end-start)/200;
System.out.println("timp procesare= "+(end-start)/200);
myGui.notifyUser("Procesarea pasului "+pas_propriu+" pentru "+tip_produs+" pentru +cnt+ produse terminata dupa "+timp_procesare+" secunde.");
}
public void TrimiteMesaj(String inform)
{
ACLMessage done= new ACLMessage(ACLMessage.INFORM);
done.addReceiver(TAAgent);
done.setContent(inform);
myAgent.send(done);
}
public void action()
{
tip_produs=produs;
pas_propriu=pas;
switch(tip_produs){
case "Produs-1": switch(pas_propriu){
case "P1": PrimireMesaj(); timp_procesare_curent=45; Transport(3,"depozit","celula1"); DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu); TrimiteMesaj("Procesare Terminata in celula 1") TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P2": PrimireMesaj(); timp_procesare_curent=10; Transport(3,"celula1","celula2"); DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 2");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P3": PrimireMesaj(); timp_procesare_curent=80; Transport(3,"celula2","celula3"); DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 3");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P4": PrimireMesaj();
timp_procesare_curent=20;
Transport(3,"celula3","celula4");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 4");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P5": PrimireMesaj();
timp_procesare_curent=60;
Transport(3,"celula4","celula5");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 5");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Transport(3,"celula5","depozit2");
break;
}
sfarsit=true;
break;
case "Produs-2": switch(pas_propriu){
case "P1": PrimireMesaj();
timp_procesare_curent=30;
Transport(3,"celula2","celula1");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 1");
TrimiteMesaj("rezultatul dorit a fost obtinut ");
break;
case "P2": contor2++;
myGui.notifyUser("contor2 are valoarea: "+contor2);
PrimireMesaj();
if(cantitate==0)
{
timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
if(cantitate==1)
{if(contor2==1)
{timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
else
{ timp_procesare_curent=10;
Transport(3,"celula4","celula2");
}}
if(cantitate==2)
{
if(contor2==1 || contor2==2)
{
timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
else {
timp_procesare_curent=10;
Transport(3,"celula4","celula2");
}
}
if(cantitate==3)
{
if(contor2==1 || contor2==2 || contor2==3)
{timp_procesare_curent=15;
Transport(3,"depozit","celula2");
}
else {
timp_procesare_curent=10;
Transport(3,"celula4","celula2");
}
}
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 2");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P3": PrimireMesaj();
timp_procesare_curent=30;
Transport(3,"celula4","celula3");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 3");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Break;
case "P4": PrimireMesaj();
contor4++;
timp_procesare_curent=40;
if(cantitate==1)
{
if(contor4==1)
{
Transport(3,"celula1","celula4");
}
else
{
Transport(3,"celula2","celula4");
}
}
if(cantitate==2)
{
if(contor4==1 || contor4==2)
{Transport(3,"celula1","celula4");
}
else
{Transport(3,"celula2","celula4");
}
}
if(cantitate==3)
{
if(contor4==1 || contor4==2 || contor4==3)
{
Transport(3,"celula1","celula4");
}
else
{
Transport(3,"celula2","celula4");
}
}
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 4");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P5": PrimireMesaj();
timp_procesare_curent=60;
Transport(3,"celula3","celula5");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 5");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Transport(3,"celula5","depozit");
break;
}
sfarsit=true;
break;
case "Produs-3": switch(pas_propriu){
case "P1": PrimireMesaj();
contor1++;
if (cantitate==0)
timp_procesare_curent=10;
if(cantitate==1)
{
if(contor1==1)
timp_procesare_curent=10;
else
timp_procesare_curent=30;
}
if(cantitate==2)
{ if(contor1==1|| contor1==2)
timp_procesare_curent=10;
else
timp_procesare_curent=30;
}
if(cantitate==3)
{if(contor1==1 || contor1==2 || contor1==3)
timp_procesare_curent=10;
else
timp_procesare_curent=30;
}
Transport(3,"celula3","celula1");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 1");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P3": PrimireMesaj();
contor3++;
if(cantitate==0)
{
timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
if(cantitate==1)
{if(contor3==1)
{ timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
else
{ timp_procesare_curent=20;
Transport(3,"celula4","celula3");
}
}
if(cantitate==2)
{if(contor3==1 || contor3==2)
{ timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
else
{ timp_procesare_curent=20;
Transport(3,"celula4","celula3");
}
}
if(cantitate==3)
{if(contor3==1 ||contor3==2 || contor3==3)
{ timp_procesare_curent=30;
Transport(4,"depozit","celula3");
}
else
{ timp_procesare_curent=20;
Transport(3,"celula4","celula3");
}
}
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 3");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P4": PrimireMesaj();
timp_procesare_curent=70;
Transport(3,"celula1","celula4");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 4");
TrimiteMesaj("rezultatul dorit a fost obtinut");
break;
case "P5": PrimireMesaj();
timp_procesare_curent=30;
Transport(3,"celula1","celula5");
DurataDeProcesare(timp_procesare_curent,tip_produs,pas_propriu);
TrimiteMesaj("Procesare Terminata in celula 5");
TrimiteMesaj("rezultatul dorit a fost obtinut");
Transport(3,"celula5","depozit");
break;
}
sfarsit=true;
break;
}
}
public boolean done()
{
return sfarsit;
}
}
}
Pachetul “ProceseFabricatie.AgentTask”
TACgui.java
package ProceseFabricatie.AgentTask;
import ProceseFabricatie.AgentResursa.RA;
public interface TACgui {
void setAgent(TA a);
// void setAgent(TA1 a);
void show();
void hide();
void notifyUser(String message);
void notifyUserInt(int x);
void dispose();
}
TAC.java
package ProceseFabricatie.AgentTask;
import jade.gui.TimeChooser;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.util.Date;
@SuppressWarnings("all")
public class TAC extends JFrame implements TACgui {
private TA agentulMeu;
//private TA1 agentulMeu1;
private JTextField idTF, cantitateDoritaTF, dataLimitaTF,deadlineTF,lista_proceselor, lista_timpilor,maxDelayTF;
private JButton sendB, resetB, exitB, allertB;
private JTextArea logTA;
private JComboBox combo,combo1;
int contorTA=0;
public TAC() {
super();
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
agentulMeu.doDelete();
}
} );
JPanel containerPrincipal = new JPanel();
//containerPrincipal.setBackground(Color.white);
containerPrincipal.setLayout(new GridBagLayout());
containerPrincipal.setPreferredSize(new Dimension(100, 140));
JLabel l = new JLabel("Produs");
// l.setHorizontalAlignment(SwingConstants.LEFT);
GridBagConstraints gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
///
String ID[] = {"","Produs-1","Produs-2","Produs-3"};
combo = new JComboBox(ID);
GridBagConstraints gridsBagConstraints = new GridBagConstraints();
gridsBagConstraints.gridx = 1;
gridsBagConstraints.gridy = 0;
gridsBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridsBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
combo.setBackground(Color.gray);
combo.setForeground(Color.black);
combo.setMinimumSize(new Dimension(100, 20));
containerPrincipal.add(combo,gridsBagConstraints);
combo.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String str = (String)combo.getSelectedItem();
idTF.setText(str);
}
});
idTF = new JTextField(15);
idTF.setMinimumSize(new Dimension(100, 20));
idTF.setPreferredSize(new Dimension(100, 20));
// idTF.setEnabled(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(idTF, gridBagConstraints);
l = new JLabel("Numar produse");
l.setHorizontalAlignment(SwingConstants.LEFT);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
containerPrincipal.add(l, gridBagConstraints);
String ID1[] = {"","1","2","3"};
combo1 = new JComboBox(ID1);
gridsBagConstraints = new GridBagConstraints();
gridsBagConstraints.gridx = 1;
gridsBagConstraints.gridy = 1;
gridsBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridsBagConstraints.insets = new java.awt.Insets(5, 3, 0, 3);
combo1.setBackground(Color.gray);
combo1.setForeground(Color.black);
combo1.setMinimumSize(new Dimension(100, 20));
containerPrincipal.add(combo1,gridsBagConstraints);
combo1.addItemListener(new ItemListener(){
public void itemStateChanged(ItemEvent ie){
String cant = (String)combo1.getSelectedItem();
cantitateDoritaTF.setText(cant);
if(idTF.getText().equalsIgnoreCase("Produs-1"))
{if(cantitateDoritaTF.getText().equalsIgnoreCase("1"))
{lista_proceselor.setText("P1,P2,P3,P4,P5");
lista_timpilor.setText("45,10,80,20,60");
}
else
{
if(cantitateDoritaTF.getText().equalsIgnoreCase("2"))
{
lista_proceselor.setText("P1,P1,P2,P2,P3,P3,P4,P4,P5,P5");
lista_timpilor.setText("45,45,10,10,80,80,20,20,60,60");
}
else
{
lista_proceselor.setText("P1,P1,P1,P2,P2,P2,P3,P3,P3,P4,P4,P4,P5,P5,P5");
lista_timpilor.setText("45,45,45,10,10,10,80,80,80,20,20,20,60,60,60");
}
}
}
else{
if(idTF.getText().equalsIgnoreCase("Produs-2"))
{if(cantitateDoritaTF.getText().equalsIgnoreCase("1"))
{lista_proceselor.setText("P2,P1,P4,P2,P4,P3,P5");
lista_timpilor.setText("15,30,40,10,40,30,60");
}
else{ if(cantitateDoritaTF.getText().equalsIgnoreCase("2"))
{
lista_proceselor.setText("P2,P2,P1,P1,P4,P4,P2,P2,P4,P4,P3,P3,P5,P5");
lista_timpilor.setText("15,15,30,30,40,40,10,10,40,40,30,30,60,60");
}
else{
lista_proceselor.setText("P2,P2,P2,P1,P1,P1,P4,P4,P4,P2,P2,P2,P4,P4,P4,P3,P3,P3,P5,P5,P5"); lista_timpilor.setText("15,15,15,30,30,30,40,40,40,10,10,10,40,40,40,30,30,30,60,60,60");
}
}
}
else {
if(cantitateDoritaTF.getText().equalsIgnoreCase("1"))
{lista_proceselor.setText("P3,P1,P4,P3,P1,P5");
lista_timpilor.setText("30,10,70,20,30,40");
}
else
{ if(cantitateDoritaTF.getText().equalsIgnoreCase("2" {
lista_proceselor.setText("P3,P3,P1,P1,P4,P4,P3,P3,P1,P1,P5,P5"); lista_timpilor.setText("30,30,10,10,70,70,20,20,30,30,40,40");
} else{lista_proceselor.setText("P3,P3,P3,P1,P1,P1,P4,P4,P4,P3,P3,P3,P1,P1,P1,P5,P5,P5"); lista_timpilor.setText("30,30,30,10,10,10,70,70,70,20,20,20,30,30,30,40,40,30");
}
}
}
}
}
});
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
cantitateDoritaTF = new JTextField(15);
cantitateDoritaTF.setMinimumSize(new Dimension(100, 20));
cantitateDoritaTF.setPreferredSize(new Dimension(100, 20));
cantitateDoritaTF.setEnabled(false);
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(cantitateDoritaTF, gridBagConstraints);
l = new JLabel(" Lista Proces:");
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setMinimumSize(new Dimension(100, 20));
l.setPreferredSize(new Dimension(100, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;//coloana 0
gridBagConstraints.gridy = 3;//randul 3
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
containerPrincipal.add(l, gridBagConstraints);
lista_proceselor = new JTextField(50);
lista_proceselor.setMinimumSize(new Dimension(120, 20));
lista_proceselor.setPreferredSize(new Dimension(120, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(lista_proceselor, gridBagConstraints);
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
l = new JLabel(" Lista Timpilor:");
l.setHorizontalAlignment(SwingConstants.LEFT);
l.setMinimumSize(new Dimension(100, 20));
l.setPreferredSize(new Dimension(100, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 0;//coloana 0
gridBagConstraints.gridy = 5;//randul 5
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
containerPrincipal.add(l, gridBagConstraints);
lista_timpilor = new JTextField(50);
lista_timpilor.setMinimumSize(new Dimension(120, 20));
lista_timpilor.setPreferredSize(new Dimension(120, 20));
gridBagConstraints = new GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 5;
gridBagConstraints.gridwidth = 5;
gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new Insets(5, 3, 0, 3);
containerPrincipal.add(lista_timpilor, gridBagConstraints);
containerPrincipal.setBorder(new BevelBorder(BevelBorder.LOWERED));
getContentPane().add(containerPrincipal, BorderLayout.NORTH);
logTA = new JTextArea();
logTA.setEnabled(false);
logTA.setDisabledTextColor(Color.black);
logTA.setFont(new Font("",Font.BOLD,12));
JScrollPane jsp = new JScrollPane(logTA);
jsp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
jsp.setMinimumSize(new Dimension(400, 270));
jsp.setPreferredSize(new Dimension(400, 280));
logTA.setLineWrap(true);
logTA.getCaret().setDot( logTA.getText().length() );
jsp.scrollRectToVisible(logTA.getVisibleRect() );
JPanel p = new JPanel();
p.setBorder(new BevelBorder(BevelBorder.LOWERED));
p.add(jsp);
getContentPane().add(p, BorderLayout.CENTER);
p = new JPanel();
//Buton "SEND"
sendB = new JButton("Send");
sendB.setBackground(Color.green);
sendB.setForeground(Color.DARK_GRAY);
Font fontS = new Font("", Font.BOLD,13);
sendB.setFont(fontS);
sendB.addActionListener(new ActionListener(){
//la apasarea butonului SEND se vor salva datele din casute
public void actionPerformed(ActionEvent e) {
String id = idTF.getText();
int q_ty=-1;
String listTime ;
String listProcess;
//doar daca id-ul pentru ordinul de fabricatie a fost introdus
if (id != null && id.length() > 0) {
try {
//salvam datele din casute
q_ty=Integer.parseInt(cantitateDoritaTF.getText()); listProcess=(String)(lista_proceselor.getText());
listTime=(String)(lista_timpilor.getText());
agentulMeu.createTA(id,q_ty,listProcess,listTime);
notifyUser("Ordin de fabricatie: "+id+"\n se doreste efectuarea pasilor: "+listProcess+"\n cu lista timpilor de procesare: "+listTime+"\n cantitate: "+q_ty+" produs(e)\n");
}
catch (Exception ex1) {
// Eroare valori
JOptionPane.showMessageDialog(TAC.this, "Eroare!Utilizati valori numerice", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
else {
// Nu s-a completat casuta cu ordinul de fabricatie
JOptionPane.showMessageDialog(TAC.this, "Eroare: Introduceti ordinul de fabricatie", "WARNING", JOptionPane.WARNING_MESSAGE);
}
}
}
);
//Buton de RESET
resetB = new JButton("Reset");
resetB.setBackground(Color.orange);
resetB.setForeground(Color.DARK_GRAY);
Font fontR = new Font("", Font.BOLD,13);
resetB.setFont(fontR);
resetB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
idTF.setText("");
cantitateDoritaTF.setText("");
lista_proceselor.setText("");
lista_timpilor.setText("");
}
} );
//Buton "EXIT"
exitB = new JButton("Exit");
exitB.setBackground(Color.red);
exitB.setForeground(Color.DARK_GRAY);
Font fontE = new Font("", Font.BOLD,13);
exitB.setFont(fontE);
//la apasarea butonului agentul va fi sters
exitB.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
agentulMeu.doDelete();
}
} );
//Buton "Alert"
ImageIcon redButton=new ImageIcon("images/red-button.jpg");
allertB=new JButton(redButton);
p.add(sendB);
p.add(resetB);
p.add(exitB);
//butoanele sunt aranjate in partea de jos
getContentPane().add(p, BorderLayout.SOUTH);
pack();
setResizable(true);
//fereastra nu va avea dimensiune fixa
}
public void setAgent(TA a) {
agentulMeu = a;
setTitle(agentulMeu.getName());
}
//
public void notifyUser(String message) {
logTA.append(message+"\n");
}
public void notifyUserInt(int x)
{
logTA.append(x+"\n");
}
}
TA.java
package ProceseFabricatie.AgentTask;
import DirectorServicii.SDF;
import jade.core.*;
import jade.core.behaviours.*;
import jade.lang.acl.*;
import jade.domain.*;
import jade.domain.FIPAAgentManagement.*;
import java.util.Vector;
import java.util.Date;
import jade.content.lang.Codec.CodecException;
@SuppressWarnings("all")
/**
Clasa TA
**/
public class TA extends Agent{
//Lista cu agentii RA care asigura servicii de fabricatie
private Vector RAAgents = new Vector();
private Vector RATransport=new Vector();
public String idf;
private AID[] RA;
//Interfata GUI ce interactioneaza cu userul
private TAC myGui;
protected ServiceDescription[]SDF;
private MessageTemplate mt;
int contorPasi=0;
private UpdateManager manager;
String sirproces;
String sirtimp;
int lungime;
int contorL=0;
int j=0;
String ultimulMesaj1="";
/**
* Initializarea agentului
**/
protected void setup() {
// Printam un mesaj
System.out.println("Agent TA: "+getAID().getName()+" este pregatit.");
//Salvam numele agentilor ce au fost introdusi in linia de comanda
Object[] args = getArguments();
if (args != null && args.length > 0) {
for (int i = 0; i < args.length; ++i) {
AID mRA = new AID((String) args[i], AID.ISLOCALNAME);
RAAgents.addElement(mRA);
}
}
// Pornim interfata grafica
myGui = new TAC();
myGui.setAgent(this);
myGui.show();
// RegisterService();
}
/**
* Urmatorul cod ne va ajuta sa cautam la fiecare 20 de secunde, agentii disponibili
* fabricarii produselor.
* TA trimite o cerere de realizare a primului pas de fabricatie, necesar in
* obtinerea unui produs solicitat, catre SDF
**/
/**
* Distrugerea agentilor
**/
protected void takeDown() {
if (myGui != null) {
myGui.dispose();
}
System.out.println("Agentul TA "+getAID().getName()+" a fost distrus");
}
//porneste un agent task pentru un ordin fabricatie nou primit de la ERP
public void createTA(String id,int cantitate,String listProcess,String listTime)
{ idf=id;
/*trimitem o cerere de realizare a primului pas de fabricatie,
necesar in obtinerea unui produs solicitat, catre SDF*/
addBehaviour(new JobToRA(this));
/* contractul va fi acordat RA ce a depus cererea cea mai avantajoasa,
conform unui mecanism de acordare de tip CNP */
addBehaviour(new UpdateManager(this,id,cantitate,listProcess,listTime));
}
private class JobToRA extends TickerBehaviour{
double t1 = System.currentTimeMillis();
private JobToRA (Agent a){
super(a,1000); //timpul de asteptare
}
public void onTick() {
/* TA trimite o cerere de realizare a primului pas de fabricatie,necesar in obtinerea unui produs solicitat catre SDF.Agentul nostru se va axa doar pe agentii care sunt participanti la procesul de negociere*/
if(idf != null)
{
DFAgentDescription template = new DFAgentDescription();
SDF = new ServiceDescription[2];
ServiceDescription tempSDF = new ServiceDescription();
tempSDF.setType("Procesare_pas");
SDF[0] = tempSDF;
template.addServices(SDF[0]);
try {
DFAgentDescription[] result = DFService.search(myAgent, template);
/*dupa ce primeste prima cerere de contractare legata de serviciul publicat Ta va cere SDF stergerea serviciului*/
RAAgents.clear();
for (int i = 0; i < result.length; ++i) {
RAAgents.addElement(result[i].getName());
}
}
catch (FIPAException fe) {
fe.printStackTrace();
}
}
}//de la functia onTick
}//de la clasa JobToRA
public void publishJob(String sms){
DFAgentDescription template = new DFAgentDescription();
SDF = new ServiceDescription[5];
ServiceDescription tempSDF = new ServiceDescription();
tempSDF.setType(sms);
SDF[0] = tempSDF;
template.addServices(SDF[0]);
try {
DFAgentDescription[] result = DFService.search(this, template);
/*dupa ce primeste prima cerere de contractare legata de serviuciul publicat
Ta va cere SDF stergerea serviciului*/
RAAgents.clear();
for (int i = 0; i < result.length; ++i) {
RAAgents.addElement(result[i].getName());
}
}
catch (FIPAException fe) {
fe.printStackTrace();
}
}
public class UpdateManager extends TickerBehaviour {
public String id;
public int q_ty;
public String listProcess;
public String listTime;
int end=0;
private int period;
public void setFixedPeriod(boolean fixedPeriod)
{
fixedPeriod=false;
}
/*protected long getPeriod(String lTime)
{
perioadai= Integer.parseInt(lTime.substring(0,2));
return perioadai;
}*/
void setari(String lTime)
{
period= Integer.parseInt(lTime.substring(0,2));
setFixedPeriod(false);
}
public UpdateManager(Agent a, String ID, int cantitate,String lProcess,String lTime) {
super(a,12000);
id = ID;
q_ty = cantitate;
listProcess=lProcess;
listTime=lTime;
contorPasi++;
}
public void ReceptieMesaj1()
{
ACLMessage done4=myAgent.receive();
if(done4 != null)
{
ultimulMesaj1 = done4.getContent();
//System.out.println("mesajul ce a ajuns de la "+done3.getSender().getName()+" este "+ultimulMesaj);
myGui.notifyUser(ultimulMesaj1);
}
}
public void onTick() {
if(listProcess!=null){
if(contorL <= (listProcess.length())/3)
{
if(contorL==0)
{
sirproces=listProcess;
sirtimp=listTime;
System.out.println("lista proceselor: "+sirproces);
System.out.println("lista timpilor: "+sirtimp);
}
else
{ sirproces=sirproces.substring(3);
sirtimp=sirtimp.substring(3);
System.out.println("lista proceselor: "+sirproces);
System.out.println("lista timpilor: "+sirtimp);
}
myAgent.addBehaviour(new handleService(id,q_ty,sirproces,sirtimp,this));
contorL++;
}
else
{ myGui.notifyUser("Procesare terminata in celula 5");
myGui.notifyUser("rezultatul dorit a fost obtinut");
myGui.notifyUser("Produsul a fost fabricat");
end=1;
manager.stop();
}
}
}
}
/**
* Cererile de contractare sunt evaluate si contractul va fi acordat RA ce a depus
* cererea cea mai avantajoasa conform unui mecanism de acordare de tip CNP
* ce presupune urmatorul protocol(TA-initiator, RA-urile -participanti)
**/
private class handleService extends Behaviour {
private String id;
private String listTime;
private int q_ty;
private String listProcess;
private AID bestOffer; // Agentul ofertant care vine cu cea mai buna oferta
private int bestTimeProcess;// cea mai rentabila oferta va fi cu timpul de procesare mai redus
private int req_qty;// cantitatea ceruta
private int repliesCnt = 0; // un numarator pentru agentii RA
// un sablon pentru a primi doar mesajele ce ne intereseaza
private boolean sfarsit = false;
private int step=0;
public int contor=0;
String ultimulMesaj;
public handleService(String ID,int qty,String procese,String timpi,UpdateManager m)
{
super(null);
id = ID;
listTime = timpi;
q_ty=qty;
listProcess=procese;
manager = m;
}
public void ReceptieMesaj()
{
ACLMessage done3=myAgent.receive();
if(done3 != null)
{
ultimulMesaj = done3.getContent();
}
}
public void action() {
String rez=listProcess.substring(0,2);
String tmp=listTime.substring(0,2);
switch(step)
{
case 0:
// Trimitem catre agentii RA un call for proposal(CFP)
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
for (int i = 0; i < RAAgents.size(); ++i) {
cfp.addReceiver((AID)RAAgents.elementAt(i));
}
cfp.setContent(rez); //Ne intereseaza doar un anumit pas de fabricatie
cfp.setConversationId("Procesare_pas");
cfp.setReplyWith("cfp"+System.currentTimeMillis()); // Valoare unica
myAgent.send(cfp);
myGui.notifyUser("Se doreste efectuarea pasului "+rez+" cu timpul de executie "+tmp);
myGui.notifyUser("Am trimis propunerea de tip CFP catre "+RAAgents.size()+" agenti RA");
//Pregatim sablonul in care vom selecta doar ofertele ce ne intereseaza
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("Procesare_pas"),MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
step=1;
break;
case 1:
//Primim toate propunerile/refuzurile de la agentii RA
ACLMessage reply = myAgent.receive(mt);
if (reply != null) {
// Am primit raspunsul
if (reply.getPerformative() == ACLMessage.PROPOSE) {
// Avem oferta de la agentul RA
String PasProcesare = (String) (reply.getContent());
myGui.notifyUser("Am primit o cerere de contractare de la: " +reply.getSender().getLocalName()+"\n cu urmatoarele informatii aferente job-ului\n"+PasProcesare+" .\n");
if(bestOffer==null)
{
bestTimeProcess=Integer.parseInt(tmp);
//selectam cea mai buna oferta
bestOffer = reply.getSender();
}
}
repliesCnt++;
if (repliesCnt >= RAAgents.size()) {
// Am primit toate raspunsurile. Nu mai exista in acest moment agenti RA
step = 2;
}
}
else {
block();
}
break;
case 2:
//verificam daca cea mai buna oferta trimisa de participant
//se incadreaza in cerintele impuse ce catre initiator
if (bestOffer != null ) {
//Se trimite un mesaj de acceptare agentului care a venit cu cea mai buna oferta
ACLMessage order = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
String e="";
order.addReceiver(bestOffer);
order.setContent(id);
order.setConversationId("Procesare_pas");
order.setReplyWith("order"+System.currentTimeMillis());
myAgent.send(order);
ReceptieMesaj();
ReceptieMesaj();
myGui.notifyUser("Trimitem: Accept Proposal catre: "+ bestOffer.getLocalName());
//Se pregateste sablonul pentru a primi raspunul
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("Procesare_pas"),MessageTemplate.MatchInReplyTo(order.getReplyWith()));
step = 3;
}
else {
// Daca nu se primeste nicio propunere acceptata, agentii se distrug
step =7;
break;
}
myGui.notifyUser("\n Ceilalti agenti intrati la licitatie au primit"+" Reject-Proposal");
break;
case 3:
// Participantul care a primit de realizat task-ul trimite catre TA
// un mesaj de informare
reply = myAgent.receive(mt);
if (reply != null) {
// Ordinul de fabricatie a fost receptionat
if (reply.getPerformative() == ACLMessage.INFORM) {
myGui.notifyUser("Licitatia s-a incheiat.Avem urmatoarele informatii\n\tCastigatorul licitatiei este:"+reply.getSender().getLocalName()+"\n\tProdusul ce va fi fabricat: "+id+"\n\tPasul de fabricatie: "+reply.getContent()+"\n\tLot de productie: "+q_ty+" produse");
}
step = 4;
}
else {
block();
}
break;
case 4:
System.out.println("se doreste realizarea a "+q_ty+" produse");
ACLMessage request = new ACLMessage(ACLMessage.INFORM);
request.addReceiver(bestOffer);
request.setContent(Integer.toString(q_ty));
request.setConversationId("Pocesare_pas");
request.setReplyWith("prelucrare"+System.currentTimeMillis());
myAgent.send(request);
myGui.notifyUser("Cerem agentului "+bestOffer+" inceperea procesarii pasului "+rez);
step=5;
break;
case 5:
myGui.notifyUser("Incepe procesarea pasului "+rez+" cu timpul de executie "+tmp+".");
step=6;
break;
case 6:
step=7;
break;
} //sfarsit switch
}
public boolean done() {
return step==7;
}
}
}
Copyright Notice
© Licențiada.org respectă drepturile de proprietate intelectuală și așteaptă ca toți utilizatorii să facă același lucru. Dacă consideri că un conținut de pe site încalcă drepturile tale de autor, te rugăm să trimiți o notificare DMCA.
Acest articol: Controlul Distribuit al Proceselor de Fabricatie cu Ajutorul Mediului Multi Agent Jade (ID: 162231)
Dacă considerați că acest conținut vă încalcă drepturile de autor, vă rugăm să depuneți o cerere pe pagina noastră Copyright Takedown.
