next up previous contents
Next: 4.2 Table-lookup coding Up: 4. Efficient simulation of Previous: 4. Efficient simulation of   Contents

Subsections


4.1 Translating CDL to Java

The description of a cellular automaton in CDL, cellang, or caxl can be translated fairly directly into Java, since most language constructs of CDL have direct equivalents in Java. These are: arithmetic and logical operators, assignment, if-statement, blocks, and case-statements. Most primitive data types can also be translated into Java primitive types, but Java does not have primitive enumeration types or range types. The range types can be translated into suitable primitive integer types. The enumeration types can be translated into integers as well, or into a type-safe system of sub-classes, which however is less memory-efficient. As an example, the following translation is shown:

CDL:


cellular automaton T4 ;

type celltype = record 
    a: boolean;
    b: 0..3;
end;

rule begin
    *[0].a := ( *[-1].a AND *[0].a ) XOR *[1].a;
    
    if  *[0].a AND *[-1].a AND *[1].a then
        *[0].b := ((*[1].b ) + (*[0].b DIV 2) ) MOD 4
    else
        *[0].b := *[0].b;
end;
Java: First, some declarations and the constructor:

public class T4 extends State {

protected celltype mystate;
protected class celltype implements Serializable {
    boolean a;
    /*0..3*/ int b;
}

public T4(){
    mystate = new celltype();
}
Then, the state transition method:

public void transition(Cell cell){
    final State [] neighbors = cell.getNeighbors();
    {
        mystate.a = (((T4)neighbors[1]).mystate.a  
	          && ((T4)neighbors[0]).mystate.a)
	           ^ ((T4)neighbors[2]).mystate.a;
        if (( (T4)neighbors[0]).mystate.a 
	  && ((T4)neighbors[1]).mystate.a 
	  && ((T4)neighbors[2]).mystate.a
	){
            mystate.b = ((((T4)neighbors[2]).mystate.b) 
	               + (((T4)neighbors[0]).mystate.b / 2)) % 4;
        }else{
            mystate.b = ((T4)neighbors[0]).mystate.b;
        };
    }
}
More Java code (not shown here) is generated for initialization and display.

4.1.1 Groups

A concept of CDL which does not exist in Java is the concept of a ``group''. This is similar to a vector in Java, with iterators defined to loop through all elements of the group (in CDL: for, one, all, num, sum). There are two possible ways to translate this feature of CDL into Java. One way is to translate it into vectors and iterators. The second possibility exploits the fact that the group is (in our language definition) fixed, i.e., all elements are known, and thus the action of iterators can be expanded explicitly into a sequence of statements (for) or expressions. Both possibilities are used in CASim: The first is used for groups with the name ``neighbors'', which makes it possible for CDL to be written independently of the dimension and neighborhood of the lattice (selection of the neighborhood is done in the simulation environment). The second possibility is used for all other cases, since it is more efficient for small groups.

As an example, the following CDL-code is translated into Java using the two different options.

CDL:


cellular automaton TestGroup;
  type celltype = 0 .. 2;
  group neighbors = {*[0],*[-1],*[1]};
  var n : celltype;

rule begin
    for  n in neighbors do
       if n > 0 then 
           .....
end
Java with array:

public void transition(Cell cell){
   int n;
   final State [] neighbors = cell.getNeighbors();
   for (int i=0; i<neighbors.length; i++){
      n = ((TestGroup)neighbors[i]).mystate;
      if (n > 0){
          .....
      }
   }
}
Java directly expanded:

public void transition(Cell cell){
   final State [] neighbors = cell.getNeighbors();
   {
      if (((TestGroup)neighbors[0]).mystate > 0){
          .....
      };
      if (((TestGroup)neighbors[1]).mystate > 0){
          .....
      };
      if (((TestGroup)neighbors[2]).mystate > 0){
          .....
      };
   }
}

4.1.2 Statements in expressions

A small complication appears if we use the first translation option for the expressions one, num, all, sum. The Java code uses statements, but the CDL expressions can occur inside complicated expressions, and Java does not allow statements to occur inside expressions. One possible solution is to use anonymous inner classes, but it is more efficient to generate temporary variables which are assigned a value directly before the expression in which they are used. Example:

CDL:


    r := (1+num( n in neighbors: n = 1)) mod 3;
Java directly expanded: (Here no difficulty appears, as the num-expression is expanded into another expression)

r = (1 + (
    (((TestGroup)neighbors[0]).mystate == 1?1:0) 
   +(((TestGroup)neighbors[1]).mystate == 1?1:0) 
   +(((TestGroup)neighbors[2]).mystate == 1?1:0)
  )) % 3;
Java with array: (Here a temporary variable is used, since the num-expression expands into statements)

int temp1_=0;
for (int i=0; i<neighbors.length; i++){
    n = ((TestGroup)neighbors[i]).mystate;
    temp1_+= ( n == 1)?1:0;
}
r = (1 + temp1_) % 3;
Note that the translation system must have detailed type information to determine the type of the temporary variable (boolean, integer, or float).

4.1.3 Record types

Record (and union) types of CDL are translated into inner classes in Java. The components of a record then become the member variables of the class. Variables of such a record type would normally be translated into variables of the new class type, and be local to the transition function. In this case they need to be instantiated (created) at the beginning of the transition function. Unfortunately, creating objects is a very expensive operation in Java, therefore we have to avoid any object creation in the inner loop of the simulation. This can be done by re-using all objects, e.g., by making record (class) variables static.

4.1.4 Neighbor access

The access to neighboring cells can be done through two different mechanisms. One possibility is to translate each cell access into a call of the method ``cell.getNeighborRelative(dx,dy)''. This method must check the coordinates and access the lattice of cells to return the appropriate State-object. These operations involve a certain amount of overhead. Another possibility is to collect all neighboring states into an array once, and access them using this array. In CASim this array is actually preserved between time steps, since the neighborhood does not change between time steps. This option is called ``cache neighborhood'' in the CASim system and can be turned on or off, since caching the neighborhood involves a cost in memory but improves performance (if enough memory is available).


next up previous contents
Next: 4.2 Table-lookup coding Up: 4. Efficient simulation of Previous: 4. Efficient simulation of   Contents
Jörg R. Weimar