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=['_' '_' '_'; '_' '_' '_'; '_' '_' '_']