image thumbnail
from Multi-Knapsack solver by Sebastien PARIS
Multi-Knapsack solver by two stochastic optimizer : CEM & BK algorithms

cemcmc_knapsack(p , W , c , option)
function out = cemcmc_knapsack(p , W , c , option)
%
%
% Multiple knapsack problem solves by Botev-Kroeze (BK) optimization
% algorithm
%
%  max S(x)=(p^{t}x)
%  st. Wx <= c
%
% equivalent to maximize
% 
% max S(x)=C(x) + p^{t}x, where C(x)=alpha sum_{i=1,...,m}(min(ci -
% Wi^{t}xj , 0) and alpha = 1 + 1^{t}p/(max_{i,j}(ci-wij)
%
% Usage
% ------
%
% out = cemcmc_knapsack(p , W , c , [option])
%
%  Inputs
%  ------
%
%   p                     Weights vector    (n x 1)
%   W                     Matrix Weights    (m x n)
%   c                     Costs vector      (m x 1)
%   option                Structure for the option of the BK algorithm (optional) 
%
%    option.N             Number of Bernouilli vectors to generate for each iteration (default 1000)
%    option.rho           Threshold for selectionning the best rho*N samples (default 0.1)
%    option.b             Number of gibbsampler burnin (default = 2*n)
%    option.d             Indicate how many BK iterations to wait until declaring a solution is found (default 10)
%    option.T_max         Maximum number of iterations (default 10000)
%    option.epsilon       Absolute relative difference between 2 consecutives solution

%
% Outputs
% -------
%
% out
%    X_opt                Optimal solution. a (n + 1 x 1) index vector.
%    S_opt                Cost associated with the optimal solution
%    St                   Optimal cost versus time iteration of the algorithm
%    gammat               rho-Percentile versus time
%
% 
%
% Example
% -------
%
% load weish01.mat
% out = cemcmc_knapsack(p , W , c);
% disp(sprintf('\nS_CEMCMC = %5.1f, S_opt = %5.1f' , out.S_opt , S_opt))
%
% Author : Sbastien PARIS (sebastien.paris@lsis.org)
% --------
%
%
% Ref    : "An efficient Algorithm for Rare-Event Probability Estimation, Combinatorial, Optimization, and Counting", 
% ---          Z. I. Botev, D. P. Kroese, Methodology and Computing in Applied Probability, vol. 10
%
% see    http://iew3.technion.ac.il/CE/about.php

[m , n]   = size(W);

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

    option.N          = 1000;
    option.rho        = 0.5;
    option.b          = 10*n;
    option.winjec     = 5;
    option.nbinjec    = round(4*log10(n));
    option.Kgamma     = 1/100;
    option.Kb         = 1/10;
    option.Krho       = 1/50;
    option.rhomax     = 0.7;
    option.KN         = 1/10;
    option.X_ini      = [];
    option.gamma_ini  = [];    
    option.T_max      = 500;
    option.verbose    = 1;

end

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

    option.N                     = 10*round(log10(n))*n;

end

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

    option.b                     = round(5*log10(n))*n;

end

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

    option.rho                   = log10(n)*0.2; %0.5;

end

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

    option.winjec                = 5;

end

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

    option.nbinjec               = round(4*log10(n));

end

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

    option.Kgamma                = 1/100;

end

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

    option.Kb                    = 1/10;

end

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

    option.Kb                    = 1/10;

end

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

    option.rhomax               = 0.7;

end

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

    option.KN                   = 1/10;

end

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

    option.X_ini                = [];

end

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

    option.gamma_ini            = [];

end

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

    option.T_max                = 10000;

end

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

    option.verbose               = 1;

end


b              = option.b;

rho            = option.rho;

N              = option.N;


Nrho           = round(N*rho);

St             = zeros(1 , option.T_max);

gammat         = zeros(1 , option.T_max);


ind_Nrho       = (1 : Nrho);

alpha          = (1 + sum(p))./(max(max(c(: , ones(1 , n)) - W)));


%%%%%%%%%%%%% Initial run t = 0 %%%%%%%%%%%%%

if(~isempty(option.X_ini))

    X              = option.X_ini(: , ON);

else

    X              = binornd(0.5 , n , option.N);

end





%%% Descending Sorting %%

[S , index]    = sort(cost_knapsack(X , p , W , c , alpha) , 2 , 'descend');

if(isempty(option.gamma_ini))

    gammat_old     = S(Nrho);

else

    gammat_old     = option.gamma_ini;

end


%%% Index of Elite Samples %%

I              = index(ind_Nrho);

S_opt          = -inf;

S_old          = S_opt;

t              = 1;

cons           = 0;

injec          = 0;

    
while((t < option.T_max) && (injec < option.nbinjec) )

    %%%%%%%% Best Elite Samples Xtilde ~ g*(x|gamma_{t-1}) %%%%%%%%%%
 
    Xtilde          = X(: , I);
    
    Stilde          = S(ind_Nrho);
        
    %%%%%%%%%%%%%%%% Bootstrapping Xtilde => Y ~ g*(x|gamma_{t-1}) %%%%%%%%%%%%%%
    
    ind_bootstrap   = ceil(Nrho*rand(1 , N));
    
    Y               = Xtilde(: , ind_bootstrap);
    
    SY              = Stilde(ind_bootstrap);

     %%%%%%%%%%%%%%%% Gibbsampler Y = > X %%%%%%%%%%%%%%
     
    [X , SX]        = gibbsampler_knapsack(Y , SY , p , W , c , alpha , gammat_old , b); 
    
    [S , index]     = sort(SX , 2 , 'descend');
    
%     /// Matlab code of the gibbsampler_knapsack ///
%
%     bino_mat        = binornd(0.5 , option.b , option.N);
%          
%     indexgibbs      = ceil(n*rand(1 , option.b));        % randomize update order of condition pdf's of the gibbsampler
%     
%     for i = 1:option.b
% 
%         ii             = indexgibbs(i);
%         
%         Y(ii , :)      = bino_mat(ii , :);
%          
%         Sd             = cost_knapsack(Y , p , W , c , alpha);
%                  
%         ind            = (Sd < gammat_old);
% 
%         Y(ii , ind)    = ~Y(ii , ind);
%         
%         SY(~ind)       = Sd(~ind);
% 
%     end
%     
%     X               = Y;
%    
%    [S , index]     = sort(SY , 2 , 'descend');

    %%% Index of Elite Samples %%

    I               = index(ind_Nrho);
       
    if( (S(Nrho) > gammat_old))

        gammat(t)   = S(Nrho);

    elseif(cons > option.winjec)

        injec       = injec + 1;

        gammat(t)   = round(gammat_old*(1 - injec*option.Kgamma));

        b           = round(option.b*(1 + injec*option.Kb));

        rho         = min(option.rhomax , option.rho*(1 + injec*option.Krho));

        Nold        = N;

        N           = round(option.N*(1 + injec*option.KN));

        ind         = ceil(Nold*rand(1 , (N - option.N)))  ;

        Nrho        = round(rho*N);

        ind_Nrho    = (1 : Nrho);

        index       = [index , index(ind)];

        I           = index(ind_Nrho);

    else

        gammat(t)   = gammat_old;

    end
   
    %%% Best current Score %%

    S_new           = S(1);

    if ((gammat(t) == gammat_old) && (S_new == S_old) );

        cons         = cons + 1;
             
    else 
        
        cons         = 0;

    end


    if(S_new > S_opt)
        
        X_opt      = X(: , I(1));

        S_opt      = S_new;

    end

    St(t)      = S_opt;

    S_old      = S_new;
    
    gammat_old = gammat(t);
    
    if (option.verbose == 1)

        disp(sprintf('N=%d, rho=%3.2f, S_{opt} = %6.2f, S(%d) = %6.2f, gamma(%d) = %6.2f, b=%d, d=%d, i=%d' , N , rho, S_opt, t, S(1) , t, gammat(t), b, cons, injec))

    end
    
    t          = t + 1;
    
    drawnow

end


St(t:option.T_max)      = [];
gammat(t:option.T_max)  = [];

out.S_opt               = S_opt;
out.X_opt               = X_opt;
out.St                  = St;
out.gammat              = gammat;


Contact us at files@mathworks.com