/**
* Name: Corridor Multi-Level Architecture with Mathematics Model and Agent Based Model
* Author: Ngoc Anh, Anh, Jean-daniel
* Description: This model shows how to use multi-level architecture. Two corridors are presented : one which can capture the pedestrians
* going through it and computing for them the time before releasing them at the end of the corridor, and an other doing nothing, letting
* the pedestrians moving by themselves in the corridor.
* Tags: multi_level, agent_movement
*/
model pedestrian_corridor_Hybrid_vs_ABM
global
{
//Parameters of the environment
int environment_width <- 200 const: true;
int environment_height <- 100 const: true;
geometry shape <- rectangle(environment_width, environment_height);
float pedestrian_speed <- 2.0;
//Parameters of the corridors
int corridor_width <- 160 ;
int corridor_height <- (int(environment_height * 0.1));
point corridor_location_0 <- {environment_width / 2, environment_height / 4};
geometry corridor_shape_0 <- ( (rectangle ({corridor_width, corridor_height})) at_location corridor_location_0) ;
point corridor_location_1 <- {environment_width / 2, environment_height * 0.75};
geometry corridor_shape_1 <- ( (rectangle ({corridor_width, corridor_height})) at_location corridor_location_1) ;
//Parameters of pedestrian generation
int new_pedestian_generate_frequency <- 2 update: rnd(10) + 1;
point pedestrian_source_0 <- {0, corridor_location_0.y} ;
point pedestrian_source_1 <- {0, corridor_location_1.y} ;
init
{
create corridor number: 2 returns: new_corridors;
ask (new_corridors at 0)
{
do init_corridor corridor_shape: corridor_shape_0 is_hybrid: false;
}
ask (new_corridors at 1)
{
do init_corridor corridor_shape: corridor_shape_1 is_hybrid: true;
}
}
//Generation of pedestrians according to the frequency of generation : one for each corridor
reflex generate_pedestrians when: ( (cycle mod new_pedestian_generate_frequency) = 0 )
{
create pedestrian number: 2 returns: new_pedestrians;
ask (new_pedestrians at 0)
{
do init_location loc: pedestrian_source_0;
}
ask (new_pedestrians at 1)
{
do init_location loc: pedestrian_source_1;
}
}
}
//Species for the pedestrians which can move
species pedestrian skills: [moving] {
corridor last_corridor;
point target_location;
float speed <- pedestrian_speed;
rgb color;
//Initialisation of the target location according to its generation location
action init_location (point loc) {
location <- loc;
target_location <- {environment_width, location.y};
int i <- rnd(255);
color <- rgb(i,i,i);
}
//Reflex to move the agent to its target location and make it die once it reached its target
reflex move_left
{
do move heading: (self) towards (target_location);
if ( (target_location.x - location.x) <= speed )
{
do die;
}
}
}
//Species for the corridor which can capture pedestrians
species corridor {
bool capture_pedestrians;
action init_corridor (geometry corridor_shape, bool is_hybrid)
{
shape <- corridor_shape;
capture_pedestrians <- is_hybrid;
}
float max_speed <- pedestrian_speed;
float macro_length min: 0.0 <- float(corridor_width); // the length of macro_patch
//Species to model the pedestrian captured by the corridor
species captured_pedestrian parent: pedestrian schedules: []
{
float released_time;
aspect default { }
}
init
{
create corridor_info_drawer number: 1 with: [target :: self];
}
//Reflex to capture the pedestrians overlapping the corridor ie entering the corridor
reflex aggregate when: capture_pedestrians
{
list tobe_captured_pedestrians <- (pedestrian overlapping shape) where ( (each.last_corridor != self) and ((each.location).x < (self.location).x) ) ;
if !(empty (tobe_captured_pedestrians))
{
capture tobe_captured_pedestrians as: captured_pedestrian returns: cps {
last_corridor <- myself;
}
if !(empty (cps))
{
//Computation of the time when the pedestrians captured will be released according to the speed
// and the time they should make to pass the corridor if they move by themselves
float group_outgoing_time <- time + (corridor_width / (pedestrian_speed) );
loop cp over: cps
{
cp.released_time <- group_outgoing_time;
}
}
}
}
//Reflex to release the pedestrians when we consider they were enough time inside the corridor
reflex disaggregate
{
list tobe_released_pedestrians <- members where (time >= (captured_pedestrian (each)).released_time);
if !(empty (tobe_released_pedestrians))
{
release tobe_released_pedestrians as: pedestrian in: world returns: released_pedestrians;
loop rp over: released_pedestrians
{
rp.speed <- pedestrian_speed;
rp.location <- {((environment_width / 2) + (corridor_width / 2)), ((corridor_shape_1).location).y};
}
}
}
}
species corridor_info_drawer
{
corridor target;
aspect base
{
if target.capture_pedestrians
{
draw 'Hybrid model (coupling: ABM and Mathematical Model)' color: #yellow at: {(target.location).x - target.shape.width/2, (target.location).y - 10} font: font("Helvetica", 20 * #zoom, #bold);
draw 'Captured agents: ' + string(length(target.members)) color: #yellow at: {(target.location).x + 1 - target.shape.width/2, (target.location).y + 1} font: font("Helvetica", 20 * #zoom, 0);
}
else
{
draw 'Agent-Based Model (ABM)' color: #yellow size: 7 at: {(target.location).x - target.shape.width/2, (target.location).y - 10} font: font("Helvetica", 20 * #zoom, #bold);
}
}
}
experiment default_experiment type: gui autorun: true
{
float minimum_cycle_duration <- 10 #msec;
output
{
display default_display background: #black toolbar: false fullscreen: true
{
species pedestrian {
draw circle(2) color: color;
}
species corridor {
draw shape wireframe: true color: #white;
}
species corridor_info_drawer aspect: base;
}
}
}