Code covered by the BSD License  

Highlights from
Cross Entropy TSP Solver

image thumbnail
from Cross Entropy TSP Solver by Sebastien PARIS
Solve TSP problem with a CE method.

TSP_CE(L , X1 , option)
function [X_opt , S_opt , Pt , T] = TSP_CE(L , X1 , option)

% Solve the classic Travel Sale Man problem with a Cross Entropy
% (CE) optimization algorithm.
%
% Usage : 
%
% [X_opt , S_opt , Pt , T] = TSP_CE(L , [X1] , [option])
%
% Inputs
% -------
%
% L         : Distance/cost matrix (n x n)
% X1        : (optional) start city  (default X1 = 1);
% option    : (optional) structure for the option of the CE algorithm
%
%   option.N             : Number of paths to generate for each iteration (default 3*n*n)
%   option.rho           : Threshold for selectionning the best rho*N paths (default 5*10e-3)
%   option.alpha         : Weight for updating Transition Matrix (default 0.8)
%   option.beta          : Determine the fraction of the Nrho*N sample who will be kept for each iteration (default 0.7)
%   option.d             : Indicate how many CE iterations to wait until declaring a solution is found (default 5)
%   option.T_max         : Maximum number of iterations (default 10000)
%   option.epsilon       : Absolute relative difference between 2 consecutives solution
%   option.digit         : Truncation rank (default 5)
%   option.verbose       : 1 for real time plot;
%   option.V             : Towns coordinates (n x 2). option.verbose = 1 is requiered;  
%
% Outputs
% 
% X_opt                  : optimal solution. a (n + 1 x 1) index vector.
% S_opt                  : Distance associated with the optimal path
% Pt                     : Transition Matrix (n x n) estimated at the end of the CE algorithm
% T                      : Number of CE iteration needed( < option.T_max)
%
% Example
%
% n                        = 20;
% V                        = 10*rand(n , 2);
% L                        = distmat(V);
% X_opt                    = TSP_CE(L);
% plot(V(: , 1) , V(: , 2) , 'b+' , V(X_opt , 1) , V(X_opt , 2) , 'r' ,  'markersize' , 8 , 'linewidth' , 2)
% text(V(: , 1) , V(: , 2) , num2str((1 : n)' , '%0.0f') , 'fontname' , 'times' , 'fontsize' , 13);

%
% Author : Sbastien PARIS
%
% Ref    : "The Cross Entropy method", P-T de Boer, D. P. Kroese, S.
% Mannor, R. Y. Rubinstein.
%
% see    http://iew3.technion.ac.il/CE/about.php


[n , d] = size(L);

if((n ~= d))

    error('L must be  a square(n x n)');

end

if ((nargin < 2) || isempty(X1) )

    X1 = 1;

end

if ( (X1 < 1) || (X1 > n))

    error('Start city index must be within [1, ... , n]');

end

if ( (nargin < 3) || isempty(option))

    option.N             = round(5*n*n);

    option.rho           = 5*10e-3;        % threshold for selectionning the best rho*N paths

    option.alpha         = 0.7;            % weight for updating Transition Matrix with new paths candidates

    option.beta          = 0.7;            % Determine the fraction of the Nrho*N sample who will be keep in each iteration

    option.d             = 5;              % indicate how many iterations to wait until declaring the solution is reached

    option.T_max         = 10000;          % Maximum number of CE iterations

    option.epsilon       = 100*eps;

    option.digit         = 5;

    option.verbose       = 0;              % Display Best current solution of the CE algorithm

end

if (option.verbose == 1)

    if (~any(strcmp(fieldnames(option) , 'V')))

        disp('option.V must be provided tp verbose, switching verbose = 0');

        option.verbose = 0;

    end

    fig1        = figure(1);

    set(fig1 , 'renderer' , 'zbuffer');

    set(fig1 , 'doublebuffer' , 'on');

    subplot(121)

    set(gca , 'nextplot' , 'replace');

    subplot(122)

    set(gca , 'nextplot' , 'replace');

    str_n   = num2str((1 : n)' , '%0.0f');


end


Nrho                      = round(option.rho*option.N);

betaR1                    = round(option.beta*Nrho);


ind_Nrho                  = (1 : Nrho);

ind_betaR1                = (1 : betaR1);

ind_betaR2                = (betaR1 + 1 : option.N);

ind_n                     = (n + 1: -1 : 1);

ctelog                    = 1/log(10);


NN                        = option.N - betaR1;

%%==== Initial Transition Matrix =====%%

cten1                     = 1/(n - 1);

Pt                        = cten1(ones(n));

Pt(1 : n + 1 : n*(n + 1)) = 0;

%%===== Initialization iteration ========%%

X                         = generation_TSP(Pt , option.N , X1);

[S , indice]              = sort(cost_TSP(L , X));

Gt                        = S(1);

I                         = indice(ind_Nrho);

tp_X                      = X(: , I);



%a) troncate to the N digits the Nrho first values of S %

x                         = abs(S(ind_Nrho));

m                         = ceil(log(x)*ctelog);

k                         = (x <= 10.^(m - 1));

m(k)                      = m(k) - 1;

f                         = 10.^(option.digit - m);

x                         = fix(x.*f)./f;

%b) Find sequential identical values

ind2                      = find((x(2 : Nrho) - x(1 : Nrho - 1)) == 0) + 1;

if ( ~isempty(ind2) )

    ind1                 = [ind2(1) - 1 , ind2((ind2(2 : end) - ind2(1 : end - 1) ~= 1)) + 1];

    ind3                 = ind2((tp_X(2 , ind2) < tp_X(n , ind2)));

    tp_X(: , ind3)       = tp_X(ind_n , ind3);

    ind4                 = ind1(((tp_X(2 , ind1) ~= tp_X(2 , ind1 + 1))));

    tp_X(: , ind4)       = tp_X(ind_n , ind4);

end


Pt                        = (1 - option.alpha)*update_matrix(tp_X) + option.alpha*Pt ;

X_opt                     = X(: , I(1));

S_opt                     = S(1);


t                         = 1;

cons                      = 0;

Gt_old                    = Gt;

X(: , ind_betaR1)         = tp_X(: , ind_betaR1);

if (option.verbose)

    maxi             = max(option.V);

    mini             = min(option.V);

    fig1             = figure(1);

    subplot(121);


    p1                = plot(option.V(: , 1) , option.V( : , 2) ,  '+' , 'markersize' , 7);

    text(option.V(: , 1) , option.V(: , 2) , str_n , 'fontname' , 'times' , 'fontsize' , 12)

    axis([mini(1) , maxi(1) , mini(2) , maxi(2)])

    drawnow

    subplot(122);

    bar3(Pt);

    axis([0 , n+1 , 0 , n+1 , 0 , 1])

    view([-50 50]);

    title(sprintf('\\bf{P_{%d}}' ,t ) , 'fontsize' , 12 , 'fontname' , 'times');

    drawnow


end


%%========== Main Loop ==========%%


while( (t < option.T_max) && (cons < option.d))

    X(: , ind_betaR2)    = generation_TSP(Pt , NN , X1);

    [S , indice]         = sort(cost_TSP(L , X));

    Gt_new               = S(1);

    if ((abs(Gt_new - Gt_old) < option.epsilon) && (Gt_new == Gt_old) );

        cons = cons + 1;

    else

        cons = 0;

    end

    I                  = indice(ind_Nrho);

    tp_X               = X(: , I);

    %a) troncate to the N digits the Nrho first values of S %

    x                         = abs(S(ind_Nrho));

    m                         = ceil(log(x)*ctelog);

    k                         = (x <= 10.^(m - 1));

    m(k)                      = m(k) - 1;

    f                         = 10.^(option.digit - m);

    x                         = fix(x.*f)./f;

    %b) Find sequential identical values

    ind2                      = find((x(2 : Nrho) - x(1 : Nrho - 1)) == 0) + 1;

    if ( ~isempty(ind2) )
        
        ind3                 = ind2((tp_X(2 , ind2) < tp_X(n , ind2)));
        
        tp_X(: , ind3)       = tp_X(ind_n , ind3);

        ind1                 = [ind2(1) - 1 , ind2((ind2(2 : end) - ind2(1 : end - 1) ~= 1)) + 1];
        
        ind4                 = ind1(((tp_X(2 , ind1) ~= tp_X(2 , ind1 + 1))));
        
        tp_X(: , ind4)       = tp_X(ind_n , ind4);

    end

    Pt                 = (1 - option.alpha)*update_matrix(tp_X) + option.alpha*Pt ;

    if (S(1) < S_opt)

        X_opt           = X(: , I(1));

        S_opt           = S(1);

    end

    Gt_old            = Gt_new;

    X(: , ind_betaR1) = tp_X(: , ind_betaR1);

    t                 = t + 1;

    %%===========  Display ===========%%

    if (option.verbose)

        subplot(121);

        p1          = plot(option.V(X_opt , 1) , option.V(X_opt , 2) , 'r' , option.V(: , 1) , option.V( : , 2) ,  '+' , 'markersize' , 8 , 'linewidth' , 2);

        text(option.V(: , 1) , option.V(: , 2) , str_n , 'fontname' , 'times' , 'fontsize' , 13);

        axis([mini(1) , maxi(1) , mini(2) , maxi(2)])

        title(sprintf('\\bf{n = %d, N = %d, \\gamma_{%d}^{opt}=%6.2f , \\gamma_{%d} = %6.2f, cons = %d}' , n , option.N , t ,  S_opt , t , Gt_new , cons) , 'fontsize' , 12 , 'fontname' , 'times');


        subplot(122);

        bar3(Pt);

        axis([0 , n+1 , 0 , n+1 , 0 , 1])

        view([-50 50]);

        title(sprintf('\\bf{P_{%d}}' , t ) , 'fontsize' , 12 , 'fontname' , 'times');

        drawnow

    end

end

T             = t - 1;

Contact us at files@mathworks.com