-
Notifications
You must be signed in to change notification settings - Fork 0
Home
(implementation by Nikolay Vasilev and Rubén Ríos)
*NOTE: * This document still is in status draft
which means that there could be parts which are not translated properly or which need rewriting. But with little bit of patience, soon this will be changed. We keep working on it. All suggestions, improvements and fixes found by the users of our code (or this short manual) are very welcomed! :)
This project was created after the implementation of concrete task, which was given as final project for the subject "Multi-agent Systems Programming", in the Ms. Sc. program "Software Engineering and Artificial Intelligence" (2008-2009) at University of Málaga, Spain.
The reason which forced us to create this project was that at the moment of the implementation of our task (June 2009), we needed JADE-based implementation of the FIPA English Auction Interaction Protocol. Unfortunately nowhere in Internet we found such one (at least open source and free one). There was only the experimental protocol specification available on the official FIPA site. For that reason we have developed our own implementation of the protocol. We decided to publish it, in order to help to other fans of the Multi-agent System development who use JADE as programming language and who need this implementation.
(We have to note, that the original version of this document was written in Spanish, but we decided to translate it in English as well. Correspondingly the original Spanish version is going to be kept in this wiki, but the updates on the document first would appear here, and later there)
During the implementation of our course-task, we tried to decouple as much as possible the implementation of the protocol from our specific-task domain logic in order the latter, to be able to evolve independently and to not affect (neither to be affected) by the domain logic to which it is applied. The idea is if there are further changes in the FIPA specification, they to be applied to our implementation without affecting the rest of the logic.
The concrete task, which was the reason for the implementation of the FIPA specification is: there are given number of producers of some goods, and correspondingly given number of consumers. It is needed to be developed negotiation protocol between the producers and the consumers for the price of the goods.
The communication protocol between the producer and the consumers is chosen to be of the type English Auction, in which the producer offers its production on a given initial price $0
and sells it to consumers, who correspondingly starts to bid up the price. At the end the consumer, who has offered highest price, win the bidding and receive the goods.
The model (for the both sides - producer and consumer) consists of implementation of two sub-protocols (realized as behaviours):
The first protocol implements the auction. The second is responsible for the execution of the payment.
In the beginning is executed the first protocol. If there is winner in the auction, it is executed the second protocol. Otherwise, the second protocol is omitted and the protocol Producer-Consumer
finishes without winner.
Each of these protocols are implemented as a Finite State Machine (using the class jade.core.behaviours.FSMBehaviour
). Each of the states is a behaviour (jade.core.behaviours.Behaviour
). According to the definition, each finite state machine has primitive internal memory, which is used for coordination between the states. In our case, as memory used for coordination between the internal states, is used an object of the type jade.core.behaviours.DataStore
(which de facto is a map of the type jade.util.leap.HashMap
).
Both implementations of the protocol (from the point of view of the producer, and correspondingly - of the consumer side) have similar structure.
This protocol is implemented by the class ProducerBehaviour
, which inherit the class FSMBehaviour
. The diagram of the states is the following:
According to the English Auction IP
protocol specification, if there is winner in the auction the protocol have to prepare an ACLMessage
message with performative REQUEST
, which will be used as a initialization message by the Request IP
protocol.
If there is a winner, the English Auction IP
protocol creates the REQUEST
message and stores it in the coordination memory. Afterwards is executed the other protocol (behaviour) - Request IP
. It uses the previously stored message to start with the winner the communication related to the payment. After that the termination of the Request IP
, from the ProducerBehaviour
terminates as well.
If there is no REQUEST
message the ProducerBehaviour
protocol (behaviour) terminates directly.
This is the declaration of the enum
:
public enum AuctionTerminationEvent {
NO_WINNER,
WINNER_REFUSE_TO_PAY,
PAYMENT_FAILURE,
PAYMENT_OK
}
It is used in the communication between the agent and the behaviour. Its aim is to let the producer know how the auction has finished.
Also this class declare several abstract methods which must be implemented by the agent, which wants to use that behaviour. The methods are the following one:
-
public double getPrice()
- each time invoked, this method returns a new price for the auction iteration. -
public void handleTerminateEvent(AuctionTerminationEvent)
- notifies the producer for the event of exit from the auction.
This protocol implements the class ConsumerBehaviour
, which inherits the class FSMBehaviour
. The state diagram is the following:
The model of the consumer side is similar to the one of producer side. Before the termination of the behaviour English Auction IP
the agent "knows" whether it is winner or not. If it is not winner, the protocol ConsumerBehaviour
terminates. If the agent is winner is executed the protocol Request IP
. During the initialization of the protocol Request IP
is expected a REQUEST
message which should arrive from the producer. Afterwards starts the communication between the agents between which will be performed the payment.
NOTE: The payment is not implemented in this protocol. This functionality is delegated to the consumer agent because it is quite specific for our implementation.
This class declares several abstract methods which must be implemented by the agent which wants to use this behaviour. The methods are the following:
-
public boolean isPriceAcceptable(double)
- Returnstrue
if the price proposed by the producer in order to sell the goods is accepted by the consumer andfalse
otherwise. -
public boolean isReadyToPay(double)
- Checks whether the consumer is ready for the proposed payment or not. -
public boolean executePayment(AID,double)
- Executes the payment to the producer and returnstrue
if the payment is successful andfalse
otherwise.
At this moment, the specification of the protocol is in status "Experimental" and so far there is no implementation in the used Jade
distribution. For that reason the English auction protocol had to be implemented from scratch.
The main part of the protocol is implemented in the class EnglishAuctionInitiator
which inherits from the class FSMBehaviour
. Although at the end the agent uses the class EnglishAuctionInitiatorImpl
(which inherits from EnglishAuctionInitiator
), which makes the connection between the protocol and the agent, using the methods defined in the class ProducerBehaviour
.
The state diagram is the following:
Each of the states is a behaviour (which in most of the cases inherit from jade.core.behaviours.OneShotBehaviour
). Again as shared memory is used an object of type jade.core.behaviours.DataStore
. In fact this DataStore
is used by ProducerBehaviour
as well.
The producer performs a broadcast
to all agents registered in DFService
independently of the name of the registered service.
The main part of the protocol is implemented in the class EnglishAuctionParticipant
which inherits from the class FSMBehaviour
. Finally, the agent uses the class EnglishAuctionParticipantImpl
(which inherits from EnglishAuctionParticipant
), which connects the protocol and the agent, using the methods provided by the class ConsumerBehaviour
.
The state diagram is the following:
Each of the states is a behaviour (which in most of the cases inherits from jade.core.behaviours.OneShotBehaviour
). Again, as a shared memory is used the object of type jade.core.behaviours.DataStore
. This memory is used by the ConsumerBehaviour
as well.
At this moment, the specification of the protocol is with status "Standard", thus there is implementation of in the used Jade
distribution. According to JADE Programmer's Guide, in order to implement this protocol are needed to be used the classes jade.proto.AchieveREInitiator
and jade.proto.AchieveREResponder
. For that reason were used these classes.
The main part of the protocol is implemented by the class RequestInteractionProtocolInitiator
which inherits from the class AchieveREInitiator
. In fact the agent uses the class RequestInteractionProtocolInitiatorImpl
(which inherits from RequestInteractionProtocolInitiator
), which is the connection between the protocol and the agent, using the methods defined in the class ProducerBehaviour
.
In the beginning, the class RequestInteractionProtocolInitiator
obtains the REQUEST
message from the DataStore
, stored by the English auction behaviour.
At the end of the execution, the class RequestInteractionProtocolInitiatorImpl
uses the methods by the class ProducerBehaviour
and notifies the producer agent for the exit of the payment.
The main part of the protocol is implemented by the class RequestInteractionProtocolResponder
which inherits from the class AchieveREResponder
. In fact the agent uses the class RequestInteractionProtocolResponderImpl
(which inherits from RequestInteractionProtocolResponder
), which is the connection between the protocol and the agent, using the methods defined in the class ConsumerBehaviour
.
At the beginning, the class RequestInteractionProtocolResponder
receives the REQUEST
message by the producer and prepare the response.
The class RequestInteractionProtocolResponderImpl
uses the methods of the class ConsumerBehaviour
and "asks" the corresponding agent whether is ready to pay. Respectively if the answer is positive, the payment terminates successfully.
The architecture of the protocol Producer-Consumer
is the following:
All the classes from this protocol use the standard Java logging
. Its configuration could be modified in the class ProdConsConfiguration
.
The internal states of the English auction protocol (in the both sides - producer and consumer) are implemented as nested classes
.
The nested classes by the producer side are implemented in the class EnglishAuctionInitiator
. They are as follows:
-
PrepareInitiations
- prepares the initiation messages of the protocol (with performativeINFORM
). -
SendInitiations
- sends the initiation messages. -
PrepareCfps
- prepares the initiation messages for each iteration of the auction (with performativeCFP
). -
SendCfps
- sends the initiation messages of the initiation of an auction iteration. -
ReplyReceiver
- responsible for collection of the received messages. -
SeqChecker
- verifies that the received messages are in the expected by the protocol sequence. -
NotUnderstoodHandler
- manage the messages which are not expected by the protocol. -
FailureHandler
- manages the messages causing failure. -
OutOfSequenceHandler
- manages the messages which are not in sequence. -
ProposeHandler
- manages the confirmations by the consumer (messages with performativePROPOSE
). -
SessionsVerifier
- verifies that each consumer which is contacted participates in the auction (for the purpose, there is an session object which is kept by the producer). -
PrepareProposals
- prepares the notifications which the consumer receives whether it is winner in the current iteration of the auction (i.e. messages with performativesACCEPT_PROPOSAL
andREJECT_PROPOSAL
). -
SendProposals
- sends the notifications. -
TerminateBiddingIteration
- terminates the current iteration of the auction. -
PrepareClosingInforms
- prepares the messages for termination of the auction (messages with performativeINFORM
and which is the winner of the auction). -
SendClosingInforms
- sends the messages for termination of the English auction to the consumers (message with performativeINFORM
). -
PrepareWinnerRequest
- prepares the message with performativeREQUEST
which will be used as initialization message by the protocolRequest Interaction Protocol
.
The nested classes by the side of the consumer are implemented in the class EnglishAuctionParticipant
. They are the following:
-
InitInformReceiver
- receives the message with performativeINFORM
with which the producer starts the protocol. -
NextMsgReceiver
- receives the messages after the firstINFORM
message. -
SeqChecker
- verifies that the received messages are in sequence expected by the protocol. -
OutOfSeqHandler
- manages the messages which are out of sequence. -
NextReplySender
- sends the responses of the messages received during the auction. -
CfpHandler
- manages the offers by the producer (messages with performativeINFORM
. -
AcceptProposalHandler
- manages the confirmation of the producer which the producer in the current iteration of the auction (message with performativeACCEPT_PROPOSAL
). -
RejectProposalHandler
- manages the rejection of the producer to the consumers which are not winners in the current iteration of the auction (message with performativeREJECT_PROPOSAL
). -
TerminateBiddingIteration
- terminates the current iteration of the auction and cleans the coordination memory from the temporary information stored during the iteration. -
ClosingInformHandler
- manages the message which closes the auction (message with performativeINFORM
).
This protocol is implemented using Java SDK 1.6
and Jade 3.7
.
In order to participate in an auction, the consumer must register at least one service in DFService
.
The agents have to create the behaviours using the respective constructors of the classes ProducerBehaviour
and ConsumerBehaviour
. The producer and consumer have to create an anonymous class (or just a class which inherits from the needed behaviour) implementing the abstract methods defined respectively in ProducerBehaviour
and ConsumerBehaviour
.
The producer's behaviour can be used in the following manner:
public class ProducerAgent extends Agent {
public ProducerAgent() {
}
// --- Methods (Agent) ---
@Override
protected void setup() {
// ...
pb = new ProducerBehaviour(this) {
@Override
public double getPrice() {
// your calculation of the new price here
double newPrice = ...;
return newPrice;
}
@Override
public void handleTerminateEvent(AuctionTerminationEvent event) {
// your handling of the exit event from the auction here
}
};
addBehaviour(pb);
// ...
}
}
The class ProducerMockAgent
is an simple example of a producer agent.
The consumer's behaviour can be used in the following manner:
public class ConsumerAgent extends Agent {
public ConsumerAgent() {
}
// --- Methods (Agent) ---
@Override
protected void setup() {
// ...
ConsumerBehaviour cb = new ConsumerBehaviour(this) {
@Override
public boolean isPriceAcceptable(double offeredPrice) {
// your implementation here
boolean isAcceptable = ...;
return isAcceptable;
}
@Override
public boolean isReadyToPay(double price) {
boolean isReadyToPay = ...; // your implementation here
return isReadyToPay;
}
@Override
public boolean executePayment(AID aid, double price) {
// your implementation of the payment here
boolean isPaymentSuccessful = ...;
return isPaymentSuccessful;
}
};
addBehaviour(cb);
// ...
}
}
The class ConsumerMockAgent
is an simple example of a consumer agent.
In the folder examples
there is a demonstration how is used the protocol Producer-Consumer
.
In the package agentes09.negotiation.ProdConsProtocol.mock.agents
are implemented several fake agents:
Here there is short description of the classes from the diagram:
-
MockAgent
- a fake agent which registers itself inDFService
. -
ProducerMockAgent
- a fake producer agent which creates and adds among its behaviours the behaviour of the protocolProducerBehaviour
. -
ConsumerMockAgent
- a fake consumer agent, which creates and adds to its behaviours the behaviour of the protocolConsumerBehaviour
. -
OnceBidConsumer
- a fake consumer agent which participates in the auction, but confirms only in the first iteration. -
TwiceBidsConsumer
- a fake consumer agent which participates in the auction, but confirms only the first two iterations. -
ThreeBidsConsumer
- a fake consumer agent which participates in the auction and the confirms only the first three times of the auction. It is an abstract class. -
ThreeBidsConsumerNotReadyToPay
- a fake consumer agent of typeThreeBidsConsumer
, which implements the methodisReadyToPay(double)
to return alwaysfalse
. This causes the termination of the protocol and the payment step is never performed. -
ThreeBidsConsumerReadyToPayWithPaymentFailure
- a fake consumer agent of typeThreeBidsConsumer
, which implements the methodisReadyToPay(double)
to return alwaystrue
but the methodexecutePayment(AID,double)
always to returnfalse
. In other words, a failure occurs during the payment by the consumer. -
ThreeBidsConsumerReadyToPayPaymentOK
- a fake consumer agent of typeThreeBidsConsumer
which implements the methodsisReadyToPay(double)
andexecutePayment(AID,double)
always to returntrue
. This means that there is a winner in the auction the purchase is successful. -
DoNothingAgent
- a fake agent which only "overhear" the messages and prints them in the command line. Its aim is to demonstrate that the provider sends messages not only to the consumers but to all of the agents (i.e. that the producers makes abroadcast
). -
LazyAgent
- a fake fictitious agent which only "overhear" for messages. -
SleepyAgent
- a fake fictitious agent which only "overhear" for messages. -
NotServicesRegisteredAgent
- a fake fictitious agent which does not register any service inDFService
and for that reason later is not discovered by the producer agent. The aim of this agent is to demonstrate that if an agent does not register any service, it does not participate in the auction.
The examples are in the package agentes09.negotiation.ProdConsProtocol.examples
. The classes implement several general cases:
-
ExampleProdCons
- an abstract class which prepares and tests the agents container. -
ExampleProdConsNoConsumers
- in this class is shown the case when there are no consumers. Just the producer terminates the behaviour without sending any message. -
ExampleProdConsWinnerRefuseToPay
- in this class are created a producer and three consumers. One consumer is of typeOnceBidConsumer
, other is of typeTwiceBidsConsumer
and the third -ThreeBidsConsumerNotReadyToPay
. In this case the protocol terminates without purchase (with messageREFUSE
). -
ExampleProdConsPaymentFails
- in this class are created a producer and thee consumers. One consumer is of typeOnceBidConsumer
, other is of typeTwiceBidsConsumer
and the third -ThreeBidsConsumerNotReadyToPay
. In this case the protocol terminates without purchase (with messageREFUSE
). This a simulation of a failure that occurs during the payment by the consumer. -
ExampleProdConsOK
- in this class are created a producer and thee consumers. One consumer is of typeOnceBidConsumer
, other is of typeTwiceBidsConsumer
and the third -ThreeBidsConsumerNotReadyToPay
. This is a simulation of termination of the protocol successfully, i.e. there is a winner in the auction and it purchases (i.e. successfully pays) the won good.
All these classes are initialized by an agent of type jade.tools.sniffer.Sniffer
, which intercepts the communication between the producer and consumers and visualize the message exchange between the agents.
Here is presented the output of the agent Sniffer
in each of the examples (except the first one).
In each of the outputs can be seen that the agents lazy-agent
and sleepy-agent
(as they are not consumers, but they have registered services in DFService
) receive the messages from the auction. On the other hand, the agent named no-registered
does not receive any message from the auction, because it has not registered any services in DFService
.
This is an output after the execution of the class ExampleProdConsWinnerRefuseToPay
:
It can be see seen that the last message sent by the winner consumer is with performative REFUSE
.
This is an output from the execution of the class ExampleProdConsPaymentFails
:
It can be seen that the last message sent by the consumer-winner is with performative FAILURE
.
This is an output from the execution of the class ExampleProdConsOK
:
It can be seen that the last message sent by the consumer-winner is with performative INFORM
, which means that the payment is terminated successfully.
The Producer-Consumer
protocol could be improved in the following ways:
-
Could be separated the coordination memory which at the moment is used by the
Producer-Consumer
protocol (the classesProducerBehaviour
andConsumerBehaviour
) and its sub-protocolsFIPA English Auction IP
(EnglishAuctionInitiator
andEnglishAuctionParticipant
) andFIPA Request IP
(RequestInteractionProtocolInitiator
andRequestInteractionProtocolResponder
). In other words, at the moment for example on the producer's side, the coordination memory of the behaviuorProducerBehaviour
which is used for communication between the sub-behavioursEnglishAuctionInitiator
andRequestInteractionProtocolInitiator
, is used as well for the coordination between the internal states (behaviours) of theEnglishAuctionInitiator
yRequestInteractionProtocolInitiator
. As a solution, it is possible in each of the classesEnglishAuctionInitiator
andRequestInteractionProtocolInitiator
to be created an object of typejade.core.behaviours.DataStore
, which will be used for coordination of the internal states of these sub-protocols. In that way the coordination memory ofProducerBehaviour
will contain only information related to the execution of theProducerBehaviour
. The situation of the classes which implements the consumer's side -ConsumerBehaviour
,EnglishAuctionParticipant
andRequestInteractionProtocolResponder
is equivalent. -
It is possible to be refactored the nested classes of the
FIPA English Auction IP
protocol, especially the one which prepare the messages for sending and the one which sends the aforementioned messages. -
It is interesting to refactor the classes
EnglishAuctionInitiator
andEnglishAuctionParticipant
to reuse the logic implemented inJade
, i.e. how is possible to be inherited the classesjade.proto.Initiator
andjade.proto.Responder
respectively by the classesEnglishAuctionInitiator
andEnglishAuctionParticipant
.