/**
* Name: comparison_ABM_EBM_SIR
* Author: Benoit Gaudou 
* Description: Comparison between an agent-based and an equation-based model of the SIR model. 
* 	The ABM use a grid to place the agents, and each cell will be the location of an agent, while the EBM 
* 	is only using a ODE System and no geographical representation.
* Tags: equation, math, grid
*/
model comparison_ABM_EBM_SIR

global {
	//Number of susceptible individuals
	int number_S <- 499; 
	//Number of infectious individuals
	int number_I <- 1; 
	//Number of Resistant individuals
	int number_R <- 0; 
	//Beta parameter used for the infection of susceptible individuals
	float beta <- 0.1; 
	//Gamma parameter used for the resistance gained by the infectious individuals
	float gamma <- 0.01;
	//Size of the neighbours
	int neighbours_size <- 2;
	//Total number of individuals
	int N <- number_S + number_I + number_R;
	//Number of hosts (for ABM)
	int nb_hosts <- number_S + number_I + number_R update: length(Host);
	//Number of infected hosts (for ABM)
	int nb_infected <- number_I update:  Host count (each.is_infected);
	float hKR4 <- 0.7;
	geometry shape <- square(50);
	init {
		//Create the number of hosts susceptibles
		create Host number: number_S {
			is_susceptible <- true;
			is_infected <- false;
			is_immune <- false;
			color <- rgb(46,204,113);
		}
		//Create the number of hosts infectious
		create Host number: number_I {
			is_susceptible <- false;
			is_infected <- true;
			is_immune <- false;
			color <- rgb(231,76,60);
		}
		//Create the node agent for the SIR ODE System
		create node_agent number: 1 {
			S <- float(number_S);
			I <- float(number_I);
			R <- float(number_R);
		}
	}

}
//Grid that will be used to discretize space
grid sir_grid width: 50 height: 50 {
		rgb color <- #white;
		list neighbours <- (self neighbors_at neighbours_size) of_species sir_grid;
	}
	
//Species host which represents the host of the disease
species Host {
	
	//Different booleans to know in which state is the host
	bool is_susceptible <- true;
	bool is_infected <- false;
	bool is_immune <- false;
	
	//Color of the host
	rgb color <- rgb(46,204,113);
	
	//Location of the agent among the grid
	sir_grid myPlace;
	//Count of neighbors infected 
    int ngb_infected_number function: self neighbors_at(neighbours_size) count(each.is_infected);
	
	init {
		//The location is chosen randomly
		myPlace <- one_of(sir_grid);
		location <- myPlace.location;
	}
	//Reflex to move the agent in the neighbours cells
	reflex basic_move {
		myPlace <- one_of(myPlace.neighbours);
		location <- myPlace.location;
	}
	//Reflex to pass the agent to the state infected 
	reflex become_infected when: is_susceptible {
			//Probability of being infected according to the number of infected among the neighbours
    		if (flip(1 - (1 - beta)  ^ ngb_infected_number)) {
        		is_susceptible <-  false;
	            	is_infected <-  true;
	            	is_immune <-  false;
	            	color <-  rgb(231,76,60);       			
			}    				
	}
	//Reflex to pass the agent to the state immune
	reflex become_immune when: (is_infected and flip(gamma)) {
		is_susceptible <- false;
		is_infected <- false;
		is_immune <- true;
		color <- rgb(52,152,219);
	} 
	
	aspect basic {
		draw circle(1) color: color;
	}

}
//Species node agent that will represent the SIR Ordinary differential equations system
species node_agent {
	float t;
	float I;
	float S;
	float R;
	equation eqSIR {
		diff(S,t) = -beta * S * I / N ;
		diff(I,t) = beta * S * I / N - gamma* I;
		diff(R,t) = gamma* I;
    }
	reflex solving {solve eqSIR method:#rk4 step_size: 1;}
	
}

experiment Simulation_ABM_EBM type: gui {
	parameter 'Number of Susceptible' type: int var: number_S <- 495 category: "Initial population";
	parameter 'Number of Infected' type: int var: number_I <- 5 category: "Initial population";
	parameter 'Number of Removed' type: int var: number_R <- 0 category: "Initial population";
	parameter 'Beta (S->I)' type: float var: beta <- 0.1 category: "Parameters";
	parameter 'Gamma (I->R)' type: float var: gamma <- 0.01 category: "Parameters";
	parameter 'Size of the neighbours' type: int var: neighbours_size <- 1 min: 1 max: 5 category: "Infection";
	output {
		layout #split;
		display sir_display axes: false { 
			grid sir_grid border: #lightgray;
			species Host aspect: basic;	
		}
		display ABM axes: false { 
			chart 'Population' type: series background: #white style: exploded {
				data 'susceptible' value: (Host as list) count (each.is_susceptible) color: rgb(46,204,113) marker_size: 0.5;
				data 'infected' value: (Host as list) count (each.is_infected) color: rgb(231,76,60) marker_size: 0.5;
				data 'immune' value: (Host as list) count (each.is_immune) color: rgb(52,152,219) marker_size: 0.5;
			}
		}
		display EBM axes: false { 
			chart "Population" type: series background: #white {
				data 'S' value: first(node_agent).S color: rgb(46,204,113) marker: false;
				data 'I' value: first(node_agent).I color: rgb(231,76,60) marker: false;
				data 'R' value: first(node_agent).R color: rgb(52,152,219) marker: false;
			}
		}
		display ABM_EBM  axes: false { 
			chart 'Population' type: series background: #white style: exploded {
				data 'susceptible' value: (Host as list) count (each.is_susceptible) color: rgb(39,174,96) marker_size: 0.5;
				data 'infected' value: (Host as list) count (each.is_infected) color: rgb(192,57,43) marker_size: 0.5;
				data 'immune' value: (Host as list) count (each.is_immune) color: rgb(41,128,185) marker_size: 0.5;
				data 'S' value: first(node_agent).S color: rgb(46,204,113) marker: false;
				data 'I' value: first(node_agent).I color: rgb(231,76,60) marker: false;
				data 'R' value: first(node_agent).R color: rgb(52,152,219) marker: false;
			}
		}
	}

}