[英]Finding overlapping areas in Julia grid system performance question
我目前正在嘗試計算網格中特定類型的一組位置。 手頭的問題與 2D 打包優化問題有關。
打包物品時,我需要在網格中為該物品選擇一個位置(i,j)
。 由於項目大小,還可以覆蓋網格中的其他幾個位置。 因此,我需要一個集合Qijc
,這是放置項目 c 可能覆蓋位置(i,j)
的正方形集合。 例如,如果項目 c 的大小為 2x2,則Qijc
包含{(i,j),(i-1,j-1),(i-1,j),(i,j-1)}
。 如果項目 c 位於這些位置中的任何一個.. 位置(i,j)
也被覆蓋。
我有當前的工作代碼。 但是,它會蠻力計算並且在達到 150x400 的網格大小時非常慢。 我一直在嘗試優化代碼,我相信我遺漏了一些簡單的東西。 任何建議,將不勝感激。
目前,我將信息存儲在字典中以建立“一對多”關系。 該問題的另一個警告是我只存儲項目 c 的位置,如果該位置在網絡中可用於項目 c,則它將涵蓋位置(i,j)
。
在給定的示例中,如果項目c = 3
,並且我們正在查看位置(4,3)
將覆蓋的位置是(4,2)
和(4,3)
,但是位置(5,3)
也會但是,通常不存儲封面(4,3)
,因為項目 c 無法到達此位置。 ( 我希望這是有道理的)
我相信我有幾個冗余循環,並且可以以更快的方式完成,但是,我很難把頭繞在它周圍。
function validpositions(UnusuableSpace::Matrix{Int64}, nCargoes::Int64, SquaresL::Vector{Int64}, SquaresW::Vector{Int64})
# This function should return all position that are valid in the layout for
# cargo c in C. This should be returned as a tuple e.g. pos = [(1,1),(4,3),..,(18,1)].
N = []
for c in 1:nCargoesM
pos = Vector{Tuple{Int64,Int64}}()
for i in SquaresL[c]:size(UnusuableSpace)[1] # skip some of the rows. If the cargo has dimensions > 1.
for j in 1:size(UnusuableSpace)[2]
# Check if position includes a pillar / object
if UnusuableSpace[i,j] != 1
# Check if these is space for the cargo in the position.
if (i-SquaresL[c]) >= 0 && (j+SquaresW[c]-1) <= size(UnusuableSpace)[2]
# Check if position i,j covers an are with pillars in due to cargo
# dimensions.
if sum(UnusuableSpace[i-SquaresL[c]+1:i,j:j+SquaresW[c]-1]) == 0
push!(pos,(i,j))
end
end
end
end
end
push!(N,pos)
end
# return all valid positions of the cargo c.
return N
end # end valid position function
nCargoesM = 3
SquaresL = [1,2,3]
SquaresW = [1,2,2]
UnusableSpace = [
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 1 0 0 0
0 0 1 1 1 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0]
N = validpositions(UnusableSpace, nCargoesM, SquaresL, SquaresW)
function coveringSet(UnusableSpace::Matrix{Int64}, nCargoes::Int64, SquaresL::Vector{Int64}, SquaresW::Vector{Int64}, N)
Qijc = Dict{}()
for c in 1:nCargoesM
for i in 1:size(UnusableSpace)[1]
for j in 1:size(UnusableSpace)[2]
tmpset = []
for (k, l) in N[c]
# Get the points/nodes of the areas to check
vec1 = [i, j]
vec2 = [k-SquaresL[c]+1:k, l:l+SquaresW[c]-1]
tmp = [[x, y] for x in vec1[1], y in vec1[2]]
tpm = [[x, y] for x in vec2[1], y in vec2[2]]
# Check for overlapping
if sum([tmp in tpm for tmp = tmp]) > 0
push!(tmpset, [k, l])
end
end
push!(Qijc, [i, j, c] => tmpset)
end
end
end
return Qijc
end
Qijc = coveringSet(UnusableSpace, nCargoesM, SquaresL, SquaresW, N)
一段時間后,我實際上自己解決了這個問題。 您可以預先計算字典中的所有鍵並執行循環。 檢查貨物的位置,是否是允許的位置。
function coveringSet_new_threaded(UnusableSpace, nCargoesM::Int64, SquaresL::Vector{Int64}, SquaresW::Vector{Int64})
# Create dictionary
Qijc4 = Dict{}()
for c in 1:nCargoesM
for i in 1:size(UnusableSpace)[1]
for j in 1:size(UnusableSpace)[2]
push!(Qijc4, [i, j, c] => [])
end
end
end
# Finding the combinations of cargo size
combinationsCargo = Vector{Tuple{Int64,Int64}}()
for i in 1:length(SquaresL)
push!(combinationsCargo, (SquaresL[i], SquaresW[i]))
end
# The unique combinations available
CargoTypes = unique(combinationsCargo)
Threads.@threads for c in 1:length(CargoTypes)
typeindx = findall(x -> x == CargoTypes[c], combinationsCargo)
# Index to control where to find information regarding squaresL and squaresW
sizeidx = typeindx[1]
#Threads.@threads for c in 1:nCargoesM
for i in 1:size(UnusableSpace)[1]
for j in 1:size(UnusableSpace)[2]
tmpset = []
# Generate the range of positions to check. (h,m) check if it also covers (i,j)
# due to cargo size.
for h in i:i+SquaresW[sizeidx]-1
for m in j-SquaresL[sizeidx]+1:j
# Check that the position is actually within the layout of the ship
if (h > 0 && m > 0 && h <= size(UnusableSpace)[1] && h <= size(UnusableSpace)[2])
# Check that the position is not unusable.
if UnusableSpace[h, m] != 1
# Check that the position given cargo size is withon the layout of the ship.
if (h - SquaresW[sizeidx]) >= 0 && (m + SquaresL[sizeidx] - 1) <= size(UnusableSpace)[2]
# Check that the cargo, when in position (h,m) does not collide with any unusable space.
if sum(UnusableSpace[h-SquaresW[sizeidx]+1:h, m:m+SquaresL[sizeidx]-1]) == 0
# Only then is it a position for cargo c that covers (i,j).
push!(tmpset, [h, m])
end
end
end
end
end
end
# Push in set for that position. It may be empty.
for k in typeindx
Qijc4[[i, j, k]] = tmpset
end
end
end
end
return Qijc4
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.