Code covered by the BSD License  

Highlights from
GA-tuned Input Shaper

image thumbnail

GA-tuned Input Shaper

by

 

27 May 2008 (Updated )

A Shaper is presented whose parameters are tuned with Genetic Alg. suitable for unknown dynamics

shaperScan(model,numC,maxT,N,maxepochs,perf,show,plot,initC,initT)
function shaperScan(model,numC,maxT,N,maxepochs,perf,show,plot,initC,initT)

% Use a Genetic Algorithm to find shaper parameters which best fit model
% response
%
% shaperScan(model,numC,maxT,N,maxepochs,perf,show,plot,initC,initT)
%
% Input
%       model    : name of simulink model
%       numC     : number of shaper coefficients
%       maxT     : time interval (s) in which shaper should work (default=0.3 s)
%       N        : population size (default=10)
%       maxepochs: default=100 
%       perf     : performance index to be achieved (default=0)
%       show     : displays intermediate results after 'show' epochs
%       plot     : enable plotting (default=true)
%       initC    : coefficients vector to be put into initial population (default=[])
%       initT    : time instants vector to be put into initial population (default=[])
%
% Ouput
%       bestC and bestT returned into workspace

if nargin<10, initT=[]; end
if nargin<9, initC=[]; end
if nargin<8, plot=true; end
if nargin<7, show=1; end
if nargin<6, perf=0; end
if nargin<5, maxepochs=100; end
if nargin<4, N=10; end
if nargin<3, maxT=0.3; end

if isempty(plot), plot=true; end
if isempty(show), show=1; end
if isempty(perf), perf=0; end
if isempty(maxepochs), maxepochs=100; end
if isempty(N), N=10; end
if isempty(maxT), maxT=0.3; end

if numC<=1
    disp('error: numC must be greater than 1.');
    return;
end

numT=numC-1;

% perf should be not negative
perf=max(0,perf);

% N should be even
if mod(N,2)
    N=N+1;
end

% translate maxT in milliseconds
maxT=max(round(1000*maxT),10);

% params for mutation
prob=0.5;
deltaC_inc=1.3;
deltaC_dec=0.7;
deltaT=10;

len=numC+numT;

Cidx=find(mod(1:len,2));
Tidx=find(~mod(1:len,2));

% create initial population
Pop=zeros(len,N);
% randomly initialized
Pop(Cidx,:)=rand(numC,N);
Pop(Tidx,:)=round((maxT-1)*rand(numT,N)) + 1;

% reshape to apply constraints
for i=1:N
    Pop(Cidx,i)=Pop(Cidx,i)/sum(Pop(Cidx,i));
end

for i=1:N
    lim=sum(Pop(Tidx,i));
    if lim>maxT
        Pop(Tidx,i)=floor(Pop(Tidx,i)*maxT/lim);
    end
end

if (~isempty(initC)) && (~isempty(initT))
    if (length(initC)~=numC) && (length(initT)~=numT)
        disp('error: wrong dimension for initC and/or initT.');
        return;
    end
    Pop(Cidx,1)=initC;
    Pop(Tidx,1)=initT;
end

global stopFlag;

stopFlag=false;

epochs=1;
s=1;

NewPop=Pop;
fitness=zeros(N,1);

% get time step from within the model
load_system(model);
stopTime=str2double(get_param(bdroot,'StopTime'));
close_system;

time=(0:.001:stopTime)';
u=zeros(length(time),1);
u(find(time>=0.1))=1; %#ok<FNDSB>

figure('Color',[1 1 1]);
uicontrol('Style','pushbutton','String','Stop',...
          'Position',[10 10 40 30],'Callback',@stop);

while epochs<=maxepochs

    % calculate fitness function
    minJ=inf;
    for i=1:N
        assignin('base','C',Pop(Cidx,i));
        assignin('base','T',Pop(Tidx,i));        
                
        [t,x,y1,y2,J]=sim(model,[time(1) time(end)],[],[time u]);
        fitness(i)=J(end);

        if fitness(i)<minJ
            besty=y1;
            bestsh=y2;
            minJ=fitness(i);
        end
    end
    
    % sort
    [fitness,idx]=sort(fitness);
        
    % create new population
    
    % elitism => first two parents hold
    NewPop(:,1)=Pop(:,idx(1));
    NewPop(:,2)=Pop(:,idx(2));

    % crossover of the first two parents
    % select random crossover point
    p=round((len-3)*rand)+2;
    NewPop(1:p,3)=NewPop(1:p,1);
    NewPop((p+1):end,3)=NewPop((p+1):end,2);    
    NewPop(1:p,4)=NewPop(1:p,2);
    NewPop((p+1):end,4)=NewPop((p+1):end,1);
    
    % mutation of the first two parents
    m=floor(len*prob);
    if m
        sel=1:len;
        for i=1:m
            for j=3:4
                % select a random point not already choosen
                tmp=round((length(sel)-1)*rand)+1;
                p=sel(tmp);
                sel(tmp)=[];
                if ismember(p,Cidx)
                    if round(rand)
                        NewPop(p,j)=NewPop(p,j)*deltaC_inc;
                    else
                        NewPop(p,j)=NewPop(p,j)*deltaC_dec;
                    end
                else
                    NewPop(p,j)=NewPop(p,j)+2*round(deltaT*rand)-deltaT;
                    if NewPop(p,j)<0
                       NewPop(p,j)=0; 
                    end
                end
            end
        end
    end
        
    % remove last two chromosomes from new population
    idx=idx(3:(end-2));
    
    for i=1:(N/2-2)
        % select chromosomes
        tmp=round((length(idx)-1)*rand)+1;
        idx1=idx(tmp);
        idx(tmp)=[];

        tmp=round((length(idx)-1)*rand)+1;
        idx2=idx(tmp);
        idx(tmp)=[];
        
        j=5+2*(i-1);
        
        % crossover
        p=round((len-3)*rand)+2;
        NewPop(1:p,j)=Pop(1:p,idx1);
        NewPop((p+1):end,j)=Pop((p+1):end,idx2);    
        NewPop(1:p,j+1)=Pop(1:p,idx2);
        NewPop((p+1):end,j+1)=Pop((p+1):end,idx1);
                
        % mutation
        m=floor(len*prob);
        if m
            j=j- 1;
            sel=1:len;
            for h=1:m
                for k=1:2
                    % select a random point not already choosen
                    tmp=round((length(sel)-1)*rand)+1;
                    p=sel(tmp);
                    sel(tmp)=[];
                    if ismember(p,Cidx)
                        if round(rand)
                            NewPop(p,j+k)=NewPop(p,j+k)*deltaC_inc;
                        else
                            NewPop(p,j+k)=NewPop(p,j+k)*deltaC_dec;
                        end
                    else
                        NewPop(p,j+k)=NewPop(p,j+k)+2*round(deltaT*rand)-deltaT;
                        if NewPop(p,j+k)<0
                           NewPop(p,j+k)=0; 
                        end                        
                    end
                end
            end
        end
        
    end
    
    % reshape to apply constraints
    for i=1:N
        NewPop(Cidx,i)=NewPop(Cidx,i)/sum(NewPop(Cidx,i));
    end

    for i=1:N
        lim=sum(NewPop(Tidx,i));
        if lim>maxT
            NewPop(Tidx,i)=floor(NewPop(Tidx,i)*maxT/lim);
        end
    end
    
    Pop=NewPop;
    
    if s==show
        text=sprintf('epoch = %d/%d; performance = %f/%f;',epochs,maxepochs,minJ,perf);
        disp(text);
        
        if plot
            stairs(t,[u bestsh besty],'LineWidth',2);
            title(text);
            drawnow;
        end

        s=1;
    else
        s=s+1;
    end       
        
    assignin('base','bestC',Pop(Cidx,1));
    assignin('base','bestT',Pop(Tidx,1));
    
    if (minJ<=perf) || stopFlag
        if s~=1
            disp(sprintf('epoch = %d/%d; performance = %f/%f;',epochs,maxepochs,minJ,perf));
        end

        if minJ<=perf
            disp('performance achieved.');
        end
        
        break;
    end
    
    epochs=epochs+1;    
end

if epochs>=maxepochs
    disp('max epoch reached.');
end


function stop(obj,event) %#ok<INUSD>

global stopFlag;

stopFlag=true;

Contact us