You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
5.8 KiB
165 lines
5.8 KiB
/* Conway's Game of Life garden of eden checker */
|
|
|
|
/* Written and converted to GNU MathProg by NASZVADI, Peter, 199x-2017
|
|
<vuk@cs.elte.hu> */
|
|
|
|
/*
|
|
Conway's Game of Life (ref'd: CGoL) is a Cellular Automata described and
|
|
inspected by John H. Conway in the 1970s. CGoL is nothing but a 0-player
|
|
game on an infinite two-dimensional Euclydean grid. In the beginning of
|
|
the "game", some 1 values are put on some of the grid vertices, and all
|
|
others are set to 0. Grid vertices with values are called cells, and a
|
|
cell is called "alive", if its value is 1, and called "dead" otherwise,
|
|
these are the two "states". The game then turns to an infinite repetitive
|
|
process: all cells change together independently at the same time their
|
|
states depending only on their actual state and the actual number of
|
|
living cells in their so called Moore-neighbourhood: the 4 orthogonal and
|
|
4 diagonal neighbouring cells. Conway also defined the transitions rule:
|
|
dead cell become alive if it has exactly 3 living adjacents, and an alive
|
|
cell survives only if it has 2 or 3 living neighbours. After executing a
|
|
transition for all cells, the two patterns are in a relationship: the
|
|
older is the father, the newer is the child.
|
|
|
|
It is an interesting problem both in Mathematics and Phylosophy if
|
|
there is a fatherless pattern (in CGoL). Fairly trivial existence
|
|
proofs had been published since then, and immediately explicit
|
|
constructions are followed.
|
|
|
|
This GMPL model searches for a father pattern of the pattern specified in
|
|
the c parameter matrix, and prints the found one if any both in human
|
|
readable format and in RLE format, which could be open with some Cellular
|
|
Automata simulators like Golly, for example.
|
|
|
|
See more about Garden of Edens:
|
|
http://conwaylife.com/wiki/Garden_of_Eden
|
|
|
|
Golly CA simulator:
|
|
http://golly.sourceforge.net/
|
|
|
|
Tip for running with the example pattern:
|
|
glpsol --math life_goe.mod --cuts --last
|
|
|
|
WARNING: Rather CPU- and memory-intensive process to find out if a given
|
|
pattern is a GOE if it really is!
|
|
*/
|
|
|
|
param height, integer, > 0;
|
|
/* height of the successor pattern */
|
|
|
|
param width, integer, > 0;
|
|
/* width of the successor pattern */
|
|
|
|
set ROWS := 0..height + 1;
|
|
/* set of rows of the predecessor */
|
|
|
|
set COLUMNS := 0..width + 1;
|
|
/* set of columns of the predecessor */
|
|
|
|
set MOORE := {(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (-1, 1), (1, -1),
|
|
(-1, -1)};
|
|
/* Moore-neighbourhood relative coordinates */
|
|
|
|
param c{ROWS, COLUMNS}, >= 0;
|
|
/* Denotes the cellspace of 1st generation, where 0, 1 and 2 means dead,
|
|
alive or arbitrary cell values respectively. Usually the frame values
|
|
must be set to "2", and also "2" is allowed in the inner rectangle. */
|
|
|
|
set IJalive := setof{(i, j) in ROWS cross COLUMNS: c[i, j] = 1}(i, j);
|
|
/* set of alive cells in the child */
|
|
|
|
set IJdead := setof{(i, j) in ROWS cross COLUMNS: c[i, j] = 0}(i, j);
|
|
/* set of dead cells in the child */
|
|
|
|
set IJ := IJalive union IJdead;
|
|
/* set of cells in the child with enforced states */
|
|
|
|
var x{ROWS, COLUMNS}, binary;
|
|
/* father's states */
|
|
|
|
var dpos{ROWS, COLUMNS}, >= 0;
|
|
/* positive part of the distances from 6 */
|
|
|
|
var dneg{ROWS, COLUMNS}, >= 0;
|
|
/* negative part of the distances from 6 */
|
|
|
|
var dposup{ROWS, COLUMNS}, binary;
|
|
/* positive part's upper bound enforcement */
|
|
|
|
var dnegup{ROWS, COLUMNS}, binary;
|
|
/* negative part's upper bound enforcement */
|
|
|
|
s.t. maincons{(i, j) in IJ}:
|
|
x[i, j] + sum{(a, b) in MOORE} (2 * x[i + a, j + b]) =
|
|
6 + dpos[i,j] - dneg[i,j];
|
|
/* in the LHS, there is a function that maps from all possible 512 state
|
|
combinations of a father cell and its Moore-neighbourhood to [0..17].
|
|
And for CGoL, if the child is alive, then it should be between 5 and 7.
|
|
Also implicit introduced "d" as distance from 6 in RHS, and immediately
|
|
decomposed "d" into positive and negative parts denoted dpos and dneg. */
|
|
|
|
s.t. posbound{(i,j) in IJ}: dpos[i,j] <= 11 * dposup[i,j];
|
|
/* constraining positive part of distance */
|
|
|
|
s.t. negbound{(i,j) in IJ}: dneg[i,j] <= 6 * dnegup[i,j];
|
|
/* constraining negative part of distance */
|
|
|
|
s.t. mutex{(i,j) in IJ}: dposup[i,j] + dnegup[i,j] = 1;
|
|
/* Ensuring that at most one is positive among the pos./neg. parts */
|
|
|
|
s.t. alive{(i,j) in IJalive}: dpos[i,j] + dneg[i,j] <= 1;
|
|
/* LHS of maincons must be 5, 6 or 7 either due to child cell is alive */
|
|
|
|
s.t. dead{(i,j) in IJdead}: dpos[i,j] + dneg[i,j] >= 2;
|
|
/* LHS of maincons must be at most 4 or at least 8 */
|
|
|
|
/* This is a feasibility problem, so no objective is needed */
|
|
|
|
solve;
|
|
|
|
printf '\nFound a father pattern:\n\n';
|
|
for{i in ROWS}{
|
|
for{j in COLUMNS}{
|
|
printf '%s%s', if j then ' ' else '', x[i, j].val;
|
|
}
|
|
printf '\n';
|
|
}
|
|
|
|
printf '\nThe father pattern in rle format:\n\n';
|
|
for{i in ROWS}{
|
|
for{j in COLUMNS}{
|
|
printf '%s', if x[i, j].val then 'o' else 'b';
|
|
}
|
|
printf '$';
|
|
}
|
|
printf '!\n\n';
|
|
|
|
data;
|
|
/*
|
|
This example is a halved of a 10x10 garden of eden pattern from:
|
|
http://wwwhomes.uni-bielefeld.de/achim/orphan_7th.html
|
|
It has a 90 degree rotational symmetry, so if having enough resources,
|
|
just comment the line denoted with "8", and uncomment the following part!
|
|
And also do not forget to increase height parameter, respectively!
|
|
*/
|
|
|
|
param height := 7;
|
|
|
|
param width := 10;
|
|
|
|
param c : 0 1 2 3 4 5 6 7 8 9 10 11 :=
|
|
0 2 2 2 2 2 2 2 2 2 2 2 2
|
|
1 2 0 1 0 1 1 1 0 1 0 0 2
|
|
2 2 0 0 1 0 1 0 1 0 0 1 2
|
|
3 2 1 0 1 1 1 0 0 1 1 0 2
|
|
4 2 0 1 0 1 1 1 1 1 0 1 2
|
|
5 2 1 0 0 1 0 0 1 1 1 1 2
|
|
6 2 1 1 1 1 0 0 1 0 0 1 2
|
|
7 2 1 0 1 1 1 1 1 0 1 0 2
|
|
8 2 2 2 2 2 2 2 2 2 2 2 2;
|
|
|
|
/* 8 2 0 1 1 0 0 1 1 1 0 1 2
|
|
9 2 1 0 0 1 0 1 0 1 0 0 2
|
|
10 2 0 0 1 0 1 1 1 0 1 0 2
|
|
11 2 2 2 2 2 2 2 2 2 2 2 2; */
|
|
|
|
end;
|