350 likes | 1.62k Views
Primitive Behaviours. Simple Behaviour: A basic class that can be extend in various ways and most often is the best solution when other promising behaviours are found to have some hidden quirks.Cyclic Behaviour: This behaviour stays active as long as its agent is alive and is called repeatedly after every event. Quite useful to handle message reception. Ticker Behaviour: A cyclic behaviour which periodically executes some user-defined piece of code.One Shot Behaviour: This executes ONCE and d9455
E N D
1. Using Jade Behaviours By Kiran
3. Composite Behaviours Parallel Behaviour: Controls a set of children behaviours that execute in parallel.
The important thing is the termination condition: we can specify that the group terminates
when ALL children are done
N children are done
or ANY child is done.
Sequential Behaviour: This behaviour executes its children behaviours one after the other and terminates when the last child has ended.
4. Behaviour Methods Most of the time, added behaviours disappear automatically when their job is done; however, it is also possible to remove them explicitly.
There are 2 versions of add and remove methods depending whether the behaviours are at the top level or part of a composite behaviour.
in Agent
void add Behaviour( Behaviour )
void remove Behaviour( Behaviour )
in Composite Behaviour
void add SubBehaviour( Behaviour )
void remove SubBehaviour( Behaviour )
5. Two-step revisited The problem of combining a recurrent action which prints a message every 300 ms with a sequence where we output 2 messages at specified times.
First for the Looping, before we relied on block(dt) to wait for dt msec.
Now we use Jade's Ticker Behaviour where the recurring actions is specified in the onTick method. Below we show how its use resolves concisely the Looping part of the problem:
6. First Step
7. Output
8. Second Step
We want the agent to do a 4 things in order:
wait 0.25 sec
print out a first message
wait 0.5 sec
print out a second message
Two simple solutions which don't use a SequentialBehaviour
9. Second Step - First Method We create two parallel Wakers to trigger at 250 ms and 750 ms espectively;
timeout specified for a WakerBehaviour represents a delay from the time the Behaviour is CREATED, not from the time it STARTS executing.
Note that we use addBehaviour directly on the agent and not addSubBehaviour on a sequence.
addBehaviour( new WakerBehaviour( this, 250 )
{
protected void handleElapsedTimeout()
{
System.out.println( "... Message 2" );
addBehaviour( new WakerBehaviour( myAgent, 500 ) { protected void handleElapsedTimeout() { System.out.println( "... Message1" ); }
});
}
});
10. Second Step - Second Method we achieve sequentiality by creating the second Waker when the first finishes.
In this case the timeout, can be set to the delay (500ms) and not to the absolute time (750ms).
addBehaviour( new WakerBehaviour( this, 250 )
{
protected void handleElapsedTimeout()
{
System.out.println( "... Message 2" );
addBehaviour( new WakerBehaviour( myAgent, 500 ) { protected void handleElapsedTimeout() { System.out.println( "... Message1" ); }
});
}
});
11. Delay Behaviours If you wish to introduce delays as steps in SequentialBehaviours, we need to apply delay from the time the behaviour starts.
This can be achieved by modifying the code of the WakerBehaviour to obtain the DelayBehaviour class which computes the wakeup time in the onStart() method.
Whenever the behaviour is activated, we compute dt, the time remaining to wakeup. If it is negative, we call handleElapsedTimeout and "finish"; otherwise we block for the remaining time
13. Buyers and Sellers Consider a simplified E-commerce situation where:
Buyer agents ask for quotes from Seller Agents and then proceed to purchase at the cheapest price - if it's within budget; if not, they ask for another round of quotes.
Sellers answer requests with a (random) price which is valid for a limited time.
The Sellers keep tabs on what price they quoted to each client and accept a purchase if the offered price is equal to the amount quoted AND if the request is received in time.
14. Buyers and Sellers Message Exchange
15. In this case, there are several interesting problems that have to be solved:
providing timeouts to limit the time spent waiting for answers.
chaining Behaviours to achieve coherent conversations
handling parallel requests
handling parallel conversations
dealing with unwanted messages left in the input queue
16. Timeout Mechanism In our application, we don't want to wait forever for answers to requests.
So we need a behaviour with a timeout mechanism which waits until either the required message arrives or a specified delay has passed.
When we create a Behaviour, we need to specify a template for the message we wish to receive and a timeout.
The Behaviour terminates when either the message arrives or the delay elapses.
17.
Class definition for myReciever class
public class myReceiver extends SimpleBehaviour
{
private MessageTemplate template;
private long timeOut, wakeupTime;
private boolean finished;
private ACLMessage msg;
public ACLMessage getMessage() { return msg; }
public myReceiver(Agent a, int millis, MessageTemplate mt)
{
super(a);
timeOut = millis;
template = mt;
}
18. The handle method receives the message as a parameter or NULL if the timeout occurred first.
addBehaviour( new myReceiver(this, 40000, MessageTemplate.MatchPerformative(ACLMessage.INFORM_ REF) {
public void handle( ACLMessage msg )
{
If (msg == null)
System.out.println("Timeout");
else
System.out.println("Received: "+ msg);
}
});
19. Implementing conversations We need to assign a unique identifier to each conversation called the conversationID (CID).
A field is reserved for the CID in all ACLMessages and Jade's message templates allow the selection of messages based on conversationID.
Sample code to generate unique identifiers:
protected static int cidCnt = 0;
String cidBase ;
String genCID() {
if (cidBase==null) {
cidBase = getLocalName() + hashCode() + System.currentTimeMillis()%10000 + "_";
}
return cidBase + (cidCnt++);
}
20. The first part of the ID is private to each agent. It is based on the agent's local name - which is globally unique - combined with the hashCode and the clock.
To use this (unique ID) in the initialization ACL messages:
ACLMessage newMsg( int perf, String content, AID dest)
{
ACLMessage msg = newMsg(perf);
if (dest != null)
msg.addReceiver( dest );
msg.setContent( content );
return msg;
}
ACLMessage newMsg( int perf)
{
ACLMessage msg = new ACLMessage(perf);
msg.setConversationId( genCID() );
return msg;
}
21. Seller Agent setup method for Seller agents receives the QUERY_REF message
For each QUERY_REF message , a Transaction object is created.
A Transaction object
Builds and schedules the behaviours required to send a quote and wait for a confirmation
Its attributes will enable those behaviours to share information.
In particular, the QUERY msg whose conversationID will serve as a unique identifier for the conversation.
A field is reserved for the CID in all ACLMessages and Jade's message templates allow the selection of messages based on conversationID.
23. Transaction class is a subclass of SequentialBehaviour.
In Transaction, a conversation consists of 2 behaviours:
- a DelayBehaviour to simulate processing time [0-2 s] before sending the quote
- a Receiver where we wait for a possible order and agree or refuse depending on the price
These are created in the onStart() method which is called once by Jade after the object is created
26. Buyer Agent A Sequence of behaviours is built in setup() where a QUERY_REF is boradcasted to 3 Sellers asking for price quotations, which sets off the whole process.
The Behaviours include:
3 receivers in Parallel to treat the answers from the Sellers.
These have a 1 sec timeout.
A random (0-2s) Delay before sending off a REQUEST to the lowest bidder
A Receiver which waits for AGREE/REFUSE with the common conversation ID.
In case of any failure, the Buyer sets off another round of negotiation by simply calling setup again.
29. Result - Seller Here is the result of running the Sellers in the main container.
We started off 2 Buyers, James and Helen, in another window.
vor% java jade.Boot s1:Seller s2:Seller s3:Seller
- s1 <- QUERY from james. Will answer $14 in 485 ms
- s2 <- QUERY from james. Will answer $80 in 439 ms
- s3 <- QUERY from james. Will answer $24 in 402 ms
- s2 <- QUERY from helen. Will answer $76 in 268 ms
- s1 <- QUERY from helen. Will answer $20 in 1822 ms
- s3 <- QUERY from helen. Will answer $92 in 1128 ms
Got proposal $71 from helen & my price is $76 == REFUSE
- s1 <- QUERY from helen. Will answer $91 in 565 ms
- s2 <- QUERY from helen. Will answer $9 in 602 ms
- s3 <- QUERY from helen. Will answer $80 in 1564 ms
30. Got proposal $68 from james & my price is $14 == AGREE
Timeout ! quote $24 from s3 is no longer valid
Timeout ! quote $80 from s2 is no longer valid
Timeout ! quote $92 from s3 is no longer valid
Timeout ! quote $20 from s1 is no longer valid
Timeout ! quote $91 from s1 is no longer valid
Timeout ! quote $9 from s2 is no longer valid
Timeout ! quote $80 from s3 is no longer valid
- s2 <- QUERY from helen. Will answer $78 in 556 ms
- s1 <- QUERY from helen. Will answer $41 in 1223 ms
- s3 <- QUERY from helen. Will answer $22 in 564 ms
Got proposal $47 from helen & my price is $22 == AGREE
Timeout ! quote $78 from s2 is no longer valid
Timeout ! quote $41 from s1 is no longer valid
31. Result - Buyer phobos% java jade.Boot -container -host vor helen:Buyer james:Buyer
Buyer helen gets prices.
Buyer james gets prices.
Got quote $76 from s2
Got quote $24 from s3
Got quote $80 from s2
Got quote $14 from s1
Best Price $76 from s2
ORDER at 71
Got REFUSE from s2
Buyer helen gets prices.
Best Price $14 from s1
ORDER at 68
32. Got AGREE from s1
--------- Finished ---------
Got quote $91 from s1
Got quote $9 from s2
Best Price $9 from s2
ORDER at 77
==helen timed out
Buyer helen gets prices.
Got quote $78 from s2
Got quote $22 from s3
Best Price $22 from s3
ORDER at 47
Got AGREE from s3
--------- Finished ---------