Tech.Appendix: LCS as ZCS0

The following code is not yet complete. It shows a first version where you can set some start values with the command line (startposition, size of the grid, etc.) and then will the ANIMAT operate completely at random, if MODE=0. This can give important benchmarles compared to those versions, where the ANIMAT is extended with some rules and strategies. Different to the version of Wilson (1994) we do not assume an 'infinite finite' world but a finite one with an adjustable size. This allows more detailed investigations depending from ther available space. For more informations see the chapters about GAs and LCSs)

//**************************************************************
// File: zcs_wood1.sce
// Authors: Gerd Doeben-Henisch
// Version Start: April-14, 2010
//**********************************************************
// Update: April-14, 2010
// Updatet: April-15, 2010
// Update: April-16, 2010
// Update: April-17, 2010
// Update: April-20, 2010 (Change of coordinates: X for columns and Y for rows)
// Update: April-22, 2010 (Including the random number test procedures)
// Update: April-23, 2010 (A GRID with less food, Searching the distance to the next food for an ANIMAT)
// Update: April-24, 2010
// Update: April-25, 2010 (New Testfields for the random case)
// Update: April-26, 2010
// Update: April-28, 2010
// Update: May-02, 2010
// Update: May-03, 2010 (Final Version of automatic generation of transition table transprob(), transprob_tst())
//******************************************************************
// CONTENT: Necessary code for the ZCS system of Wilson (1994) and
// his wood1 environment
//
//***************************************************
// X-Y Coordinates
//
// scilab has the Y-axis 'inverted': scilab '1,2,...' = Usually '-1,-2,...'
// Thus we will write 'YI' for the scilab Y-axis
// Furthermore has the scilab matrix notation
// M(i,j) to be interpreted M(YI,X)
//

//************************************************
// 2-DICE PROBABILITIES
// Examples from Knuth (1981)(See lecture notes for details)

PROBABILITIES= [2 3 4 5 6 7 8 9 10 11 12; 1/36 1/18 1/12 1/9 5/36 1/6 5/36 1/9 1/12 1/18 1/36]

 DICETEST1 =[2 4 10 12 22 29 21 15 14 9 6]
DICETEST2 = [4 10 10 13 20 18  18 11 13 14 13]
DICETEST3 = [3 7 11 15 19 24 21 17 13 9 5]



//***********************************
// BEHAVIOR FUNCTION WITH CLASSIFIERS
//

CLASSIFIERS = [
'11##############:0001-100'; 
'##11############:0010-100'; 
'####11##########:0011-100'; 
'######11########:0100-100'; 
'########11######:0101-100'; 
'##########11####:0110-100'; 
'############11##:0111-100'; 
'##############11:1000-100'; 
]

//**********************************
// GRID 'WOOD1' 
//
// Y = r=1...15, X = c=1...55
// The Y-axis is from above (north) to bottom (south), the X-axis is from left (west) to right (east)
// '.' := No Food; encoded '00'
// 'O' := Object (Rock); encoded '10'
// Attention: scilab assumes GRID(Y,X) columns first and then rows!


//********************************************************************
// DYNAMIC GRID GENERATION
// Using the wood1-structure as building blocks
//
// YYMAX := Max number of rows multiplied by 5
// XMAX := Max number of columnsXNtiplied by 5


function[GRID]=gridgen(YYMAX,XXMAX)
  
  if (YYMAX < 1) | (XXMAX < 1) then printf("gridgen:ERROR WITH YYMAX, XXMAX\n\n"), end
  
  for k=1:5:5*YYMAX
  i=k
    for j=1:5*XXMAX, GRID(i+0,j)='.',end
  i=k+1
  for j=1:5:5*XXMAX, 
    GRID(i,j+0)='.'
    GRID(i,j+1)='O'
    GRID(i,j+2)='O'
    GRID(i,j+3)='F'
    GRID(i,j+4)='.'
  end
  i=k+2
  for j=1:5:5*XXMAX, 
    GRID(i,j+0)='.'
    GRID(i,j+1)='O'
    GRID(i,j+2)='O'
    GRID(i,j+3)='O'
    GRID(i,j+4)='.'
  end
  
  i=k+3
  for j=1:5:5*XXMAX, 
    GRID(i,j+0)='.'
    GRID(i,j+1)='O'
    GRID(i,j+2)='O'
    GRID(i,j+3)='O'
    GRID(i,j+4)='.'
  end
  i=k+4
  for j=1:5*XXMAX, GRID(i+0,j)='.',end
  end
  
   
endfunction





//********************************************************************
// DYNAMIC GRID GENERATION
// Using theextended  wood1-structure as building block
//
// Allows less food cells in the world
//
// YYMAX := Max number of rows multiplied by 5
// XMAX := Max number of columnsXNtiplied by 5
// S := Inverse scaling to lower the density of food


function [GRID]=gridgen2(YYMAX,XXMAX,S)
  
  if (YYMAX < 1) | (XXMAX < 1) then printf("gridgen:ERROR WITH YYMAX, XXMAX\n\n"), end
  
  r=0
  for k=1:5:5*YYMAX
  i=k
    for j=1:5*XXMAX, GRID(i+0,j)='.',end
  i=k+1
  for j=1:5:5*XXMAX, 
    GRID(i,j+0)='.'
    GRID(i,j+1)='O'
    GRID(i,j+2)='O'
    
    if (S>0) & (r==S) then  GRID(i,j+3)='F', r=0, else  GRID(i,j+3)='O', r=r+1,end
    
    GRID(i,j+4)='.'
  end
  i=k+2
  for j=1:5:5*XXMAX, 
    GRID(i,j+0)='.'
    GRID(i,j+1)='O'
    GRID(i,j+2)='O'
    GRID(i,j+3)='O'
    GRID(i,j+4)='.'
  end
  
  i=k+3
  for j=1:5:5*XXMAX, 
    GRID(i,j+0)='.'
    GRID(i,j+1)='O'
    GRID(i,j+2)='O'
    GRID(i,j+3)='O'
    GRID(i,j+4)='.'
  end
  i=k+4
  for j=1:5*XXMAX, GRID(i+0,j)='.',end
  end
  
   
 endfunction
 
 
 

//********************************************************************
// TESTGRIDS WITH OBJECTS
// 
//

GD3O2F1=['.' '.' '.'; 'O' 'O' '.'; '.' 'F' '.' ]


GD3O2F12=['.' '.' '.'; '.' 'O' 'O'; '.' 'F' '.' ]

GD3O2F13=['.' '.' '.'; '.' 'O' '.'; '.' 'F' '.' ]
   
//*************************************************
// AUTOMATIC GENERATION OF TRANSITION TABLE
// Takes every cell of a given GRID and computes the transition probabilities
// with regard to every possible direction 1 ... 8
//


function [TGRID]=transprob(GRID)
  
[r,c]=size(GRID)
TGRID=zeros()
N=r*c

MAX=9
Y=0
  while(Y<N)
    for y=1:r,
      
      for x=1:c, Y=Y+1
        
      
     // printf("\n---------------Y = %d----------------------\n\n",Y)
   
      m=1
      
      //Catch wrong indices and evaluate cases
        
        if  (y-1)<1 then m=m+1, elseif GRID(y-1, x) == 'O' then TGRID(Y,(y-1)*c+x)=0, m=m+1,else  TGRID(Y,(y-1-1)*c+x)=1/MAX, end
        if  (y-1)<1|(x+1)>c then m=m+1,elseif GRID(y-1, x+1) == 'O' then  TGRID(Y,(y-1)*c+x)=0,m=m+1,else  TGRID(Y,(y-1-1)*c+x+1)=1/MAX, end
        if  (x+1)>c then m=m+1,elseif GRID(y, x+1) == 'O' then  TGRID(Y,(y-1)*c+x)=0,m=m+1,else  TGRID(Y,(y-1)*c+x+1)=1/MAX, end
        if  (y+1)>r|(x+1)>c then m=m+1,elseif GRID(y+1, x+1) == 'O' then  TGRID(Y,(y-1)*c+x)=0,m=m+1,else  TGRID(Y,(y-1+1)*c+x+1)=1/MAX, end
        if  (y+1)>r then m=m+1,elseif GRID(y+1, x) == 'O' then  TGRID(Y,(y-1)*c+x)=0,m=m+1,else  TGRID(Y,(y-1+1)*c+x)=1/MAX,  end
        if  (y+1)>r|(x-1)<1 then m=m+1,elseif GRID(y+1, x-1) == 'O' then  TGRID(Y,(y-1)*c+x)=0,m=m+1,else  TGRID(Y,(y-1+1)*c+x-1)=1/MAX, end
        if   (x-1)<1 then m=m+1,elseif GRID(y, x-1) == 'O' then  TGRID(Y,(y-1)*c+x)=0,m=m+1,else  TGRID(Y,(y-1)*c+x-1)=1/MAX, end
        if  (y-1)<1|(x-1)<1 then m=m+1,elseif GRID(y-1, x-1) == 'O' then  TGRID(Y,(y-1)*c+x)=0,m=m+1,else  TGRID(Y,(y-1-1)*c+x-1)=1/MAX, end
        
        if GRID(y, x)=='O' then  for z=1:N,TGRID(Y,z)=0,end
            else TGRID(Y,Y)=m/MAX, end
          
     
    
    end //x
  end //y
  end //Y
 
endfunction

//*************************************************
// AUTOMATIC GENERATION OF TRANSITION TABLE
// Takes every cell of a given GRID and computes the transition probabilities
// with regard to every possible direction 1 ... 8
//


function [TGRID]=transprob_tst(GRID)
  
[r,c]=size(GRID)
TGRID=zeros()
N=r*c

MAX=9
Y=0
  while(Y<N)
    for y=1:r,
      
      for x=1:c, Y=Y+1
        
      
      printf("\n---------------Y = %d----------------------\n\n",Y)
   
      m=1
      
      //Catch wrong indices and evaluate cases
        
        if  (y-1)<1 then printf(" __BORDER__"), m=m+1, elseif GRID(y-1, x) == 'O' then printf(" __OBJECT__"),TGRID(Y,(y-1)*c+x)=0, m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1-1)*c+x)=1/MAX, printf("(y,x) = (%d,%d) with m = %d TG(Y,Y) = (%d,%d) = %f\n",y,x,m,Y,(y-1-1)*c+x, TGRID(Y,(y-1-1)*c+x)), end
        if  (y-1)<1|(x+1)>c then printf(" __BORDER__"), m=m+1,elseif GRID(y-1, x+1) == 'O' then printf(" __OBJECT__"), TGRID(Y,(y-1)*c+x)=0,m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1-1)*c+x+1)=1/MAX, printf("(y,x) = (%d,%d) with m = %d TG(Y,Y) = (%d,%d) = %f\n",y,x,m,Y,(y-1-1)*c+x+1,TGRID(Y,(y-1-1)*c+x+1)), end
        if  (x+1)>c then printf(" __BORDER__"), m=m+1,elseif GRID(y, x+1) == 'O' then printf(" __OBJECT__"), TGRID(Y,(y-1)*c+x)=0,m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1)*c+x+1)=1/MAX, printf("(y,x) = (%d,%d) with m = %d TG(Y,Y) = (%d,%d) = %f\n",y,x,m,Y,(y-1)*c+x+1,TGRID(Y,(y-1)*c+x+1)), end
        if  (y+1)>r|(x+1)>c then printf(" __BORDER__"), m=m+1,elseif GRID(y+1, x+1) == 'O' then printf(" __OBJECT__"), TGRID(Y,(y-1)*c+x)=0,m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1+1)*c+x+1)=1/MAX, printf("(y,x) = (%d,%d) with m = %d TG(Y,Y)  = (%d,%d) = %f\n",y,x,m,Y,(y-1+1)*c+x+1,TGRID(Y,(y-1+1)*c+x+1)), end
        if  (y+1)>r then printf(" __BORDER__"), m=m+1,elseif GRID(y+1, x) == 'O' then printf(" __OBJECT__"), TGRID(Y,(y-1)*c+x)=0,m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1+1)*c+x)=1/MAX,  printf("(y,x) = (%d,%d) with m = %d TG(Y,Y) = (%d,%d) = %f\n",y,x,m,Y,(y-1+1)*c+x,TGRID(Y,(y-1+1)*c+x)), end
        if  (y+1)>r|(x-1)<1 then printf(" __BORDER__"), m=m+1,elseif GRID(y+1, x-1) == 'O' then printf(" __OBJECT__"), TGRID(Y,(y-1)*c+x)=0,m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1+1)*c+x-1)=1/MAX, printf("(y,x) = (%d,%d) with m = %d TG(Y,Y)  = (%d,%d) = %f\n",y,x,m,Y,(y-1+1)*c+x-1,TGRID(Y,(y-1+1)*c+x-1)), end
        if   (x-1)<1 then printf(" __BORDER__"), m=m+1,elseif GRID(y, x-1) == 'O' then printf(" __OBJECT__"), TGRID(Y,(y-1)*c+x)=0,m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1)*c+x-1)=1/MAX, printf("(y,x) = (%d,%d) with m = %d TG(Y,Y)  = (%d,%d) = %f\n",y,x,m,Y,(y-1)*c+x-1,TGRID(Y,(y-1)*c+x-1)), end
        if  (y-1)<1|(x-1)<1 then printf(" __BORDER__"), m=m+1,elseif GRID(y-1, x-1) == 'O' then printf(" __OBJECT__"), TGRID(Y,(y-1)*c+x)=0,m=m+1,else  printf(" __MOVE__"),TGRID(Y,(y-1-1)*c+x-1)=1/MAX, printf("(y,x) = (%d,%d) with m = %d TG(Y,Y)  = (%d,%d) = %f\n",y,x,m,Y,(y-1-1)*c+x-1,TGRID(Y,(y-1-1)*c+x-1)), end
        
        if GRID(y, x)=='O' then  for z=1:N,TGRID(Y,z)=0,end
            else TGRID(Y,Y)=m/MAX, end
          
     
    
    end //x
  end //y
  end //Y
 
endfunction



   
//**********************************************
// SOME TEST RESULTS
// Mean and StandardDeviation directly by scilab:
//
// M=[],for i=1:6, M(i,1)=mean(D2RESULTS0(i,:)), M(i,2)= st_deviation(D2RESULTS0(i,:)), end
// Extracting the MAXima of a run
// MAXD2=max(D2RESULTS0,"c")
// Extracting the 1st row out of the results
// D2R30=D2RESULTS0([1],[:])
// Starting a counter for the frequencies
// F30=zeros(1,MAXD2(1,1)+1)
// F40=zeros(1,MAXD2(2,1)+1)
// Computing the frequency of the values of a run
// for i=1:c, F30(1,D2R30(1,i)+1)=F30(1,D2R30(1,i)+1)+1,end
// for i=1:c, F40(1,D2R40(1,i)+1)=F40(1,D2R40(1,i)+1)+1,end
// F30 =[12 8 2 3] := 12 x 0, 8 x 1, ...
// Compute the means by using the values in T and the frequencies in F
// N=sum(F), MEAN=0, for i=1:length(T), MEAN=MEAN+(F(1,i)*T(1,i)),end; MEAN=MEAN/N
// DIFFs=[], for i=1:length(F30), DIFFs(1,i)=(i-1)-MEAN,end
// DIFs2=[],for i=1:length(F30), DIFs2(1,i)=DIFFs(1,i)^2,end
// Attention: the index of the array FX30 as 'i-1'  is the observed value!
// SAQs=[],for i=1:length(F30), SAQs(1,i)=F30(1,i)*DIFs2(1,i),end
// standard deviation
// N=sum(F30),s=sqrt(sum(SAQs)/(N-1))
   
//**********************************
// RANDOM TEST WORLD FOR BENCHMARKING 
//
// This world has one food cell with 'F' in the center and
// has a fixed diameter d according to the distance which
// shall be explored.


function[GRID]=testgrid(DISTANCE)
  
  D=DISTANCE
  //Generate normal empty space '.'
  for j=1:(2*D)+1,
    for i=1:(2*D)+1 
      GRID(i,j)='.',
    end
  end
  
  //Locate the food in the center
  GRID(D+1,D+1)='F'

endfunction



//*************************************************
// ANIMAT STRUCTURE

Xanimat = 3
Yanimat = 5
RewTotal = 0
RewActual = 0

ANIMAT = list(Xanimat, Yanimat, RewTotal, RewActual)

//****************************************************
// HISTORY
// Collecting data during one life-cycle
// 1 := Cycle number k
// 2 := Object before move
// 3 := X-Pos
// 4 := Y-Pos
// 5 := REWTotal

HISTORY =[]

//***************************************************
// Function to decode the content of a cell

function[CELLVALUE]=contdecode(YI,X,GRID,SHOW)
  
  [YMAX, XMAX]=size(GRID)
  
  if (SHOW==1) then printf("contdecode: SIZE OF GRID (X,Y) = (%d,%d)\n",XMAX,YMAX),end
  
  CELLVALUE=[]
  
  if (SHOW==1) then printf("contdecode: YI= %d, X= %d\n",YI,X),end
  
  if (X > XMAX) | (X < 1) | (YI > YMAX) | (YI <1) then CELLVALUE='BB'
    elseif GRID(YI,X) =='.' then CELLVALUE='00'
    elseif GRID(YI,X) =='O' then CELLVALUE='10'
    elseif  GRID(YI,X) =='F' then CELLVALUE='11'
    else printf("contdecode:ERROR AT CELL =( %d,%d)\n",X,YI)
    end
    
endfunction



//*************************************************
// SENSING ENVIRONMENT
//
// Loocking to the 'north' the Animat can see the content of all it's neighbouring cells clockwise around.
// The encoding is as follows:
// '.' := Empty space encoded '00'
// 'O' := Object Rock encoded '10'
// 'F' := Object Food encoded '11'
//
// Different to Wilson (1994) we do not assume an 'infinite finite' world by 15 rows and 55 columns
// but a finite world with  dynamic shape. This allows to investigate the effect of GRID size onto different parameters.
//

function [SENSINPUT,INPUT]=animsens(YI,X,GRID,SHOW)
  
  //Having a 'number' version of the input
  SENSINPUT=[]
  //Having a 'sring' version of the input
  INPUT=""
  
//The cells will be searched from 'north' in clockwise order
// The coordinates below are relativ to the actual position of the ANIMAT

  P=[-1,0; -1,1; 0,1; 1,1; 1,0; 1, -1; 0,-1; -1,-1 ]
  
[r,c]=size(P)
for j=1:r, SENSINPUT(j)=contdecode(YI+P(j,1),X+P(j,2),GRID),
  INPUT=INPUT+string(SENSINPUT(j))
end

if (SHOW==1) then
  printf("Sens Input: %s\n\n",INPUT)
  end
    
endfunction



//*************************************************
// RANDOM MOVEMENT GENERATOR
// Generates movements based on  uniform random numbers from 0 ... 8
//
// XO, YO := old X-Y-Position
// XN, XN := new X-Y-Position



function [XN,YN] =mover(XO, YO, GRID)
  
  R=floor(9*rand())  
  //printf("mover:RANDOM NUMBER R= %d\n\n",R)
  
   //The cells will be searched from 'north' in clockwise order
   
   if R == 0 then XN=XO, YN=YO
   elseif R == 1 then YN=YO-1, XN=XO
     elseif R==2  then YN=YO-1, XN=XO+1
     elseif R==3  then YN=YO, XN=XO+1
     elseif R==4 then  YN=YO+1, XN=XO+1
     elseif R==5 then  YN=YO+1, XN=XO
     elseif R==6 then  YN=YO+1, XN=XO-1
     elseif R==7  then YN=YO, XN=XO-1
     elseif R==8 then  YN=YO-1, XN=XO-1
     else printf("mover:ERROR WITH MOVEMENT AT = (XO, YO) = ( %d,%d)\n",XO,YO)
       end
    
  endfunction




//*************************************************
// FOOD DISTANCE EVALUATOR
// Starting the search at the actual position of the ANIMAT
// the search searches all cells with distance=i in a
// clockwise order. If it finds food cells these will
// be 'tracked' and the distance is is fixed to i.
//
// Attention: If the ANIMAT is located near the boarder of the GRID one
// has to 'neutralize' thoses values which point 'beyond' the GRID


function [FDISTANCE,GLIST]=foodsearch(ANIMAT, GRID,SHOW)
  
  if(SHOW==1) then
    printf("foodsearch: START AT (%d,%d)\n\n",ANIMAT(1),ANIMAT(2)),end
  
   //The cells will be searched from 'north' in clockwise order
   // GOALFLAG indicates having found a food cell
   // FDISTANCE measures the distance
   // K is an index to list the goal coordinates
   // GLIST collects the coordinates of the goals
   
   [row,col]=size(GRID)
   
   if(SHOW==1) then printf("row = %d, col = %d\n",row,col),end
   
   GOALFLAG=0
   FDISTANCE=0
   X=ANIMAT(1),YI=ANIMAT(2)
   GLIST=[] 
   K=1
   
     if(SHOW==1) then
     printf("foodsearch: 1\n\n"),end
     
   L=1
   while(GOALFLAG==0)| (2*L>floor(sqrt(row^2+col^2)))
     
          if(SHOW==1) then
     printf("foodsearch: 2, L=%d\n\n",L),end
     
    for j=-L:L,  for i=-L:L, 
       
    if(SHOW==1) then
      if(X+i <1)|(YI+j <1)| (X+i >col) |(YI+j>row) then printf("BEYOND\n"),
      else printf("foodsearch: 3 (YI,X) = (%d,%d) = %s\n\n",YI+j,X+i,GRID(YI+j,X+i)),end
      end
       
    if(X+i >1)&(YI+j >1)& (X+i <col) &(YI+j<row) & GRID(YI+j,X+i)=='F' then  GOALFLAG=1, FDISTANCE=L,GLIST(K,1)=X+i, GLIST(K,2)=YI+j,K=K+1,end
 
               end // FOR
                end //FOR
          L=L+1
     end //WHILE

    
  endfunction



//*************************************************
// MOVEMENT EVALUATION
// DEPENDING FROM CONTENT OF NEW PROPOSED POSITION SELECT ACTION
//
// Borderline   := -3 (negative reward)
// Object    := -2 (negative reward)
// Empty cell  := -1 (move into it, but looses energy)
//// Food      := (move into it, reward +1000)
//
// Borderline := XXMAX = YYMAX = 1 or YYMAX or XXMAX
//
// CONT := Decoded content
// GRID := Assumed GRID
// REW := Reward inferred
// ACT := No Move as 0, Move as 1



function [REW,ACT,OBJ] =moveeval(CONT, GRID,SHOW)
  
   
   if CONT == 'BB' then REW=-1, ACT=0, OBJ=-1
   elseif CONT == '00' then REW=-2, ACT=1, OBJ=0
   elseif CONT == '10' then REW=-1, ACT=0, OBJ=1
   elseif CONT == '11' then REW=1000, ACT=1, OBJ=2
     else printf("moveeval:ERROR WITH MOVEEVAL\n\n")
     end
     
     if (SHOW==1) then
     printf("moveeval:REWARD = %d, ACTION = %d\n\n",REW,ACT)
   end
   
  endfunction



//*************************************************
// UPDATE ANIMAT
//
// Either keep position or move.
// Summarize reward


function [ANIMAT] = updateAnim(ANIMAT,REW,ACT,XN,YN,SHOW)
  
   
   if ACT == 1 then ANIMAT(1) = XN, ANIMAT(2) = YN,  ANIMAT(4) = REW, ANIMAT(3)=ANIMAT(3)+REW
     else ANIMAT(4) = REW, ANIMAT(3)=ANIMAT(3)+REW
     end
     
     if (SHOW==1) then
     printf("update ANIMAT: A-POS = (%d,%d), A-REW = %d, A-REW-SUM = %d\n\n",ANIMAT(1), ANIMAT(2), ANIMAT(4), ANIMAT(3))
   end
   
  endfunction


//***************************************************
// Function to fetch the conditions out of the classifier set
// 

function [CONDITIONS]=getCondition(CLASSIFIERS)
  
 [r,c]=size(CLASSIFIERS)
  CONDITIONS=""
 
for j=1:r
  T=tokens(CLASSIFIERS(j,1),[':']), CONDITIONS(j)=string(T(1,1))
end


endfunction


//***************************************************
// Get set of matching conditions

function [MATCHSET]=getCondition(CONDITIONS, INPUT)
  
 [r,c]=size(CONDITIONS)
  
 //...to be completed...

endfunction

//***************************************************
// SIMPLE AUTOMATED TEST FRAMEWORK FOR ZCS
//
// Automatic testing for a certain GRID with given numers of runs
//
// ANIMAT := Structure OF ANIMAT system
// HISTORY := Protocol of movements and cumulated rewards
// GRID := Content of environment
// MODE := random (=0), non-random (=1)
// YYMAX := Number of rows times 5
// XXMAX := Number of columns times 5
// RUNS := How many cycles the simulation shall run. 1 cycle means one action
// S := scaling factor in the sparse food case
// GRID := Fixed GRID from external source
// DISTANCE := General distance from food in test field


function [ANIMAT,HISTORY,GRID,FOOD]=liveR(ANIMAT,CLASSIFIERS,MODE,YYMAX, XXMAX, S,GRID,DISTANCE, RUNS,HISTORY,SHOW)
  
  if (RUNS<0) then error('RUNS is not specified'),end
  
  //GENERATE FIXED TEST GRID
  if (S==-1) then [GRID]=testgrid(DISTANCE),
  
  //GENERATE dynamic GRID
  elseif (S == 0) then [GRID]=gridgen(YYMAX, XXMAX),
  
  //GENERATE dynamic GRID with sparse food
elseif (S == 1) then [GRID]=gridgen2(YYMAX,XXMAX,S),

  // USE external GRID
else S =2,
end

  
  //SET GLOBAL VARIABLES TO ZERO
  HISTORY=[]
  ANIMAT(3)=0
  f=1 //Index to store in which cycle food has been found
  FOOD=[] //Storage for differences
  FOLD=0
  FNEW=0


  k=1
  while(k < RUNS+1),
    
    if (SHOW==1) then
    printf("-----CYCLE %d---------------------------------------------------\n\n",k)
    end
  
  [YMAX,XMAX]= size(GRID)
  //printf("DIMENSION OF GRID - ROWS = %d, COLUMNS = %d\n\n",ZMAX,XMAX)
  
  // (1) Get actual position (XO,YO) from Animat 
  // Is given with argument ANIMAT(1) = rows and ANIMAT(2) = columns
  
  XO= ANIMAT(1)
  YO= ANIMAT(2)
  
  if (SHOW==1) then
  printf("ACTUAL POSITION =(XO,YO) = (%d, %d)\n\n",XO,YO)
end


// Get SENSINPUT as string: INPUT

if(MODE==1) then
[SENSINPUT,INPUT]=animsens(YO,XO,GRID,SHOW)
end


  
  // (2) Generate new move (XN,YN)
  
  [XN,YN] =mover(XO, YO, GRID)
  
   if (SHOW==1) then
  printf("NEW POSITION PROPOSED=(XN,YN)= (%d, %d)\n\n",XN,YN),end


  // (3) Decode the content of new position
  
  [CELLVALUE]=contdecode(YN,XN,GRID,SHOW)
  
   if (SHOW==1) then,
  printf("CONTENT OF NEW POSITION= %s\n\n",CELLVALUE),end


  // (4) Depending from content finalize move
  
  [REW,ACT,OBJ] =moveeval(CELLVALUE, GRID,SHOW)
  
  // (5) Update ANIMAT
  
  [ANIMAT] = updateAnim(ANIMAT,REW,ACT,XN,YN,SHOW)
  
  if  (REW==1000) then FNEW=k,FOOD(f,1)=FNEW-FOLD, FOLD=FNEW, f=f+1, end
  if (SHOW==1) & (REW==1000) then  printf("FOOD in CYCLE = %d\n\n",k),end
  
  // Update PATHHISTORY
  
  [r,c]=size(HISTORY)
  
  //INDEX
  
  HISTORY(r+1,1)=k
  
  //CONTENT
  
  HISTORY(r+1,2)=OBJ
  
  // POSITION
  HISTORY(r+1,3)=XN, HISTORY(r+1,4)=YN
  
  //REWARDTOTAL
  HISTORY(r+1,5)=ANIMAT(3)
  
  //Update while loop
  
  
  k=k+1,
  
end
MEAN=mean(FOOD)

printf("REWSUM/1000 = %f\n, TIMES FOOD = %f, MEAN LENGHT = %f\n\n",ceil((ANIMAT(3)/1000)),length(FOOD),MEAN)

endfunction


//***************************************************
// SIMPLE AUTOMATED TEST FRAMEWORK FOR ZCS
// WITH REPETITION
//
// ANIMAT := Structure OF ANIMAT system
// HISTORY := Protocol of movements and cumulated rewards
// GRID := Content of environment
// MODE := random (=0), non-random (=1)
// YYMAX := Number of rows times 5
// XXMAX := Number of columns times 5
// RUNS := How many cycles the simulation shall run. 1 cycle means one action
// S := scaling factor in the sparse food case
// GRID := Fixed GRID from external source
// DISTANCE := General distance from food in test field
// N:= Number of repetitions of an experiment with RUNS-many actions
// FOODHITS := List of food hits per repetition
// MEAN := statistical mean
// STD := standard deviation


function [FOODHITS,MEAN, STD]=experiment(ANIMAT,CLASSIFIERS,MODE,YYMAX, XXMAX, S,GRID,DISTANCE, RUNS,HISTORY,SHOW,N)
  
  FOODHITS=[]
  
  for i=1:N,
  
  [ANIMAT,HISTORY,GRID,FOOD]=liveR(ANIMAT,CLASSIFIERS,MODE,YYMAX, XXMAX, S,GRID,DISTANCE, RUNS,HISTORY,SHOW),
  
   
  [r,c]=size(FOODHITS),
  
  //INDEX
  
  FOODHITS(r+1,1)=length(FOOD),
  
end
MEAN=mean(FOODHITS)
STD=st_deviation(FOODHITS)


endfunction

  

//*************************************************
// RANDOM NUMBER GENERATOR TESTs
// Testing the quality of the produced pseudo-random numbers
// according to some procedures described by Knuth 1989.
//
// N := Numbers of psyeudo random numbers to generate
// EQUISUMS := counting each number r_i within N
// SHOW := Flag, if '1' then print random numbers, otherwise not
// C := Number of categories +1


function [EQUISUMS] =countingrands(N,C,SHOW)
  
  
  // Matrix for counting the C-many different events
  
  EQUISUMS=zeros(1,C)

  //Loop to generate pseudo random numbers
 
  i=0
  while (i<N),
    
    R=floor(C*rand())
    
    //PRINT 'on demand'  
    if (SHOW==1) then printf("countingrands:RANDOM NUMBER R= %d\n",R)
    end
    
    //Counting occurences of different numbers
    
    for j=1:C, 
    if (R==j-1) then EQUISUMS(j)= EQUISUMS(j)+1,end
        end
  
  i=i+1
  end
endfunction


//*************************************************
// RANDOM NUMBER GENERATOR TESTs
// Testing the quality of the produced pseudo-random numbers
// according to some procedures described by Knuth 1989.
//
// N := Numbers of psyeudo random numbers to generate
// EQUISUMS := counting each number r_i within N
// SHOW := Flag, if '1' then print random numbers, otherwise not
// C := Number of categories +1


function [EQUISUMS] =countingMatrix1(N,C,SHOW)
  
  
  // Matrix for counting the C-many different events
  
  EQUISUMS=zeros(1,C)

//Generate pseudo random numbers

RANDMATRIX=rand(1,N)

    //Counting occurences of different numbers
    
    for i=1:N
      RANDMATRIX(1,i)=floor(RANDMATRIX(1,i)*C)
    for j=1:C, 
    if (RANDMATRIX(1,i)==j-1) then EQUISUMS(j)= EQUISUMS(j)+1,end
  end
  end
  
endfunction

//*************************************************
// RANDOM NUMBER GENERATOR TESTs
// Testing the quality of the produced pseudo-random numbers
// according to some procedures described by Knuth 1989.
//
// N := Numbers of psyeudo random numbers to generate
// EQUISUMS := counting each number r_i within N
// SHOW := Flag, if '1' then print random numbers, otherwise not
// C := Number of categories +1


function [EQUISUMS] =countingMatrix2(N,C,SHOW)
  
  
  // Matrix for counting the C-many different events
  
  RANDMATRIX=zeros(1,N)
  EQUISUMS=zeros(1,C)

//Generate pseudo random numbers

RANDMATRIX=grand(1,N,'uin',0,C-1)
printf("\nSeed after %d\n",rand('seed'))

    //Counting occurences of different numbers
    
    for i=1:N
    for j=1:C, 
    if (RANDMATRIX(1,i)==j-1) then EQUISUMS(j)= EQUISUMS(j)+1,end
  end
  end
  
endfunction

//*************************************************
// RANDOM NUMBER GENERATOR TESTs
// Testing the quality of the produced pseudo-random numbers
// according to some procedures described by Knuth 1989.
//
// Computing the differences between theoreticalyl expected and observed values


function [DIFFSUMS] =sumdifferences(N,C,EQUISUMS)
  
  DIFFSUMS=zeros(1,C)
  
for i=1:C,  DIFFSUMS(i)=(N/C)-EQUISUMS(i), DIFFSUMS(i)=DIFFSUMS(i)/(N/(C/100)),end


endfunction



//*************************************************
// RANDOM NUMBER GENERATOR TESTs
// Testing the quality of the produced pseudo-random numbers
// according to some procedures described by Knuth 1989.
//
// Computing the Chi-square statistics assuming equally distributed probabilities


function [CHISQUARE] =chisquare1(N,C,EQUISUMS,SHOW)
  
 
  np=(1/C)*N
  S=0
  for i=1:C,
    if (SHOW==1) then
    printf(" i= %d, Observed= %d, Expected = %f\n",i,EQUISUMS(i), np),
    printf(" i= %d,Diff= %f,Diff-Square = %f\n",i,EQUISUMS(i)- np, (EQUISUMS(i)- np)^2),
    printf(" i= %d,Quotient = %f\n",i,((EQUISUMS(i)- np)^2)/np), end
 
 S=S+((EQUISUMS(i)-np)^2)/np,
 end
  
  CHISQUARE=S

endfunction

//*************************************************
// RANDOM NUMBER GENERATOR TESTs
// Testing the quality of the produced pseudo-random numbers
// according to some procedures described by Knuth 1989.
//
// Computing the Chi-square statistics assuming different probabilities
// PROBABILITIES := Array of different probabilities


function [CHISQUARE] =chisquare1b(N,C,EQUISUMS,SHOW)
  
  
  [r,c]=size(EQUISUMS)
  
  if(c <> C) then printf("chisquare1b: c and C DIFFERENT!!!\n\n"),end
  
  PROBABILITIES=zeros(r,c)
  for i=1:c, PROBABILITIES(1,i)=1/C,end
  
    S=0
    for i=1:c
  S=S+((EQUISUMS(i)-N*PROBABILITIES(1,i))^2)/(N*PROBABILITIES(1,i)),end
  
        CHISQUARE=S
        
endfunction
    



//*************************************************
// RANDOM NUMBER GENERATOR SIMULATING TWO DICES
//
// N := Numbers of psyeudo random numbers to generate
// EQUISUMS := counting each number r_i within N
// SHOW := Flag, if '1' then print random numbers, otherwise not
// C := Number of overall categories +1
// MAXDICE := MAximum of onbe dice


function [EQUISUMS] =counting2rands(N,SHOW,MAXDICE)
  
  
  // Matrix for counting the C-many different events
  EQUISUMS=zeros(1,(MAXDICE*2)-1)

  //Loop to generate pseudo random numbers
 
  i=0
  while (i<N),
    R1=floor(MAXDICE*rand())+1
    R2=floor(MAXDICE*rand())+1
    X = R1+R2
    
    //PRINT 'on demand'  
    if (SHOW==1) then printf("countingrands:RANDOM NUMBERs R1= %d, R2=%d, X=%d\n",R1,R2,X)
    end
    
    //Counting occurences of different numbers
    
    for j=2:MAXDICE*2, 
      if (X==j) then EQUISUMS(j-1)= EQUISUMS(j-1)+1,
        end
        end
  
  i=i+1
  end
endfunction

  

//*************************************************
// RANDOM NUMBER GENERATOR TESTs
// Testing the quality of the produced pseudo-random numbers
// according to some procedures described by Knuth 1989.
//
// Computing the Chi-square statistics assuming different probabilities
// PROBABILITIES := Array of different probabilities


function [CHISQUARE] =chisquare2(N,EQUISUMS,PROBABILITIES,SHOW)
  
  
  [RR,CC]=size(PROBABILITIES)
  [r,c]=size(EQUISUMS)
  if (c <> CC) then  printf("chisquare2:EQUISUMS and PROBABILITIES have DIFFERENT columns\n\n"),end
    
    CHISQUARE=0
    S=0
    for i=1:CC, 
      if (SHOW==1) then
    printf(" i= %d, Observed= %d, Expected = %f\n",i,EQUISUMS(i), N*PROBABILITIES(2,i)),
    printf(" i= %d,Diff= %f,Diff-Square = %f\n",i,EQUISUMS(i)- N*PROBABILITIES(2,i), (EQUISUMS(i)- N*PROBABILITIES(2,i))^2),
  printf(" i= %d,Quotient = %f\n",i,((EQUISUMS(i)- N*PROBABILITIES(2,i))^2)/N*PROBABILITIES(2,i)), end
  
  S=S+((EQUISUMS(i)-N*PROBABILITIES(2,i))^2)/(N*PROBABILITIES(2,i)),end
  
        CHISQUARE=S
        
endfunction


//*************************************************
// CELLDISTANCE
// Measured in Manhattan Distance
// Not usable for movements because movements can happen as diagonal moves too!
//
// V1 =(X1,Y1)
// V2 = (X2,Y2)

function [CELLDIST] =celldistance(V1,V2)
  

CELLDIST=( abs(V1(1,1)-V2(1,1)) + abs(V1(1,2)-V2(1,2))  )

  endfunction
  
  
//********************************************************* 

//Some common constants

//Conversion of radiants into grade

grad=(2*%pi)/360

//Conversion of radiants into degrees

igrad=360/(2*%pi)


//***************************************************
//Function to compute the sum of a vector v and the i-th row of a matrix M

function[M]=vecAddMi(M,i,v)

//Test whether the length of v is equal to the columns of M


[r,c]=size(M);
if l <> c then error('SIZE of VECTOR DOES NOT MATCH MATRIX'),
else  
  for j=1:c, M(i,j) = M(i,j)+v(j),
    end
  end
endfunction


//***************************************************
//Function to compute the difference of a vector v and the i-th row of a matrix M

function[M]=vecSubMi(M,i,v)

//Test whether the length of v is equal to the columns of M

l=length(v);
[r,c]=size(M);
if l <> c then error('SIZE of VECTOR DOES NOT MATCH MATRIX'),
else  
  for j=1:c, M(i,j) = M(i,j)-v(j),
    end
  end
endfunction



//***************************************************
//Function to compute the product of two vectors v,w

function[u]=vecprod(v,w)

lv=length(v);
lw=length(w);

u=0

if lv <> lw then error('DIFFERENT LENGTH OF VECTORS');

else  for i=1:lv, u=u + (v(i)*w(i));
end
end

endfunction

//***************************************************
//Function to compute the projection of a vector v onto a line with angle theta
//angle in degree

function[y]=vecproj(v,t)

//Convert radiants into degree
t=t/igrad

y=norm(v)*cos(t)

endfunction

//***************************************************
//Function to compute the projection of a vector v onto a line with line w

function[y]=vecprojL(v,w)


y=vecprod(v,w)/norm(w)

endfunction


//*************************************************************
//Function to compute the angle of two vectors v,w in 360 degree
//Vectors v,w are column or row vectors

function[y]=cosvec(v,w)

y=vecprod(v,w)/(norm(v)*norm(w))
  
//The result in y is the cos-value. We need the invers of this

y=acos(y)

//The inverse is given in radiants. We want the conversion to degrees

y=y/grad

endfunction
//End of function cosvect ******************************************

//*******************************************************
//Function to multiply a vector v with a quadratic matrix M generating a vector u

function[u]=vmprod(v,M)

[r,c]=size(M)
lv=length(v)
u=zeros(1,lv)

if (r <> lv)  then error('sizes of vector and matrix do not match')
else

for i=1:c  //Following the columns of matrix
for j=1:r  //Working through all elements of v and rows of M
u(j)=u(j) + (v(i) *M(i,j))
end
end
end

endfunction



//*******************************************************
//Function to multiply a vector v with a selectable matrix M generating a vector u


function[u]=vmprod2(M,v)

[r,c]=size(M)
lv=length(v)
u=zeros(1,lv)

if (r <> lv) then error('sizes of vector and matrix do not match')
else

for j=1:r  //Following the rows of matrix
for i=1:c  //Working through all elements of v and columns of M
u(j)=u(j) + (v(i) *M(j,i))
end
end
end

endfunction


//*******************************************************
//Macro for the usage of vmprod2()
//


function [OUTPUT]=vmprod2makro(WEIGHT,INPUT,RUNS)
  
  for i=1:RUNS,
    [OUTPUT]=vmprod2(WEIGHT,INPUT),
    INPUT = OUTPUT,
  end
  

endfunction


//*******************************************************
// DYNAMIC PROBABILITY FIELD
// Function for the repeated  usage of vmprod2()
//
// INPUT:= Initial Probability Distrbution of the Field (agent =1)

function [OUTPUT, STD]=fieldprob(WEIGHT,INPUT,RUNS, SHOW)
  
  for i=1:RUNS,
    [OUTPUT]=vmprod2(WEIGHT,INPUT),
    INPUT = OUTPUT,
    if (SHOW==1) then printf("RUN= %d : ",i), for j=1:length(OUTPUT), printf(" %f ",OUTPUT(1,j)),
        end, printf("\n\n"),
      end
    
  end
  
  STD=st_deviation(OUTPUT)

endfunction

//****************************************************
//Funcion to generate a m x n - Matrix with the scalar c

function[C] = matrixC(r,c,a)

C=[] //New Matrix 
for i=1:c; for j=1:r; C(i,j)=a; end;  end //Generate new matrix with scalar a
C

endfunction


//****************************************************
//Funcion to generate a m x n - Matrix with the scalar c out of a given matrix M

function[C] = matrixCC(M,a)

C=[] //New Matrix 
[c,r]=size(M) //Get dimension of given matrix M by columns and rows
for i=1:r, for j=1:c, C(i,j)=a, end, end //Generate new matrix with scalar a

endfunction



Subsections

Gerd Doeben-Henisch 2012-03-31