Functions of Reactive Agent: A1_reactive_functions.sci

//**************************************************************
// File: A1_reactive_functions.sci
// Authors: Gerd Doeben-Henisch
// Version Start: May-18, 2010
//---------------------------------
// Last Change: Nov-26, 2012, 19:20h
//**********************************************************
// diary
//******************************************************************
// CONTENT: Necessary code for an A1-reactive-agent, the successor of the
// ANIMAT0-agent.

// ANIMAT = list(Xanimat, Yanimat, RewTotal, RewActual, CLASSIF, Energy)
// HISTORY =[]
// [CELLVALUE]=decode(YI,X,GRID,SHOW)
// [PERC]=ainp(YI,X,GRID,SHOW)
// [ANIMAT]=impact(CELLVALUE,ANIMAT,SHOW)
// [ANIMAT]=feedback(CLASSIF, ANIMAT, SHOW)
// Matchset, 2 cases:
// VITAL==1: then look for free space and the highest reward
// VITAL==0: look first for food and hifhest reward; if not then for space
// [MATCHV]=matchV(CLASSIF,j, VITALNOW,SHOW)
// [MATCHP]=matchP(CLASSIF,j, PERC, SHOW)
// [MATCHSET]=selectM(CLASSIF,PERC, VITALNOW,SHOW)
// [MATCHVP]=match2(CLASSIF,j,PERC, VITALNOW,SHOW)
// [IDXM,CAND, MATCHSET,ACTIONSET]=makeCAND(MATCHSET,SHOW)
// [ANIMAT,OLDACTIONS]=manageOldActs(IDXM,CAND,OLDACTIONS,ACTIONSET,ANIMAT,FOODIDX)
// [YN, XN]=aout(ACT,SHOW, YO, XO)
// [ANIMAT,HISTORY,GRID,FOOD]=liveR2(ANIMAT,GRID, RUNS,SHOW)
// [FOODHITS,MEAN, STD]=experiment1(ANIMAT,YS, XS,ENERGYS, GRID, RUNS,HISTORY,SHOW,N)
// [HISTORY]=updateHIST(HISTORY,k, CELLVALUE,XN,YN,ANIMAT)
// [FOOD]=FOOD(HISTORY,RUNS)
// [ANIMAT]=zeroCLASSIFFEEDB(ANIMAT,CLASSIF)
// Set OLDACTIONS to zero
// [ANIMAT, OLDACTIONS]=oldActZero(ANIMAT,OLDACTIONS)

//***************************************************
//The Generation of ENVIRONMENTS as GRIDS will be done by another PREPARATORY
// SCRIPT
// Here we have only a few special TEST GRIDS
 


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

HISTORY =[]


//***************************************************
// Function to decode the content of a cell
//
// Only change: Border 'BB' is replaced by value '01'

function[CELLVALUE]=decode(YI,X,GRID,SHOW)
  
  [YMAX, XMAX]=size(GRID)
  
  if (SHOW==1) then printf("decode: SIZE OF GRID (X,Y) = (%d,%d)\n",XMAX,YMAX),end
  
  CELLVALUE=[]
  
  
  if (SHOW==1) then printf("decode: YMAX=%d, XMAX=%d,YI= %d, X= %d\n",YMAX, XMAX,YI,X),end
  if (X > XMAX) | (X < 1) | (YI > YMAX) | (YI <1) then CELLVALUE='01'
    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("decode:ERROR AT CELL =( %d,%d)\n",X,YI)
    end
    
endfunction

//*************************************************
// SENSING ENVIRONMENT
// Function ainpe(POS,DISTANCE) from ANIMAT1-agent
//
// Loocking to the 'north' the Animat can see the content of all it's neighbouring cells clockwise around.
// Enhancing the distance by 1 extends the field to the next 'circle'
// The encoding is as follows:
// '.' := Empty space encoded '00'
// Border BB := has to be encoded as '01'
// 'O' := Object Rock encoded '10'
// 'F' := Object Food encoded '11'


function [PERC]=ainp(YI,X,GRID,SHOW)
  
  //Having a 'number' version of the input
  SENSINPUT=[]
  PERC=""
  
//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)=decode(YI+P(j,1),X+P(j,2),GRID, SHOW),
  PERC=PERC+string(SENSINPUT(j))
end

if (SHOW==1) then
  printf("ainp: PERC = %s\n\n",PERC)
  end
    
  endfunction
  

//*************************************************
// IMPACT
// impact: PERC x ENERGY  ---> ENERGY x VITAL
//
// Depending on the actual state of ENERGY  will the perception PERC
// eventually change the state of ENERGY and thereby of VITAL.
// FOOD will increase the state of  ENERGY and NON-FOOD
// will decrease the state.

function [ANIMAT]=impact(CELLVALUE,ANIMAT,SHOW)
  
  // Get new energy
if(CELLVALUE == '11') then
  
    ANIMAT(15)=1  
    ANIMAT(4)= ANIMAT(10) //Input Food
    else   ANIMAT(4)=ANIMAT(11) // Input No-Food
    end
   
    ANIMAT(3) = ANIMAT(3)+ANIMAT(4)
 
 // Update the VITAL state; compare Threshold ANIMAT(12)= 0.5* FOODIDX
 if (ANIMAT(3) > ANIMAT(12)) then ANIMAT(6) = 1,
 else ANIMAT(6) = 0
     
 end
 
endfunction

//*************************************************
// matchP: PERC x CLASSIFIERS ---> {0,1}
//
// matchP matches the PERCEPTION-part of a classifier and the P parameter
// of the system
//
// Does match : '0'
// Does not match : '1'
// j := IDX of Classifier

function [MATCHP]=matchP(CLASSIF,j,PERC, SHOW)
  
  [r,c]=size(CLASSIF)
  l = length(PERC)
  m=0
  i=1
  
  // Strings have to be converted into vectors first
  
  [pc]=strsplit(CLASSIF(j,1))
  pr=pc'
  [percc]=strsplit(PERC)
  percr=percc'
  
  while(( i<l+1) & (m==0))
    
    if (percr(i) == '0') & ((pr(i) == '0') | (pr(i) == '#')) then m=0, 
      if(SHOW == 1) then
       printf("matchP: Case 0, i = %d\n ",i),end
      
    elseif (percr(i) == '1') & ((pr(i) == '1') | (pr(i) == '#')) then m=0, 
            if(SHOW == 1) then
       printf("matchP: Case 1, i = %d\n ",i),end
      
    else m=1, 
            if(SHOW == 1) then
       printf("matchP: NO-Case, i = %d\n ",i),end
      
    end //IF
    
    i=i+1
    
    end //WHILE
  
  MATCHP=m
  
endfunction


//*************************************************
// SELECTM
// selectM: PERC x VITALl X CLASSIF ---> MATCHSET
//
//   

function [ANIMAT,MATCHSET]=selectM(ANIMAT, CLASSIF,PERC,MATCHSET,SHOW)
  
  
  MATCHSET=[], k=1
  [r,c]=size(CLASSIF)
  
  for j=1:r,
    if(matchP(CLASSIF,j, PERC, SHOW)==0)  then MATCHSET(k,:)=CLASSIF(j,:), 
      
       if(SHOW == 5) then
       printf("selectM: selected=%d, k=%d\n",j,k), end
       
      k=k+1,
      end// IF matchP
    end// FOR
    
    ANIMAT(13) = MATCHSET
    
    disp('MATCHSET END OF selectM')
    disp(MATCHSET)
    
endfunction

//***************************************************
// makeCANDpath
// 
// searches all classifiers from the matchset with a path option,
// then takes that option with highest reward
// makeCAND : MATCHSET ---> IDXCAND, ACTIONSET
// 

function [IDXM,CAND, MATCHSET,ACTIONSET,ACT]=makeCANDpath(MATCHSET,SHOW)
 
 [mr,mc]=size(MATCHSET)
  
 // Searches for classifiers with path option
 
 j=0  // Index for ACTSET, copy if path matches
 needle='00' //Hint for path
 for i=1:mr,
     if grep(MATCHSET(i,1),needle)<>[] then 
         j=j+1,
         ACTIONSET(j,:)=MATCHSET(i,:)  
         end 
      
  end
  
  MATCHSET=[]
  MATCHSET=ACTIONSET
  
   [mr,mc]=size(MATCHSET)
  MAX=0
  
  //Searches for the HIGHEST value of REW
  
  for i=1:mr,
    if(eval(MATCHSET(i,4)) > MAX) then MAX=eval(MATCHSET(i,4)),
      end
   
 end
 
     disp('MATCHSET MIDDLE OF makeCANDpath')
    disp(MATCHSET)
 // Identifies all elements of MATCHSET which have the highest REW-value
 
 k=1
 CAND=[]
 
   for i=1:mr,
    if(eval(MATCHSET(i,4)) == MAX) then CAND(k)=i, k=k+1, 
      
        if or([SHOW==5 SHOW==6]) then
          printf("makeCAND: i=%d has MAX\n",i), 
          end
      
      end
   
 end
 
 // Selects an element of CAND by random
 
 IDXM=(floor(length(CAND)*rand()) )+1
 
 if or([SHOW==5 SHOW==6]) then
    
     disp(MATCHSET(CAND(IDXM),:))
     end
 
 //The index IDXM points into CAND and the IDXM-element of CAND points to the element of MATCHSET
 // CAND(IDXM) ---> element of MATCHSET
 // MATCHSET(CAND(IDXM),:) is the whole element
 //  MATCHSET(CAND(IDXM),3) is the ACT-element
  
  ACTIONSET(1,:) = MATCHSET(CAND(IDXM),:) 
  
   if or([SHOW==5 SHOW==6]) then
       disp('NEW ACTIONSET = ')
     disp(ACTIONSET)
 end
 
 ACT=MATCHSET(CAND(IDXM),3)

endfunction



//***************************************************
// makeCANDfood
// 
// searches all classifiers from the matchset with a food option,
// then takes that option with highest reward
// makeCAND : MATCHSET ---> IDXCAND, ACTIONSET
// 

function [IDXM,CAND, MATCHSET,ACTIONSET,ACT]=makeCANDfood(MATCHSET,SHOW)
 
 [mr,mc]=size(MATCHSET)
 ACTIONSET=[]
  
 // Searches for classifiers with food option
 
 j=0  // Index for ACTSET, copy if path matches
 needle='11' //Hint for path
 for i=1:mr,
     if grep(MATCHSET(i,1),needle)<>[] then 
         j=j+1,
         ACTIONSET(j,:)=MATCHSET(i,:)  
         end 
      
  end
  
  if ACTIONSET==[] then [IDXM,CAND, MATCHSET,ACTIONSET,ACT]=makeCANDpath(MATCHSET,SHOW)
  else
      
  MATCHSET=ACTIONSET
  
       disp('MATCHSET MIDDLE OF makeCANDfood')
    disp(MATCHSET)
    
   [mr,mc]=size(MATCHSET)
  MAX=0
  
  //Searches for the HIGHEST value of REW
  
  for i=1:mr,
    if(eval(MATCHSET(i,4)) > MAX) then MAX=eval(MATCHSET(i,4)),
      end
   
 end
 
 // Identifies all elements of MATCHSET which have the highest REW-value
 
 k=1
 CAND=[]
 
   for i=1:mr,
    if(eval(MATCHSET(i,4)) == MAX) then CAND(k)=i, k=k+1, 
      
        if or([SHOW==5 SHOW==6]) then
          printf("makeCAND: i=%d has MAX\n",i), 
          end
      
      end
   
 end
 
 // Selects an element of CAND by random
 
 IDXM=(floor(length(CAND)*rand()) )+1
 
 if or([SHOW==5 SHOW==6]) then
    
     disp(MATCHSET(CAND(IDXM),:))
     end
 
 //The index IDXM points into CAND and the IDXM-element of CAND points to the element of MATCHSET
 // CAND(IDXM) ---> element of MATCHSET
 // MATCHSET(CAND(IDXM),:) is the whole element
 //  MATCHSET(CAND(IDXM),3) is the ACT-element
  
  ACTIONSET(1,:) = MATCHSET(CAND(IDXM),:) 
  
   if or([SHOW==5 SHOW==6]) then
       disp('NEW ACTIONSET = ')
     disp(ACTIONSET)
 end
 
 ACT=MATCHSET(CAND(IDXM),3)
 end

endfunction

//*************************************************
// MAP ACT into POS
// Function aout: ACT --> POS

function [YN, XN]=aout(ACT,SHOW, YO, XO)
  
  // The coordinates below are relativ to the actual position of the ANIMAT
  //They work 'clockwise' around beginning with 'north'
  // Because 'no move' is encoded as '0' and the indices of the vectors
  // in scilab start with '1' we encode '0,...,8' as '1,...,9'

  P=[0,0; -1,0; -1,1; 0,1; 1,1; 1,0; 1, -1; 0,-1; -1,-1 ]
  
  YN=YO+P(evstr(ACT)+1,1), 
  XN=XO+P(evstr(ACT)+1,2)

endfunction


//*************************************************
// UPDATE HISTORY  

function [HISTORY]=updateHIST(HISTORY,k, CELLVALUE,XN,YN,ANIMAT)   

  
  [r,c]=size(HISTORY)
  
  //INDEX
  
  HISTORY(r+1,1)=k
  
  //CONTENT
  
  HISTORY(r+1,2)=evstr(CELLVALUE)
  
  // POSITION
  HISTORY(r+1,3)=YN, HISTORY(r+1,4)=XN
  
  //REWARDTOTAL
  HISTORY(r+1,5)=ANIMAT(3)
  
  //ENERGY
  HISTORY(r+1,6)=ANIMAT(4)
  
  //VITAL
  HISTORY(r+1,7)=ANIMAT(6)
  
endfunction

//*************************************************
// Compute FOOD

function [FOOD]=food(HISTORY,RUNS)
  
  // FOOD(1) := Occurences of food
  // FOOD(2) := Number of runs
  // FOOD(3) := Occurence/Number = Density
  // FOOD(4) := Mean number of actions
  
  FOOD=[0 0 0 0]
  [r,c]=size(HISTORY)
  
  for i=1:r
    if (HISTORY(i,6)> -1) then FOOD(1)=FOOD(1)+1
    end
    end
    
    FOOD(2)=RUNS
    if (FOOD(1) > 0) then FOOD(3) = FOOD(1)/FOOD(2), else FOOD(3)=0,end
   if (FOOD(1) > 0) then FOOD(4) = FOOD(2)/FOOD(1),  else FOOD(3)=0,end
    
endfunction

//*************************************************
// Set CLASSIF Feedback Values to zero-string  '000'

function [ANIMAT]=zeroCLASSIFFEEDB(ANIMAT,CLASSIF)
  
  [r,c]=size(CLASSIF)
  
  for i=1:r
    CLASSIF(i,4)='000'
    end
    ANIMAT(8) = CLASSIF
    
endfunction

//*******************************************************
// Set OLDACTIONS to zero

function [ANIMAT, OLDACTIONS]=oldActZero(ANIMAT,OLDACTIONS)

  for i=1:ANIMAT(9)
      OLDACTIONS(i,1)=0
      OLDACTIONS(i,2)=0
      end
    ANIMAT(7)=OLDACTIONS
    
endfunction



Gerd Doeben-Henisch 2013-01-14