Tech.Appendix: LCS for Tic-Tac-Toe

The following version of an LCS system is able to play the game tic-tac-toe either as beginner or as opponent. It is a first prototype which will be investigated further in the future. It is part of a case study which shall clarify the basic concepts of LCSs applied to this game (see the chapters above for more information).

Usage: Start your scilab program (from www.scilab.org), copy this source code into the editor and save it as a program file. Then Load the program from the editor into scilab and start.

//**************************************************************
// File: LCS_v0.18.sce
// Authors: Gerd Doeben-Henisch
// Version Start: May-31, 2011
// Version Last: June-16, 2011
//******************************************************************
// Function: Implements a simple LCS according to Goldberg (1989)
// and some changes by GDH. Furthermore I  constructed a complete new example
//
//*************************************************
// June-1,2011: More functions to support the game
//
//*************************************************
// June-2,2011: More functions to support the game
//
//*************************************************
// June-3,2011: Fitness function tttfitn()
//
//*************************************************
// June-4-9,2011: tttgameA2(), ttttournamentA2, ttttournamentA2history()
//
//**********************************************
// June-4,2011: Further improvements of the fitness function tttfitn(),
//  rework of ainp() as binary Matrix, no string. Implementing the second player as 
// separate unit with separate handling.
//
//*******************************************************
// June-12-13,2011: Completed evalDir() and tttfit2()
//
//*******************************************************
// June-14-16,2011: Extended the tournament functions in a way that
// the LCS system can also be a beginner
//
//*******************************************************
// Some helpful scilab-functions from the scilab libraries
//
// nancumsum ? This function returns the cumulative sum of the values of a matrix
// tabul ? frequency of values of a matrix or vector
// variance ? variance of the values of a vector or matrix
// strange ? range
// stdevf ? standard deviation (does need tabul)
// st_deviation (does not need additional functions)
// bin2dec := translate a binary string of '1','0' into a decimal number
// dec2bin
//
// SW-STRUCTURE
//
//****************************************************
//
// AGENTS
//
// Idea:
// An agent contains at least a set of classifiers. Classifiers have the compartments
// < IF THEN FIT >
// IF := state of world 9x2 Cells = 18 Cells
// THEN := action as a move (X,Y,O) 2+2+2 = 6  Cells
// FIT := fitness value as a 2 real values token and fraction  2 Cells
// Total length= 18 + 6 + 2 = 26 cells
// IF represents a possible input INP from the world,
// THEN represents a possible output  OUT to the world and 
// FIT represents an accumulated fitness value for this IF-THEN pair.
// The classifier can be encoded with integers which can be converted into
// other formats for processing.
//

CLASSIF1=[]
CLASSIF2=[]

AGENT1 = list(CLASSIF1)
AGENT2 = list(CLASSIF2)

//********************************************************
// Add a classifier
// classifNew()
//
// Idea:
// Given an input string and arandom  classifier.
//Overwrite random classifier with input
// and generat possible move as well as minimal fitness
//  

function [G]=classifNew(INP,X,Y,F,show)
 
  li =length(INP)
  lp = 26
  [P]=popgen(1,lp)
  
  
  G=zeros(1,lp) //new classifier
  
  for i=1:li 
    G(1,i) = INP(1,i),
  end
  for i = li+1:lp
    G(1,i) = P(1,i),
  end
  
  //inserts random move (X,Y,O)
  
  
  if show == 1 then disp('X='), disp(X), disp('Y='), disp(Y), end
  
  x=dec2bin(X)
  if length(x) == 1 then x= '0'+x, //strsplit() needs at least two signs...
  end
  
  xx=strsplit(x)'
  
  for i=1:2
    if xx(1,i) == '1' then G(1,li+i)=1, else  G(1,li+i)=0,
    end
  end
  
   y=dec2bin(Y)
  if length(y) == 1 then y= '0'+y,
  end
  
  yy=strsplit(y)'
  
  for i=1:2
    if yy(1,i) == '1' then G(1,li+2+i)=1, else  G(1,li+2+i)=0,
    end
  end
  
  G(1,li+5) = 1
  G(1,li+6) = 0 
  
  //generate  fitness
  
  G(1,lp-1)= F //depends from scenario
  G(1,lp) = 0 // Fraction has to computed from overall system
  
  
endfunction

//********************************************************
// Add a classifier
// classifNew2()
//
// Idea:
// Only difference the assumption of the set CLASSIF to have more columns
// c = l+p = 24+7
//  r,c := row/col of CLASSIF because CLASSIF can be extended by genetic operators
// CLASSIF
// 1-18 := board content
// 19-20 := X
// 21-22 := Y
// 23-24 := O
// l := 24
// p := 7
// l+1 := F
// 
// Input:
// r,c := row/col of CLASSIF

function [G]=classifNew2(INP,X,Y,F,r,c,show)
 
  
  l=24
  p=7
  li =length(INP)
  [P]=popgen(1,c)
  
  
  G=zeros(1,c) //new classifier
  
   if show==4 then 
     disp('classifNew2: Before G with INP')
     
     disp('INP='), disp(INP)
     
     disp('CLASSIF='),disp(CLASSIF)
     
     disp('rr ='),  disp(r), disp('cc='),disp(c)
     
   end
   

  
  for i=1:li 
    G(1,i) = INP(1,i),
  end
  
  
  for i = li+1:c
    G(1,i) = P(1,i),
  end
  
  
  //inserts random move (X,Y,O)
 
  
  x=dec2bin(X)
  if length(x) == 1 then x= '0'+x, //strsplit() needs at least two signs...
  end
  
  xx=strsplit(x)'
  
  for i=1:2
    if xx(1,i) == '1' then G(1,li+i)=1, else  G(1,li+i)=0,
    end
  end
  
   y=dec2bin(Y)
  if length(y) == 1 then y= '0'+y,
  end
  
  yy=strsplit(y)'
  
  for i=1:2
    if yy(1,i) == '1' then G(1,li+2+i)=1, else  G(1,li+2+i)=0,
    end
  end
   
  //generate  fitness
  
  G(1,l+1)= F //depends from scenario
  G(1,l+2) = 0 // Fraction has to computed from overall system
  
   if show==4 then
     
     disp('classifNew2: After G with F'), disp(G)
     
   end

endfunction


//*************************************************
// Get (X,Y) out of classifier
// getXY()
//

function [X,Y]=getXY(MROW)
  
  //Transforms row of matrix into a vector
  v=MROW(1,:)
  
  //takes the section with the X-binaries
  [X]= vec22dec(v,19,20)
  if X == 0 then X+1, 
  end
  
  //takes the section with the y-binaries
  [Y]= vec22dec(v,21,22)
  if Y == 0 then Y+1, 
  end
  
  
endfunction



//***********************************************************
// Playlist with n-many players
//

function [PList]=plistgen(n)
  
  PList=[1:1:n]
  
 
endfunction

//*********************************************
// PMatrix for n x n players
//

function [PMatrix]=pmatrixgen(PList)
  
  n=length(PList)
  PMatrix=zeros(n+1, n+1)
  for i=2:n+1
    PMatrix(1,i)=i-1
    PMatrix(i,1)=i-1
  end
  
 
endfunction

//*********************************************
// PMatrix for n x n players
//
// Input:
// N := number of games betwin random beginner 'X' and opponent 'O' with classifiers

function [PMatrix]=pmatrixgenA2(N)
  
  PMatrix=zeros(N+1, 3)
  PMatrix(1,2)=1, 
  PMatrix(1,3)=2, 
  for i=2:N+1
    PMatrix(i,1)=i-1 
  end
  
 
endfunction

//*********************************************
// Action generator
//
// Output:
// X,Y,O := an action consist of a cell-vector and a 'piece' in {'X','O'}
//      The cell-vector is (x,y) with x,y in {1,2,3}
// P := Player; 1 := Beginner, 2 := Opponent

function [X,Y,O]=tttaction0(P)
  
  X=0
  while X==0
    X=round(rand()*3)
  end
    Y=0
  while Y==0
    Y=round(rand()*3)
  end
  if P==1 then O='X', else O='O', end
  
  
 
endfunction

//*********************************************
// Action generator insertion and check whether cell free and right turn
//
// Idea:
// Checks whether a planned cell is free and checks which piece has to be played
// If number of different pieces is equal, then 'X' is needed, otherwise 'O'
//
// Input:
// W := World as Board
// X,Y := cell coordinates
// O := Piece to be placed {'X','O'}
//
// Output:
// ALLOW := Whether cell is free or not {0,1}
// W := World after insertion

function [W,ALLOW]=tttaction1(W,X,Y,O,show)
  
  [r,c]=size(W)
  ALLOW = 1
  
   // Check which piece
  
    PIX=0, PIO=0
    for i=1:r
      for j=1:c
        if W(i,j)=='X' then PIX=PIX+1,
        elseif W(i,j)=='O' then PIO=PIO+1
        end
      end
    end
    
    if show == 1 then disp('PIX = '), disp(PIX), disp('PIO = '), disp(PIO), end
     
    if PIX == PIO & O <> 'X' then ALLOW=0, 
      if show == 1 disp('X should move but does not '),  end,
      
    elseif PIX > PIO & O <> 'O' then ALLOW = 0,  
      if show == 1 disp('O should move but does not '),  end,
    end
 
  
  // Check cell free
  
  if ALLOW == 1 then
  
  if W(X,Y) <> '_' then ALLOW = 0,
  else ALLOW = 1, 
    W(X,Y) = O,
  end
  
  if show == 1 disp('Cell free = '), disp(ALLOW), end
  
end
  
endfunction

//*********************************************
// Action generator insertion and checks only whether cell free 
//
// Idea:
// Checks whether a planned cell is free 
//
// Input:
// W := World as Board
// X,Y := cell coordinates
// O := Piece to be placed {'X','O'}
//
// Output:
// ALLOW := Whether cell is free or not {0,1}
// W := World after insertion

function [W,ALLOW]=tttaction1b(W,X,Y,O,show)
  
  [r,c]=size(W)

  // Check cell free
  
  if W(X,Y) <> '_' then ALLOW = 0,
  else ALLOW = 1, 
    W(X,Y) = O,
  end
  
  if show == 1 disp('Cell free = '), disp(ALLOW), end
  
  
endfunction


//*********************************************
// Free Cell Generator
// freeCellIndex()
//
// Idea:
// receives a list of free cells CLst
// and computes randomly an index for a free cell
//
// Input:
// N := number of free cells
// 
// Output:
// K := index for free  cell
// 


function [K]=freeCellIndex(N)
  
    K=0
  while K==0
    K=round(rand()*N)
  end   
  
endfunction

//**************************************+
// diagIn()
// Inverse diagonale of a quadratic matrix
// Inverse to scilab function diag()
//
// Input:
// M := matrix
//
// Output:
// D := the right-left-diagonal values as 1-col matrix
//
// Attention: scilab uses (Y,X) notation!!!!

function [D]=diagIn(M)
  
  [r,c]=size(M)
  D=[]
  
  if r <> c then error('No Quadratic Matrix in diagIn()'), end
  
  for i=1:r
    D(i,1) = M(i,r+1-i)
    end
  
endfunction

//*********************************************
// Check whether the game is ended
//
// Idea:
// Check whether in a row or column or diagonale three pieces of one player are placed
//
// Input:
// W := World as Board
//
// Output:
// END := Whether game has ended or not {0,1}
// PLAYER := Which player has won {'X','O'}

function [PLAYER,END]=endgame(W,show)
  
  [r,c]=size(W)
  END = 0
  
  // Check diagonales
  
  [D]=diag(W)
  PIX=0, PIO=0
  for i=1:r
    if D(i,1) == 'X' then PIX=PIX+1,
    elseif D(i,1) == 'O' then PIO=PIO+1,
    end
  end
  
  if show ==1 then disp('diag D= '),disp(D), disp(PIX), disp(PIO),end
  
  if PIX == 3 then END=1, PLAYER= 'X',
  elseif PIO == 3 then END=1, PLAYER= 'O',
  else END=0, PLAYER='_'
  end
  
  if END == 0 then
    
  [D]=diagIn(W)
  PIX=0, PIO=0
  for i=1:r
    if D(i,1) == 'X' then PIX=PIX+1,
    elseif D(i,1) == 'O' then PIO=PIO+1,
    end
  end
  
  if show ==1 then disp('diag D= '),disp(D), disp(PIX), disp(PIO),end
    
   if PIX == 3 then END=1, PLAYER= 'X',
  elseif PIO == 3 then END=1, PLAYER= 'O',
  else END=0, PLAYER='_'
  end
  
end

// check Rows

  if END == 0 then
    
    i=1
    while i < r+1 & END == 0
      [D]=W(i,:)
      
      if show ==1 then disp('Row D= '),disp(D),end
      
      PIX=0, PIO=0
      
      j=1
      while j < r+1
        if D(1,j) == 'X' then PIX=PIX+1,
        elseif D(1,j) == 'O' then PIO=PIO+1,
        end
        j=j+1
      end // while j
      
      if show ==1 then disp('PIX, PIO = '), disp(PIX), disp(PIO),end
      
      if PIX == 3 then END=1, PLAYER= 'X',
      elseif PIO == 3 then END=1, PLAYER= 'O',
      else END=0, PLAYER='_'
      end // if PIX
      
      i=i+1
    end //while i
  end //if END
  

// Check Columns

  if END == 0 then
    
    i=1
    while i < r+1 & END == 0
      [D]=W(:,i), D=D'
      
      if show ==1 then disp('Column (rotated) D= '),disp(D),end
      
      PIX=0, PIO=0
      
      j=1
      while j < r+1
        if D(1,j) == 'X' then PIX=PIX+1,
        elseif D(1,j) == 'O' then PIO=PIO+1,
        end
        j=j+1
      end // while j
      
      if show ==1 then disp('PIX, PIO = '), disp(PIX), disp(PIO),end
      
      if PIX == 3 then END=1, PLAYER= 'X',
      elseif PIO == 3 then END=1, PLAYER= 'O',
      else END=0, PLAYER='_'
      end // if PIX
      
      i=i+1
    end //while i
  end //if END
  

  
endfunction

//****************************************************
// Free cells for a move
// freeCells()
//
// Idea:
// All free sells are listet for the generation of a possible move
//
// Input:
// W := world state
//
// Output:
// CLst := List of all cells with those which are free
//

function [CLst]=freeCells(W,show)
  
  [r,c]=size(W)
  CLst=[]
  
  //reading the world matrix and generate the list
  
  k=0
  for i=1:r
    for j=1:c
      
      if show==1 then disp(i), disp(j), disp('W(i,j)'), disp(W(i,j)), end
      
      if W(i,j)== '_' then k=k+1, CLst(k,1)=i, CLst(k,2)=j
        
        if show==1 then disp('k ='), disp(k), disp('CLst k 1 2 ='), disp(CLst(k,1)), disp(CLst(k,2)), end
        
      end //end if empty
     
    end //end for j
  end //end for i
  

endfunction



//****************************************************
// Input function for an agent ainp()
//
// Idea:
// The actual state of the world together with the fitness value for the last action
// is delivered to the agent. This is done with a vector.

function [INP]=ainp(W,FIT)
  
  [r,c]=size(W)
  
  //reading the world matrix and encode the cells
  
  for i=1:r
    for j=1:c
      if W(i,j)== 'X' then WI(i,j)='01', 
      elseif W4(i,j)== 'O' then WI(i,j)='10', 
      else WI(i,j)='00', 
      end,
    end,
  end
  
  //Concatenating the partial strings into one string INP
  
  INP=''
    for i=1:r
    for j=1:c
      INP = INP + WI(i,j),
    end,
  end
  
  //Concatenating the fitness value
  
  INP=INP+':'+dec2bin(FIT)
  

endfunction

//****************************************************
// Input function for an agent ainp() (as matrix)
//
// Idea:
// The actual state of the world  is delivered to the agent. This is done with a line matrix.
//
// Input:
// W := World state
// 
// Output:
// INP := Matrix with binary code of world and fitness


function [INP]=ainp2(W)
  
  [r,c]=size(W)
  l=2*c
  INP=zeros(1,l)
  
  
  //reading the world matrix and encode the cells
  
  k=1
  for i=1:r
    for j=1:c
      if W(i,j)== 'X' then INP(1,k)=0, INP(1,k+1)=1, 
      elseif W(i,j)== 'O' then INP(1,k)=1, INP(1,k+1)=0, 
      else INP(1,k)=0, INP(1,k+1)=0,  
      end,
      k=k+2
    end,
  end
  
 
endfunction


//*********************************************
// Fitness function for tic-tac-toe
// tttfitn()
//
// Idea:
// The player makes a move (X,Y,O)
// The following cases have to be evaluated:
// The new piece will be evaluated in every direction whether it 
// has n-many pieces in one direction without a piece of the opoonent.
// This can be controlled by flags FLAG=[1,2,3,4,5]
// 1 : allowness
// 2 : rows
// 3 : columns
// 4 : diagonales LR
// 5 : diagonales RL
//
// Input:
// W := World as Board
// X,Y := cell coordinates //Attention: scilab uses internally M(Y,X) !!!!!!
// O := Piece to be placed {'X','O'}
//
// Output:
// F := fitness values
// FLAG := for control reasons
// ALLOW := allownes
// W := world to show final state
//
// Style : The actual code is not very elegant. It should be improved using more abstract 
//         topological predicates implemented as basic operators.


function [F,FLAG, ALLOW,W]=tttfitn(W,X,Y,O,show)
  
   if show == 1 then disp('X,Y,O ='), disp(X), disp(Y), disp(O), end  
  
  [r,c]=size(W)
  
  ROW =[0,0,0]
  COL=[0,0,0]
  DIAL=[0,0,0]
  DIAR =[0,0,0] 
  FLAG = [0 0 0 0 0] // Allowness, Row, Col, Dia-LR, Dia-RL
  
  //*******************************
  // Check allowness
  
  if W(Y,X) == '_' then FLAG(1,1)=1, ALLOW=1, W(Y,X) = O,
  else ALLOW = 0,
    end 
    
  //*****************************************
  //Check neighborship, 3 cases (center, corner, middle)
  // with subcases
  
  
  if X == 2 & Y == 2 then C=1,
  elseif (X == 1 & Y == 1) then C=2,
    elseif (X == 3 & Y == 1) then C=3, 
    elseif (X == 3 & Y == 3) then C=4, 
    elseif (X == 1 & Y == 3) then C=5,
    elseif (X == 2 & Y == 1) then C=6, 
    elseif (X == 3 & Y == 2) then C=7, 
    elseif (X == 2 & Y == 3) then C=8, 
    elseif (X == 1 & Y == 2) then C=9
      end 
       
       if show == 1 then disp('C = '), disp(C), end  
       
       select C
         
  //****************************************
  // 1) Check Center
  
case 1 then 
  if show == 1 then  disp('Case Center'), end 
  
  //Place piece first
  
    ROW =[0,1,0]
  COL=[0,1,0]
  DIAL=[0,1,0]
  DIAR =[0,1,0] 
  
  // Search context
  // Counts only if the missing cell in one direction is free!
  
  
if W(Y-1,X) == 'X'  | W(Y+1,X) == 'X'  then COL(1,2)=0,
elseif W(Y-1,X) == 'O'  & W(Y+1,X) == 'O' then COL(1,3)=1,COL(1,1)=1,
elseif W(Y-1,X) == 'O'  | W(Y+1,X) == 'O' then COL(1,1)=1, 
  end,
  


if  W(Y-1,X+1) == 'X'  |  W(Y+1,X-1) == 'X'  then DIAR(1,2)=0,
elseif  W(Y-1,X+1) == 'O'  & W(Y+1,X-1) == 'O'  then DIAR(1,1)=1,DIAR(1,3)=1,
elseif  W(Y+1,X-1) == 'O'  | W(Y+1,X+1) == 'O' then DIAR(1,3)=1,
    end,


if  W(Y,X+1) == 'X'   | W(Y,X-1) == 'X' then ROW(1,2)=0 
elseif  W(Y,X+1) == O   & W(Y,X-1) == 'O' then ROW(1,3)=1, ROW(1,1)=1, 
elseif  W(Y,X-1) == O  | W(Y,X+1) == 'O' then ROW(1,1)=1,
  end,


if  W(Y+1,X+1) == 'X'  | W(Y-1,X-1) == 'X'  then DIAL(1,2)=0, 
elseif  W(Y+1,X+1) == O  & W(Y-1,X-1) == 'O'  then DIAL(1,3)=1,DIAL(1,1)=1, 
elseif  W(Y-1,X-1) == O | W(Y+1,X+1) == 'O' then DIAL(1,1)=1,
  end, 

  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL), 
    disp('DIAL'), disp(DIAL),
     disp('DIAR'), disp(DIAR),
     end 
     
     // Compute fitness
     
  R=sum(ROW)
  CL=sum(COL)
  DL=sum(DIAL)
  DR=sum(DIAR)
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL
  FLAG(1,4)=DL
  FLAG(1,5)=DR
  
  
  //****************************************
  // 2) Check Corner
  
case 2 then 
  
    //****************************************
    // 2.1) Check Left Upper Corner
    
  if show == 1 then  disp('Case LU Corner'), end 
  
  
  //Place piece first
  
    ROW =[1,0,0]
  COL=[1,0,0]
  DIAL=[1,0,0] 
  
  // Search context
  

  if W(Y+1,X) == 'X' | W(Y+2,X) == 'X' then COL(1,1)=0,
  elseif W(Y+1,X) == 'O' & W(Y+2,X) == O then COL(1,3)=1,COL(1,2)=1, 
  elseif W(Y+1,X) == O | W(Y+2,X) == O then COL(1,2)=1,
  end
  
  if  W(Y+1,X+1) == 'X' | W(Y+2,X+2) == 'X' then DIAL(1,1)=0,
 elseif W(Y+1,X+1) == 'O' & W(Y+2,X+2) == O then DIAL(1,3)=1, DIAL(1,2)=1,
 elseif W(Y+1,X+1) == O | W(Y+2,X+2) == O then DIAL(1,2)=1, 
 end
 
  if  W(Y,X+1) == 'X' | W(Y,X+2) == 'X' then ROW(1,1)=0,
  elseif  W(Y,X+1) == O & W(Y,X+2) == O then ROW(1,3)=1,ROW(1,2)=1
  elseif  W(Y,X+1) == 'O' | W(Y,X+2) == O then ROW(1,3)=1,
  end
    
  
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL), 
    disp('DIAL'), disp(DIAL), 
     end 
  
  R=sum(ROW)
  CL=sum(COL)
  DL=sum(DIAL) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL
  FLAG(1,4)=DL 
  
  
case 3 then 
  
  
    //****************************************
    // 2.2) Check Right Upper Corner

  
  if show == 1 then  disp('Case RU Corner'), end 
  
   
  
  //Place piece first
  
    ROW =[0,0,1]
  COL=[1,0,0]
  DIAR=[1,0,0] 
  
  // Search context
  
    if W(Y+1,X) == 'X' | W(Y+2,X) == 'X' then COL(1,1)=0,
  elseif W(Y+1,X) == O & W(Y+2,X) == O then COL(1,2)=1,COL(1,3)=1,
  elseif W(Y+1,X) == 'O' | W(Y+2,X) == O then COL(1,3)=1, 
  end
  
 
 if  W(Y+1,X-1) == 'X' | W(Y+2,X-2) == 'X' then DIAR(1,1)=0,
 elseif W(Y+1,X-1) == O & W(Y+2,X-2) == O then DIAR(1,2)=1, DIAR(1,3)=1,  
 elseif W(Y+1,X-1) == 'O'| W(Y+2,X-2) == O then DIAR(1,3)=1,
 end
 
   if  W(Y,X-1) == 'X' | W(Y,X-2) == 'X' then ROW(1,3)=0,
  elseif  W(Y,X-1) == O & W(Y,X-2) == O then ROW(1,1)=1,ROW(1,2)=1
  elseif  W(Y,X-1) == 'O' | W(Y,X-2) == O then ROW(1,1)=1,
  end
  
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL), 
    disp('DIAR'), disp(DIAR), 
     end 
  
  R=sum(ROW)
  CL=sum(COL)
  DR=sum(DIAR) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL
  FLAG(1,5)=DR
  

case 4 then 
  
  
      //****************************************
      // 2.3) Check Right Down Corner
      

  if show == 1 then  disp('Case RD Corner'), end  
 
  
  
  //Place piece first
  
    ROW =[0,0,1]
  COL=[0,0,1]
  DIAL=[0,0,1] 
  
  // Search context
  
  if W(Y-1,X) == 'X' | W(Y-2,X) == 'X' then COL(1,3)=0,
  elseif W(Y-1,X) == O & W(Y-2,X) == O then COL(1,2)=1,COL(1,1)=1,
  elseif W(Y-1,X) == 'O' | W(Y-2,X) == O then COL(1,1)=1, 
  end
  
   if  W(Y-1,X-1) == 'X' | W(Y-2,X-2) == 'X' then DIAL(1,3)=0,
 elseif W(Y-1,X-1) == O & W(Y-2,X-2) == O then DIAL(1,1)=1, DIAL(1,3)=1,  
 elseif W(Y-1,X-1) == 'O' | W(Y-2,X-2) == O then DIAL(1,1)=1,
 end
 
  
   if  W(Y,X-1) == 'X' | W(Y,X-2) == 'X' then ROW(1,3)=0,
  elseif  W(Y,X-1) == O & W(Y,X-2) == O then ROW(1,1)=1,ROW(1,2)=1
  elseif  W(Y,X-1) == 'O' | W(Y,X-2) == O then ROW(1,1)=1,
  end
  
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL), 
    disp('DIAL'), disp(DIAL), 
     end 
  
  R=sum(ROW)
  CL=sum(COL)
  DL=sum(DIAL) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL
  FLAG(1,4)=DL

case 5 then 
  
  
  //****************************************
  // 2.4) Check left down corner

   if show == 1 then  disp('Case LD Corner'), end  
   
   
  //Place piece first
  
    ROW =[1,0,0]
  COL=[0,0,1]
  DIAR=[0,0,1] 
  
  // Search context
  
 
  if W(Y-1,X) == 'X' | W(Y-2,X) == 'X' then COL(1,3)=0,
  elseif W(Y-1,X) == O & W(Y-2,X) == O then COL(1,2)=1,COL(1,1)=1,
  elseif W(Y-1,X) == 'O' | W(Y-2,X) == O then COL(1,1)=1, 
  end
  
  
 if  W(Y-1,X+1) == 'X' | W(Y-2,X+2) == 'X' then DIAR(1,3)=0,
 elseif W(Y-1,X+1) == O & W(Y-2,X+2) == O then DIAR(1,2)=1, DIAR(1,1)=1, 
 elseif W(Y-1,X+1) == 'O' | W(Y-2,X+2) == O then DIAR(1,1)=1, 
 end
   
  
  if  W(Y,X+1) == 'X' | W(Y,X+2) == 'X' then ROW(1,1)=0,
  elseif  W(Y,X+1) == O & W(Y,X+2) == O then ROW(1,3)=1,ROW(1,2)=1
  elseif  W(Y,X+1) == 'O' | W(Y,X+2) == O then ROW(1,3)=1,
  end
    
  
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL), 
    disp('DIAR'), disp(DIAR), 
     end 
  
  R=sum(ROW)
  CL=sum(COL)
  DR=sum(DIAR) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL
  FLAG(1,5)=DR 
  
  //*****************************************
  // 3) Check Middle of Boarder
  

case 6 then 
  
    //*****************************************
    // 3.1) Check Middle Upper  Boarder
    
  if show == 1 then  disp('Case MU BOARDER'), end 
  
  //Place piece first
  
    ROW =[0,1,0]
  COL=[1,0,0] 
  
  // Search context
 
  if  W(Y,X-1) == 'X' | W(Y,X+1) == 'X' then ROW(1,2)=0,
  elseif  W(Y,X-1) == O & W(Y,X+1) == O then ROW(1,1)=1,ROW(1,3)=1
  elseif  W(Y,X-1) == 'O'| W(Y,X+1) == O then ROW(1,3)=1,
  end
  
  if W(Y+1,X) == 'X' | W(Y+2,X) == 'X' then COL(1,1)=0,
  elseif W(Y+1,X) == O & W(Y+2,X) == O then COL(1,2)=1,COL(1,3)=1,
  elseif W(Y+1,X) == 'O' | W(Y+2,X) == O then COL(1,3)=1, 
  end
   
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL),  
     end 
  
  R=sum(ROW)
  CL=sum(COL) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL 
  
 
case 7 then 
  
    //*****************************************
    // 3.2) Check Middle Right Boarder
    
  if show == 1 then  disp('Case MR BOARDER'), end  
  
   //Place piece first
  
    ROW =[0,0,1]
    COL=[0,1,0] 
    
  // Search context
  
   if  W(Y,X-1) == 'X' | W(Y,X-2) == 'X' then ROW(1,3)=0,
  elseif  W(Y,X-1) == O & W(Y,X-2) == O then ROW(1,1)=1,ROW(1,2)=1
  elseif  W(Y,X-1) == 'O'| W(Y,X-2) == O then ROW(1,1)=1,
  end
  
  if W(Y+1,X) == 'X' | W(Y-1,X) == 'X' then COL(1,2)=0,
  elseif W(Y+1,X) == O & W(Y-1,X) == O then COL(1,1)=1,COL(1,3)=1,
  elseif W(Y+1,X) == 'O' | W(Y-1,X) == O then COL(1,1)=1, 
  end
   
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL),  
     end 
  
  R=sum(ROW)
  CL=sum(COL) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL 

case 8 then 
  
      //*****************************************
      // 3.3) Check Middle Down Boarde
      
  if show == 1 then  disp('Case MD BOARDER'), end  
    
   //Place piece first
  
    ROW =[0,1,0]
    COL=[0,0,1] 
    
  // Search context
  
    if  W(Y,X-1) == 'X' | W(Y,X+1) == 'X' then ROW(1,2)=0,
  elseif  W(Y,X-1) == O & W(Y,X+1) == O then ROW(1,1)=1,ROW(1,3)=1
  elseif  W(Y,X-1) == 'O' | W(Y,X+1) == O then ROW(1,3)=1,
  end
  
  if W(Y-1,X) == 'X' | W(Y-2,X) == 'X' then COL(1,3)=0,
  elseif W(Y-1,X) == O & W(Y-2,X) == O then COL(1,2)=1,COL(1,1)=1,
  elseif W(Y-1,X) == 'O'| W(Y-2,X) == O then COL(1,1)=1, 
  end
  
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL),  
     end 
  
  R=sum(ROW)
  CL=sum(COL) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL 
  

case 9 then 
  
      //*****************************************
      // 3.4) Check Middle Left Boarde
      
  if show == 1 then  disp('Case ML BOARDER'), end  
  
   //Place piece first
  
    ROW =[1,0,0]
    COL=[0,1,0] 
    
  // Search context
  
    
   if  W(Y,X+1) == 'X' | W(Y,X+2) == 'X' then ROW(1,1)=0,
  elseif  W(Y,X+1) == O & W(Y,X+2) == O then ROW(1,3)=1,ROW(1,2)=1,
  elseif  W(Y,X+1) == 'O' | W(Y,X+2) == O then ROW(1,3)=1,
  end
  
  if W(Y+1,X) == 'X' | W(Y-1,X) == 'X' then COL(1,2)=0, 
  elseif W(Y+1,X) == O & W(Y-1,X) == O then COL(1,1)=1,COL(1,3)=1,
  elseif W(Y+1,X) == 'O' | W(Y-1,X) == O then COL(1,1)=1,
  end
    
  
  
  if show == 1 then  disp('ROW'), disp(ROW),
    disp('COL'), disp(COL),  
     end 
  
  R=sum(ROW)
  CL=sum(COL) 
  
  FLAG(1,1)=ALLOW
  FLAG(1,2)=R
  FLAG(1,3)=CL 
  

else break
  
end //select

 if show == 1 then  disp('FLAG Final'), disp(FLAG), end

  // Compute final fitness value
  F=0
  for k=2:5
    if FLAG(1,k) > F then F=FLAG(k),end
  end
  F=F*5 //Enhancing the differences between the cases
 


endfunction

//****************************************************
// Match a line L with a matrix M 
//
// Idea:
// Start comparison of line L with matrix M.
// Every time there is a match the results matrix TX will notify a '1'

function [TX]=mmmatch(L,M)
  
  [r,c]=size(M)
  TX=ones(r,1)
  l=length(L)
  
  for i=1:r
    for j=1:l
      if L(1,j)<>M(i,j) then TX(i,1)=0, break, 
      end //if <>
    end //for j
  end //for i
  
  
endfunction

//*************************************
// Evaluation of a dirction
// evalDir()
//
// Idea:
// Take a direction of a world state w_i of world W with n=length
// Direction is row, column or diagonal
// Look for a certain player P in {'X', 'O'}
// Count the piecesm  of this player if there are no pieces of the opponent
// Every dimension counts as 1
// Every dimension with m >= round(n/2)+1)-many pieces receives m times a bonus additionally
//
// Input:
// W := World as Board
// DIM := Which kind of dimension {R,C,L,D}, Row, Columns, LR diagonal, RL diagonal
// INDEX := within W row or colum or 1 := DL or n = DR
// P := type of player,  'X' := Beginner, 'O' := opponent
//
// Output:
// M := Number of pieces in that dimension with no opponent
// BONUS := If m >= round(n/2)+1) then m (times a bonus)
//
// Computation:
// Go through a dimension DIM and count the pieces 

function [M,BONUS]=evalDir(W,DIM,IND,P,show)
  
  [r,c]=size(W)
  M=0 //Counter for player
  MM=0 //Flag for opponent
  BONUS=0
  if P == 'X' then PP = 'O', else PP='X', end //Define opponent
  
  select DIM
    
    //------------------ROW-------------------
    
  case 'R' 
    
    if show == 1 then
      disp('Player ='), disp(P),
      disp('ROW No ='), disp(IND)
    end
    
    for j=1:c
      
      if W(IND,j) == P then M=M+1
      elseif W(IND,j) == PP then MM=1, break
      end
    end
    if MM==1 then M=0, BONUS=0
      elseif M >= round(r/2) then BONUS=M
      end
      
     
    
    
    //------------------COL-------------------
    
    
  case 'C'
    if show == 1 then
    disp('COLUMN No ='), disp(IND)
  end
  
      for j=1:r
      
      if W(j,IND) == P then M=M+1
      elseif W(j,IND) == PP then MM=1, break
      end
    end
    if MM==1 then M=0, BONUS=0
      elseif M >= round(r/2) then BONUS=M
    end
  
    //------------------LR DIAG-------------------
  
  case 'L'
    if show == 1 then
      disp('LEFT-TO-RIGHT DIAGONAL'), 
    end
    
    for j=1:c
      
      if W(j,j) == P then M=M+1
      elseif W(j,j) == PP then MM=1, break
      end
    end
    if MM==1 then M=0, BONUS=0
      elseif M >= round(r/2) then BONUS=M
    end
    
    
    //------------------RL DIAG-------------------
    
  case 'D'
    
    if show == 1 then
      disp('RIGHT-TO-LEFT DIAGONAL')
    end
    
    for j=1:c
      
      if W(j,c+1-j) == P then M=M+1
      elseif W(j,c+1-j) == PP then MM=1, break
      end
    end
    if MM==1 then M=0, BONUS=0
      elseif M >= round(r/2) then BONUS=M
    end   
    
    //------------------ERROR-------------------
    
  else 
    error('Wrong selector in evalDir()')
    break;

end


endfunction


//*********************************************
// Second Fitness function for tic-tac-toe
// tttfitn2()
//
// Idea:
// Every move of a player creates a new state w_i of a world  W
// Every state w_i  represents 'as it is' a potential value for a player.
// Depending on the type of player 'X' or 'O' the evaluation is different
// The value is derived from the knowledge of the 'goal states' G subset W
// In a goal state w_g.i of G one player has n pieces (n = length of board) in one direction.
// A direction is given as row or column or as diagonal.
// Thus every piece in a state w_i has a certain value with regard to the goal states:
// (i) The number of possible directions in which there is no piece of the opponent
// (ii) The number m of all pieces in one potential direction with m >= round((n/2)+1) times a bonus value 
// 
// Assuming Bonus = 5
// w_5:
//
// |_O_|
// |XXO|
// |X__|
//
// val_X(w_5) = 1+2+3+2xBonus + 2xBonus = 6+4xBonus = 26
//
// w_6:
//
// |_OO|
// |XXO|
// |X__|
//
// val_O(w_6) = 1+1+1+2xBonus+2xBonus = 3+4xBonus = 23
//
// Based on such an evaluation-fnction different strategied can be generated. These are not part of the
// fitnes function
//
// Counting dimensions: FLAG=[1,2,3,4,5]
// 1 : Times for Bonus
// 2 : rows
// 3 : columns
// 4 : diagonales LR
// 5 : diagonales RL
//
// Input:
// W := World as Board
// P := type of player,  'X' := Beginner, 'O' := opponent
//
// Output:
// F := fitness values
// FLAG := for control reasons
// W := world to show final state
//
// Computation:
// Looks into every direction and computes all pieces of the target player P for this direction
//


function [W,FLAG,F]=tttfit2(W,P,BON,show)
  

  [r,c]=size(W)
  
  FLAG = [0 0 0 0 0] // Times, Row, Col, DiaL DiaR
  
  //*******************************
  // Check all cases
  
  // ROW
  
  for i=1:r
    [M,BONUS]=evalDir(W,'R',i,P,show)
    FLAG(1,1)=FLAG(1,1)+BONUS
    FLAG(1,2)=FLAG(1,2)+M
    end
    
  
  // COLUM
  
    for i=1:r
    [M,BONUS]=evalDir(W,'C',i,P,show)
    FLAG(1,1)=FLAG(1,1)+BONUS
    FLAG(1,3)=FLAG(1,3)+M
    end
  
  // DIAL
  
    [M,BONUS]=evalDir(W,'L',0,P,show)
    FLAG(1,1)=FLAG(1,1)+BONUS
    FLAG(1,4)=FLAG(1,4)+M

  
  // DIAR
  
    [M,BONUS]=evalDir(W,'D',0,P,show)
    FLAG(1,1)=FLAG(1,1)+BONUS
    FLAG(1,5)=FLAG(1,5)+M

  
  // FINAL SUM UP
  
  F=sum(FLAG)-FLAG(1,1)+BON*FLAG(1,1)
  
 
  
endfunction

  
  
  
  
//****************************************************
// Match a line L with a matrix M 
//
// Idea:
// Start comparison of line L with matrix M.
// Every time there is a match the results matrix TX will notify a '1'

function [TX]=mmmatch(L,M)
  
  [r,c]=size(M)
  TX=ones(r,1)
  l=length(L)
  
  for i=1:r
    for j=1:l
      if L(1,j)<>M(i,j) then TX(i,1)=0, break, 
      end //if <>
    end //for j
  end //for i
  
  
endfunction



//********************************************************
// Main game function tttgame() for the tic-tac-toe game
//
// Idea: 
// Two players play TTT. Beginner uses the piece 'X', the opponent uses 'O'.
// Every turn one player makes a move alternating. As soon as one player has 
// reached 3 pieces in one direction (rowwise, columnwise or in a diagonal) he
// has won.
//
// Input:
// W := World as a 3 x 3 grid
// show := debug
//
// Output:
// W := final state of the world
// PMatrix := Win 1 point, No-Win 0 point; left-upper corner: number of games until beginning
//

function [W,PLAYER,END]=tttgame(W,show)
  

  P=1 //Player 1
  END=0
  i=1
  
  while END == 0 & i < 10
    
    ALLOW=0
    while ALLOW == 0
      
      [X,Y,O]=tttaction0(P), // generate a random (!) move
      [W,ALLOW]=tttaction1(W,X,Y,O,show), //Check allowness (cell free, right order)
    end //while ALLOW
    
    if show == 2 then disp('Turn : '), disp(i), disp(W), end
    
    // Check end of game
    [PLAYER,END]=endgame(W,show)
    
    
    if END == 0 & P==1 then P=0, else P=1 //change player
    end //if
    
    i=i+1
    
  end //while END, i
 
endfunction



//********************************************************
// !!! Do not use because overwritten !!!
// Main game function tttgameA2() for the tic-tac-toe game
// Different to tttgame() is here the 2nd agent -- the opponent -- repalced by a classifier
// system instead of a pure random agent
//
// Idea: 
// Two players play TTT. Beginner uses the piece 'X', the opponent uses 'O'.
// Every turn one player makes a move alternating. As soon as one player has 
// reached 3 pieces in one direction (rowwise, columnwise or in a diagonal) he
// has won.
// With two random players the beginner has an advantage. In the A2 version the random
// opponent is replaced by a learning classifier system. The questioin is, whether the
// LCS can beat the random agent.
//
// Input:
// W := World as a 3 x 3 grid
// AGENT := Name of Agent as opponent
// show := debug
//
// Output:
// W := final state of the world
//

function [W,PLAYER,END,CLASSIF]=tttgameA2_old(W,AGENT, CLASSIF, show)
  

  P=1 //Player 1
  END=0
  n=9,l=26 //n=9 is deliberately, can be changed; l=28 is minimum
  AGENT(1) = CLASSIF
  
  //Start a general loop for the game alternating between the beginner 'X' playing completely at random
  // and as opponent  an LCS using 'O'.
  
  i=1
  while END == 0 & i < 10
    
    if show == 2 then disp('TURN = '), disp(i), disp('PLAYER = '), disp(P), end
    
    
    ALLOW=0
    
    if P == 1 then O='X' 
      
      while ALLOW == 0
      [X,Y,O]=tttaction0(P), // generate a random (!) move
      [W,ALLOW]=tttaction1b(W,X,Y,O,show), //Check allowness (cell free, right order)
    end //if P=1
    
  elseif P == 2 then O='O'
   
      // Get input of state
      [INP]=ainp2(W)
      l=length(INP)
      
      if show == 2 then disp('INP = '), disp(INP), end
      
      //Check match with given classifiers
      [TX]=mmmatch(INP,AGENT(1)) //AGENT(1) uses classifier set CLASSIF
      
      
      
      if sum(TX) == 0 then //no match
        
        while ALLOW == 0
          [X,Y,O]=tttaction0(P), // generate a random (!) move to find a free cell
          [F,FLAG,ALLOW,W]=tttfitn(W,X,Y,O,show) //Check allowness, insert object, and evaluate fitness
        end
        
        if show == 2 then disp('X ='), disp(X), disp('Y ='), disp(Y), end
        
        if show == 2 then disp('FLAG PLAYER 2 ='), disp(FLAG), disp('FITNESS ='), disp(F), end
        
        [G]=classifNew(INP,X,Y,F,show) // Now new classifier
        CLASSIF=[CLASSIF; G(1,:)] //Extending the set CLASSIF by G         
      else //There is a match
        
        
        if show == 2 then disp('TX = '), disp(TX), end
        
       // if show == 2 then disp('CLASSIF = '), disp(CLASSIF), end
        
       // if show == 2 then  disp('Select matching classifiers'), end
        
        
        //find classifier with highest fitness
        
        CSel=[]
        FMax=0
        [n,c2]=size(TX)
        
       //Find MAX Fitness
       for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25)>FMax then FMax = CLASSIF(k,25),
         end
       end
       
       //Select candidates
       j=1
       for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25) == FMax then CSel(j,1)=k, j=j+1
         end
       end
       
        
        if show == 2 then  disp('Candidates after matching'), 
          disp(CSel),  
        end
        
        [n2,c3]=size(CSel)
        cc=round(rand()*n2)
        if cc == 0 then cc = 1,end
        ccc=CSel(cc,1)
        G=CLASSIF(ccc,:)
        
          if show == 2 then  disp('Selected Candidate from Candidates after matching'), 
            disp('No = '), disp(ccc), disp(G),  
          end
          
          //Extract coordinates for move
          
          X=vec22dec(G(1,:),21,22), Y=vec22dec(G(1,:),23,24)
       
          [F,FLAG,ALLOW,W]=tttfitn(W,X,Y,O,show) //Check allowness, insert object, and evaluate fitness
          
          if ALLOW == 0 then
            while ALLOW == 0
              [X,Y,O]=tttaction0(P), // generate a random (!) move to find a free cell
              [F,FLAG,ALLOW,W]=tttfitn(W,X,Y,O,show) //Check allowness, insert object, and evaluate fitness
            end //while
            
            [G]=classifNew(INP,X,Y,F,show) // Now new classifier
            CLASSIF=[CLASSIF; G(1,:)] //Extending classif by G as vector
            
            if show == 2 then 
              disp('Matched Classifier with new move'), disp('X ='), disp(X), disp('Y ='), disp(Y),
               end
                 if show == 2 then disp('FLAG PLAYER 2 ='), disp(FLAG), disp('FITNESS ='), disp(F), end
                 
          else //ALLOW == 1
            CLASSIF(ccc,25)=F
            
            if show == 2 then 
              disp('Matched Classifier with old, new fitness'), disp('X ='), disp(X), disp('Y ='), disp(Y),
               end
               if show == 2 then disp('FLAG PLAYER 2 ='), disp(FLAG), disp('FITNESS ='), disp(F), end
             end
             
            
      end //if sum
      
      // Computing the fitness of CLASSIF
      
end //P=1 oder P=2

    
    
     if show == 2 then disp('BOARD : '), disp(W), end
    
    // Check end of game
    [PLAYER,END]=endgame(W,show)
    
    
     if show == 2 then disp('END : '), disp(END), end
    
    if (END == 0) then  
      if (P == 1) then P=2, 
      else P=1 //change player
      end //if P==1
    end //if END
           

   i=i+1
    
  end //while END, i
  
endfunction

//********************************************************
// Main game function tttgameA2() for the tic-tac-toe game
// Different to tttgame() is here the 2nd agent -- the opponent -- replaced by a classifier
// system instead of a pure random agent
//
// Idea: 
// Two players play TTT. Beginner uses the piece 'X', the opponent uses 'O'.
// Every turn one player makes a move alternating. As soon as one player has 
// reached 3 pieces in one direction (rowwise, columnwise or in a diagonal) he
// has won.
// With two random players the beginner has an advantage. In the A2 version the random
// opponent is replaced by a learning classifier system. The questioin is, whether the
// LCS can beat the random agent.
//
// Input:
// W := World as a 3 x 3 grid
// AGENT := Name of agent as opponent
// show := debug
//
// Output:
// W := final state of the world
// PLAYER := Who has won {'X', 'O'}
// END := Ended '1' or not '0'
// CLASSIF := Final set of classifiers
//

function [W,PLAYER,END,CLASSIF]=tttgameA2(W,AGENT, CLASSIF, show)
  

  P=1 //Player 1
  END=0
  n=9,l=26 //n=9 is deliberately, can be changed; l=28 is minimum
  AGENT(1) = CLASSIF
  BON=5  //Bonus for fitness function
  
  //Start a general loop for the game alternating between the beginner 'X' playing completely at random
  // and as opponent  an LCS using 'O'.
  
  i=1
  P=1
  
  while END == 0 & i < 10
    
    if show == 2 then disp('TURN = '), disp(i), disp('PLAYER = '), disp(P), 
      end
      
      
    //*****************************************************
    //TURN with P1
    //*****************************************************
      
    if P == 1 then O='X' 
      
      [CLst]=freeCells(W,show) //List of free cells
      N=length(CLst)/2,
      [K]=freeCellIndex(N) //Index into this list
      Y=CLst(K,1), X=CLst(K,2)
      W(Y,X)='X' // New move for 'X'
      
    //*****************************************************
    //TURN with P2
    //*****************************************************
      
  elseif P == 2 then O='O'
    
      //********************************
      // Get input of state
      
      [INP]=ainp2(W)
      l=length(INP)
      
      if show == 2 then disp('INP = '), disp(INP), 
        end
      
      
      //********************************
      //Check match with given classifiers
      
      [TX]=mmmatch(INP,AGENT(1)) //AGENT(1) uses classifier set CLASSIF
      
      
      if sum(TX) == 0 then
        
        //********************************
        // No match
        // Generate new move with new classifier
        
     
        if show == 2 then disp('X ='), disp(X), disp('Y ='), disp(Y), end 
        
        [CLst]=freeCells(W,show) //List of free cells
        
        N=length(CLst)/2,
        
        [K]=freeCellIndex(N) //Index into this list
        
        Y=CLst(K,1), X=CLst(K,2)
        
        W(Y,X)='O'
        
        [W,FLAG,F]=tttfit2(W,'O',BON,show)

        [G]=classifNew(INP,X,Y,F,show) // Now new classifier
        CLASSIF=[CLASSIF; G(1,:)] //Extending the set CLASSIF by G  
           
      else
        
         //****************************************
         //There is a match
         
         if show == 2 then disp('TX = '), disp(TX), 
         end
         
         // if show == 2 then disp('CLASSIF = '), disp(CLASSIF), end
         // if show == 2 then  disp('Select matching classifiers'), end
        
         //find classifier with highest fitness
        
        CSel=[]
        FMax=0
        [n,c2]=size(TX)
        
        //Find MAX Fitness
        
        for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25)>FMax then FMax = CLASSIF(k,25),
         end
       end
       
       
       
       //Select candidates
       
       j=1
       for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25) == FMax then CSel(j,1)=k, j=j+1
         end
       end
       
        
        if show == 2 then  disp('Candidates after matching'), 
          disp(CSel),  
        end
        
        [n2,c3]=size(CSel)
               
        // Find a candidate whose move matches free cells
        
        //List of free cells
          
          [CLst]=freeCells(W,show) 
          [r3,c4]=size(CLst)
          
          r=1
          while (r <= n2)
            //Search for every candidate from CSel
            G=CLASSIF(CSel(r,1),:)                 
            
             if show == 2 then  disp('Selected Candidate from Candidates after matching'), 
                    disp('No = '), disp(CSel(r,1)), disp(G), 
                  end
                  
            //Extract coordinates for move
                  
            X=vec22dec(G(1,:),21,22), 
            Y=vec22dec(G(1,:),23,24)
            
            
             ALLOW=0
             k=1
             
             while(ALLOW==0 & k <= r3)
               
               //Search all free cells for one classifier
               
               if CLst(k,1)==Y & CLst(k,2)==X then  
                 
                 //If a cell matches insert Object according classifier
   
                    W(Y,X)='O', 
                    [W,FLAG,F]=tttfit2(W,'O',BON,show)
                    
                    // Update classifier with fitness
                    
                    CLASSIF(CSel(r,1),25)=F,
                    ALLOW=1
                    
                    if show == 2 then 
                      disp('Matched Classifier with old, new fitness'), disp('X ='), disp(X), disp('Y ='), disp(Y),
                    end

                    break
                  end //if there is a match
                  
                  k=k+1
                end //while
                
                r=r+1
                
              end //while r
               
               if ALLOW==0 then 
                 
                  //No free cell for no selected classifier could be found
                  // Create new classifier
                  
                N=length(CLst)/2,
                [K]=freeCellIndex(N) //Index into this list
                Y=CLst(K,1), X=CLst(K,2)
                W(Y,X)='O'
                [W,FLAG,F]=tttfit2(W,'O',BON,show)
                [G]=classifNew(INP,X,Y,F,show) // New classifier
                CLASSIF=[CLASSIF; G(1,:)] //Extending classif by G as vector
                
                if show == 2 then 
                  disp('New Classifier because matched had wrong move'), disp('X ='), disp(X), disp('Y ='), disp(Y),
                end
                if show == 2 then disp('FLAG PLAYER 2 ='),  disp('FITNESS ='), disp(F), 
                end
              end // if no match with old classifiers
              
            end //if sum
            
          end //P=1 oder P=2
          

    
    
     if show == 2 then disp('BOARD : '), disp(W), end
    
    // Check end of game
    [PLAYER,END]=endgame(W,show)
    
    
     if show == 2 then disp('END : '), disp(END), end
    
    if (END == 0) then  
      if (P == 1) then P=2, 
      else P=1 //change player
      end //if P==1
    end //if END
           

   i=i+1
    
  end //while END, i
  
endfunction


//********************************************************
// Main game function tttgameA3() for the tic-tac-toe game
// Different to tttgameA2() is here the inclusion of simple genetic operators
//
// Input:
// W := World as a 3 x 3 grid
// AGENT := Name of agent as opponent
// show := debug
//
// Output:
// W := final state of the world
// PLAYER := Who has won {'X', 'O'}
// END := Ended '1' or not '0'
// CLASSIF := Final set of classifiers. It is assumed that the set CLASSIF has the miimal size of 
//            c = l + p
//            with  'l=24' length of strings and 'p=7' as parameter offset
//

function [W,PLAYER,END,CLASSIF]=tttgameA3(W,AGENT, CLASSIF, l,p,show)
  

  P=1 //Player 1
  END=0
  
  [rw,cw]=size(W), n=rw*cw
  [rc,cc]=size(CLASSIF)
  
  AGENT(1) = CLASSIF
  BON=5  //Bonus for fitness function
  FITNESS_ALL = 0
  
  //Start a general loop for the game alternating between the beginner 'X' playing completely at random
  // and as opponent  an LCS using 'O'.
  
  i=1
  P=1
  
  while END == 0 & i < 10
    
    if show == 2 then disp('TURN = '), disp(i), disp('PLAYER = '), disp(P), 
      end
      
      
    //*****************************************************
    //TURN with P1
    //*****************************************************
      
    if P == 1 then O='X' 
      
      [CLst]=freeCells(W,show) //List of free cells
      N=length(CLst)/2,
      [K]=freeCellIndex(N) //Index into this list
      Y=CLst(K,1), X=CLst(K,2)
      W(Y,X)='X' // New move for 'X'
      
    //*****************************************************
    //TURN with P2
    //*****************************************************
      
  elseif P == 2 then O='O'
    
      //********************************
      // Get input of state
      
      [INP]=ainp2(W)
      l=length(INP)
      
      if show == 2 then disp('INP = '), disp(INP), 
        end
      
      
      //********************************
      //Check match with given classifiers
      
      [TX]=mmmatch(INP,AGENT(1)) //AGENT(1) uses classifier set CLASSIF
      
      
      if sum(TX) == 0 then
        
        //********************************
        // No match
        // Generate new move with new classifier
        
     
        if show == 2 then disp('X ='), disp(X), disp('Y ='), disp(Y), end 
        
        [CLst]=freeCells(W,show) //List of free cells
        
        N=length(CLst)/2,
        
        [K]=freeCellIndex(N) //Index into this list
        
        Y=CLst(K,1), X=CLst(K,2)
        
        W(Y,X)='O'
        
        [W,FLAG,F]=tttfit2(W,'O',BON,show)
        
        //disp('Before classifNew')
        
        [rr,cc]=size(CLASSIF)
        
        [G]=classifNew2(INP,X,Y,F,rr,cc,show) // Now new classifier
        
        //disp('After classifNew'),disp('G ='), disp(G)

        
        CLASSIF=[CLASSIF; G(1,:)] //Extending the set CLASSIF by G  
 
           
      else
        
         //****************************************
         //There is a match
         
         if show == 2 then disp('TX = '), disp(TX), 
         end
         
         //find classifier with highest fitness
        
        CSel=[]
        FMax=0
        [n,c2]=size(TX)
        
        //Find MAX Fitness
        
        for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25)>FMax then FMax = CLASSIF(k,25),
         end
       end
       
       
       
       //Select candidates
       
       j=1
       for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25) == FMax then CSel(j,1)=k, j=j+1
         end
       end
       
        
        if show == 2 then  disp('Candidates after matching'), 
          disp(CSel),  
        end
        
        [n2,c3]=size(CSel)
               
        // Find a candidate whose move matches free cells
        
        //List of free cells
          
          [CLst]=freeCells(W,show) 
          [r3,c4]=size(CLst)
          
          r=1
          while (r <= n2)
            //Search for every candidate from CSel
            G=CLASSIF(CSel(r,1),:)                 
            
             if show == 2 then  disp('Selected Candidate from Candidates after matching'), 
                    disp('No = '), disp(CSel(r,1)), disp(G), 
                  end
                  
                  //Extract coordinates for move
                  //1-18 := 3x3 board
                  //19-20 := X
                  // 21-22 := Y 
                  // 23-24 := O
                  // 25 := F
                  
            X=vec22dec(G(1,:),19,20), 
            Y=vec22dec(G(1,:),21,22)
            
            
             ALLOW=0
             k=1
             
             while(ALLOW==0 & k <= r3)
               
               //Search all free cells for one classifier
               
               if CLst(k,1)==Y & CLst(k,2)==X then  
                 
                 //If a cell matches insert Object according classifier
   
                    W(Y,X)='O', 
                    [W,FLAG,F]=tttfit2(W,'O',BON,show)
                    
                    // Update classifier with fitness
                    
                    CLASSIF(CSel(r,1),25)=F,
                    
                    ALLOW=1
                    
                    if show == 2 then 
                      disp('Matched Classifier with old, new fitness'),disp(CLASSIF(CSel(r,1),:)) 
                    end

                    break
                  end //if there is a match
                  
                  k=k+1
                end //while
                
                r=r+1
                
              end //while r
               
               if ALLOW==0 then 
                 
                  //No free cell for no selected classifier could be found
                  // Create new classifier
                  
                N=length(CLst)/2,
                [K]=freeCellIndex(N) //Index into this list
                Y=CLst(K,1), X=CLst(K,2)
                W(Y,X)='O'
                [W,FLAG,F]=tttfit2(W,'O',BON,show)
                
                [rr,cc]=size(CLASSIF)
                [G]=classifNew2(INP,X,Y,F,rr,cc,show)// New classifier
                
                CLASSIF=[CLASSIF; G(1,:)] //Extending classif by G as vector

                if show == 2 then 
                  disp('New Classifier because matched had wrong move'), disp(G(1,:)) 
                end
                if show == 2 then disp('FLAG PLAYER 2 ='),  disp('FITNESS ='), disp(F), 
                end
              end // if no match with old classifiers
              
            end //if sum
            
            //***********************************************
            // Apply crossover
            //****************************************************
            
            
            l=23  //fitness assumes F at l+2, but with CLASSIF F is at l+1!
            
            [FITNESS_ALL]=fitness(CLASSIF,l)
            
            
            if FITNESS_ALL == 0 then FITNESS_ALL=FITNESS_ALL+0.0001,end
            
            l=23  //fitness assumes F at l+2, but with CLASSIF F is at l+1!            
           
           [MFITNESS]=maxfitness(CLASSIF,l)
           
            l=23  //fitness assumes F at l+2, but with CLASSIF F is at l+1!           
            
            [CLASSIF,AFITNESS]=rfitness(CLASSIF,l,FITNESS_ALL)
 
             if show == 4 then
               disp('CLASSIF after rfitness'), disp(CLASSIF)
             end
             
            
            // if show == 1 then disp(CLASSIF), end
                
            [CLASSIF]=newMember(CLASSIF,l,n)
            
            if show == 1 then disp(CLASSIF), end  
           
            
            [CLASSIF]=newPop2(CLASSIF,l,p,n)
            
            
          end //P=1 oder P=2

     if show == 2 then disp('BOARD : '), disp(W), end
    
    // Check end of game
    [PLAYER,END]=endgame(W,show)
    
    
     if show == 2 then disp('END : '), disp(END), end
    
    if (END == 0) then  
      if (P == 1) then P=2, 
      else P=1 //change player
      end //if P==1
    end //if END
           

   i=i+1
    
  end //while END, i
  
endfunction

//********************************************************
// Main game function tttgameA3X() for the tic-tac-toe game
// Different to tttgameA3() is here that the LCS system is the beginner
//
// Input:
// W := World as a 3 x 3 grid
// AGENT := Name of agent as opponent
// show := debug
//
// Output:
// W := final state of the world
// PLAYER := Who has won {'X', 'O'}
// END := Ended '1' or not '0'
// CLASSIF := Final set of classifiers. It is assumed that the set CLASSIF has the miimal size of 
//            c = l + p
//            with  'l=24' length of strings and 'p=7' as parameter offset
//

function [W,PLAYER,END,CLASSIF]=tttgameA3X(W,AGENT, CLASSIF, l,p,show)
  

  P=1 //Player 1
  END=0
  
  [rw,cw]=size(W), n=rw*cw
  [rc,cc]=size(CLASSIF)
  
  AGENT(1) = CLASSIF
  BON=5  //Bonus for fitness function
  FITNESS_ALL = 0
  
  //Start a general loop for the game alternating between the beginner 'X' playing completely at random
  // and as opponent  an LCS using 'O'.
  
  i=1
  P=1
  
  while END == 0 & i < 10
    
    if show == 2 then disp('TURN = '), disp(i), disp('PLAYER = '), disp(P), 
      end
      
      
    //*****************************************************
    //TURN with P1 as LCS
    //*****************************************************
      
    if P == 1 then O='X' 
 
    
      //********************************
      // Get input of state
      
      [INP]=ainp2(W)
      l=length(INP)
      
      if show == 2 then disp('INP = '), disp(INP), 
        end
      
      
      //********************************
      //Check match with given classifiers
      
      [TX]=mmmatch(INP,AGENT(1)) //AGENT(1) uses classifier set CLASSIF
      
      
      if sum(TX) == 0 then
        
        //********************************
        // No match
        // Generate new move with new classifier
       
        
        [CLst]=freeCells(W,show) //List of free cells
        
        N=length(CLst)/2,
        
        [K]=freeCellIndex(N) //Index into this list
        
        Y=CLst(K,1), X=CLst(K,2)
        
        if show == 2 then disp('X ='), disp(X), disp('Y ='), disp(Y), end 
        
        W(Y,X)='X'
        
        [W,FLAG,F]=tttfit2(W,'X',BON,show)
        
        //disp('Before classifNew')
        
        [rr,cc]=size(CLASSIF)
        
        [G]=classifNew2(INP,X,Y,F,rr,cc,show) // Now new classifier
        
        //disp('After classifNew'),disp('G ='), disp(G)

        
        CLASSIF=[CLASSIF; G(1,:)] //Extending the set CLASSIF by G  
 
           
      else
        
         //****************************************
         //There is a match
         
         if show == 2 then disp('TX = '), disp(TX), 
         end
         
         //find classifier with highest fitness
        
        CSel=[]
        FMax=0
        [n,c2]=size(TX)
        
        //Find MAX Fitness
        
        for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25)>FMax then FMax = CLASSIF(k,25),
         end
       end
       
       
       
       //Select candidates
       
       j=1
       for k=1:n
         if TX(k,1) == 1 & CLASSIF(k,25) == FMax then CSel(j,1)=k, j=j+1
         end
       end
       
        
        if show == 2 then  disp('Candidates after matching'), 
          disp(CSel),  
        end
        
        [n2,c3]=size(CSel)
               
        // Find a candidate whose move matches free cells
        
        //List of free cells
          
          [CLst]=freeCells(W,show) 
          [r3,c4]=size(CLst)
          
          r=1
          while (r <= n2)
            //Search for every candidate from CSel
            G=CLASSIF(CSel(r,1),:)                 
            
             if show == 2 then  disp('Selected Candidate from Candidates after matching'), 
                    disp('No = '), disp(CSel(r,1)), disp(G), 
                  end
                  
                  //Extract coordinates for move
                  //1-18 := 3x3 board
                  //19-20 := X
                  // 21-22 := Y 
                  // 23-24 := O
                  // 25 := F
                  
            X=vec22dec(G(1,:),19,20), 
            Y=vec22dec(G(1,:),21,22)
            
            
             ALLOW=0
             k=1
             
             while(ALLOW==0 & k <= r3)
               
               //Search all free cells for one classifier
               
               if CLst(k,1)==Y & CLst(k,2)==X then  
                 
                 //If a cell matches insert Object according classifier
   
                    W(Y,X)='X', 
                    [W,FLAG,F]=tttfit2(W,'X',BON,show)
                    
                    // Update classifier with fitness
                    
                    CLASSIF(CSel(r,1),25)=F,
                    
                    ALLOW=1
                    
                    if show == 2 then 
                      disp('Matched Classifier with old, new fitness'),disp(CLASSIF(CSel(r,1),:)) 
                    end

                    break
                  end //if there is a match
                  
                  k=k+1
                end //while
                
                r=r+1
                
              end //while r
               
               if ALLOW==0 then 
                 
                  //No free cell for no selected classifier could be found
                  // Create new classifier
                  
                N=length(CLst)/2,
                [K]=freeCellIndex(N) //Index into this list
                Y=CLst(K,1), X=CLst(K,2)
                W(Y,X)='X'
                [W,FLAG,F]=tttfit2(W,'X',BON,show)
                
                [rr,cc]=size(CLASSIF)
                [G]=classifNew2(INP,X,Y,F,rr,cc,show)// New classifier
                
                CLASSIF=[CLASSIF; G(1,:)] //Extending classif by G as vector

                if show == 2 then 
                  disp('New Classifier because matched had wrong move'), disp(G(1,:)) 
                end
                if show == 2 then disp('FLAG PLAYER 2 ='),  disp('FITNESS ='), disp(F), 
                end
              end // if no match with old classifiers
              
            end //if sum
            
            //***********************************************
            // Apply crossover
            //****************************************************
            
            
            l=23  //fitness assumes F at l+2, but with CLASSIF F is at l+1!
            
            [FITNESS_ALL]=fitness(CLASSIF,l)
            
            
            if FITNESS_ALL == 0 then FITNESS_ALL=FITNESS_ALL+0.0001,end
            
            l=23  //fitness assumes F at l+2, but with CLASSIF F is at l+1!            
           
           [MFITNESS]=maxfitness(CLASSIF,l)
           
            l=23  //fitness assumes F at l+2, but with CLASSIF F is at l+1!           
            
            [CLASSIF,AFITNESS]=rfitness(CLASSIF,l,FITNESS_ALL)
 
             if show == 4 then
               disp('CLASSIF after rfitness'), disp(CLASSIF)
             end
             
            
            // if show == 1 then disp(CLASSIF), end
                
            [CLASSIF]=newMember(CLASSIF,l,n)
            
            if show == 1 then disp(CLASSIF), end  
           
            
            [CLASSIF]=newPop2(CLASSIF,l,p,n)
            
    //*****************************************************
    //TURN with P2 as random opponent
    //*****************************************************
      
  elseif P == 2 then O='O'
            
 [CLst]=freeCells(W,show) //List of free cells
      N=length(CLst)/2,
      [K]=freeCellIndex(N) //Index into this list
      Y=CLst(K,1), X=CLst(K,2)
      W(Y,X)='O' // New move for 'O'
      

            
          end //P=1 oder P=2
          

     if show == 2 then disp('BOARD : '), disp(W), end
    
    // Check end of game
    [PLAYER,END]=endgame(W,show)
    
    
     if show == 2 then disp('END : '), disp(END), end
    
    if (END == 0) then  
      if (P == 1) then P=2, 
      else P=1 //change player
      end //if P==1
    end //if END
           

   i=i+1
    
  end //while END, i
  
endfunction



//********************************************************
// Main tournament function ttttournament() for the tic-tac-toe game
//
// Idea: 
// The tournament function can repeatedly call a tttgame() function where two players can have alternating
// roles either as beginner or as opponent to a beginner. Furthermore will the results be kept in a
// game matrix with '1' for e win and '0' for a non-win.
//
// Input:
// W := World as a 3 x 3 grid
// p := Number of players which shall play
// N := number of games to be played against each other (usuall x2 because of two roles)
// show := debug
//
// Output:
// PMatrix := Win 1 point, No-Win 0 point; left-upper corner: number of games until beginning
//

function [PMatrix]=ttttournament(W,p,N,show)
  
  [PList]=plistgen(p)
  [PMatrix]=pmatrixgen(PList)
  
  if show == 3 then disp(PMatrix),end
  
  for i=1:N
    
    ROLE=0 //Player P1 is beginner
    WI=W //Use empty world for each game
    
    //if show == 3 then disp('Before tttgame() '), disp(i), disp(W),end
    
    [WE,PLAYER,END]=tttgame(WI,show),
    
    if show == 3 then disp('Round = '), disp(i), disp(WE),end
  
  
  // Insert results in game table
  
  if PLAYER == 'X' then PMatrix(2,2)=PMatrix(2,2)+1,
  elseif PLAYER == 'O' then PMatrix(2,3)=PMatrix(2,3)+1,
  end
  PMatrix(1,1)=PMatrix(1,1)+1
  
end //for i

 
endfunction

//********************************************************
// Main tournament function ttttournament2() for the tic-tac-toe game
//
// Idea: 
// The tournament function can repeatedly call a tttgame() function where two players can have alternating
// roles either as beginner or as opponent to a beginner. Furthermore will the results be kept in a
// game matrix with '1' for e win and '0' for a non-win.
//
// Input:
// W := World as a 3 x 3 grid
// p := Number of players which shall play
// N := number of games to be played against each other (usuall x2 because of two roles)
// show := debug
//
// Output:
// PMatrix := Win 1 point, No-Win 0 point; left-upper corner: number of games until beginning
//

function [PMatrix, PX,PY]=ttttournament2(W,p,N,show)
  
  [PList]=plistgen(p)
  [PMatrix]=pmatrixgen(PList)
  
  if show == 3 then disp(PMatrix),end
  
  for i=1:N
    
    ROLE=0 //Player P1 is beginner
    WI=W //Use empty world for each game
    
    //if show == 3 then disp('Before tttgame() '), disp(i), disp(W),end
    
    [WE,PLAYER,END]=tttgame(WI,show),
    
    if show == 3 then disp('Round = '), disp(i), disp(WE),end
  
  
  // Insert results in game table
  
  if PLAYER == 'X' then PMatrix(2,2)=PMatrix(2,2)+1,
  elseif PLAYER == 'O' then PMatrix(2,3)=PMatrix(2,3)+1,
  end
  PMatrix(1,1)=PMatrix(1,1)+1
  
end //for i

PlayerX = sum(PMatrix(:,2))-1, PX = PlayerX/(PMatrix(1,1)/100)
PlayerY = sum(PMatrix(:,3))-2, PY = PlayerY/(PMatrix(1,1)/100)

disp('RESULT ='), disp('Player X = '), disp(PX), disp('Player Y = '), disp(PY)

 
endfunction


//********************************************************
// Main tournament function ttttournamentA2() for the tic-tac-toe game
// assuming one opponent player with learning classifiers
//
// Idea: 
// The tournament function can repeatedly call a tttgameA2() function where the opponent is the one which uses 
// classifiers. Furthermore will the results be kept in a
// game matrix with '1' for e win and '0' for a non-win.
//
// Input:
// W := World as a 3 x 3 grid
// AGENT := which type of agent shall be used
// N := number of games to be played against each other
// CLASSIF := Set of classifiers of opponent which will beinherited from game to game
// show := debug
//
// Output:
// PMatrix := Win 1 point, No-Win 0 point; left-upper corner: number of games until beginning
// CLASSIF := Set of classifiers of opponent which will beinherited from game to game
//

function [PMatrix, CLASSIF,PX, PY]=ttttournamentA2(W,AGENT,CLASSIF,N,show)
  
  
  [PMatrix]=pmatrixgenA2(N) //Table for 2 players and N-many games
  
  if show == 3 then disp(PMatrix),end
  
  for i=1:N
    
    WI=W //Use empty world for each game
    
    //if show == 3 then disp('Before tttgame() '), disp(i), disp(W),end
    
    
    [WE,PLAYER,END,CLASSIF]=tttgameA2(WI,AGENT, CLASSIF, show)
    
    if show == 3 then disp('Round = '), disp(i), disp(WE),end
  
  
  // Insert results in game table
  
  if PLAYER == 'X' then PMatrix(i+1,2)=PMatrix(i+1,2)+1,
  elseif PLAYER == 'O' then PMatrix(i+1,3)=PMatrix(i+1,3)+1,
  end
  PMatrix(1,1)=PMatrix(1,1)+1
  
end //for i

PlayerX = sum(PMatrix(:,2))-1, PX = PlayerX/(PMatrix(1,1)/100)
PlayerY = sum(PMatrix(:,3))-2, PY = PlayerY/(PMatrix(1,1)/100)

disp('RESULT ='), disp('Player X = '), disp(PX), disp('Player Y = '), disp(PY)



endfunction


//********************************************************
// Main tournament function ttttournamentA3() for the tic-tac-toe game
// assuming one opponent player with learning classifiers
//
//Input additionally:
// l:= length of information part (24)
// p := offset (7)

function [PMatrix, CLASSIF,PX, PY]=ttttournamentA3(W,AGENT,CLASSIF,N,l,p,show)
  
  
  [PMatrix]=pmatrixgenA2(N) //Table for 2 players and N-many games
  
  if show == 3 then disp(PMatrix),end
  
  for i=1:N
    
    WI=W //Use empty world for each game
    
    //if show == 3 then disp('Before tttgame() '), disp(i), disp(W),end
    

    [WE,PLAYER,END,CLASSIF]=tttgameA3(WI,AGENT, CLASSIF, l,p,show)
    
    if show == 5 then disp('Round = '), disp(i), disp(WE),end
  
  
  // Insert results in game table
  
  if PLAYER == 'X' then PMatrix(i+1,2)=PMatrix(i+1,2)+1,
  elseif PLAYER == 'O' then PMatrix(i+1,3)=PMatrix(i+1,3)+1,
  end
  PMatrix(1,1)=PMatrix(1,1)+1
  
end //for i

PlayerX = sum(PMatrix(:,2))-1, PX = PlayerX/(PMatrix(1,1)/100)
PlayerY = sum(PMatrix(:,3))-2, PY = PlayerY/(PMatrix(1,1)/100)

disp('RESULT ='), disp('Player X = '), disp(PX), disp('Player Y = '), disp(PY)


endfunction

//********************************************************
// Main tournament function ttttournamentA3X() for the tic-tac-toe game
// assuming one beginning player with learning classifiers
//
//Input additionally:
// l:= length of information part (24)
// p := offset (7)

function [PMatrix, CLASSIF,PX, PY]=ttttournamentA3X(W,AGENT,CLASSIF,N,l,p,show)
  
  
  [PMatrix]=pmatrixgenA2(N) //Table for 2 players and N-many games
  
  if show == 3 then disp(PMatrix),end
  
  for i=1:N
    
    WI=W //Use empty world for each game
    
    //if show == 3 then disp('Before tttgame() '), disp(i), disp(W),end
    

    [WE,PLAYER,END,CLASSIF]=tttgameA3X(WI,AGENT, CLASSIF, l,p,show)
    
    if show == 5 then disp('Round = '), disp(i), disp(WE),end
  
  
  // Insert results in game table
  
  if PLAYER == 'X' then PMatrix(i+1,2)=PMatrix(i+1,2)+1,
  elseif PLAYER == 'O' then PMatrix(i+1,3)=PMatrix(i+1,3)+1,
  end
  PMatrix(1,1)=PMatrix(1,1)+1
  
end //for i

PlayerX = sum(PMatrix(:,2))-1, PX = PlayerX/(PMatrix(1,1)/100)
PlayerY = sum(PMatrix(:,3))-2, PY = PlayerY/(PMatrix(1,1)/100)

disp('RESULT ='), disp('Player X = '), disp(PX), disp('Player Y = '), disp(PY)


endfunction




//********************************************************
// Tournament history tournamenthistory()
// With two random agents as benchmark
//
// The set CLASSIF is not used
//
//Input additionally:
// l:= length of information part (24)
// p := offset (7)

function [PMX]=ttttournamenthistory(W,N,M,show)
  
  p=2
  PMX=[]
  
  
  for i= 1:M
    [PMatrix, PX,PY]=ttttournament2(W,p,N,show)
    PMX(i,1)=i
    PMX(i,2)=PX
    PMX(i,3)=PY
    
    disp('--------------------------------'),disp('Tournament No. ='), disp(i), disp('--------------------------------')
    
    
  end //end i
    
  //Show final table
  
  disp(PMX)
  MEAN_X=mean(PMX(:,2))
  STD_X=st_deviation(PMX(:,2))
  MEAN_O=mean(PMX(:,3))
  STD_O=st_deviation(PMX(:,3))
  disp('MEAN_X='), disp(MEAN_X),disp('STD_X='), disp(STD_X),
  disp('MEAN_O='), disp(MEAN_O),disp('STD_O='), disp(STD_O),
  
  //Show Plot
  
  X=[1:1:M]';
  clf()
  xdel
  Y1=PMX(:,2)
  Y2=PMX(:,3)
  plot2d(X,[Y1 Y2])
  

endfunction


//********************************************************
// Tournament history tournamentA2history()
//
// Idea: 
// Collects all results of different tournaments to show a graph
//
// Input:
// W := World as a 3 x 3 grid
// AGENT := which type of agent shall be used
// CLASSIF := Set of classifiers of opponent which will beinherited from game to game
// N := number of games to be played against each other
// M := number of tournaments to be played against each other
// show := debug
//
// Output:
// PMX := List of tournament results
// CLASSIF := Set of classifiers of opponent which will beinherited from game to game
//

function [PMX,CLASSIF]=ttttournamentA2history(W,AGENT,CLASSIF,N,M,show)
  
  PMX=[]
  
  
  for i= 1:M

    [PMatrix, CLASSIF,PX, PY]=ttttournamentA2(W,AGENT,CLASSIF,N,show)
    PMX(i,1)=i
    PMX(i,2)=PX
    PMX(i,3)=PY
    
    disp('--------------------------------'),disp('Tournament No. ='), disp(i), disp('--------------------------------')
    
    
    fd=mopen('CLASSIF'+string(evstr(i)),'w')
    fprintfMat('CLASSIF'+string(evstr(i)),CLASSIF,'%1f');
    mclose(fd)
  end
  
  X=[1:1:M]';
  clf()
  xdel
  Y1=PMX(:,2)
  Y2=PMX(:,3)
  plot2d(X,[Y1 Y2])
  

endfunction



//********************************************************
// Tournament history tournamentA3history()
//
//Input additionally:
// l:= length of information part (24)
// p := offset (7)

function [PMX,CLASSIF]=ttttournamentA3history(W,AGENT,CLASSIF,N,M,l,p,show)
  
  PMX=[]
  
  
  for i= 1:M

    [PMatrix, CLASSIF,PX, PY]=ttttournamentA3(W,AGENT,CLASSIF,N,l,p,show)
    PMX(i,1)=i
    PMX(i,2)=PX
    PMX(i,3)=PY
    
    disp('--------------------------------'),disp('Tournament No. ='), disp(i), disp('--------------------------------')
    
    
    
    fd=mopen('CLASSIF'+string(evstr(i)),'w')
    fprintfMat('CLASSIF'+string(evstr(i)),CLASSIF,'%1f');
    mclose(fd)
  end
  
  //Show final table
  
  disp(PMX)
  MEAN_X=mean(PMX(:,2))
  STD_X=st_deviation(PMX(:,2))
  MEAN_O=mean(PMX(:,3))
  STD_O=st_deviation(PMX(:,3))
  disp('MEAN_X='), disp(MEAN_X),disp('STD_X='), disp(STD_X),
  disp('MEAN_O='), disp(MEAN_O),disp('STD_O='), disp(STD_O),
  
  //Show Plot
  
  X=[1:1:M]';
  clf()
  xdel
  Y1=PMX(:,2)
  Y2=PMX(:,3)
  plot2d(X,[Y1 Y2])
  

endfunction


//********************************************************
// Tournament history tournamentA3Xhistory()
//
//Input additionally:
// l:= length of information part (24)
// p := offset (7)

function [PMX,CLASSIF]=ttttournamentA3Xhistory(W,AGENT,CLASSIF,N,M,l,p,show)
  
  PMX=[]
  
  
  for i= 1:M

    [PMatrix, CLASSIF,PX, PY]=ttttournamentA3X(W,AGENT,CLASSIF,N,l,p,show)
    PMX(i,1)=i
    PMX(i,2)=PX
    PMX(i,3)=PY
    
    disp('--------------------------------'),disp('Tournament No. ='), disp(i), disp('--------------------------------')
    
    
    
    fd=mopen('CLASSIF'+string(evstr(i)),'w')
    fprintfMat('CLASSIF'+string(evstr(i)),CLASSIF,'%1f');
    mclose(fd)
  end
  
  //Show final table
  
  disp(PMX)
  MEAN_X=mean(PMX(:,2))
  STD_X=st_deviation(PMX(:,2))
  MEAN_O=mean(PMX(:,3))
  STD_O=st_deviation(PMX(:,3))
  disp('MEAN_X='), disp(MEAN_X),disp('STD_X='), disp(STD_X),
  disp('MEAN_O='), disp(MEAN_O),disp('STD_O='), disp(STD_O),
  
  //Show Plot
  
  X=[1:1:M]';
  clf()
  xdel
  Y1=PMX(:,2)
  Y2=PMX(:,3)
  plot2d(X,[Y1 Y2])
  

endfunction


//*******************************************************************************************
// All data are organized in a dynamical table. Left hand the actual genes, in the  middle
// supporting parameters and to the right intermediate modifications of the genes to the left.
//
// POP FORMAT
// l := length of strings
// p := number of cells between string <1...l> and <l+p+1, ..., l+p+l>
// Pos 1-l := String
// Pos l+1 := Decimal Value of binary string
// Pos l+2 := Fitness for l+1 (and l+p in special cases)
// Pos l+3 := Percentage of overall fitness
// Pos l+4 := Expected count according to fitness
// Pos l+5 := Realized count
// Pos l+6 := 2nd Decimal value of a compund fitness
// Pos l+7 := crossover flag
// p := 7

// Variable for overall Fitness

FITNESS_ALL = 0

// Variable for average Fitness

AFITNESS = 0


//***************************************************
//Function to generate automatically a population with random values
// Input:
// l := length of strings
// n := size of population
// Output:
// A population according to the above defined format
//

function[POPX]=popgen(n,l)
  
  //Generate a matrix with only '0's
  
  POPX = zeros(n,l)
  MaxCells = n*l
  
  // Distribute randomly '1's
  
  for i=1:n
    for j=1:l
      if( rand() < 0.5 ) then POPX(i,j) = 0, else POPX(i,j) = 1, end
    end
    end
         
       endfunction
       
       
       
//***************************************************
//Function to test the randomness of a bit-string
// (see: A.L.Rukhin 2011, Statistical Testing of Randomness)
//
// Input:
// POP := Set of binary strings of length l
//
// Output:
// PX := Set of Probabilities of binary strings with 
//       binary string as (S_n + n)/2 and S_n = X_1 + ... + X_n
//       X_k = 2e_k - 1 (k in [1,n] and e in {0,1})

function[STD,M,PX]=bitness(POP,l)
  
  [r,c] = size(POP)
  PX = zeros(r,3) 
  M=0  
  
  for i=1:r, PX(i,1)=i,
    for j=1:l,PX(i,2)=PX(i,2)+(2*POP(i,j)-1),end, 
    PX(i,2)=(PX(i,2)+l)/2,
    PX(i,3)=PX(i,2)/l, M=M+PX(i,3),
  end
  M=M/r
   STD=st_deviation(PX(:,3))
    
endfunction
              
//***************************************************
//Function to generate random numbers between [1,up]
// 
// n := number of choices

function[Xs]=randInt(n, up)
  
  Xs = []
  
  for i=1:n
    x=0
    while(x==0)
      x = round(up*rand())
      end
    Xs(i) = x
      end
 
endfunction



//***************************************************
//Function to compute descriptive parameters of a population
// Input:
// l := length of strings
// n := size of population
// Output:
// Pc := Percentage of possible space (PSpace)
// Pb := Probability of gitting a certain individual of PSpace

function[Pc, Pb]=popDescr(n,l)
  
  // Cardinality of PSpace
  
  PSPC = 2^l
  
  // Percentage Pc
  
  Pc = n/(PSPC/100)
  
  // Probability Pb
  
  Pb = n/2^l
         
endfunction




//***************************************************
//Function to compute the frequencies of the elements of a population
//
// Input:
// l := length of strings
// n := size of population
// N := number of events
// show := if '1' then display the POPX-matrix
//
// Output:
// FX := Vector of freuencies ordered along the decimal values of a string (1st column)
// FXDif := Vector of Differences compared to theoretical expectation in % (2nd column)
// MEAN := The mean value of the differences
// STD := The standard deviation of the differences
//
// Idea: Generate a sequence of populations, count the occurences, and check the degree of agreement between 
// empirical values and theoretica lexpectations

function[DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,FX, POPX]=frequCheck(l,n,N,show)
  
  
  // Install the counters
  
  r= (2^l)
  c= 3
  
  FX = zeros(r,c)
  
  // Generate an internal index for display
  
  for j=1:r
    FX(j,1)=j-1
    end
  
  // Generate the populations
  
  for i=1:N
  
  [POPX]=popgen(n,l)
  
  
  if show==1 then printf("POPX first\n"), disp(POPX), end
  
  //Compute decimal value ('0' is placed at index '1' !!!)
  // Count occurences 
  
  for j=1:n
    v=POPX(j,:),  d = vec2dec(v,l), [POPX(j,l+1)]= d, FX(d+1,2)=FX(d+1,2)+1 
  end//n 
  
  if show==1 then printf("POPX second\n"), disp(POPX), end
  
end //N

for j=1:r
  
    FX(j,3)=(FX(j,2)/n)/N //Normal frequency
    FX(j,4)=(FX(j,2)/n)/(((1/2^l)*N)/100) // Frequency as percentage
  end//m 
  
  
  disp(FX)
  
  FREQ1=tabul(FX(:,3))
  MEAN1=mean(FREQ1(:,1)) 
  STD1= stdevf(FREQ1(:,1), FREQ1(:,2))
  FREQ=tabul(FX(:,4))
  MEAN=mean(FREQ(:,1)) 
  STD= stdevf(FREQ(:,1), FREQ(:,2))
  MAX=max(FREQ(:,1))
  MIN=min(FREQ(:,1))
  DIST=MAX-MIN
  DIST2=DIST/2
  
  
  printf("Number of Events n * N = %d\n",n*N)
  
  // Show Plot
  
 // clf(), xdel,
 // plot2d(FREQ(:,1), FREQ(:,2))
         
endfunction


//***************************************************
//Function to compute the frequencies of the elements of a population
// and using a fitness function to compute 'virtual' fitness to compare
// the populations with others by fitness. But the function does not make use of these values.
//
// Input:
// l := length of strings
// n := size of population
// N := number of events
// show := if '1' then display the POPX-matrix
//
// Output:
// FX := Vector of freuencies ordered along the decimal values of a string (1st column)
// FXDif := Vector of Differences compared to theoretical expectation in % (2nd column)
// MEAN := The mean value of the differences
// STD := The standard deviation of the differences
//
// Idea: Generate a sequence of populations, count the occurences, and check the degree of agreement between 
// empirical values and theoretica lexpectations

function[FITNESS_ALL_PERC1,DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,FX, POPX]=frequCheck1(l,n,N,show)
  
  
  // Install the counters
  
  r= (2^l)
  c= 3
  
  FX = zeros(r,c)
  FITNESS_ALLLOG1=[]
  
  // Generate an internal index for display
  
  for j=1:r
    FX(j,1)=j-1
    end
  
  // Generate the populations
  
  for i=1:N
  
  [POPX]=popgen(n,l)
  
  
  if show==1 then printf("POPX first\n"), disp(POPX), end
  
  //Compute decimal value ('0' is placed at index '1' !!!)
  // Count occurences 
  
  for j=1:n
    v=POPX(j,:),  
    d = vec2dec(v,l), [POPX(j,l+1)]= d, //decimal values
    FX(d+1,2)=FX(d+1,2)+1, //occurences
    [POPX(j,l+2)]= fitness1(POPX(j,l+1)) //fitness values 
  end//n
  
  [FITNESS_ALL]=fitness(POPX,l)
  FITNESS_ALLLOG1(i)=FITNESS_ALL
  
  if show==1 then printf("POPX second\n"), disp(POPX), end
  
end //N

for j=1:r
  
    FX(j,3)=(FX(j,2)/n)/N //Normal frequency
    FX(j,4)=(FX(j,2)/n)/(((1/2^l)*N)/100) // Frequency as percentage
  end//m 
  
  
  disp(FX)
  
  FREQ1=tabul(FX(:,3))
  MEAN1=mean(FREQ1(:,1)) 
  STD1= stdevf(FREQ1(:,1), FREQ1(:,2))
  FREQ=tabul(FX(:,4))
  MEAN=mean(FREQ(:,1)) 
  STD= stdevf(FREQ(:,1), FREQ(:,2))
  MAX=max(FREQ(:,1))
  MIN=min(FREQ(:,1))
  DIST=MAX-MIN
  DIST2=DIST/2
  
  
  printf("Number of Events n * N = %d\n",n*N)
  
// Compute the maximal value and the percentage of success

[MAXFIT]=maxfit02(l,n)
FITNESS_ALL_PERC1=[]

for i=1:N, FITNESS_ALL_PERC1(i) = FITNESS_ALLLOG1(i)/(MAXFIT/100), end

// Show graphical results

  if show==2 then
     clf(), xdel, 
     plot2d([1:1:N], [FITNESS_ALL_PERC1]),
   end
         
endfunction

//***************************************************
//Function to repeat frequency  checks
//
// Input:
// l := length of strings
// n := size of population
// N := Number of events
// K := how often steps should be applied
//
// Output:
// FX := Vector of freuencies ordered along the decimal values of a string (1st column)
// FREQ := Vector of frequencies and their occurences
// MEAN := The mean value of the differences
// STD := The standard deviation of the difference
// DIST2 := Half distances between MAX and MIN


  function[MEANX, DIST2X, MEAN1X, STD1X,DIST20, MEAN0]=freqCheckRep(l,n,N,K,show)

  
  // Counter for MEANX, DIST2X...
  
  MEAN1X=[]
  STD1X =[]
  
  MEANX=[]
  DIST2X =[]
  
 for j=1:K
     
    [DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,FX, POPX]=frequCheck(l,n,N,show) 
    
    
      MEAN1X(j,1) = MEAN1
      STD1X(j,1) = STD1
      MEANX(j,1) = MEAN
      DIST2X(j,1) = DIST2
          
        end //j
        
        
        MEAN10 = mean(MEAN1X(:,1))
        STD10 = mean(STD1X(:,1))
        MEAN0 = mean(MEANX(:,1))
        DIST20 = mean(DIST2(:,1))
        
        
       
  // Show Plot
  
 // clf(), xdel,
//  plot2d([DIST2SUM(:,1)], [DIST2SUM(:,4)])
         
endfunction


//***************************************************
//Function to repeat frequency  checks with gassimple0()
//
// Input:
// l := length of strings
// n := size of population
// N := Number of events
// K := how often steps should be applied
//
// Output:
// FX := Vector of freuencies ordered along the decimal values of a string (1st column)
// FREQ := Vector of frequencies and their occurences
// MEAN := The mean value of the differences
// STD := The standard deviation of the difference
// DIST2 := Half distances between MAX and MIN


  function[MEANX, DIST2X, MEAN1X, STD1X,DIST20, MEAN0]=freqCheckRep0(POP,l,p,n,N,K, MThreshold,show)

  
  // Counter for MEANX, DIST2X...
  
  MCount = 0
  MEAN1X=[]
  STD1X =[]
  
  MEANX=[]
  DIST2X =[]
  XDIM=[]
  
  for j=1:K
    
    XDIM(j,1)=j*N
    [MCount,DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,POP,FX]=gasimple0(POP,l,p,n,N, j,MThreshold,MCount,show)
    
    
     disp(MCount)
    
      MEAN1X(j,1) = MEAN1
      STD1X(j,1) = STD1
      MEANX(j,1) = MEAN
      DIST2X(j,1) = DIST2
          
        end //j
        
        
        MEAN10 = mean(MEAN1X(:,1))
        STD10 = mean(STD1X(:,1))
        MEAN0 = mean(MEANX(:,1))
        DIST20 = mean(DIST2(:,1))
        
        
       
       // Show Plot
       
  
 if show==2 then clf(), xdel, plot2d([XDIM(:,1)], [DIST2X(:,1)]), end
         
endfunction




//***************************************************
//Function to compute the changing quality of solution sets
//
// Input:
// l := length of strings
// n := size of population
// N := Number of events
// K := how often should be incremented
//
// Output:
// MEAN=:= Mean value of events
// DIST20 := Mean value of 1/2-Distance of events between MAX and MIN
// DIST2X := Series of DIST0s
// MEANX := Series of  MEANOs
// FX := Summary of all values


  function[MDX]=solutionSetApproach(l,n,N,K,show)

  
  // Counter
  
  MDX=zeros(K,6)
  
  for j=1:K
    
    disp(j)
     
    [DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,FX, POPX]=frequCheck(l,n,j*N,show)  
    
        
    MDX(j,1) = j*N
    MDX(j,2) = MEAN
    MDX(j,3) = DIST2
    MDX(j,4) = STD
    MDX(j,5) = MEAN1
    MDX(j,6) = STD1 
    
          
   end //j
        
  // Show Plot
  
  clf(), xdel,
  
  x=[MDX(:,1)], 
  y1=[MDX(:,3)], subplot(3,1,1)
  plot2d(x,y1), xtitle=("DIST2[%]")
  y2=[MDX(:,4)],subplot(3,1,2)
  plot2d(x,y2), xtitle=("STD[%]")
  y3=[MDX(:,6)], subplot(3,1,3)
  plot2d(x,y3), xtitle=("STD")
         
endfunction





//***************************************************
//Function to integrate multiple frequency simulations
//
// Input:
// l := length of strings
// n := size of population
// step := Inrement for number of events
// K := how often steps should be applied
//
// Output:
// DIST2SUM := Summary of distances DIST2 with regard to number of events 


  function[DIST2SUM]=distSum(l,n,step,K,show)

  
  // Counter for DIST2
  
  DIST2SUM=zeros(K,4)
  
 for j=1:K
      disp(j)
    
    [DIST2,STD, MEAN, FREQ,FX, POPX]=frequCheck(l,n,j*step,show) 
    
    
    DIST2SUM(j,1) = j*step
    DIST2SUM(j,2) = MEAN
    DIST2SUM(j,3) = DIST2
    DIST2SUM(j,4) = DIST2SUM(j,3)/(MEAN/100)
    
   end //j

  
  // Show Plot
  
  clf(), xdel,
  plot2d([DIST2SUM(:,1)], [DIST2SUM(:,4)])
         
       endfunction
       
//***************************************************
// Adapt LCS matrices to GA matrices by doubbleing fitness values
// conformFit()
//
// Idea:
// The GA-pop matrices have a fitness value at l+2 based on l+1.
// The LCS-pop matrices have their fitness values at l+1
//
// l := length of fitness strings before fitness

function[CLASSIF,l]=conformFit(CLASSIF)
  
  [r,c]=size(CLASSIF);
  l=c-2
  
  // Take every row and compute the fitness as copy of fitness
  
for j=1:r
  CLASSIF(j,l+2)=CLASSIF(j,l+1)
end

endfunction

//***************************************************
//Function to compute the overall fitness of a matrix POP
// Sum up all the l+2-th positions
// l := length of fitness strings

function[FITNESS_ALL]=fitness(POP,l)
  
 FITNESS_ALL=0;
[r,c]=size(POP);
for j=1:r
  FITNESS_ALL=FITNESS_ALL+POP(j,l+2)
end

endfunction



//***************************************************
//Function to compute the maximal individual fitness of a matrix POP
// Compute all the l+2-th positions
// l := length of fitness strings

function[MFITNESS]=maxfitness(POP,l)
  
  // Extracts column l+2 and selects the maximal values
  
MFITNESS = max(POP([:],l+2))

endfunction


//***************************************************
//Function to compute the relative fitness of a string
// along with the average fitness 
// Compute all the l+3-th positions
// l := length of fitness strings

function[POP,AFITNESS]=rfitness(POP,l, FITNESS_ALL)

[r,c]=size(POP);

for j=1:r, 
  if POP(j,l+2)==0 then POP(j,l+2)=POP(j,l+2)+0.0001, end
  
  POP(j,l+3)=POP(j,l+2)/FITNESS_ALL
end

AFITNESS=FITNESS_ALL/r

endfunction


//***************************************************
//Function to compute the fitness ratio r=f1/f0
//
// l := length of fitness strings
// f1 := fitness of all individuals with a allele value '1' at a position
// f0 := fitness of all individuals with a allele value '0' at a position 
// r = f1/f0
//
// Assumption: POP has the relativ fitness available at l+3


function[POP,ratio,f1,f0]=fratio10(POP,l,show)

[r,c]=size(POP);
f1=0;
f0=0;

for i=1:r
  for j=1:l
    if (POP(i,j)== 1) then f1=f1+POP(i,l+3),
    else f0=f0+POP(i,l+3)
    end
    end //j
end//i

ratio=f1/f0

if show == 2 then disp(POP),  disp(f1), disp(f0), disp(ratio), end

endfunction

//*************************************************************
// Computing the worst case convergence time tcw
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)
// POP := a predefined population (can be done automatically)
// 
// f1 := fitness of all individuals with a allele value '1' at a position
// f0 := fitness of all individuals with a allele value '0' at a position 
// r = f1/f0
// tcw := worst case convergence time
//
// Assumption: POP has the relativ fitness available at l+3



function[POP,tcw,tcabin,ratio,f1,f0]=ftcw(POP,l,p,n,show)
  
  for i=1:n, v=POP(i,:),  
    d= vec2dec(v,l),  //decimal value
    [POP(i,l+1)]= d,  //decimal value
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
  
  [FITNESS_ALL]=fitness(POP,l)
  
  [MFITNESS]=maxfitness(POP,l)
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
  [POP,ratio,f1,f0]=fratio10(POP,l,show)
  
  tcw = log((n-1)^2)/log(ratio)
  tcabin = log(n-1)/log(ratio)
  
endfunction




//***************************************************
//Function to compute the relative count of a string
// along with the realized new count by 'rounding up' 
// Compute all the l+4 and l+5-th positions
//
// Problem: if the sum of the new proposals is  bigger than n
// Solution: 
// l := length of fitness strings
// n :=  number of individuals in POP


function[POP]=newMember(POP,l,n)

[r,c]=size(POP);

for j=1:r
  POP(j,l+4)=POP(j,l+3)*n
  POP(j,l+5)=round(POP(j,l+4))
end

//Check for sum of proposals

r2 = 0
for j=1:r, r2=r2+POP(j,l+5), end

while r2>n
  z=round(rand()*r)
  if z==0 then z=1,end //if
  POP(z,l+5) = POP(z,l+5)-1
  r2=0, for j=1:r, r2=r2+POP(j,l+5), end//for
  end//while r2

endfunction



//***************************************************
// Dummy function to replace newMember in simplegas0
//
// along with the realized new count by 'rounding up' 
// Compute all the l+4 and l+5-th positions
// l := length of fitness strings
// n :=  number of individuals in POP

function[POP]=newMember0(POP,l,n)

[r,c]=size(POP);

for j=1:r
  POP(j,l+4)=1
  POP(j,l+5)=1
end


endfunction

//***************************************************
// Make a copy of a string from row_old to row_new: L --> R
// where the copy starts at position l+p+1
// l := length of string
// j := row_old
// k := row_new
// p := number of parameters (P=5)

function[POP]=strcpyLR(POP,l,p,j,k)
  
  show=0
[r,c]=size(POP);

// Testing the boundaries

if (j < 1) then if show == 1 then printf('ERROR: Position of old String outside of Matrix! r = %d, j = %d', r,j),end, j=1,
  elseif  (j > r) then  if show == 1 then printf('ERROR: Position of old String outside of Matrix!, r = %d, j = %d', r,j),end, j=r,
  elseif (k < 1) then  if show == 1 then printf('ERROR: Position of new String outside of Matrix!, r = %d, k = %d', r,k),end, k=1
  elseif (k > r) then if show == 1 then  printf('ERROR: Position of new String outside of Matrix!, r = %d, k = %d', r,k), end, k=r
  end
  
  // Making a copy
  
for i=1:l
    POP(k,l+p+i) = POP(j,i)
    end

endfunction

//***************************************************
// Make a copy of a string from row_old to row_new: R --> L
// where the copy starts at position l+p+1
// l := length of string
// j := row_old
// k := row_new
// p := number of parameters (p=5)

function[POP]=strcpyRL(POP,l,p,j,k)
  
  show=0
[r,c]=size(POP);

// Testing the boundaries

if (j < 1) then if show == 1 then  printf('ERROR: Position of old String outside of Matrix! r = %d, j = %d', r,j),end, j=1
  elseif  (j > r) then if show == 1 then  printf('ERROR: Position of old String outside of Matrix!, r = %d, j = %d', r,j),end, j=r
  elseif (k < 1) then  if show == 1 then printf('ERROR: Position of new String outside of Matrix!, r = %d, k = %d', r,k), end, k=1
  elseif (k > r) then if show == 1 then  printf('ERROR: Position of new String outside of Matrix!, r = %d, k = %d', r,k),end, k=r
  end
  
  // Making a copy
  
for i=1:l
    POP(j,i) = POP(k,l+p+i)
    end

endfunction

//***************************************************
// Make a copy of all strings from the old rows to the new ones
// where the new copies will start at position l+p+1
// l := length of string
// j := row_old
// k := row_new
// p := number of parameters
// r2 := memory of position for new strings

function[POP]= newPop(POP,l,p,n)

[r,c]=size(POP);
r2 = 1
  
  for j=1:r
    
    if POP(j,l+p) > 0 then r3 = POP(j,l+p)-1,
      
      for k=r2:(r2+r3)
        [POP]=strcpyLR(POP,l,p,j,k)
      end
      
      r2=k+1
      
      end
    end

endfunction

//***************************************************
// Make a copy of all strings from the old rows to the new ones
// where the new copies will start at position l+p+1
//
// Problem: If the sum of new copies is greater than n then this causes a fault!
// Solution: At least check the sum before operation
//
// l := length of string
// j := row_old
// k := row_new
// p := number of parameters
// r2 := memory of position for new strings

function[POP]= newPop2(POP,l,p,n)

[r,c]=size(POP);

//Check for sum of proposals

r2 = 0

for j=1:r, r2=r2+POP(j,l+5), end

if r2 >n then error('In newPop2() sum of proposals >n!!!'),end
  
  
r2 = 1
  
for j=1:r
    
    if POP(j,l+5) > 0 then r3 = POP(j,l+5)-1,
      
      for k=r2:(r2+r3), //printf('\n k = %d\n', k)
        [POP]=strcpyLR(POP,l,p,j,k)
      end
      
      r2=k+1
      
      end
    end

endfunction


//***************************************************
// Prepare the crossover operations within a population POP 
// by randomly selecting the new strings and copy them onto the 
// POP base area  [1,l] 
//
// General Assumption: the number of members n is even!!!
//
// The strings are assumed to be in the area starting at l+p+1
// The parameter at l+p has been changed to a flag '1' := not yet mated
// j := target position in the base area for copy action


function[POP]= crossoverPrep(POP,l,p,n)

[r,c]=size(POP);

// Set a flag at position l+7 with '1'
  
  for j=1:r
     POP(j,l+7)=1
   end
   
// Select randomly the strings for transfer   

   j = 1 //:= Baseline for filling up with strings
   
 while(j < n+1)
   
   S = 1 //:= Flag for searching a string to be copied
   
   while(S == 1)
         
         k1 = round(n * rand())
         if k1==0 then k1=1
         end //if
   
   if POP(k1,l+7) <> 0 then POP=strcpyRL(POP,l,p,j,k1)
     //mshow(POP,n,l+p+l)
     POP(k1,l+7) = 0,
      S=0
    else S=1
    end //if
    
   end //while == S
    
       //      printf('k1 = %d\n',k1)
       //   printf('j = %d\n',j)
       
       j = j+1
       
   // mshow(POP,n,l+p+l)
 
 end // while == j 
   
    
endfunction

//***************************************************
// Apply a crossover operation onto two adjacent strings at intersection x
// The strings are assumed to be randomly paired in the area at position 1
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)

function[POP]= crossover(POP,l,p,n)
  
  // Take a first row
  r=1 
  while(r < n)
    
   // printf('r = %d\n',j)
   
   // Select randomly a point in this row
   
   x = round(l * rand()), if(x == 0) then x=1,end,
   
        // printf('x = %d\n',x)
         
         for i=x:l, m=POP(r+1,i)
           POP(r+1,i) = POP(r,i)
           POP(r,i) = m
         end
         
         r=r+2
    end

endfunction


//***************************************************
// Apply a mutation operation onto one randomly selected string 
// Select randomly a point in the string and replace it's
// value by it's inverse '1' --> '0', '0' --> '1'

function[POP]= mutation(POP,l,p,n)
  
  // Find a point in a string
  
     c = round(l * rand())
         if c == 0 then c=1  // This does not change anything
         end
         
 // Find a row in the table
         
     r = round(n * rand())
         if r == 0 then r=1  // This does not change anything
         end
         
 // replace the value
         
         if(POP(r,c) == 1) then POP(r,c) = 0,
         else POP(r,c) = 1
           end
           
 printf('mutation point at row = %d col = %d\n',r,c)         

endfunction

//***************************************************
// Print the content of a matrix
//
// d := depth of matrix 'downwards'
// w := width of  matrix from left to right



function[M]= mshow(M,d,w)
  
  for j=1:d,// printf('\n j= %3.1d : ',j)
    for i=1:w, //printf(' %3.1d ',M(j,i)) 
      end
      //printf('\n')
    end

endfunction

//***************************************************
// Translate strings with binaries '0', '1' as decimal numbers
//
// v = vector of binaries from a POP-matrix (left part)
// l := length of string
// D := decimal computed out of binaries


function[D]= vec2dec(v,l)
  
  str=string(v(1:l))
  for i=2:l, str(1)=str(1)+str(i)
  end
  D=bin2dec(str(1))
  
endfunction

//***************************************************
// Translate strings with binaries '0', '1' as decimal numbers
//
// v = vector of binaries from a POP-matrix (left part)
// l := length of string
// D := decimal computed out of binaries


function[D]= vec22dec(v,l1,l2)
  
  
  str=string(v(l1:l2))
  for i=2:l2-l1+1, str(1)=str(1)+str(i)
  end
  D=bin2dec(str(1))
  
endfunction

//***************************************************
// Translate strings with binaries '0', '1' and n-many compartments as decimal numbers
//
// v = vector of binaries from a POP-matrix (left part)
// l := length of string
// b := number of bins for one number
// D := Array of decimals


function[D]= vec222dec(v,l,b,show)
  
  D=[]
  k=1
  
  for j=1:b:l+1-b
    if show==1 then printf('j = %d ',j),end
      
  str=string(v(j:j+b-1))
  for i=2:b, str(1)=str(1)+str(i)
  end //i
  
  if show==1 then printf('k = %d ',k),end
  
  D(k)=bin2dec(str(1))
  
  
  if show==1 then printf('D(k) = %d\n',D(k)),end
  
  k=k+1
  
  end //j
  
endfunction

//***************************************************
// maxfit01 builds a string of length l and computes the decimal value
//
// l := length of string
// MF := decimal computed out of binaries


function[MF]= maxfit01(l)
  
  FitString=""
  v=ones(1,l)
  str=string(v)
  for i=1:l, FitString = FitString + str(i)
  end
  MF=bin2dec(FitString)
  
endfunction

//***************************************************
// maxfi02 computes with maxfit01 the decimal value of a string with length l and
// then compares the maximal value according to the fitness function y=x^2 
// multiplied by the number n of strings in a population 
//
// l := length of string
// MF := decimal computed out of binaries


function[MAXFIT]= maxfit02(l,n)
  
  MAXFIT=n*(maxfit01(l)^2)
  
endfunction

//***************************************************
// Simple fitness-function f=(x^2)
//
// D := decimal computed out of binaries


function[F]= fitness1(D)
  
  F=D^2
  
endfunction

//***************************************************
// Fitness-function f for a world W which is realized as a table t:D --> R
// IF (d,r) in t then f(d1,d2)=100, ELSE f(d1,d2)=0
//
// d1,d2 := decimal values of population POP
// W := a world organized as a table
// n := number of elements in W
// F := fitness value


function[F]= fitness2(d1,d2,W)
  
  [r,c]=size(W)
  upper =10
  goal = upper*2
  
  i=1
  while i < r+1, 
    if W(i,1) == d1 & W(i,2) == d2 then F=goal, i=r+1,
    else F=round(upper * rand()), i=i+1,
    end //if
    end//while
  
endfunction

//***************************************************
// Fitness-function f for a world W which is realized as a table t:D --> R
// IF (d,r) in t then f(d1,d2)=goal, ELSE f(d1,d2)=random(upper)
//
// D := Array of pairs of decimal values
// W := a world organized as a table
// F := fitness value


function[F,goal]= fitness3(D,W)
  
  [r,c]=size(W)
  [r2,c2]=size(D)
  F2=[]
  
  upper =10  // range of numbers for non-goals [0,upper]
  goal = upper*2  
  
  j=1 //Index for D
  for i=1:r //Look to every pair in W
    if W(i,1) == D(j) & W(i,2) == D(j+1) then F2(i)=goal,
    else F2(i)=round(upper * rand()),
    end //if
  j=j+2
end // for i

F=sum(F2)
  
endfunction


//*************************************************************
// Function to compute only the fitness of a population
//
// Input:
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings
// n := number of elements in POP
// Output
// POP := a population
// MFITNESS := Maximal Fitness of each individual

function[POP,MFITNESS, FITNESS_ALL]=popFit(l,p,n)
  
  [POP]=popgen(n,l+p)
  
  MFITNESS=0
 
  
  for j=1:n, v=POP(j,:),  [POP(j,l+1)]= vec2dec(v,l)
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
  
  [FITNESS_ALL]=fitness(POP,l)
  
  [MFITNESS]=maxfitness(POP,l)
  
endfunction


//*************************************************************
// Function to compute  the maximal fitness of an individuum 
// for several populations
//
// Input:
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings
// n := number of elements in POP
// run := number of choices
// Output
// POP := a population
// MFITNESS := Maximal Fitness of each individual
// MFITNESSX := Array with maximal fitness

function[POP,MEAN, MFITNESSX]=popFitX(l,p,n,run)
  
  MAXFITUP = ((2^l)^2)
  
  for k=1:run
      [POP]=popgen(n,l+p)
  
  for j=1:n, v=POP(j,:),  [POP(j,l+1)]= vec2dec(v,l)
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
  
  [MFITNESSX(k)]=maxfitness(POP,l)
  
end

for k=1:run
  MFITNESSX(k)=MFITNESSX(k)/(MAXFITUP/100)
end
MEAN = mean(MFITNESSX)

// Show graphical results

//clf(), xdel, 

//plot2d([1:1:run], MFITNESSX)
  
endfunction



//*************************************************************
// Function to compute  the maximal fitness of an individuum 
// for several populations
// for increasing n
//
// Input:
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings
// n := number of elements in POP
// run := number of choices
// Output
// POP := a population
// MFITNESS := Maximal Fitness of each individual
// MFITNESSX := Array with maximal fitness

function[MEAN, MEANX]=popFitXN(l,p,m,run)
  
  for i=1:m
    
  [POP,MEAN, MFITNESSX]=popFitX(l,p,i,run)
  
  MEANX(i) = MEAN
  
end

MEAN = mean(MEANX)

// Show graphical results

clf(), xdel, 

plot2d([1:1:m], MEANX)
  
endfunction


//*************************************************************
// Function to compute  the maximal fitness of a population 
// for several generations
//
// Input:
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings
// n := number of elements in POP
// run := number of generations
// Output
// POP := a population
// FITNESS_ALL := Maximal Fitness of a population
// FITNESS_ALLX := Array with maximal fitness
// MEAN := Mean value of array

function[STD,MEAN, FITNESS_ALLX]=popMaxFitX(l,p,n,run)
  
  MAXFITUP = ((2^l)^2)*n
  
  for k=1:run
      [POP]=popgen(n,l+p)
  
  for j=1:n, v=POP(j,:),  [POP(j,l+1)]= vec2dec(v,l)
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
 
  [FITNESS_ALLX(k)]=fitness(POP,l)
  
   end

for k=1:run
  FITNESS_ALLX(k)=FITNESS_ALLX(k)/(MAXFITUP/100)
end
MEAN = mean(FITNESS_ALLX)
mf=tabul(FITNESS_ALLX)
STD=stdevf(mf([:],1), mf([:],2))

// Show graphical results

//clf(), xdel, 

//plot2d([1:1:run], MFITNESSX)
  
endfunction



//*************************************************************
// All Functions Unified
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)
// POP := a predefined population (can be done automatically)
// run := number of cycles
// MThreshold := number of cycles which have to be waited until the mutation operators will be applied

function[POP,FITNESS_ALLLOG]=gasimple(POP,l,p,n,run, MThreshold)
  
  MCount = 0 
  
  FITNESS_ALLLOG=[]
  
for cyc = 1:run  
  
  [M]= mshow(POP,n,l+p)
  
  for j=1:n, v=POP(j,:),  [POP(j,l+1)]= vec2dec(v,l)
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
  
  [FITNESS_ALL]=fitness(POP,l)
  FITNESS_ALLLOG(cyc)=FITNESS_ALL
  
  [MFITNESS]=maxfitness(POP,l)
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
  [POP]=newMember(POP,l,n)
  [POP]=newPop(POP,l,p,n)
  [POP]= crossoverPrep(POP,l,p,n)
  [POP]= crossover(POP,l,p,n)
  
  printf('Mutationcount = %d\n', MCount)
  
  if(MCount > MThreshold) then [M]= mshow(POP,n,l+p), 
    [POP]= mutation(POP,l,p,n), 
    [M]= mshow(POP,n,l+p), 
    MCount=0,
  end
  
  MCount = MCount + 1
  
end //for == run

// Compute the maximal value and the percentage of success

[MAXFIT]=maxfit02(l,n)
FITNESS_ALL_PERC=[]

for i=1:run, FITNESS_ALL_PERC(i) = FITNESS_ALLLOG(i)/(MAXFIT/100), end

// Show graphical results

clf(), xdel, 
//plot2d([1:1:run], FITNESS_ALLLOG) 
plot2d([1:1:run], FITNESS_ALL_PERC) 



endfunction

//*************************************************************
// A system with GA without any additional parameters
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)
// POP := a predefined population (can be done automatically)
// N := number of cycles
// MThreshold := number of cycles which have to be waited until the mutation operators will be applied

function[FITNESS_ALL_PERC,POP]=ga(POP,l,p,n,N, MThreshold,show)
  
  MCount = 0
  FITNESS_ALLLOG=[]
  
for cyc = 1:N 
  
  for j=1:n, v=POP(j,:),  
    d= vec2dec(v,l),  //decimal value
    [POP(j,l+1)]= d,  //decimal value
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
  
  [FITNESS_ALL]=fitness(POP,l)
  FITNESS_ALLLOG(cyc)=FITNESS_ALL
  
  [MFITNESS]=maxfitness(POP,l)
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
  [POP]=newMember(POP,l,n)
  [POP]=newPop(POP,l,p,n)
  [POP]= crossoverPrep(POP,l,p,n)
  [POP]= crossover(POP,l,p,n)
  
  if show==1 then
    printf('Mutationcount = %d\n', MCount),
    end
    
  
  if(MCount > MThreshold) then 
    [POP]= mutation(POP,l,p,n), 
     if show==1 then  disp(POP),  end
      MCount=0,
  end
  
  MCount = MCount + 1
  
end //for == N
  
  printf("Number of Events n * N = %d\n",n*N)
  
  // Compute the maximal value and the percentage of success 

[MAXFIT]=maxfit02(l,n)
FITNESS_ALL_PERC=[]

for i=1:N, FITNESS_ALL_PERC(i) = FITNESS_ALLLOG(i)/(MAXFIT/100), end

// Show graphical results

if show==2 then
clf(), xdel,  
plot2d([1:1:N], FITNESS_ALL_PERC),
end


endfunction



//*************************************************************
// A system with GA
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)
// POP := a predefined population (can be done automatically)
// N := number of cycles
// MThreshold := number of cycles which have to be waited until the mutation operators will be applied

function[FITNESS_ALL_PERC,DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,FX, POP]=ga0(POP,l,p,n,N, MThreshold,show)
  
 // Install the counters
  
  r= (2^l)
  c= 6
  
  FX = zeros(r,c)
  MCount = 0 
  FITNESS_ALLLOG=[]
  
   // Generate an internal index for display
  
  for j=1:r
    FX(j,1)=j-1
    end
 
  
for cyc = 1:N 
  
  for j=1:n, v=POP(j,:),  
    d= vec2dec(v,l),  //decimal value
    [POP(j,l+1)]= d,  //decimal value
    FX(d+1,2)=FX(d+1,2)+1, //occurences
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
  
  [FITNESS_ALL]=fitness(POP,l)
  FITNESS_ALLLOG(cyc)=FITNESS_ALL
  
  [MFITNESS]=maxfitness(POP,l)
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
  [POP]=newMember(POP,l,n)
  [POP]=newPop(POP,l,p,n)
  [POP]= crossoverPrep(POP,l,p,n)
  [POP]= crossover(POP,l,p,n)
  
  if show==1 then
    printf('Mutationcount = %d\n', MCount),
    end
    
  
  if(MCount > MThreshold) then 
    [POP]= mutation(POP,l,p,n), 
     if show==1 then  disp(POP),  end
      MCount=0,
  end
  
  MCount = MCount + 1
  
end //for == N

for j=1:r
  
    FX(j,3)=(FX(j,2)/n)/N //Normal frequency
    FX(j,4)=(FX(j,2)/n)/(((1/2^l)*N)/100) // Frequency as percentage
  end//m 

  
  disp(FX)
  
  FREQ1=tabul(FX(:,3))
  MEAN1=mean(FREQ1(:,1)) 
  STD1= stdevf(FREQ1(:,1), FREQ1(:,2))
  FREQ=tabul(FX(:,4))
  MEAN=mean(FREQ(:,1)) 
  STD= stdevf(FREQ(:,1), FREQ(:,2))
  MAX=max(FREQ(:,1))
  MIN=min(FREQ(:,1))
  DIST=MAX-MIN
  DIST2=DIST/2
  
  
  printf("Number of Events n * N = %d\n",n*N)
// Compute the maximal value and the percentage of success

[MAXFIT]=maxfit02(l,n)
FITNESS_ALL_PERC=[]

for i=1:N, FITNESS_ALL_PERC(i) = FITNESS_ALLLOG(i)/(MAXFIT/100), end

// Show graphical results

if show==2 then
clf(), xdel,  
plot2d([1:1:N], FITNESS_ALL_PERC),
end



endfunction



//*************************************************************
// GA algorithm without fitness
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)
// POP := a predefined population (can be done automatically)
// N := number of events
// K := Number of repetitions from calling function
// MThreshold := number of events which have to be waited until the mutation operators will be applied

function[MCount,DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,POP,FX]=gasimple0(POP,l,p,n,N, K,MThreshold,MCount,show)
  
  
   // Install the counters
  
  r= (2^l)
  c= 5
 
  
  FX = zeros(r,c)
  
  // Generate an internal index for display
  
  for j=1:r
    FX(j,1)=j-1
  end
  
 
  
  for cyc = 1:N*K //Start Cyle for events
    

    if show ==1 then  disp(cyc), end
    
      for j=1:n
    v=POP(j,:),  d = vec2dec(v,l), [POP(j,l+1)]= d, FX(d+1,2)=FX(d+1,2)+1 
  end//n
  
   if show ==1 then  printf("\nFX after Count\n\n"), disp(FX), end
    
  [POP]=newMember0(POP,l,n) //Prepares copies by inserting '1' at position l+4 and l+5
  [POP]=newPop(POP,l,p,n) //Copies old strings to the right
  [POP]= crossoverPrep(POP,l,p,n)
  [POP]= crossover(POP,l,p,n)
  
 if show ==1 then printf('Mutationcount = %d\n', MCount),disp(POP), end
  
  if(MCount > MThreshold) then   [POP]= mutation(POP,l,p,n), 
    
    if show ==2 then printf('Mutationcount (MCount, cyc)= (%d,%d)\n', MCount, cyc), end
    
    MCount = 0, end
  
  MCount = MCount + 1
  
  if show==1 then printf("POP after Operators\n"), disp(POP), end
 
  
end //cyc=N

for j=1:r
  
    FX(j,3)=(FX(j,2)/n)/(N*K) //Normal frequency
    FX(j,4)=(FX(j,2)/n)/(((1/2^l)*(N*K))/100) // Frequency as percentage
  end//m 
  
  
  disp(FX)
  
  FREQ1=tabul(FX(:,3))
  MEAN1=mean(FREQ1(:,1)) 
  STD1= stdevf(FREQ1(:,1), FREQ1(:,2))
  FREQ=tabul(FX(:,4))
  MEAN=mean(FREQ(:,1)) 
  STD= stdevf(FREQ(:,1), FREQ(:,2))
  MAX=max(FREQ(:,1))
  MIN=min(FREQ(:,1))
  DIST=MAX-MIN
  DIST2=DIST/2
  
  
  printf("Number of Events n * N * K = %d\n",n*N*K)
  
endfunction
  

//*************************************************************
// GA algorithm with fitness and conditioned mutation
//
// Works like 'normal' GA but uses mutation only if the actual maximal fitness
// stays 'constant' over MT-many cycles and is below te theoretical maximum
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)
// POP := a predefined population (can be done automatically)
// N := number of events
// MT := mutation trigger; number of values to monitor for to trigger mutation

function[FITNESS_ALL_PERC,DIST2,STD, MEAN, FREQ,STD1, MEAN1, FREQ1,FX, POP]=ga1(POP,l,p,n,N, MT,show)
  
  
  //Theoretical Maximum for Fitness according to y=x^2
  
  TMaxFit = ((2^l)-1)^2*n
  
 // Install the counters
  
  r= (2^l)
  c= 6
  
  FX = zeros(r,c)

  MCount = 0 
  FITNESS_ALLLOG=[]
  MTriggerEstimator=[]
  
   // Generate an internal index for display
  
  for j=1:r
    FX(j,1)=j-1
    end
 
  
for cyc = 1:N 
  
  for j=1:n, v=POP(j,:),  
    d= vec2dec(v,l),  //decimal value
    [POP(j,l+1)]= d,  //decimal value
    FX(d+1,2)=FX(d+1,2)+1, //occurences
  end
  
  for i=1:n,[POP(i,l+2)]= fitness1(POP(i,l+1))
  end
  
  [FITNESS_ALL]=fitness(POP,l)
  FITNESS_ALLLOG(cyc)=FITNESS_ALL
  
  [MFITNESS]=maxfitness(POP,l)
  
  if show ==1 then disp(FITNESS_ALL), end
    
    MTriggerEstimator(cyc)=FITNESS_ALL
    
    
  if show ==1 then disp(MTriggerEstimator(cyc)), end
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
  [POP]=newMember(POP,l,n)
  [POP]=newPop(POP,l,p,n)
  [POP]= crossoverPrep(POP,l,p,n)
  [POP]= crossover(POP,l,p,n)
  
   if show ==1 then disp(MCount),   end
    
  
  if(MCount > MT) then 
    
     if show ==1 then disp(MTriggerEstimator(cyc)), disp(MTriggerEstimator(cyc-MT)), disp(TMaxFit), end
    if (MTriggerEstimator(cyc) == MTriggerEstimator(cyc-MT) & MTriggerEstimator(cyc) < TMaxFit) then [POP]= mutation(POP,l,p,n), 
      if show==1 then  disp(POP),  end
      end
      MCount=0,
  end
  
  MCount = MCount + 1
  
end //for == N

for j=1:r
  
    FX(j,3)=(FX(j,2)/n)/N //Normal frequency
    FX(j,4)=(FX(j,2)/n)/(((1/2^l)*N)/100) // Frequency as percentage
  end//m 

  
  disp(FX)
  
  FREQ1=tabul(FX(:,3))
  MEAN1=mean(FREQ1(:,1)) 
  STD1= stdevf(FREQ1(:,1), FREQ1(:,2))
  FREQ=tabul(FX(:,4))
  MEAN=mean(FREQ(:,1)) 
  STD= stdevf(FREQ(:,1), FREQ(:,2))
  MAX=max(FREQ(:,1))
  MIN=min(FREQ(:,1))
  DIST=MAX-MIN
  DIST2=DIST/2
  
  
  printf("Number of Events n * N = %d\n",n*N)
// Compute the maximal value and the percentage of success

[MAXFIT]=maxfit02(l,n)
FITNESS_ALL_PERC=[]

for i=1:N, FITNESS_ALL_PERC(i) = FITNESS_ALLLOG(i)/(MAXFIT/100), end

// Show graphical results

if show==2 then
clf(), xdel,  
plot2d([1:1:N], FITNESS_ALL_PERC),
end



endfunction

//*************************************************************
// A system with GA for a world with a table
//
// A world W organized as a table  maps a set D into a set R
// l := length of strings
// p := number of cells between string <1...l> and <l+p+1, ..., l+p+l>
// Pos 1-l := String
// Pos l+1 := Decimal Value of binary string
// Pos l+2 := Fitness for l+1 and l+p
// Pos l+3 := Percentage of overall fitness
// Pos l+4 := Expected count according to fitness
// Pos l+5 := Realized count
// Pos l+6 := 2nd Decimal value of a compund fitness
// Pos l+p := flag for crossover
// p := 7
// POP := a predefined population (can be done automatically)
// n := number of elements in POP
// N := number of cycles
// MT := number of cycles which have to be waited until the mutation operators will be applied

function[FITNESS_ALL_PERC,POP]=gaw1(W,POP,l,p,n,N, MT,l1,show)
  
  MCount = 0
  FITNESS_ALLLOG=[]
  
  for cyc = 1:N 
    
   if show == 1 then disp('cyc ='),disp(cyc),disp(' '),end
  
  for j=1:n, v=POP(j,:),  
    d1= vec22dec(v,1,l1),  //decimal value1
    d2= vec22dec(v,l1+1,l),  //decimal value2
    [POP(j,l+1)]= d1,  //decimal value 
    [POP(j,l+6)]= d2,  //decimal value 
  end
  
  
  if show == 1 then printf('New Numbers in POP '), disp(POP), end
  
  for i=1:n,[POP(i,l+2)]= fitness2(POP(i,l+1),POP(i,l+6),W)
  end
  
  
  [FITNESS_ALL]=fitness(POP,l)
  
  if show == 1 then printf('FITNESS_ALL = %f\n',FITNESS_ALL), end
  
  FITNESS_ALLLOG(cyc)=FITNESS_ALL
  
  [MFITNESS]=maxfitness(POP,l)
  
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
  if show == 1 then disp(POP), end
  
  [POP]=newMember(POP,l,n)
  [POP]=newPop2(POP,l,p,n)
  
  if show == 1 then disp(POP), end
  
  [POP]= crossoverPrep(POP,l,p,n)
  [POP]= crossover(POP,l,p,n)
  
    if show == 1 then disp(POP),printf('MCount = %d\n',MCount), end

  if(MCount > MT) then 
    [POP]= mutation(POP,l,p,n), printf('Mutation at cycle = %d\n',cyc),
     if show==1 then  disp(POP),  end
      MCount=0,
  end
  
  MCount = MCount + 1
  
end //for == N
  
  printf("Number of Events n * N = %d\n",n*N)
  
  // Compute the maximal value and the percentage of success 
  
MAXFIT=20*n   //The value '20' is set in the function fitness2()
FITNESS_ALL_PERC=[]

for i=1:N, FITNESS_ALL_PERC(i) = FITNESS_ALLLOG(i)/(MAXFIT/100), end

// Show graphical results

if show==2 | show == 1 then
clf(), xdel,  
plot2d([1:1:N], FITNESS_ALL_PERC),
end


endfunction


//*************************************************************
// A system with GA for a world with a table
//
// A world W organized as a table  maps a set D into a set R
// l := length of strings
// p := number of cells between string <1...l> and <l+p+1, ..., l+p+l>
// Pos 1-l := String
// Pos l+1 := Decimal Value of binary string
// Pos l+2 := Fitness for l+1 and l+p
// Pos l+3 := Percentage of overall fitness
// Pos l+4 := Expected count according to fitness
// Pos l+5 := Realized count
// Pos l+6 := 2nd Decimal value of a compund fitness
// Pos l+7 := flag for crossover
// p := 7
// POP := a predefined population (can be done automatically)
// n := number of elements in POP
// N := number of cycles
// MT := number of cycles which have to be waited until the mutation operators will be applied
// b := number of bins for one number
// V := version

function[FITNESS_ALL_PERC,MAXGENOMECOUNT,POP,V]=gaw2(W,POP,l,n,N, MT,b,show,V)
  
  p = 7
  MCount = 0
  FITNESS_ALLLOG=[]
  
  for cyc = 1:N 
    
   if show == 1 then disp('cyc ='),disp(cyc),disp(' '),end

    
  for i=1:n , v=POP(i,:), [D]= vec222dec(v,l,b,show),  [POP(i,l+2),goal]= fitness3(D,W),  end //for i
  
  if show == 1 then printf('New Numbers in POP '), disp(POP), end
  
  
  [FITNESS_ALL]=fitness(POP,l)
  
  if show == 1 then printf('FITNESS_ALL = %f\n',FITNESS_ALL), end
  
  FITNESS_ALLLOG(cyc)=FITNESS_ALL
  
  [MFITNESS]=maxfitness(POP,l)
  
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
 // if show == 1 then disp(POP), end
  
  [POP]=newMember(POP,l,n)
  
  if show == 1 then disp(POP), end  
  
  [POP]=newPop2(POP,l,p,n)
  
  if show == 1 then disp(POP), end
  
  [POP]= crossoverPrep(POP,l,p,n)
  [POP]= crossover(POP,l,p,n)
  
    if show == 1 then disp(POP),printf('MCount = %d\n',MCount), end

  if(MCount > MT) then 
    [POP]= mutation(POP,l,p,n), printf('Mutation at cycle = %d\n',cyc),
     if show==1 then  disp(POP),  end
      MCount=0,
  end
  
  MCount = MCount + 1
  
end //for == N
  
  printf("Number of Events n * N = %d\n",n*N)
  
  // Compute the maximal value and the percentage of success 
  
  [r,c]=size(POP)
  [r2,c2]=size(W)
  
  MAXFIT=goal*r2*r //The value 'goal' is set in the function fitness3()
  MAXFITGENOME = goal*r2  // To count the complete genomes in a population
FITNESS_ALL_PERC=[]

MAXGENOMECOUNT = 0
for i=1:r, 
  if POP(i,l+2) == MAXFITGENOME then MAXGENOMECOUNT =MAXGENOMECOUNT+1, end,
  end
for i=1:N, FITNESS_ALL_PERC(i,1)=i, FITNESS_ALL_PERC(i,2) = FITNESS_ALLLOG(i)/(MAXFIT/100), end

// Show graphical results

if show==2 | show == 1 then
  clf(), xdel, 
  scf(V), 
plot2d([1:1:N], FITNESS_ALL_PERC(:,2)),
end


endfunction



//*************************************************************
// Computing the worst case convergence time tcw
//
// p := number of parameters between strings left and right (actually  p=5)
// l := length of strings ( actually l=5)
// n := number of elements in POP (actually n=4)
// POP := a predefined population (can be done automatically)
// 
// f1 := fitness of all individuals with a allele value '1' at a position
// f0 := fitness of all individuals with a allele value '0' at a position 
// r = f1/f0
// tcw := worst case convergence time
//
// Assumption: POP has the relativ fitness available at l+3



function[POP,tcw,tcabin,ratio,f1,f0]=ftcw2(W,POP,l,p,n,l1,show)
  
  
   for j=1:n, v=POP(j,:),  
    d1= vec22dec(v,1,l1),  //decimal value1
    d2= vec22dec(v,l1+1,l),  //decimal value2
    [POP(j,l+1)]= d1,  //decimal value 
    [POP(j,l+6)]= d2,  //decimal value 
  end
  
  for i=1:n,[POP(i,l+2)]= fitness2(POP(i,l+1),POP(i,l+6),W)
  end
  
  [FITNESS_ALL]=fitness(POP,l)
  
  [MFITNESS]=maxfitness(POP,l)
  
  [POP,AFITNESS]=rfitness(POP,l,FITNESS_ALL)
  
  [POP,ratio,f1,f0]=fratio10(POP,l,show)
  
  tcw = log((n-1)^2)/log(ratio)
  tcabin = log(n-1)/log(ratio)
  
endfunction




//***********************************************************************
// Examples
//
POP = [0 1 1 0 1 13 169 0 0 0; 1 1 0 0 0 24 576 0 0 0; 0 1 0 0 0  8 64 0 0 0; 1 0 0 1 1 19 361 0 0 0;]

W=[1 3; 2 1; 3 2]

W2=[1 3; 2 1; 3 2; 4 4; 5 7; 6 5]

W3=['_' '_' '_'; '_' '_' '_'; '_' '_' '_']


Gerd Doeben-Henisch 2012-03-31