The simulation system CASim is an environment for simulating cellular automata. In this manual, the usage of the simulation environment is described. The system CASim is written entirely in Java and consists of three different programs:
For simplification, the archive casim.jar
contains a small class
casim
so that the program can be started simply with
On all systems additional output is printed to the shell, most error messages appear as small dialog boxes.
By default, CASim starts with a two-dimensional lattice of 10 by 10 cells, so in the beginning you don't need to specify any lattice settings.
In the next step, you need to decide how to describe the cell state and the state transition function. The simulation system CASim supports three ways of doing this:
The second prossibility allows far more freedom in describing the state and state transition function and is described in section 3. The third possibility of using CDL is described elsewhere.
After entering the name and number of states, you see in the central part of the window a list of state transition rules, and in the lower part a table with one row per state.
Every rule consists of three parts. On the left, you enter the current state of the cell by selecting it from the list of possible states. In the middle, you specify the state of the neighbors, and on the right the new state for the cell.
As an example, to specify the rules for the Greenberg-Hastings CA with the
transition rules
enter a name, and 3 for the number of states. Then add a new rule, select 0 as the current state, 2 for the first neighbor, an 2 for the new state, and thus the first rule is entered. The following rules do not need any neighbor information. The simulation system checks the rules for a match from top to bottom. Figure 5 shows all four rules.
In this simple mode the geometry of the neighborhood is not taken into account. The system simply determines whether there is one neighbor in each of the neighborhood states given in the state transition rule, without regard to the order. In the example, the first rule simply says that at least one neighbor must be in state 2. Neighbors with the value ``.'' are wildcards and can have any value.
Figure 6 shows an example. Every row shows the properties of one state, from left to right:
Confirm all entries by pressing OK. The lattice should now be initialized.
Continue changing cells until you have reached the desired initial conditions. You may also use this possibility during the simulation to modify individual cells. The menu item Simulation - Reset resets the lattice to new probabilistic initial conditions.
This concludes the description of how to specify a cellular automaton using the graphical user interface. You can skip the description of how to specify a CA in Java and go directly to the simulation in section 4 on page .
State
in the package de.tubs.cs.sc.casim
, which represents the
interface to the
user-specified CA.
To program a new cellular automaton, only
basic knowledge of JAVA is necessary.
As a first step, it is best to let the simulation system create skeleton code into which you then insert your own code. This skeleton code is created with File - New JAVA File . You will be asked for a file name, and you should use the name of you CA (no spaces) and the ending ``.java''. The resulting file looks like the one in Figure 8.
Please note that in Java, a class must be declared in a file with the same name as the class name and that this name must begin with a letter. Upper- and lowercase letters are distinguished even on operating systems like Windows.
This newly generated Java file can now be edited to include the code specific to the cellular automaton to be described. The file conatins a number of comments which indicate the positions where changes need to be made. in Java, comments start with //, /* oder /**. Comments starting with // end with the end of the line, the other comments must be ended explicitly with a closing */. Nested coments are not allowed. The skeleton file contains numbered comments, and we refer to these numbers in the following sections.
For the example Greenberg-Hastings CA, a simple integer is sufficient. JAVA does not have enumeration types or types to declare a subrange of an integer.
private int condition;Here
private
means that the variable condition
may only be used
inside the class.
For example, one could insert the follwing code in the constructor:
option
is used to distinguish between different experiments.
This is an integer which can be set from the user interface at simulation time.
The class Lattice provides information about the size of the lattice
with the methods int getX()
, getY()
, and getZ()
and access to the individual cells through the method State getState(...)
,
which takes the coordinates as arguments. Note that the objet returned by
getState
must be typecast to the class you are programming before the
state variables can be accessed. In the example, a simple initialization could
be
((GreenbergHastings)l.getState(3,3)).condition = 2;Note that cell numbering starts with 0. This example only works for lattices of the correct dimension and size. A more complex initialization which works for any lattice size and dimension is:
int x = l.getX()/2; int y = l.getY()/2; int z = l.getZ()/2; ((GreenbergHastings)l.getState(x,y,z)).condition = 2; if (option == 1){ ((GreenbergHastings)l.getState(x+1,y,z)).condition = 1; }
public String toString()to the code which returns a string representing the state.
To use color, insert code into the getColor
-method to return a color
value depending on the state. One possibility is to use predefined colors and
select one color with a switch
statement:
switch(condition) { case 1: return Color.darkGrey; case 2: return Color.black; } return null;
In this case state 0 will not be colored, since getColor
returns
null
in this case, which is also the default setting.
Fo rmore complex automata, and if colors different from the predefined colors are to be used, it is convenient to create an array of colors which are then returned depending on the state:
private static Color[] colors; static { colors = new Color[3]; colors[0] = null; colors[1] = new Color(150,150,255); // pink colors[2] = Color.red; } public Color getColor() { return colors[condition]; }Colors can also be created on the fly depending on the cell state, such as in
public Color getColor() { return new Color(50*condition,50*condition,50*condition); }
public java.awt.image.ImageProducer getIcon();which tells the simulation system which image to display for this cell. This method is only called if
getColor()
returned null
.
To simplify the use of icons, a helper class
de.tubs.cs.sc.cavis.IconManager
is included in the simulation system.
This class makes it posible to create one image containing many or all needed
icons, and then to select one icon in the image depending on the state of a cell.
The iconmanager can be called as a program to create code that can be included
in the new class. In this case, three parameters must be given, first name of
the image file, which may be a GIF file or a JPEG file. Then, two parameters
give the number of icons contained in the image in x- and in y-direction. An
example is:
java de.tubs.cs.sc.cavis.IconManager arrvn.gif 7 4for the image 9 in the file ``arrvn.gif'' with icons.
This call creates code that contains the complete information from the image file, so that the image file need not be present any further in the simulation. The code should be included in the new class.
To display a cell as an icon, the method getIcon()
uses the IconManager
to display the icon from a certain position in the given image:
public java.awt.image.ImageProducer getIcon(){ if (...) return im.getIcon("arrvn.gif",state%7,state/7); };
copy
which copies the state from
another object. This method should simply copy all state variables,
in the example:
public void copy(State s) { GreenbergHastings source = (GreenbergHastings)s; condition = source.condition; }
In the second line, the parameter s is type cast into the new Java class, then all state variables (here only one) are copied.
transition
. Here you can use the full power of the programming
language Java to express the state transition function, such as loops,
if
-statements, or arrays for storing tables.
The method transition
has one parameter Cell c
. Through thi
sparameter, access to the neighbors is provided. The method
c.getNeighbors()
returns an array of State
s, which conatins all
neighbors of the current cell. The cell itself is included in this neighborhood,
and is always the first element in the array. To make the code efficient, the
method c.getNeighbors()
should only be called when necessary, i.e., for
those states where the transition function really does depend on the neighbors.
The example Greenberg-Hastings CA could be programmed as shown in Figure
10. In this example, only if
condition
is zero is it necessary to consider the neighbors.
Therefore a call to c.getNeighbors()
is used to obtain an array of
State
s. Then a loop over all elements
of this array is used to determine if at least one neighbor has value 2. Note
that the elements need to be type cast into objects of the current class (in
this case GreenbergHastings
) for the state variables to be accessible.
This leads to the expression ((GreenbergHastings)neighbors[i])
.
If no neighbor has value 2, the variable condition remains unchanged,
in this case with value 0.
With these changes, the celllular automaton has been programmed completely in Java. Figure 11 shows the complete sourcecode which must now be compiled and loaded in CASimFrame.
tools.jar
, which can be found in one of the library folders of
the Java installation, be included in the environment variable CLASSPATH
.
To load a java file, simply select the menu item File - Open and select
the Java file for opening. This file will then be compiled and loaded, You can
also compile it separately, and then load the .class
file.
If the compilation was not successful, you will see a dialog window, and should compile the file separately to see the compilation error produced. Otherwise you will see the initial state of the CA as in Figure 12.
The simulation of the CA proceeds in the same way for states specified with Java as for states specified interactively, and is described in the following section.
Loading a class can also be achieved from the command line by specifying a file
with the ending .html
, which describes a configuration, or a file with
ending .java
or .class
, which conatins only the class to be loaded
and not the lattice configuration. It is also possible to first specify a
.java
file, which is then translated, and as a second argument a
.html
file, which specifies the lattice configuration (for example
java casim MyClass.java MyClass.html
).
First, click on Step. The program CASimFrame now simulates the first time step. After executing three more steps, your automaton should look like the one in Figure 13.
This concludes the description of the basic steps needed to simulate a CA. All further controls are described in the following section.
.java
.
.html
).
JAVA source or bytecode files should always contain the description of a
cellular automaton, i.e., a class derived from the class State
. Source
files are compiled and then the class is loaded. If loading the class was
successfull, the simulation system directly initializes the cellular automaton.
.ca
and allows you to load the specification again for modification or
presentation. For CA specified from a java program, this option is not
available.
TableState
, which in turn is derived from
State
. You can now modify this code and load it as described in section
7.
The resulting HTML file can be used for WEB-presentations using applets, or to reload the same configuration and view settings using File - Open.
.m
is used to store the current
state of the cellular automaton in a format that can be read by the program
Mathematica or by other programs that can read ASCII-text files. The states are
described using the result of the toString
-method.
The printout contains the currently displayed situation, but with better
resolution than on the screen. On most systems you can also print into a file,
in which case Postscript is generated. If you want to use the resulting files as
EPS-files to be included into other texts, you should use a program to convert
them, such as ps2eps
(for more information contact
J.Weimar @ tu-bs.de).
Depending on the Dimension of the lattice, you can enter the size in the different dimensions in the center portion of the dialog. x determines the width, y the height, and z the depth of the lattice.
The neighborhood of a cell can be selected as the Moore neighborhood or the vonNeumann neighborhood, both with arbitrary integer radius. In the two-dimensional square lattice, the vonNeumann neighborhood of cell with radius is defined as i.e., the sum of the distances on the lattice in any dimension between the two cells must be less than or equal to . The Moore neighborhood is defined as i.e., the largest distance in any of the dimensions must be less than or equal to . These neighborhoods can be generalized to the other geometries, where steps on the lattice are counted in one of the six directions for the hexagonal lattice, and in one of the three directions for the triangular neighborhood. The vonNeumann neighborhood can be straightforwardly adapted to these lattices, while the Moore-neighborhood has only be adapted for the hexagonal case, where the Moore neighborhood of radius is taken to be those cells, for which the shortest path to the center cell involves a maximum of steps in any of the six directions. Cells for which a path with not more than steps in any one direction exists, but is not the shortest path, are ignored.
If the problem at hand requires a special neighborhood different from the
predefined neighborhoods, you need to use the possibility of defining arbitraty
neighborhoods, which exitsts when you specify the automaton in Java or CDL.
The settings in the lattice dialog only apply to those cases, where the function
getNeighbors()
is used to obtain the neighbors. In all other cases, such
as when the function getNeighborsMoore()
is used, the setting in the
dialog have no effect,
Since the neighborhood does not change from one time step to the next, the simulation system can create a list of neighbors for ach cell and store this list instead of recreating it at every time step. This option is called ``caching the neighborhood''. The advantage is that execution is faster, the disadvantage is that it needs more memory. The option is on by default, but should be turned off for large simulations where memory is scarce.
For every lattice the boundary conditions need to be specified.
The default in CASim is to use periodic boundary conditions.
This can be changed
for every border of the lattice separately. The possible
boundary conditions are periodic, reflective, or constant. Reflective boundary
conditions approximate a mirror set at the border of the lattice. Note that for
hexagonal and triangular lattices, this is only an approximation in the current
implementation. For constant boundary conditions, a constant value is returned
for all accesses to cells outside the lattice. The value of this constant can be
set by using the constants constantcell
or constantcellright
etc.
in CDL or by implementing the method State getConstant()
in the Java
code. Different values can be returned for the different boundaries by
having a method
public State getConstant(int dim, boolean dir)return different values. Here
dim
gives the dimension (x-axis is 1, y-axis 2, and z-axis 3), and
dir
gives the side of the lattice (true for positive end, false for
negative end).
To select different initial conditions, the dialog contains a field for
entering an integer number. This number is passed as second argument to the
method
initialize
. This method in the Java class can then create different
initial conditions depending on this value. In theCDL specification, this value
can be accesses by the name option
in the initial section.
toString()
in the Java class, or simply the integer code for
interactively specified automata. When the CA is specified using CDL, this text
is generated automatically.
In the statistics window, each state that occurs at least once is shown in one line. First the name of the state (text), then the color, and finally the number of cells in the lattice with this state.
Another option is to assign a ``dont' draw'' color value to some states (return
null
in Java). These cells are then transparent and let the cells behind
be seen. Unfortunately, this possibility comes with a severe performance
penalty, since in this case all cells must be draw, while otherwise only the
outside cells need to be drawn.
BlockState
), can possibly be reversible. If they are,
Simulation - Back simulates one step backwards.
The choice lets you select 1, 2, 3, 5, 10, 20, 50 or 100 as the number of steps simulated between successive displays. This choice is used for both the Step and the Run operations.
Since Java applets are executed within a web browser, for security reasons many operations are forbidden. An applet is in general not allowed to read or write files on the user's computer. The applet may only load files from the server from which it was originally loaded. For this reason, the applet CASimApplet does not have all the possibilities of the full simulation system CASimFrame. CASimApplet provides the possibility to interactively define a cellular automaton or use a Java class that has been compiled on the server. The applet cannot use or compile a Java class from the user's computer. It is possible to change the lattice settings interactively, but the typical use of the applet is to demonstrate a cellular automaton using parameters specified in the HTML page, as shown in the HTML example code in Figure 23, which will appear similar to Figure 24 in a web browser.
The parameters of the applet, which describe the CA class to use, the lattice,
and the appearance, i.e., all the parameters controlled by the menu items in
CASimFrame, are passed as HTML parameters with the tag param
:
Since no graphical input is used, the complete specification of the CA must be done on the command line using parameters:
java de.tubs.cs.sc.casim.CASim -s GH -l 2DS -x 10 -y 10 -g 20or shorter
java casim -s GH -l 2DS -x 10 -y 10 -g 20
This will simulate 20 time steps of the cellular automaton which is described in the class GH. It will be simulated on a two-dimensional square lattice of size 10*10 with a vonNeumann neighborhood of radius 1.
State
to describe a CA, you can also write a java class derived from
TableState
. This class is used for the interactively specifief automata,
and you can also use it when programming in Java, since it already implements a
number of the methods needed for a CA. The state in TableState
is stored
in an integer condition
, which is defined in TableState
.
The steps (1), (2) and (5) described in section 3 can be ommited,
since the corresponding methods are already implemented in TableState
.
The methods initialize(Lattice l)
(Step 3), getColor()
(Step 4) and transition(Cell c)
(Step 6) must be implemented.
The methods getColor
and
transition
need to be implemented as described in section
3. The method initialize
already has an implementation in
verb!TableState! which uses a table of probabilities to randomly initialize the
lattice. To use this, you only need to implement the methods
public int getNrOfStates(); public double getProbability(int iState);
getNrOfStates()
and initialized the lattice
with the returned probabilities for the different states. Probabilities should
be between 0 and 1, and should add up to 1.
If the probabilistic initialization is not desired, the method
initialize(...)
can be implemented.
The lattice can also be initialized interactively using the popup-menus.
To simulate a block cellular automaton, derive a class from BlockState
instead of State
. Except for steps (5) and (6) the steps are the same as
those for a regular CA. The methods copy()
and transition(Cell c)
are already defined as final in BlockState
and cannot be changed, because
they are not needed for block-CA. In addition to steps (1) to (4) you need to
implement the methods
int [][][] getBlocks(int dim)
void transition(States[] states)
void reversetransition(States[] states)
of BlockState
in steps (11) to (13).
int [][][] getBlocks(int dim)
once with the dimension of the current lattice.
You should return an array of indices consisting of a list of blocks, which are
then used cyclically in subsequent time steps.
Ech block consists of an array of addresses, each of which is a vector of
dim
integers. All blocks should have the same number of elements, and
they should be rectangular in shape.
The Margolus blocks, which consist of blocks of four cellswhich are shifted across the diagonal for subsequent steps, are defined as shown in Figure 25.
In the method getBlocks()
you can then return block2D
directly. CASim determines the number and size of the blocks and tiles the
lattice with these blocks. The cells belonging to one block are then stored in
one array and given as arguments to the functions transition
and
reversetransition
.
transition(BlockStates[] states)
. This method must be implemented
in your Java class, and must calculate the new state for all cells in array
states
, which contains the cells of one block.
You are allowed to access all fields of every element of the
block, but not access any neighbors with getNeighbors()
or similar
functions. Of course, the elements of the array must be type cast to your
subclass before you can access any fields.
reversetransition
to be able
to reverse the simulation.
Here we simply demonstrate a number of options. The simplest option (1) is to sweep through the lattice of cells line-by-line. This order also appears in the Gauss-Seidel updating method in numerical mathematics. In cellular automata this order usually leads to large artifacts, since it violates the symmetry of the CA: Information can flow from left to right over arbitrary distances in a single time step (it is sweeped along), whereas information flow from right to left proceeds only by one neighborhood radius in one time step (as in synchronous cellular automata).
The second possibility (2) is to use a fixed order of updating of all cells within each time step. To ensure that each cells gets updated exactly onece in each time step, this order should be a random permutation. Random permutations can be generated by the standard shuffling algorithm described by Knuth:
for (i=0; i<N; i++) a(i] = i; for (j=N-1; j>0; j--) { i = choose(0,j); exchange a[i] and a[j]. }where
choose(0,j)
uses any good random number generator to select a
number between 0 and j.
Note that the line-by-line sweep is just one example of a random updating oder. It occurs with probability in a lattice of cells. This is a very small probability, but some of the features of this special case appear (at least in local regions) in almost all random permutations: in some regions, information propagates much faster in certain directions than in others. Since the updating order remains unchanged between time steps, this becomes very noticable after a number of steps.
The third possibility (3) is to use a different random permutation for each time step. The fourth possibility (4) is to relax the requirement that each cell should be updated exactly one in each time step, and just randomly select the next cell to be updated. Then such updates of randomly selected cells can be considered as one time step. In this model, it is possible that the same cell is updated twice in succession before any of its neighbors are updated.
A fifth possibility (5) is to assign a waiting time to each cell and update the cells in the order in which the waiting times expire. When a cell is updated, a new waiting time is generated. The waiting times could be generated from any distribution, but to avoid rollbacks, times should be positive. A suitable distribution is the exponential distribution. To determine the next cell to be updated, a list of cells and waiting times should be kept in a heap, which is a datastructure which allows fast access to the element with minimum value, and insertion of new elements.
In JCASim, asynchronous cellular automata can be used by specifying the
following class to be used as the Lattice
, which is currently oionly
implemented for 2-D square lattices:
de.tubs.cs.sc.casim.Lattice2DAsync
This is specified in the applet by the parameter
<param name="latticeclass" value="de.tubs.cs.sc.casim.Lattice2DAsync">
and in the application by specifying the following command line option:
java casim -l de.tubs.cs.sc.casim.Lattice2DAsync
The different possible asynchronous updating methods are then selected by setting different lattice options (1..5) in the lattice dialog.
J.Weimar @ tu-bs.de
. I hope the program will be
useful for you.