%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% function [P,scoreP,num_swap] = make_swaps(P,D,A,B,max_swap)
%
% Tests swaps (i<-->j) for which D_ij > 0 and
% performs up to max_swap swaps that improve the score.
%
% Returns the new permutation matrix P, its score,
% and the number of performed swaps.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [P,scoreP,num_swap] = make_swaps(P,D,A,B,max_swap)

% INITIALIZE
scoreP = full(sum(min(A*P,P*B),'all'));
num_swap = 0;

% SPARSIFY
D = max(0,D);
[i,j,v] = find(D);
D = sparse(i(i>j),j(i>j),v(i>j));

% NOTHING TO SWAP?
if (isempty(D))
  return;
end

% MAKE UP TO MAX_SWAPS
[dMax,idx] = max(D,[],'all');
while ((dMax>0) && (num_swap<max_swap))
  [i,j] = ind2sub(size(D),idx);
  P([i j],:) = P([j i],:);
  swap_score = full(sum(min(A*P,P*B),'all'));
  if (swap_score>scoreP)
    scoreP = swap_score;
    num_swap = num_swap+1;
  else
    P([j i],:) = P([i j],:);
  end
  D(i,j) = 0;
  [dMax,idx] = max(D,[],'all');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%