我正在Matlab中实现1维Bin装箱问题(BPP)的First Fit(FF)启发式算法。
在第一次实现算法之后,我尝试改进我的代码,最后我得到了第二个实现,我认为它更好,因为在我看来它更像是优雅。
我的好奇心(让我说我是一个完美主义者)引导我运行并比较两种实现方式。他们到达的结果完全相同(应该是这样),但我的第一次实施速度提高了10倍以上!
我的问题是:你能帮我找到原因吗?第二个实现的哪个部分正在减慢我的代码?
第一次实施:
function packing = firstFit(items)
global N_items bin_size
item_assign = zeros(N_items,1);
residual = bin_size*ones(N_items,1);
tmp = residual;
% Assign each item on the list to a bin
for i = 1:N_items
j = 1; % always start by trying the first bin
% Repeat until the item is assigned to a bin
while true
if items(i) > residual(j)
j = j+1; % try to fit it in the next bin
else
residual(j) = residual(j)-items(i);
item_assign(i) = j;
break
end
end
end
% Check how many bins were needed to accommodate all items
N_bins = N_items - sum(residual == tmp);
packing = cell(N_bins,3);
for i = 1:N_bins
packing{i,1} = item_assign == i;
packing{i,2} = items(packing{i,1});
packing{i,3} = residual(i);
end
end
第二次实施:
function packing = firstFit2(items)
global N_items bin_size
% Initialize 1st bin
packing{1,1} = false(N_items,1);
packing{1,3} = bin_size;
N_bins = 1;
% Assign each item on the list to a bin
for i = 1:N_items
% Look for the first bin able to hold this item
j = find(cell2mat(packing(:,3)) >= items(i),1);
if isempty(j)
% Create a new empty bin if necessary
j = N_bins + 1;
packing{j,1} = false(N_items,1);
packing{j,3} = bin_size;
N_bins = j;
end
% Assign item to that bin
packing{j,1}(i) = true;
packing{j,2} = [packing{j,2};items(i)];
packing{j,3} = packing{j,3} - items(i);
end
end
结果:
对于给定的数据集,第一次实现时运行时间约为0.011秒,而第二次运行时间约为0.13秒。
如果您愿意,我可以为您提供数据集,请告诉我。
BPP的简要说明:
有一组具有特征长度的物品。这些物品应装入一组固定尺寸的箱子中。目标是使用尽可能少的垃圾箱来包装所有物品。
FF启发式的简要说明:
First-Fit(FF)启发式背后的想法非常简单:
答案 0 :(得分:0)
您的代码比它需要的复杂得多。要说一个实现比另一个更快,这并不容易,因为MATLAB在幕后进行了各种优化。循环,特别是在循环内改变向量的大小(正如你在第二个代码中所做的那样)通常很慢。
干净的MATLAB方式看起来像
%% do the actual work
binSize = 20;
itemMaxSize = 10;
numItems = 10;
items = randi(itemMaxSize, numItems, 1);
R = binSize * ones(numItems, 1); % there can not be more bins than items
assignment = zeros(numItems, 1);
for i = 1:numItems
assignment(i) = find( R >= items(i), 1, 'first');
R(assignment(i)) = R(assignment(i)) - items(i);
end
R = R( R < binSize );
%% make a figure
figure
hold on
for i = 1:length(R)
itemInds = find(assignment == i);
sizes = items(itemInds);
plot(i, cumsum(sizes), '*')
text(i * ones(size(sizes)) + .1, cumsum(sizes), num2str(itemInds))
end
ylim([0 round(binSize*1.1)])
plot([.5 length(R)+.5], [binSize binSize], '--')
xlim([.5, length(R)+.5]);
set(gca, 'xtick', 1:length(R))
xlabel('bin ind')
ylabel('fill')