///////////////////////////////////////////////////////////////////////////////
//
// A boolean version of the wildfire fighting domain.
//
// V4 CHANGE: In this version we want to add a third action to allow a single
// aerial water drop which has high cost but puts out a fire in all
// cells neighboring the cell where the water is dropped.
//
// Note that this change requires addition of an action fluent and
// changes to the cpfs, rewards, and action-preconditions (to
// enforce a maximum of one water drop).
//
// Author: Zhenyu Yu (fry3721@gmail.com)
//
// General reference:
//
// Karafyllidis, I., & Thanailakis, A. (1997).
// A model for predicting forest fire spreading using gridular automata.
// Ecological Modelling, 99(1), 87-97.
// http://www.dpi.inpe.br/gilberto/cursos/st-society-2013/Kara1997.pdf
//
// In a general wildfire scenario, its spread is mostly determined by
// the weather (i.e. wind), terrain slope, and fuel type (i.e. grass, wood).
// In this scenario, a map is represented with grids, size of n*n.
// Each grid has some attributes, including fuel type, terrain elevation.
// Furthermore, the fuel type and terrain elevation will affect the fire
// spreading speed. Some fuel type is more easily on fire than other,
// and higher grids are always easier to catch fire. Cell features and
// effects of wind are not modeled in this simplified version.
//
// In this version, whether a cell would be on fire is determined by its
// neighbor grids, and the fire spreading law is simplified with this function
//
// p(burning(xi, yj)=true) = 1 / (1 + exp(4.5 – k))
//
// where k is the number of neighbors on fire.
//
// The decision task to a emergency manager is to control the fire
// and keep it away from important targets.
//
// Modified for competition and translation purposes by Scott Sanner.
//
///////////////////////////////////////////////////////////////////////////////
domain wildfire_mdp_v4 {
types {
x_pos : object;
y_pos : object;
};
pvariables {
// Action costs and penalties
COST_CUTOUT : {non-fluent, real, default = -5 }; // Cost to cut-out fuel from a cell
COST_PUTOUT : {non-fluent, real, default = -10 }; // Cost to put-out a fire from a cell
PENALTY_TARGET_BURN : {non-fluent, real, default = -100 }; // Penalty for each target cell that is burning
PENALTY_NONTARGET_BURN : {non-fluent, real, default = -5 }; // Penalty for each non-target cell that is burning
// V4 CHANGE: Specify constant cost for WATER_DROP action
COST_WATERDROP : {non-fluent, real, default = -25 }; // Cost to do an aerial water drop
// Topology of the cells (can be any neighborhood topology, not necessarily rectangular)
NEIGHBOR(x_pos, y_pos, x_pos, y_pos) : { non-fluent, bool, default = false };
// High value cells that should be protected from fire
TARGET(x_pos, y_pos) : {non-fluent, bool, default = false };
// State fluents
burning(x_pos, y_pos) : { state-fluent, bool, default = false }; // cell currently on fire
out-of-fuel(x_pos, y_pos) : { state-fluent, bool, default = false }; // cell does not have fuel to burn (i.e., cut-out or already burned)
// Action fluents
put-out(x_pos, y_pos) : { action-fluent, bool, default = false }; // actions to put-out out the fire
cut-out(x_pos, y_pos) : { action-fluent, bool, default = false }; // cut-out out the fuel
// V4 ADDITION: Add new action fluent for water-drop
water-drop(x_pos, y_pos) : { action-fluent, bool, default = false }; // actions to put-out out the fire
};
cpfs {
burning'(?x, ?y) =
// V4 CHANGE: Add water-drop effect first (broader impact than put-out)
if ( water-drop(?x, ?y) | (exists_{?x2: x_pos, ?y2: y_pos} (NEIGHBOR(?x, ?y, ?x2, ?y2) ^ water-drop(?x2, ?y2)) ))
then false
else if ( put-out(?x, ?y) ) // Intervention to put out fire?
then false
// Modification: targets can only start to burn if at least one neighbor is on fire
else if (~out-of-fuel(?x, ?y) ^ ~burning(?x, ?y)) // Ignition of a new fire? Depends on neighbors.
then [if (TARGET(?x, ?y) ^ ~exists_{?x2: x_pos, ?y2: y_pos} (NEIGHBOR(?x, ?y, ?x2, ?y2) ^ burning(?x2, ?y2)))
then false
else Bernoulli( 1.0 / (1.0 + exp[4.5 – (sum_{?x2: x_pos, ?y2: y_pos} (NEIGHBOR(?x, ?y, ?x2, ?y2) ^ burning(?x2, ?y2)))]) ) ]
else
burning(?x, ?y); // State persists
// Modification: only allow non-target cells to be cut-out (cannot remove fuel from targets, e.g., housing)
out-of-fuel'(?x, ?y) = out-of-fuel(?x, ?y) | burning(?x,?y) | (~TARGET(?x, ?y) ^ cut-out(?x, ?y));
};
// V4 CHANGE: Add action precondition requirement that a water-drop can only be applied in at most one cell
action-preconditions {
[ sum_{?x: x_pos, ?y: y_pos} water-drop(?x, ?y) ] <= 1;
};
// V4 CHANGE: Add in first reward component
reward =
[sum_{?x: x_pos, ?y: y_pos} [ COST_WATERDROP*water-drop(?x, ?y) ]]
+ [sum_{?x: x_pos, ?y: y_pos} [ COST_CUTOUT*cut-out(?x, ?y) ]]
+ [sum_{?x: x_pos, ?y: y_pos} [ COST_PUTOUT*put-out(?x, ?y) ]]
// Modification: if a target is out-of-fuel, it was burnt so still penalize (since it could not have been cut-out)
+ [sum_{?x: x_pos, ?y: y_pos} [ PENALTY_TARGET_BURN*[ (burning(?x, ?y) | out-of-fuel(?x, ?y)) ^ TARGET(?x, ?y) ]]]
+ [sum_{?x: x_pos, ?y: y_pos} [ PENALTY_NONTARGET_BURN*[ burning(?x, ?y) ^ ~TARGET(?x, ?y) ]]];
}