-
Notifications
You must be signed in to change notification settings - Fork 99
BDIAgents_step2
This second step consists in defining the gold miner agents using the GAMA BDI architecture.
- Definition of global predicates
- Definition of the gold miner species
- Definition of the gold miner perceptions
- Definition of the gold miner rules
- Definition of the gold miner plans
- Creation and display of the gold miners
A classic paradigm to formalize the internal architecture of cognitive agents in Agent-Oriented Software Engineering is the BDI (Belief-Desire-Intention) paradigm. This paradigm, based on the philosophy of action (Bratman, 1987), allows to design expressive and realistic agents.
The concepts of Belief-Desire-Intention can be summarized as follow for the Gold Miner: the Miner agent has a general desire to find gold. As it is the only thing it wants at the beginning, it is its initial intention (what it is currently doing). To find gold, it wanders around (its plan is to wander). When it perceives some gold nuggets, it stores this information (it has a new belief about the existence and location of this gold nugget), and it adopts a new desire (it wants to extract the gold). When it perceives a gold nugget, the intention to find gold is put on hold and a new intention is selected (to extract gold). To achieve this intention, the plan has two steps, i.e. two new (sub)intentions: to choose a gold nugget to extract (among its known gold nuggets) and to go and take it. And so on.
In GAMA, we propose a control architecture for agents based on this paradigm. This control architecture provides the agents with 3 databases linked to the agent cognition:
- belief_base (what it knows): the internal knowledge the agent has about the world or about its internal state, updated during the simulation. A belief can concern any type of information (a quantity, a location, a boolean value, etc).
- desire_base (what it wants): objectives that the agent would like to accomplish, also updated during the simulation. Desires can have hierarchical links (sub/super desires) when a desire is created as an intermediary objective.
- intention_base (what it is doing): what the agent has chosen to do. The current intention will determine the selected plan. Intentions can be put on hold (for example when they require a sub-intention to be achieved).
In addition, the BDI architecture provides agents with three types of behavior structures
- Perception: a perception is a function executed at each iteration to update the agent's Belief base, to know the changes in its environment (the world, the other agents and itself). The agent can perceive other agents up to a fixed distance or inside a specific geometry.
- Rule: a rule is a function executed at each iteration to infer new desires or beliefs from the agent's current beliefs and desires, i.e. a new desire or belief can emerge from the existing ones.
- Plan: the agent has a set of plans, which are behaviors defined to accomplish specific intentions. Plans can be instantaneous and/or persistent, and may have a priority value (that can be dynamic), used to select a plan when several possible plans are available to accomplish the same intention.
To be more precise on the behavior of BDI agents (what the agent is going to do when activated), this one is composed of 10 steps (see (Caillou et al., 2017) and (Taillandier et al., 2016) for more details):
- Perceive: Perceptions are executed.
- Rule: Rules are executed.
- Is one of my intentions achieved?: If one of my intentions is achieved, sets the current plan to nil and removes the intention from the intention base. If the achieved intention's super-intention is on hold, it is reactivated (its sub-intention just got completed).
- Do I keep the current intention?: To take into account the environment instability, an intention-persistence coefficient is applied: with this probability, the current intention is removed from the intention stack.
- Do I have a current plan?: If I have a current plan, just execute it. Similarly to intentions, a plan-persistence coefficient is defined: with this probability, the current plan is just dropped.
- Choose a desire as new current intention: If the current intention is on hold (or the intention base is empty), choose a desire as new current intention. The new selected intention is the desire with higher priority.
- Choose a plan as a new current plan: The new current plan is selected among the plans compatible with the current intention (and if their activation condition is checked) and with the highest priority.
- Execute the plan: The current plan is executed.
- Is my plan finished?: To allow persistent plans, a plan may have a termination condition. If it is not reached, the same plan will be kept for the next iteration.
- Was my plan instantaneous?: Most agent-based simulation frameworks (GAMA included) are synchronous frameworks using steps. One consequence is that it may be useful to apply several plans during one single step. For example, if a step represents a day or a year, it would be unrealistic for an agent to spend one step to apply a plan like "choose a destination". This kind of plans (mostly reasoning plans) can be defined as instantaneous: in this case a new thinking loop is applied during the same agent step.
The architecture introduces two new main types of variables related to cognition:
-
predicate: a predicate unifies the representation of the information about the world. It can represent a situation, an event or an action.
-
mental_state: it represents the element (belief, desire, intention) manipulated by the agent and the architecture to take a decision. A mental state is composed of a modality, a predicate or another mental state, a real value and a lifetime. The modality indicates the type of the mental state (e.g. a belief or a desire), the predicate indicates the fact about which is this mental state (a mental state can also be about another mental state like a belief about a belief, etc), the value has a different interpretation depending on the modality and finally, the lifetime indicates the duration of the mental state (it can be infinite).
As a first step of the integration of the BDI agents in our model, we define a set of global predicate that will represent all the information that will be manipulated by the miner agents:
- mine_location: represents the information about the location of a gold mine.
- choose_goldmine: represents the information that the miner wants to choose a gold mine.
- has_gold: represents the information that the miner has a gold nugget.
- find_gold: represents the information that the miner wants to find gold.
- sell_gold: represents the information that the miner wants to sell gold.
We define as well two global string (mine_at_location and empty_mine_location) for simplification purpose and to avoid misspellings.
global {
...
string mine_at_location <- "mine_at_location";
string empty_mine_location <- "empty_mine_location";
predicate mine_location <- new_predicate(mine_at_location) ;
predicate choose_goldmine <- new_predicate("choose a gold mine");
predicate has_gold <- new_predicate("extract gold");
predicate find_gold <- new_predicate("find gold") ;
predicate sell_gold <- new_predicate("sell gold") ;
...
}
We then define a miner species with the moving skill and the simple_bdi control architecture. The miner agents have 5 variables:
- viewdist: distance of perception of the miner agent
- speed: speed of the agent
- mycolor: the color of the agent (random color)
- target: where the agent wants to go
- gold_sold: the number of gold nuggets sold by the agent
We define the init block of the species such as to add at the creation of the agent the desire to find gold nuggets (find_gold predicate). we use for that the add_desire action provides with the BDI architecture.
At last, we define an aspect in which we draw the agent with its mycolor color and with a depth that depends on the number of gold nuggets collected.
species miner skills: [moving] control:simple_bdi {
float viewdist<-1000.0;
float speed <- 2#km/#h;
rgb mycolor<-rnd_color(255);
point target;
int gold_sold;
init
{
do add_desire(find_gold);
}
aspect default {
draw circle(200) color: mycolor border: #black depth: gold_sold;
}
}
We add a perceive statement for the miner agents. This perceive will allow to detect the gold mine that are not empty (i.e. the quantity of gold is higher than 0) at a distance lower or equal to "viewdist". The use of the focus statement allows to add for each detected goldmine a belief corresponding to the location of this goldmine. The name of the belief will be "mine_at_location" and the location value of the goldmine will be stored in the values (a map) variable of the belief at the key "location_value". In addition, we ask the miner agent to remove the intention to find gold, allowing the agent to choose a new intention. The boolean value of the remove_intention action is used to specify if the agent should or not remove the given intention from the desire base as well. In our case, we choose to keep the desire to find golds.
species miner skills: [moving] control:simple_bdi {
...
perceive target:goldmine where (each.quantity > 0) in:viewdist {
focus id:mine_at_location var:location;
ask myself {
do remove_intention(find_gold, false);
}
}
}
Note that the perceive statement works as the ask statement: the instructions written in the statement are executed in the context of the perceive agents. It is for that that we have to use the myself keyword to ask the miner agent to execute the remove_intention action.
We define two rules for the miner agents:
- if the agent believes that there is somewhere at least one gold mine with gold nuggets, the agent gets the new desire to has a gold nugget with a strength of 2.
- if the agent believes that it has a gold nugget, the agent gets the new desire to sell the gold nugget with a strength of 3.
species miner skills: [moving] control:simple_bdi {
...
rule belief: mine_location new_desire: has_gold strength: 2.0;
rule belief: has_gold new_desire: sell_gold strength: 3.0;
}
The strength of a desire will be used when selecting a desire as a new intention: the agent will choose as new intention the one with the highest strength. In our model, if the agent has the desires to find gold, to has gold and to sell gold, it will choose as intention to sell gold as it is the one with the highest strength. It is possible to replace this deterministic choice by a probabilistic one by setting the probabilistic_choice built-in varibale of the BDI agent to true (false by default).
The last (and most important) part of the definition of BDI agents consist in defining the plans that the agents can carry out to acheive its intention.
The first plan called letsWander is defined to achieve the find_gold intention. This plan will just consists in executing the wander action of the moving skill (random move).
species miner skills: [moving] control:simple_bdi {
...
plan letsWander intention:find_gold
{
do wander;
}
...
}
The second plan called getGold is defined to achieve the has_gold intention. if the agent has no target (it does not know where to go), it adds a new sub-intention to choose a goldmine and put the current intention on hold (the agent will wait to select a gold mine to go before executing again this plan). The add_subintention has 3 arguments: the sub-intention (choose_goldmine), the super intention (extract_gold) and a boolean that defines if the sub-intention should or not be added as well as a desire. If the agent has already a target, it moves toward this target using the goto action of the moving skill. If the agent reaches its target - goldmine - (target = location), the agent tries to extract gold nuggets from it. If the corresponding goldmine (that one located at the target location) is not empty, the agent extract a gold nugget from it: the agent adds the belief that it has a gold nugget, then the quantity of golds in the gold mine is reduced. Otherwise, if the gold mine is empty, the agent adds the belief that this gold mine is empty. then the target is set to nil. get_current_intention() returns the current intention. As plan getGold is executed only when intention is about the has_gold predicate, the current intention is about this predicate.
species miner skills: [moving] control:simple_bdi {
...
plan getGold intention:has_gold
{
if (target = nil) {
do add_subintention(get_current_intention(),choose_goldmine, true);
do current_intention_on_hold();
} else {
do goto target: target ;
if (target = location) {
goldmine current_mine<- goldmine first_with (target = each.location);
if current_mine.quantity > 0 {
do add_belief(has_gold);
ask current_mine {quantity <- quantity - 1;}
} else {
do add_belief(new_predicate(empty_mine_location, ["location_value"::target]));
}
target <- nil;
}
}
}
...
}
The third plan called choose_closest_goldmine is defined to achieve the choose_goldmine intention that is instantaneous. First, the agent defines the list of all the gold mines it knows (mine_at_location beliefs), then removes the gold mines that it knows that they are empty (empty_mine_location beliefs). If the list of the possible mines is empty, the agent removes the desire and the intention to extract_gold. We use for that the remove_intention action, that removes an intention from the intention base; the second argument allows to define if the intention should be removed as well from the desire base. If the agent knows at least one gold mine that is not empty, it defines as its new target the closest gold mine.
species miner skills: [moving] control:simple_bdi {
...
plan choose_closest_goldmine intention: choose_goldmine instantaneous: true{
list<point> possible_mines <- get_beliefs_with_name(mine_at_location) collect (point(get_predicate(mental_state (each)).values["location_value"]));
list<point> empty_mines <- get_beliefs_with_name(empty_mine_location) collect (point(get_predicate(mental_state (each)).values["location_value"]));
possible_mines <- possible_mines - empty_mines;
if (empty(possible_mines)) {
do remove_intention(extract_gold, true);
} else {
target <- (possible_mines with_min_of (each distance_to self)).location;
}
do remove_intention(choose_goldmine, true);
}
...
}
The last plan called return_to_base is defined to achieve the sell_gold intention. The agent moves in direction of the market using the goto action. if the agent reaches the market, it sells its gold nugget to it: first, it removes the belief that it has a gold nugget, then it removes the intention and the desire to sell golds, at last it increments its gold_sold variable.
species miner skills: [moving] control:simple_bdi {
...
plan return_to_base intention: sell_gold {
do goto target: the_market ;
if (the_market.location = location) {
do remove_belief(has_gold);
do remove_intention(sell_gold, true);
gold_sold <- gold_sold + 1;
}
}
...
}
We define two new global variables:
- nbminer: number of gold miners
- inequality: recomputed at each simulation step: standard deviation of the number of gold nuggets extracted per miners.
In the global init, after creating the gold mines and the market, we create the gold miner agents.
At last, we define a global reflex end_simulation that is activated when all the gold mines are empty and no more miner has a gold nuggets and that pauses the simulation.
global {
...
int nbminer<-5;
float inequality <- 0.0 update:standard_deviation(miner collect each.gold_sold);
...
init
{
...
create miner number:nbminer;
}
reflex end_simulation when: sum(goldmine collect each.quantity) = 0 and empty(miner where each.has_belief(has_gold)){
do pause;
}
}
We add to the map display the miner species.
experiment GoldBdi type: gui {
output {
display map type: opengl
{
species market ;
species goldmine ;
species miner;
}
}
}
model GoldBdi
global {
int nb_mines <- 10;
int nbminer<-5;
market the_market;
string mine_at_location <- "mine_at_location";
string empty_mine_location <- "empty_mine_location";
float step <- 10#mn;
//possible predicates concerning miners
predicate mine_location <- new_predicate(mine_at_location) ;
predicate choose_goldmine <- new_predicate("choose a gold mine");
predicate has_gold <- new_predicate("extract gold");
predicate find_gold <- new_predicate("find gold") ;
predicate sell_gold <- new_predicate("sell gold") ;
float inequality <- 0.0 update:standard_deviation(miner collect each.gold_sold);
geometry shape <- square(20 #km);
init
{
create market {
the_market <- self;
}
create goldmine number:nb_mines;
create miner number:nbminer;
}
reflex end_simulation when: sum(goldmine collect each.quantity) = 0 and empty(miner where each.has_belief(has_gold)){
do pause;
}
}
species goldmine {
int quantity <- rnd(1,20);
aspect default
{
if (quantity = 0) {
draw triangle(200) color: #gray border: #black;
} else {
draw triangle(200 + quantity*50) color: #yellow border: #black;
}
}
}
species market {
int golds;
aspect default
{
draw square(1000) color: #black ;
}
}
species miner skills: [moving] control:simple_bdi {
float viewdist<-1000.0;
float speed <- 2#km/#h;
rgb mycolor<-rnd_color(255);
point target;
int gold_sold;
init
{
do add_desire(find_gold);
}
perceive target:goldmine where (each.quantity > 0) in:viewdist {
focus id:mine_at_location var:location;
ask myself {
do remove_intention(find_gold, false);
}
}
rule belief: mine_location new_desire: has_gold strength: 2.0;
rule belief: has_gold new_desire: sell_gold strength: 3.0;
plan letsWander intention:find_gold
{
do wander;
}
plan getGold intention:has_gold
{
if (target = nil) {
do add_subintention(has_gold,choose_goldmine, true);
do current_intention_on_hold();
} else {
do goto target: target ;
if (target = location) {
goldmine current_mine<- goldmine first_with (target = each.location);
if current_mine.quantity > 0 {
do add_belief(has_gold);
ask current_mine {quantity <- quantity - 1;}
} else {
do add_belief(new_predicate(empty_mine_location, ["location_value"::target]));
}
target <- nil;
}
}
}
plan choose_closest_goldmine intention: choose_goldmine instantaneous: true{
list<point> possible_mines <- get_beliefs_with_name(mine_at_location) collect (point(get_predicate(mental_state (each)).values["location_value"]));
list<point> empty_mines <- get_beliefs_with_name(empty_mine_location) collect (point(get_predicate(mental_state (each)).values["location_value"]));
possible_mines <- possible_mines - empty_mines;
if (empty(possible_mines)) {
do remove_intention(has_gold, true);
} else {
target <- (possible_mines with_min_of (each distance_to self)).location;
}
do remove_intention(choose_goldmine, true);
}
plan return_to_base intention: sell_gold {
do goto target: the_market ;
if (the_market.location = location) {
do remove_belief(has_gold);
do remove_intention(sell_gold, true);
gold_sold <- gold_sold + 1;
}
}
aspect default {
draw circle(200) color: mycolor border: #black depth: gold_sold;
}
}
experiment GoldBdi type: gui {
output {
display map type: opengl
{
species market ;
species goldmine ;
species miner;
}
}
}
- Installation and Launching
- Workspace, Projects and Models
- Editing Models
- Running Experiments
- Running Headless
- Preferences
- Troubleshooting
- Introduction
- Manipulate basic Species
- Global Species
- Defining Advanced Species
- Defining GUI Experiment
- Exploring Models
- Optimizing Model Section
- Multi-Paradigm Modeling
- Manipulate OSM Data
- Diffusion
- Using Database
- Using FIPA ACL
- Using BDI with BEN
- Using Driving Skill
- Manipulate dates
- Manipulate lights
- Using comodel
- Save and restore Simulations
- Using network
- Headless mode
- Using Headless
- Writing Unit Tests
- Ensure model's reproducibility
- Going further with extensions
- Built-in Species
- Built-in Skills
- Built-in Architecture
- Statements
- Data Type
- File Type
- Expressions
- Exhaustive list of GAMA Keywords
- Installing the GIT version
- Developing Extensions
- Introduction to GAMA Java API
- Using GAMA flags
- Creating a release of GAMA
- Documentation generation