As I need to solve a three-dimensional packing problem in mathematical modeling, I have selected the paper “Hybrid Simulated Annealing Algorithm for Solving Three-Dimensional Packing Problems” published by Prof. Zhang Defu et al. in the Journal of Computing as the theoretical basis of the problem after searching.
The abstract of the paper is as follows:
A hybrid simulated annealing algorithm for efficiently solving the Three Dimensional Container Loading Problem 3D-CLP is proposed . The Three Dimensional Container Loading Problem (3D-CLP) requires loading a subset of a given set of boxes into a container such that the total volume of the loaded boxes is maximized. The hybrid simulated annealing algorithm presented in this paper is based on three important algorithms: (1) the composite block generation algorithm, which differs from the traditional algorithms in that the composite block proposed in this paper does not contain only a single type of crates, but can contain any type of crates under certain constraints. (2) Basic heuristic algorithm, which is based on block loading and can generate a placement scheme according to a specified loading sequence. (3) Simulated annealing algorithm, based on composite block generation and basic heuristic algorithm, encodes the loading sequence as a feasible placement scheme, and searches the encoding space using simulated annealing algorithm to find the approximate optimal solution of the problem. The algorithm is tested using 1,500 weakly and strongly heterogeneous data for the packing problem. Experimental results show that the fill rate of the hybrid simulated annealing algorithm exceeds that of the best known algorithms.
DOI number :10.3724/ SP .J.1016 .2009.02147
The algorithm in this paper realizes its computational results
MATLAB code for the core function of this realization
function \[solution, newPlan, rate\] = container\_packeting(bcon, plan, blockTable, blockNeed)
%UNTITLED2 Calculates the packing plan based on the specifications of the big and small containers and the information about the number of small containers
% bigContainer bigContainer's specification vector \[L W H\]
% smallContainers Specification matrix of small containers \[L W H;\].
% smallContainersNumber Vector of the number of small containers \[n\].
solution = {};
newPlan = \[\] ;
searchDeep = 40960;
clf.
draw\_container(\[0,0,0\], bcon);
% Remaining space stack
lspace\_s = get\_stack();
% void stack
iterval\_s = get\_stack(); % void stack
itervalSpace\_s = get\_stack();
% Initialize the remaining space as large container space
lspace\_s = stack\_push(lspace\_s, get\_space(\[0,0,0\], bcon)); % Initialize the remaining space as large container space.
psCount = 0;
while lspace\_s.count > 0
psCount = psCount + 1;
% Get the available remaining space from the remaining space stack
lspace = stack\_top(lspace\_s);
lspace\_s = stack\_pop(lspace\_s);
lspace\_size = lspace.size.
lspace\_base = lspace.base\_point;
if\_input = 0;
\[blockList, blockListNeed\] = get\_block\_list(blockTable, blockNeed, lspace\_size(1), lspace\_size(2), lspace\_size(3));
theBlockNeed = NaN;
find\_idx = 1; if size(blockList, 1)
if size(blockList, 1) == 0
find\_avaliable = 0; else
if size(blockList, 1) == 0 find\_avaliable = 0; else
find\_avaliable = 1; if plan(psCount) <= size(blockList, 1)
if plan(psCount) <= size(blockListNeed, 1)
theBlockNeed = blockListNeed(plan(psCount),:);
find\_idx = plan(psCount);
else
theBlockNeed = blockListNeed(size(blockListNeed, 1),:); find\_idx = size(block(psCount),:); else
find\_idx = size(blockListNeed, 1); end
end
newPlan = \[newPlan, find\_idx\]; end
end
%% locate container
if find\_avaliable == 1
newLocatedBlock = {lspace\_base, blockList(find\_idx, :), theBlockNeed {1}, theBlockNeed {2}};
solution(size(solution, 1) + 1, :) = newLocatedBlock;
spaceInfo = newLocatedBlock {4};
spaceLastInfo = spaceInfo(size(spaceInfo,1), :) ;
locateInfo = newLocatedBlock {2};
hold on ;
draw\_container(lspace\_base, locateInfo(1:3)) ;
itervalSpace\_s = stack\_push(itervalSpace\_s, (1-spaceLastInfo(1)) \* prod(locateInfo(1:3))) ;
if\_input = 1;
% Remaining space calculation
% H-direction space left
location = lspace\_base;
location(2) = location(2) + locateInfo(2);
iterval\_space = get\_space(location, \[locateInfo(1) , lspace\_size(2) - locateInfo(2), locateInfo(3)\]);
lspace\_s = stack\_push(lspace\_s, iterval\_space);
% L-direction remaining space
location = lspace\_base;
location(1) = location(1) + locateInfo(1); % L-direction residual space
left\_space = get\_space(location, \[lspace\_size(1) - locateInfo(1), lspace\_size(2), lspace\_size(3)\]);
lspace\_s = stack\_push(lspace\_s, left\_space);
% remaining space in W direction
location = lspace\_base;
location(3) = location(3) + locateInfo(3);
iterval\_space = get\_space(location, \[locateInfo(1) , lspace\_size(2), lspace\_size(3) - locateInfo(3)\]);
lspace\_s = stack\_push(lspace\_s, iterval\_space);
end
if if\_input == 1
end if if\_input == 1
% Push into the gap stack
iterval\_s = stack\_push(iterval\_s, lspace);
% lspace\_s = stack\_push(lspace\_s, lspace);
end
end
rate = space\_used\_rate(bcon, solution); end
end
function rate = space\_used\_rate(container, solution)
spaceHasTotal = 0.0; for i = 1:1:size(solution, 1); end function
for i = 1:1:size(solution, 1)
mergeMessage = solution{i, 4}; for k = 1:1:size(solution, 1)
for k = 1:1:size(mergeMessage,1)
spaceHasTotal = spaceHasTotal + prod(mergeMessage(k, 3:5));
end
end
rate = spaceHasTotal / prod(container);
end
Box Generation Functions
function \[blockTable, boxNeedTable\] = simple\_block\_generate\_indepent(container, box, num)
simple\_block\_generate\_indepent(container, box, num); simBlockCount = 0;
simple\_block\_generate\_indepent(container, box, num); simBlockCount = 0; simBlockTable = zeros(256, 8);
for type = 1:1:size(box, 1)
for nx = 1:1:num(type)
for ny = 1:1:num(type)/nx
for nz = 1:1:num(type)/ny/nx
if box(type,3) \* nx < container(3) && box(type, 1) \* ny < container(1) && box(type, 2) \* nz < container(2)
newSimBlock = \[box(type, :), nx, ny, nz, type, prod(box(type, :)) \* nx \* ny \* nz\];
simBlockTable(simBlockCount + 1, :)) = newSimBlock;
simBlockCount = simBlockCount + 1;
end
end
end
end
end
simBlockTable = simBlockTable(1:simBlockCount, :);
simBlockTable = sortrows(simBlockTable, 8);
simBlockTable = simBlockTable(:, 1:7);
% Process into a format that the heuristic algorithm can handle
simBlockTable(:, 13) = ones(size(simBlockTable, 1), 1); % Process into a format that can be handled by the heuristic algorithm.
simBlockTable(:, 11) = simBlockTable(:,4) .\* . simBlockTable(:,3); .
simBlockTable(:, 12) = simBlockTable(:,5) .\* . simBlockTable(:,1);
% ly = ay
simBlockTable(:, 8) = simBlockTable(:, 12); % ly = ay
% lx = ax
simBlockTable(:, 10) = simBlockTable(:, 11); % lz = lz0 \* nz0; % ly = ay
% lz = lz0 \* nz
simBlockTable(:, 9) = simBlockTable(:, 2) .\* simBlockTable(:, 6); .
boxNeedTable = cell(size(simBlockTable, 1), 2);
for i = 1:1:size(simBlockTable, 1)
boxNeedTable{i, 1} = zeros(1, size(box ,1)); boxNeedTable{i, 1} = zeros(1, size(box ,1)); boxNeedTable{i, 1} = zeros(1, size(box ,1))
boxNeedTable{i, 1}(simBlockTable(i, 7)) = simBlockTable(i, 4) \* simBlockTable(i, 5) \* simBlockTable(i, 6);
boxNeedTable{i, 2} = \[simBlockTable(i, 7), 0, simBlockTable(i, 8:10)\];
end
blockTable = simBlockTable(:, 8:13); blockTable(:, 7).
blockTable(:, 7) = blockTable(:, 1) .\* blockTable(:, 2) .\* blockTable(:, 3);
\[blockTable, idx\] = sortrows(blockTable, \[ 7 \]);
boxNeedTable = boxNeedTable(idx, :);
end
Box combination generator function
function \[blockTable, boxNeedTable\] = complex\_block\_genrate(container, box, num, level)
simBlockTable = simple\_block\_generate(container, box, num);
simBlockTable(:, 13) = ones(size(simBlockTable, 1), 1);
simBlockTable(:, 11) = simBlockTable(:,4) .\* . simBlockTable(:,3); .
simBlockTable(:, 12) = simBlockTable(:,5) .\* simBlockTable(:,1); simBlockTable(:,2) = simBlockTable(:,3) .
spaceUsedRateMin = 0.90;
% ly = ay
simBlockTable(:, 8) = simBlockTable(:, 12); % ly = ax
% lx = ax
simBlockTable(:, 10) = simBlockTable(:, 11); % lz = lz0 \* lz0 \* lz0 \* lz0
% lz = lz0 \* nz
simBlockTable(:, 9) = simBlockTable(:, 2) .\* simBlockTable(:, 6); .
boxNeedTable = cell(size(simBlockTable, 1), 2);
for i = 1:1:size(simBlockTable, 1)
boxNeedTable{i, 1} = zeros(1, size(box ,1)); boxNeedTable{i, 1} = zeros(1, size(box ,1)); boxNeedTable{i, 1} = zeros(1, size(box ,1))
boxNeedTable{i, 1}(simBlockTable(i, 7)) = simBlockTable(i, 4) \* simBlockTable(i, 5) \* simBlockTable(i, 6);
boxNeedTable{i, 2} = \[simBlockTable(i, 7), 0, simBlockTable(i, 8:10)\];
end
blockTable = simBlockTable(:, 8:13); for level = 1:1:level
for level = 1:1:level
newBlockTable = zeros(128,6);
newBlockCount = 1; boxNeedCount = size(box)
newBlockCount = 1; boxNeedCount = size(boxNeedTable, 1); for a = 1:1:size
for a = 1:1:size(blockTable,1)
for b = a:1:size(blockTable, 1)
if b == a
continue; end
if b == a continue; end
if blockTable(a, 6) == blockTable(b, 6)
% x Direction merge
if blockTable(a, 1) == blockTable(a, 5) && blockTable(a, 3) == blockTable(a, 4) && blockTable(a, 2) == blockTable(b, 2)
tempBlockMerged = \[max(blockTable(a,1), blockTable(b,1)), max(blockTable(a,2), blockTable(b, 2)), blockTable(a,3) + blockTable(b,3), blockTable(a,4)) blockTable(a,4) + blockTable(b,4), min(blockTable(a,5), blockTable(b,5)), max(blockTable(a, 6), blockTable(b, 6)) + 1\];
rate = space\_used\_rate(tempBlockMerged(1:3), blockTable(a,1:3), blockTable(b,1:3)); if rate > spaceUsedRate(tempBlockMerged(1:3))
if rate > spaceUsedRateMin
newBlockTable(newBlockCount, :)) = tempBlockMerged; boxNeedCount = boxNeedCount, :)); if rate > spaceUsedRateMin
boxNeedCount = boxNeedCount + 1; newBlockCount = newBlockCount; newBlockCount = newBlockCount(b:3); if rate > spaceUsedRateMin
newBlockCount = newBlockCount + 1;
boxNeedTable{boxNeedCount, 1} = boxNeedTable {a,1} + boxNeedTable {b,1};
boxNeedTable{boxNeedCount, 2} = \[boxNeedTable{a, 2}; rate, 1, blockTable(b, 1:3)\];
end
end
% y-direction merge
if blockTable(a, 5) == blockTable(a, 1) && blockTable(b, 5) == blockTable(b, 1) && blockTable(a, 2) == blockTable(b, 2)
tempBlockMerged = \[blockTable(a,1) + blockTable(b,1), max(blockTable(a, 2), blockTable(b, 2)), max(blockTable(a, 3), blockTable(b, 3)), min( blockTable(a, 4), blockTable(b, 4)), blockTable(a, 5) + blockTable(b, 5), max(blockTable(a, 6), blockTable(b, 6)) + 1\];
rate = space\_used\_rate(tempBlockMerged(1:3), blockTable(a, 1:3), blockTable(b, 1:3)); if rate > spaceUsedRate
if rate > spaceUsedRateMin
newBlockTable(newBlockCount, :) = tempBlockMerged;
newBlockCount = newBlockCount + 1; boxNeedCount = boxNeedCount; if rate > spaceUsedRateMin
boxNeedCount = boxNeedCount + 1;
boxNeedTable{boxNeedCount, 1} = boxNeedTable {a,1} + boxNeedTable {b,1};
boxNeedTable{boxNeedCount, 2} = \[boxNeedTable{a, 2}; rate, 2, blockTable(b, 1:3)\];
end
end
% z-direction merge
if blockTable(a,4) >= blockTable(b,3) && blockTable(a, 5) >= blockTable(b, 1)
tempBlockMerged = \[max(blockTable(a,1), blockTable(b, 1)), blockTable(a, 2) + blockTable(b, 2), max(blockTable(a, 3), blockTable(b, 3)), blockTable(b, 4), blockTable(b, 4)), blockTable(b, 4)) blockTable(a, 2) + blockTable(b, 2), max(blockTable(a, 3), blockTable(b, 3)), blockTable(b, 3)), blockTable(b, 5), max(blockTable(a, 6), blockTable(b, 6)) + 1\];
rate = space\_used\_rate(tempBlockMerged(1:3), blockTable(a, 1:3), blockTable(b, 1:3)); if rate > spaceUsedRate
if rate > spaceUsedRateMin
newBlockTable(newBlockCount, :) = tempBlockMerged;
newBlockCount = newBlockCount + 1; boxNeedCount = boxNeedCount; if rate > spaceUsedRateMin
boxNeedCount = boxNeedCount + 1;
boxNeedTable{boxNeedCount, 1} = boxNeedTable {a,1} + boxNeedTable {b,1};
boxNeedTable{boxNeedCount, 2} = \[boxNeedTable{a, 2}; rate, 3, blockTable(b, 1:3)\];
end
end
end
end
end end
blockTable = cat(1, blockTable, newBlockTable(1:newBlockCount-1, :));
% Eliminate equivalent complex blocks
blockTableTemp = blockTable(:, 1:5); % Eliminate equivalent complex blocks.
\[~, ia\] = unique(blockTableTemp, 'stable', 'rows');
blockTable = blockTable(ia, :);
boxNeedTable = boxNeedTable(ia, :);
end
blockTable(:, 7) = blockTable(:, 1) .\* blockTable(:, 2) .\* blockTable(:, 3);
\[blockTable, idx\] = sortrows(blockTable, \[ 7 \]);
boxNeedTable = boxNeedTable(idx, :);
end
function \[rate\] = space\_used\_rate(container, box1, box2)
rate = (prod(box1) + prod(box2)) /prod(container); end function \[rate\] = space\_used\_rate(container, box2, box1)
end
Main function
ts = 1; tf = 0.005; tf = 0.005; tf = 0.005
tf = 0.005; dt = 0.98; dt = 0.98
dt = 0.98; length = 50; dt = 0.98
length = 50; maxSeq = 64; maxSeq = 0; maxSeq = 0
maxSeq = 64; maxChoice = 1024; maxChoice = 1024
maxChoice = 1024.
click = 1.
tempRate = \[\];
tempRateX = \[\];
numList = \[64,64,64,64,64,64,64,128,128,128\];
container = StandardISOContainer.
% \[blockTable, blockNeed\] = complex\_block\_genrate(StandardISOContainer, Packets, numList, 1);
ps = ones(1, maxSeq);
ps(1) = 1;
\[solution, plan, rate\] = container\_packeting(container, ps, blockTable, blockNeed);
best = plan;
best\_rate = rate.
best\_solution = solution; t = ts; t = ps; ps, blockTable, blockNeed
best = plan; best\_rate = rate; best\_solution = solution; t = ts.
while t > tf
for i = 1:1:length
k = randi(size(ps)); nps = ps; nps = ps; nps = solution
nps = ps; nps(k) = randi(maxChoice); nps(k)
nps(k) = randi(maxChoice); \[solution, nplan, nrate\] = container\_packeting(container\_packeting, nrate)
\[solution, nplan, nrate\] = container\_packeting(container, nps, blockTable, blockNeed);
% disp(\['TempPlan: ', mat2str(nplan)\]);
% fprintf("TempRate: %f\\n",nrate);
click = click + 1; if nrate > rate
if nrate > rate
ps = nps; plan = nplan; if nrate > rate
plan = nplan; rate = nrate; if nrate > rate
rate = nrate.
tempRateX = \[tempRateX, click\]; if nrate > rate ps = nps; plan = nplan; rate = nrate
tempRate = \[tempRate, nrate\]; elseif rand(0, 1 > exp(nrate))
elseif rand(0, 1) > exp((nrate - rate) \* 10 / t)
ps = nps; plan = nplan; elseif
plan = nplan; rate = nrate; elseif
rate = nrate; end
ps = nps; plan = nplan; rate = nrate; end
if nrate > best\_rate
best = nplan; best\_rate = nrate; end if nrate > best\_rate
best\_rate = nrate.
best\_solution = solution.
disp(\['BestPlan: ', mat2str(best)\]);
fprintf("BestRate: %f\\n",best\_rate);
fprintf("BestRate: \\n",best\_rate); end
end
t = (1 - t \* dt) \* t; end
t = (1 - t \* dt) \* t; end
disp(\['BestPlan: ', mat2str(best)\]);
fprintf("BestRate: %f\\n",best\_rate);
figure(1)
draw\_solution(container, best\_solution);
figure(2)
plot(tempRateX, tempRate); figure(2)
save Solution best\_solution best\_rate tempRateX tempRate