function [minMemb, minCost] = getMinCostCombination(candidates, ...
  fixed, patchInfos, minMembers)
% Author: saurabh.me@gmail.com (Saurabh Singh)

if max(fixed) > 1 || min(fixed) < 0
  error('"fixed" argument should be a boolean vector');
end
fixedCands = find(fixed > 0);
nonFixed = find(fixed < 1);
reorderedCand = [candidates(fixedCands); candidates(nonFixed)];
membership = zeros(size(reorderedCand));
lastInd = length(fixedCands);
membership(1:lastInd) = 1;
[minCost, minMemb] = computeCombination(reorderedCand, ...
  membership, patchInfos, minMembers, intmax(), lastInd, lastInd + 1);
minMemb([fixedCands; nonFixed]) = minMemb;
end

function [minLevCost, minMemb] = computeCombination(candidates, ...
  membership, patchInfos, minMembers, minCost, lastInd, level)

global iterIndex;
if level > minMembers
  [cost appCost, locCost, memCost] = ...
    getClusterCost(candidates, membership, patchInfos);
else
  cost = intmax();
  appCost = cost;
  locCost = cost;
  memCost = cost;
end

if cost < minCost
%   plot(iterIndex, cost, 'or');
%   plot(iterIndex, appCost, 'xg');
%   plot(iterIndex, locCost, '^b');
%   plot(iterIndex, memCost, '*m');
  iterIndex = iterIndex + 1;
  minLevCost = cost;
  minMemb = membership;
%   pause(1)
else
  minLevCost = minCost;
  minMemb = [];
end

if lastInd == length(candidates)
  return;
end

for i = lastInd + 1 : length(candidates)
  membership(i) = 1;
  [cost, memb] = computeCombination(candidates, ...
    membership, patchInfos, minMembers, minLevCost, i, level + 1);
  
  membership(i) = 0;
  if cost < minLevCost && ~isempty(memb)
    minLevCost = cost;
    minMemb = memb;
  end
end
end
