Agent的简单运用,实现卖旗子代理。这个代码实现的要求如下,这个做了很久了,突然想到,才整理出来贴出来。没法翻译,将就着看吧,看英文多了,其实觉得还不错啦。
There is a buyer who wants to buy a specific flag from one or two seller agents who are trying to offer the best (lowest) price. You are to model this situation in JADE.
The Buyer:
Each buyer tells what kind of flag he wants to buy as a command line argument and periodically requests all known seller agents to provide an offer. As soon as an offer is received the buyer agent accepts it and issues a purchase order.
If it more than one seller agent provides an offer the buyer agent accepts the lowest price. Having bought the flag the buyer agent terminates.
The two Sellers:
Each seller agent has a minimal GUI by means of which a user (you) can insert a name of a flag and the associated price of the flag for sale. Example: Japanese flag, 100 £. This is to inform the application what the seller has for sale, Seller agents continuously wait for request from buyer agents.
When asked to provide an offer for a specific flag (i.e this is when your program starts) they check if the requested flag is in store and in this case reply with the price. Otherwise they refuse. When they receive a purchase order they serve it and remove the request book from their catalogue
The sellers are not aware of each other. In short this means that the buyer asks the two sellers which of them has the lowest price on one specific flag. The buyer will immediately accept the proposal from the sellers with the lowest bid.
整个的实现是用JADE and NetBeans,建立了四个agent 类。
这个是买旗子的agent
package sellflag;
import jade.core.Agent;
import jade.core.AID;
import jade.core.behaviours.*;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
public class FlagBuyerAgent extends Agent {
// The title of the book to buy
private String targetflag;
// The list of known seller agents
private AID[] sellerAgents;//to store all the selleragents in DF
private FlagBuyerGui mybuyerGui;
// Put agent initializations here
@Override
protected void setup()
{
// Printout a welcome message
System.out.println("Hello! Buyer-agent "+getAID().getName()+" is ready.");
// Get the title of the book to buy as a start-up argument
mybuyerGui = new FlagBuyerGui(this);
mybuyerGui.show();//buyer enter the flag name
// Get the title of the book to buy as a start-up argument
// if (true) {
// Add a TickerBehaviour that schedules a request to seller agents every minute
addBehaviour(new TickerBehaviour(this, 60000)
{//wait for 1 minute to request service
protected void onTick()
{//from here we have gotten the targetflag form the GUI, if it is null ,one minute later the buyeragent terminates
if(targetflag!=null)
{
System.out.println("Trying to buy "+targetflag);
// Update the list of seller agents
DFAgentDescription template = new DFAgentDescription();
ServiceDescription sd = new ServiceDescription();
sd.setType("flag-selling");
template.addServices(sd);
try {
DFAgentDescription[] result = DFService.search(myAgent, template); //return all the agents which sell the book
System.out.println("Found the following seller agents:");
sellerAgents = new AID[result.length];//initialize selleragents array according to result length;
for (int i = 0; i < result.length; ++i)
{
sellerAgents[i] = result[i].getName();
System.out.println(sellerAgents[i].getName());//why dont we use result.getname() to print;
}
}
catch (FIPAException fe)
{
fe.printStackTrace();
}
// Perform the request
myAgent.addBehaviour(new RequestPerformer());
}
else
{
// Make the agent terminate
System.out.println("No target flag title specified");
//doDelete();
}
}
} );
}
public void getFlagtitle(final String title) {
addBehaviour(new OneShotBehaviour() {
public void action() {
targetflag= title;
}
} );
}
// Put agent clean-up operations here
protected void takeDown() {
mybuyerGui.dispose();//dispose the gui as well
// Printout a dismissal message
System.out.println("Buyer-agent "+getAID().getName()+" terminating.");
}
/**
Inner class RequestPerformer.
This is the behaviour used by Book-buyer agents to request seller
agents the target book.
*/
private class RequestPerformer extends Behaviour {
private AID bestSeller; // The agent who provides the best offer
private int bestPrice; // The best offered price
private int repliesCnt = 0; // The counter of replies from seller agents
private MessageTemplate mt; // The template to receive replies
private int step = 0;
public void action() {
switch (step) {
case 0:
// Send the cfp to all sellers
ACLMessage cfp = new ACLMessage(ACLMessage.CFP);
for (int i = 0; i < sellerAgents.length; ++i) {
cfp.addReceiver(sellerAgents[i]);
}
cfp.setContent(targetflag);
cfp.setConversationId("flag-trade");
cfp.setReplyWith("cfp"+System.currentTimeMillis()); // Unique value
myAgent.send(cfp);
// Prepare the template to get proposals
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("flag-trade"),
MessageTemplate.MatchInReplyTo(cfp.getReplyWith()));
step = 1;
break;
case 1:
// Receive all proposals/refusals from seller agents
ACLMessage reply = myAgent.receive(mt);
if (reply != null) {
// Reply received
if (reply.getPerformative() == ACLMessage.PROPOSE) {
// This is an offer
int price = Integer.parseInt(reply.getContent());
if (bestSeller == null || price < bestPrice) {
// This is the best offer at present
bestPrice = price;
bestSeller = reply.getSender();
}
}
repliesCnt++;
if (repliesCnt >= sellerAgents.length) {
// We received all replies
step = 2;
}
}
else {
block();
}
break;
case 2:
// Send the purchase order to the seller that provided the best offer
ACLMessage order = new ACLMessage(ACLMessage.ACCEPT_PROPOSAL);
order.addReceiver(bestSeller);
order.setContent(targetflag);
order.setConversationId("flag-trade");
order.setReplyWith("order"+System.currentTimeMillis());
myAgent.send(order);
// Prepare the template to get the purchase order reply
mt = MessageTemplate.and(MessageTemplate.MatchConversationId("flag-trade"),
MessageTemplate.MatchInReplyTo(order.getReplyWith()));
step = 3;
break;
case 3:
// Receive the purchase order reply
reply = myAgent.receive(mt);
if (reply != null) {
// Purchase order reply received
if (reply.getPerformative() == ACLMessage.INFORM) {
// Purchase successful. We can terminate
System.out.println(targetflag+" successfully purchased from agent "+reply.getSender().getName());
System.out.println("Price = "+bestPrice);
myAgent.doDelete();
}
else {
System.out.println("Attempt failed: requested flag already sold.");
}
step = 4;
}
else {
block();
}
break;
}
}
public boolean done() {
if (step == 2 && bestSeller == null) {
System.out.println("Attempt failed: "+targetflag+" not available for sale");
}
return ((step == 2 && bestSeller == null) || step == 4);
}
} // End of inner class RequestPerformer
}
第二个类是旗子卖家agent类
package sellflag;
import jade.core.Agent;
import jade.core.behaviours.*;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.domain.DFService;
import jade.domain.FIPAException;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import java.util.*;
public class FlagSellerAgent extends Agent {
// The catalogue of books for sale (maps the title of a book to its price)
private Hashtable catalogue;
// The GUI by means of which the user can add books in the catalogue
private FlagSellerGui myGui;
// Put agent initializations here
protected void setup() {
// Create the catalogue
catalogue = new Hashtable();
// Create and show the GUI
myGui = new FlagSellerGui(this);
myGui.show();
// Register the book-selling service in the yellow pages
DFAgentDescription dfd = new DFAgentDescription();
dfd.setName(getAID());
ServiceDescription sd = new ServiceDescription();
sd.setType("flag-selling");
sd.setName("JADE-flag-trading");
dfd.addServices(sd);
try {
DFService.register(this, dfd);
}
catch (FIPAException fe) {
fe.printStackTrace();
}
// Add the behaviour serving queries from buyer agents
addBehaviour(new OfferRequestsServer());
// Add the behaviour serving purchase orders from buyer agents
addBehaviour(new PurchaseOrdersServer());
}
// Put agent clean-up operations here
protected void takeDown() {
// Deregister from the yellow pages
try {
DFService.deregister(this);
}
catch (FIPAException fe) {
fe.printStackTrace();
}
// Close the GUI
myGui.dispose();
// Printout a dismissal message
System.out.println("Seller-agent "+getAID().getName()+" terminating.");
}
/**
This is invoked by the GUI when the user adds a new book for sale
*/
public void updateCatalogue(final String title, final int price) {
addBehaviour(new OneShotBehaviour() {
public void action() {
catalogue.put(title, new Integer(price));
System.out.println(title+" inserted into catalogue. Price = "+price);
}
} );
}
/**
Inner class OfferRequestsServer.
This is the behaviour used by Book-seller agents to serve incoming requests
for offer from buyer agents.
If the requested book is in the local catalogue the seller agent replies
with a PROPOSE message specifying the price. Otherwise a REFUSE message is
sent back.
*/
private class OfferRequestsServer extends CyclicBehaviour {
public void action() {
MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.CFP);
ACLMessage msg = myAgent.receive(mt);
if (msg != null) {
// CFP Message received. Process it
String title = msg.getContent();
ACLMessage reply = msg.createReply();
Integer price = (Integer) catalogue.get(title);
if (price != null) {
// The requested book is available for sale. Reply with the price
reply.setPerformative(ACLMessage.PROPOSE);
reply.setContent(String.valueOf(price.intValue()));
}
else {
// The requested book is NOT available for sale.
reply.setPerformative(ACLMessage.REFUSE);
reply.setContent("not-available");
}
myAgent.send(reply);
}
else {
block();
}
}
} // End of inner class OfferRequestsServer
/**
Inner class PurchaseOrdersServer.
This is the behaviour used by Book-seller agents to serve incoming
offer acceptances (i.e. purchase orders) from buyer agents.
The seller agent removes the purchased book from its catalogue
and replies with an INFORM message to notify the buyer that the
purchase has been sucesfully completed.
*/
private class PurchaseOrdersServer extends CyclicBehaviour {
public void action() {
MessageTemplate mt = MessageTemplate.MatchPerformative(ACLMessage.ACCEPT_PROPOSAL);
ACLMessage msg = myAgent.receive(mt);
if (msg != null) {
// ACCEPT_PROPOSAL Message received. Process it
String title = msg.getContent();
ACLMessage reply = msg.createReply();
Integer price = (Integer) catalogue.remove(title);
if (price != null) {
reply.setPerformative(ACLMessage.INFORM);
System.out.println(title+" sold to agent "+msg.getSender().getName());
}
else {
// The requested book has been sold to another buyer in the meanwhile .
reply.setPerformative(ACLMessage.FAILURE);
reply.setContent("not-available");
}
myAgent.send(reply);
}
else {
block();
}
}
} // End of inner class OfferRequestsServer
}
这个类是买家的界面设计
package sellflag;
import jade.core.AID;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
@author Giovanni Caire - TILAB
*/
public class FlagBuyerGui extends JFrame {
private FlagBuyerAgent mybuyerAgent;
private JTextField titleField;
FlagBuyerGui(FlagBuyerAgent a) {
super(a.getLocalName());
mybuyerAgent = a;
JPanel p = new JPanel();
p.setLayout(new GridLayout(1, 1));
p.add(new JLabel("flag want to buy:"));
titleField = new JTextField(15);
p.add(titleField);
getContentPane().add(p, BorderLayout.CENTER);
JButton addButton = new JButton("submit");
addButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ev) {
try {
String title = titleField.getText().trim();
mybuyerAgent.getFlagtitle(title);
titleField.setText("");
}
catch (Exception e) {
JOptionPane.showMessageDialog(FlagBuyerGui.this, "Invalid values. "+e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
} );
p = new JPanel();
p.add(addButton);
getContentPane().add(p, BorderLayout.SOUTH);
// Make the agent terminate when the user closes
// the GUI using the button on the upper right corner
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
mybuyerAgent.doDelete();
}
} );
setResizable(false);
}
public void show() {
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int centerX = (int)screenSize.getWidth() / 2;
int centerY = (int)screenSize.getHeight() / 2;
setLocation(centerX - getWidth() / 2, centerY - getHeight() / 2);
super.show();
}
}
最后一个是卖家界面。。
package sellflag;
import jade.core.AID;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
@author Giovanni Caire - TILAB
*/
class FlagSellerGui extends JFrame {
private FlagSellerAgent myAgent;
private JTextField titleField, priceField;
FlagSellerGui(FlagSellerAgent a) {
super(a.getLocalName());
myAgent = a;
JPanel p = new JPanel();
p.setLayout(new GridLayout(2, 2));
p.add(new JLabel("flag title:"));
titleField = new JTextField(15);
p.add(titleField);
p.add(new JLabel("Price:"));
priceField = new JTextField(15);
p.add(priceField);
getContentPane().add(p, BorderLayout.CENTER);
JButton addButton = new JButton("Add");
addButton.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent ev) {
try {
String title = titleField.getText().trim();
String price = priceField.getText().trim();
myAgent.updateCatalogue(title, Integer.parseInt(price));
titleField.setText("");
priceField.setText("");
}
catch (Exception e) {
JOptionPane.showMessageDialog(FlagSellerGui.this, "Invalid values. "+e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
} );
p = new JPanel();
p.add(addButton);
getContentPane().add(p, BorderLayout.SOUTH);
// Make the agent terminate when the user closes
// the GUI using the button on the upper right corner
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
myAgent.doDelete();
}
} );
setResizable(false);
}
public void show() {
pack();
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
int centerX = (int)screenSize.getWidth() / 2;
int centerY = (int)screenSize.getHeight() / 2;
setLocation(centerX - getWidth() / 2, centerY - getHeight() / 2);
super.show();
}
}
都是可运行代码。。。过多的解释不说了,感兴趣的我直接给你我报告。。