////////////////////////////////////////////////////////////////////
// Game of Life Boolean POMDP
//
// A simple DBN to encode Conway’s cellular automata “game of life”
// on a grid. One gets a reward for generating patterns that keep
// the most cells alive.
//
// Author: Scott Sanner (ssanner [at] gmail.com)
////////////////////////////////////////////////////////////////////
domain game_of_life_pomdp {
requirements = { reward-deterministic,partially-observed };
types {
x_pos : object;
y_pos : object;
};
pvariables {
NOISE-PROB(x_pos,y_pos) : { non-fluent, real, default = 0.1 };
NEIGHBOR(x_pos,y_pos,x_pos,y_pos) : { non-fluent, bool, default = false };
alive(x_pos,y_pos) : { state-fluent, bool, default = false };
surround-obs(x_pos,y_pos) : { observ-fluent, bool };
set(x_pos,y_pos) : { action-fluent, bool, default = false };
};
cpfs {
// Conway’s game of life rules (from Wikipedia):
// 1. Any live cell with fewer than two live neighbors dies, as if caused by under-population.
// 2. Any live cell with more than three live neighbors dies, as if by overcrowding.
// 3. Any live cell with two or three live neighbors lives on to the next generation.
// 4. Any dead cell with exactly three live neighbors becomes a live cell, as if by reproduction.
//
// For interactivity: we allow an agent to explicitly set different cells.
alive'(?x,?y) =
if ([alive(?x,?y) ^ ([sum_{?x2 : x_pos, ?y2 : y_pos} NEIGHBOR(?x,?y,?x2,?y2) ^ alive(?x2,?y2)] >= 2)
^ ([sum_{?x2 : x_pos, ?y2 : y_pos} NEIGHBOR(?x,?y,?x2,?y2) ^ alive(?x2,?y2)] <= 3)]
| [~alive(?x,?y) ^ ([sum_{?x2 : x_pos, ?y2 : y_pos} NEIGHBOR(?x,?y,?x2,?y2) ^ alive(?x2,?y2)] == 3)]
| set(?x,?y))
then Bernoulli(1.0 - NOISE-PROB(?x,?y))
else Bernoulli(NOISE-PROB(?x,?y));
surround-obs(?x,?y) =
KronDelta ([sum_{?x2 : x_pos, ?y2 : y_pos} (NEIGHBOR(?x,?y,?x2,?y2) ^ alive'(?x2,?y2))] >= 2);
};
reward = sum_{?x : x_pos, ?y : y_pos} [alive(?x,?y) – set(?x,?y)];
state-action-constraints {
forall_{?x : x_pos, ?y : y_pos}
[(NOISE-PROB(?x,?y) >= 0.0) ^ (NOISE-PROB(?x,?y) <= 1.0)];
};
}