Create a new Behaviour¶
This tutorial explains how to create a new behaviour.
The behaviours are the basis of the Skydata. An agent is composed of many behaviours. Each behaviour has a specific goal, for example:
- Regularly migrate to a new Harbour
- Manage the replication process of agents
- Maintain a replication goal
- And so on
Different types of behaviours¶
We can classify these behaviours into different types depending on the way they are called.
This is a list of the different types:
TickerBehaviour
: called every X millisecondsWakerBehaviour
: called once after X millisecondsCyclicBehaviour
: called each time a message is receivedSKAgentBehaviour
: a generic class to compose multiple behaviours
The three first types come directly from the Jade Framework, so we will not explain them.
This tutorial will show how interfacing these behaviours.
Internal update¶
In order to react to internal special event, a mechanism of callback is implemented in the prototype.
The idea is simple:
- The agents define the name of events (strings)
- The behaviours add callbacks to some events (by using the function addInternalUpdate)
- When the event occurs, the agents execute all callbacks listening on this event
Some events can execute callbacks with parameters (for example the event FAMILY_UPDATE
).
When you write a SKAgentBehaviour, take in consideration that:
- If there is no parameter, the method action
will be called
- If there is a parameter, the method actionWithParameters
will be called
Currently, the list of the events is:
AFTER_MIGRATION
: throw when the migration is finishedAFTER_REPLICATION
: throw when the replication is finishedWANT_MIGRATE
: throw when an agent wants to migrate (pass the destination as a parameter)DELETION
: throw when an agent wants to delete itselfFAMILY_UPDATE
: throw when we update the position of a family member (pass its identity as parameter)FAMILY_ADDED
: throw when we add a family memberFAMILY_REMOVED
: throw when we remove a family member
Implement a behaviour¶
In order to create a behaviour for an agent, we need to inherit the SKAgentBehaviour class.
Suppose we want to implement a behaviour that forces an SKD to migrate every time the family size changes or when the position of a family member is updated. In addition, we want to migrate every 30 seconds.
To do that, we need to know when the family size changed so we need to add a callback to FAMILY_ADDED
and to FAMILY_REMOVED
. To initiate the migration, we will use the function migrate
(See here).
Let's create the behaviour in the class MigrateFamilyChanged
:
public class MigrateFamilyChanged extends SKAgentBehaviour {
/**
* Create the behaviour and add it to the agent
*/
public MigrateFamilyChanged(SKAgent agent) {
super(agent);
}
/**
* Get a random harbour for next migration
*
* @return the identity of the next harbour
*/
public SKAID getRandom() {
return ...;
}
@Override
public void action() {
SKD agent = (SKD) this.agent;
// Migrate every 30 seconds
TickerBehaviour tickerBehaviour = new TickerBehaviour(agent, 30000) {
@Override
protected void onTick() {
SKAID harbour = getRandom();
agent.migrate(harbour.toAID());
}
};
agent.addBehaviour(tickerBehaviour);
// When the family is updated
SKAgentBehaviour familyUpdated = new SKAgentBehaviour(agent) {
// Without parameters
public void action() {
print("My family size changed, I migrate !");
SKAID harbour = getRandom();
agent.migrate(harbour.toAID());
}
// With parameters
public void actionWithParameters(Object o) {
SKAID member = (SKAID)o;
print(member.getName() + " moved, I migrate ! ");
SKAID harbour = getRandom();
agent.migrate(harbour.toAID());
}
};
// Add to callback manager
agent.addInternalUpdate('FAMILY_ADDED', familyUpdated);
agent.addInternalUpdate('FAMILY_REMOVED', familyUpdated);
agent.addInternalUpdate('FAMILY_UPDATE', familyUpdated);
}
}
Customizable behaviours¶
Generally, we would like to create a behaviour that will be customizable by adding some parameters to the behaviours. In the previous source code, it would be the delay between two migrations.
To do that, we can add arguments in the harbour description files (see here).
Then, to use it, we can use the array args
in the SKAgent
.
Let's modify the previous source code and assume the argument name is delay_migration.
The source code becomes:
public class MigrateFamilyChanged extends SKAgentBehaviour {
...
@Override
public void action() {
SKD agent = (SKD) this.agent;
int delay = (Integer)(agent.args.getOrDefault("delay_migration", 30000));
// Migrate every 30 seconds
TickerBehaviour tickerBehaviour = new TickerBehaviour(agent, 30000) {
@Override
protected void onTick() {
SKAID harbour = getRandom();
agent.migrate(harbour.toAID());
}
};
agent.addBehaviour(tickerBehaviour);
...
}
}
Some useful functions to code a new agent¶
This section lists useful functions for a new behaviour and references their documentation links:
To send or receive messages:
skSendNormal
: send a message to another agent without using the reliable sending protocol. (See here)skSendReliable
: send a message to another agent using the reliable sending protocol. (See here)broadcast
: broadcast a message to a list of agents (you can specify if you want to use reliable sending protocol) (See here)skReceive
: receive a message matching a message template (See here)
To store permanently an object in the memory of migration (even after a replication):
createStorageObject
: take a key and an object and store this object referenced by the key (See here)getStorageObject
: get an object referenced by a specific key (See here)hasStorageObject
: verify if an object is stored (See here)
Manage the migration:
afterMove
: called just after a migration (See here)doMove
: called during the migration process (See here)beforeMove
: called just before the migration process (See here)blockMigrate
: block the migration temporarily (See here)unblockMigrate
: unblock the migration (See here)canMigrate
: verify if the agent can migrate (See here)migrate
: initiate a migration process on a specific Harbour (See here)
Manage the replication:
afterClone
: called just after a replication (See here)doClone
: called during the replication process (See here)beforeClone
: called just before the replication processblockReplicate
: block the replication temporarily (See here)unblockReplicate
: unblock the replication (See here)canReplicate
: verify if the agent can replicate (See here)clone
: initiate a replication process on a specific Harbour (See here)
All function documentation is available here.