如何根据理想邻域的程度对单元进行重新排序? (进行中)
How to re-order units based on their degree of desirable neighborhood ? (in Processing)
我需要帮助来实现允许生成建筑计划的算法,这是我最近在阅读 Kostas Terzidis 教授的最新出版物时偶然发现的:Permutation Design: Buildings, Texts and Contexts (2014)。
上下文
- 考虑划分为网格系统 (a) 的站点 (b)。
- 我们还考虑要放置在站点范围内的空间列表 (c) 和邻接矩阵以确定这些空间的放置条件和相邻关系 (d)
引用 Terzidis 教授的话:
"A way of solving this problem is to stochastically place spaces within the grid until all spaces are fit and the constraints are satisfied"
上图显示了这样的问题和示例解决方案 (f)。
算法(如书中简要描述)
1/"Each space is associated with a list that contains all other spaces sorted according to their degree of desirable neighborhood."
2/"Then each unit of each space is selected from the list and then one-by-one placed randomly in the site until they fit in the site and the neighboring conditions are met. (If it fails then the process is repeated)"
九个随机生成计划的示例:
我要补充一点,作者稍后会解释这个算法不依赖于暴力破解技术。
问题
如您所见,解释相对含糊,步骤 2 相当不清楚(在编码方面)。到目前为止我只有 "pieces of a puzzle":
- a "site"(选定整数列表)
- 邻接矩阵(嵌套列表)
- "spaces"(列表字典)
每个单元:
- 一个函数 returns 它的直接邻居
- 其理想邻居的列表及其索引按排序顺序
基于其实际邻居的适应度得分
from random import shuffle
n_col, n_row = 7, 5
to_skip = [0, 1, 21, 22, 23, 24, 28, 29, 30, 31]
site = [i for i in range(n_col * n_row) if i not in to_skip]
fitness, grid = [[None if i in to_skip else [] for i in range(n_col * n_row)] for e in range(2)]
n = 2
k = (n_col * n_row) - len(to_skip)
rsize = 50
#Adjacency matrix
adm = [[0, 6, 1, 5, 2],
[6, 0, 1, 4, 0],
[1, 1, 0, 8, 0],
[5, 4, 8, 0, 3],
[2, 0, 0, 3, 0]]
spaces = {"office1": [0 for i in range(4)],
"office2": [1 for i in range(6)],
"office3": [2 for i in range(6)],
"passage": [3 for i in range(7)],
"entry": [4 for i in range(2)]}
def setup():
global grid
size(600, 400, P2D)
rectMode(CENTER)
strokeWeight(1.4)
#Shuffle the order for the random placing to come
shuffle(site)
#Place units randomly within the limits of the site
i = -1
for space in spaces.items():
for unit in space[1]:
i+=1
grid[site[i]] = unit
#For each unit of each space...
i = -1
for space in spaces.items():
for unit in space[1]:
i+=1
#Get the indices of the its DESIRABLE neighbors in sorted order
ada = adm[unit]
sorted_indices = sorted(range(len(ada)), key = ada.__getitem__)[::-1]
#Select indices with positive weight (exluding 0-weight indices)
pindices = [e for e in sorted_indices if ada[e] > 0]
#Stores its fitness score (sum of the weight of its REAL neighbors)
fitness[site[i]] = sum([ada[n] for n in getNeighbors(i) if n in pindices])
print 'Fitness Score:', fitness
def draw():
background(255)
#Grid's background
fill(170)
noStroke()
rect(width/2 - (rsize/2) , height/2 + rsize/2 + n_row , rsize*n_col, rsize*n_row)
#Displaying site (grid cells of all selected units) + units placed randomly
for i, e in enumerate(grid):
if isinstance(e, list): pass
elif e == None: pass
else:
fill(50 + (e * 50), 255 - (e * 80), 255 - (e * 50), 180)
rect(width/2 - (rsize*n_col/2) + (i%n_col * rsize), height/2 + (rsize*n_row/2) + (n_row - ((k+len(to_skip))-(i+1))/n_col * rsize), rsize, rsize)
fill(0)
text(e+1, width/2 - (rsize*n_col/2) + (i%n_col * rsize), height/2 + (rsize*n_row/2) + (n_row - ((k+len(to_skip))-(i+1))/n_col * rsize))
def getNeighbors(i):
neighbors = []
if site[i] > n_col and site[i] < len(grid) - n_col:
if site[i]%n_col > 0 and site[i]%n_col < n_col - 1:
if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1])
if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1])
if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col])
if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col])
if site[i] <= n_col:
if site[i]%n_col > 0 and site[i]%n_col < n_col - 1:
if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1])
if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1])
if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col])
if site[i]%n_col == 0:
if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1])
if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col])
if site[i] == n_col-1:
if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1])
if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col])
if site[i] >= len(grid) - n_col:
if site[i]%n_col > 0 and site[i]%n_col < n_col - 1:
if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1])
if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1])
if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col])
if site[i]%n_col == 0:
if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1])
if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col])
if site[i]%n_col == n_col-1:
if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1])
if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col])
if site[i]%n_col == 0:
if site[i] > n_col and site[i] < len(grid) - n_col:
if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1])
if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col])
if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col])
if site[i]%n_col == n_col - 1:
if site[i] > n_col and site[i] < len(grid) - n_col:
if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1])
if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col])
if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col])
return neighbors
如果有人能帮我解释一下,我将不胜感激:
- 如何根据理想邻域的程度对单元重新排序?
编辑
你们中的一些人已经注意到,该算法基于某些空间(由单元组成)相邻的可能性。按照逻辑,每个单元都将随机放置在站点范围内:
- 我们事先检查它的直接邻居(上、下、左、右)
- 如果至少有 2 个邻居,则计算适合度分数。 (=这 2+ 个邻居的权重之和)
- 如果邻接概率高,最后放置那个单元
粗略地说,它会翻译成这样:
i = -1
for space in spaces.items():
for unit in space[1]:
i+=1
#Get the indices of the its DESIRABLE neighbors (from the adjacency matrix 'adm') in sorted order
weights = adm[unit]
sorted_indices = sorted(range(len(weights)), key = weights.__getitem__)[::-1]
#Select indices with positive weight (exluding 0-weight indices)
pindices = [e for e in sorted_indices if weights[e] > 0]
#If random grid cell is empty
if not grid[site[i]]:
#List of neighbors
neighbors = [n for n in getNeighbors(i) if isinstance(n, int)]
#If no neighbors -> place unit
if len(neighbors) == 0:
grid[site[i]] = unit
#If at least 1 of the neighbors == unit: -> place unit (facilitate grouping)
if len(neighbors) > 0 and unit in neighbors:
grid[site[i]] = unit
#If 2 or 3 neighbors, compute fitness score and place unit if probability is high
if len(neighbors) >= 2 and len(neighbors) < 4:
fscore = sum([weights[n] for n in neighbors if n in pindices]) #cumulative weight of its ACTUAL neighbors
count = [1 for t in range(10) if random(sum(weights)) < fscore] #add 1 if fscore higher than a number taken at random between 0 and the cumulative weight of its DESIRABLE neighbors
if len(count) > 5:
grid[site[i]] = unit
#If 4 neighbors and high probability, 1 of them must belong to the same space
if len(neighbors) > 3:
fscore = sum([weights[n] for n in neighbors if n in pindices]) #cumulative weight of its ACTUAL neighbors
count = [1 for t in range(10) if random(sum(weights)) < fscore] #add 1 if fscore higher than a number taken at random between 0 and the cumulative weight of its DESIRABLE neighbors
if len(count) > 5 and unit in neighbors:
grid[site[i]] = unit
#if random grid cell not empty -> pass
else: pass
考虑到大部分单元不会放在第一个 运行(因为相邻概率低),我们需要反复迭代,直到所有单元都可以随机分布找到合适的。
几千次迭代后找到一个合适的并且满足所有相邻要求。
但是请注意此算法如何生成分离的组,而不是像提供的示例中那样生成未划分和统一的堆栈。我还应该补充一点,将近5000次迭代比Terzidis先生在他的书中提到的274次迭代要多得多
问题:
- 我处理这个算法的方式有问题吗?
- 如果不是,那么我缺少什么隐含条件?
我提出的解决这一挑战的解决方案是在记录有效解决方案的同时多次重复该算法。由于解决方案不是唯一的,我希望算法抛出不止 1 个解决方案。他们每个人都会有一个基于邻居亲和力的分数。
我将调用“尝试”来完成 运行 尝试找到有效的植物分布。完整脚本 运行 将包含 N
次尝试。
每次尝试都从 2 个随机(统一)选择开始:
- 网格中的起点
- 就职
一旦定义了一个点和一个办公室,就会出现一个“扩展过程”,试图将所有办公大楼放入网格中。
每个新块都按照他的程序设置:
- 第一。计算办公室每个相邻单元格的亲和力。
- 第二。随机select一个站点。选择应该由亲和力来加权。
放置完每一个办公楼后,还需要统一随机选择:下一个要放置的办公楼。
选择后,您应该再次计算每个站点的亲和力,并随机(加权)select 新办公室的起点。
0
affinity offices don't add. Probability factor should be 0
for
that point in the grid. Affinity function selection is an iteresting
part of this problem. You could try with the addition or even the
multiplication of adjacent cells factor.
扩展过程再次参与,直到办公室的每一块都被放置。
所以基本上,办公室选择遵循均匀分布,然后,加权扩展过程发生在 selected 办公室。
尝试什么时候结束?,
如果:
- 没有必要在网格中放置一个新办公室(都有
affinity = 0
)
- Office 无法扩展,因为所有亲和力权重都等于 0
那么该尝试无效,应该放弃并转向全新的随机尝试。
否则,如果所有块都适合:它是有效的。
重点是办公室应该团结在一起。这是该算法的关键点,它随机尝试根据亲和力来适应每个新办公室,但仍然是一个随机过程。如果不满足条件(无效),随机过程将再次开始选择新的随机网格点和办公室。
抱歉,这里只有算法,没有代码。
注意:我相信亲和力计算过程可以改进,甚至您可以尝试一些不同的方法。这只是帮助您获得解决方案的想法。
希望对您有所帮助。
我相信 Kostas Terzidis 教授会是一位出色的计算机理论研究人员,但他的算法解释根本无济于事。
首先,邻接矩阵没有任何意义。在你说的问题评论中:
"the higher that value is, the higher the probability that the two spaces are adjecent is"
但 m[i][i] = 0
,这意味着同一 "office" 的人更喜欢其他办公室作为邻居。这与您的预期完全相反,不是吗?我建议改用这个矩阵:
With 1 <= i, j <= 5:
+----------------+
| 10 6 1 5 2 |
| 10 1 4 0 |
m[i][j] = | 10 8 0 |
| 10 3 |
| 10 |
+----------------+
有了这个矩阵,
- 最高值为 10。所以
m[i][i] = 10
正是您想要的意思:同一个办公室的人应该在一起。
- 最低值为0。(根本不应该联系的人)
算法
第一步:开始随机放置所有地方
(很抱歉基于 1 的矩阵索引,但它要与邻接矩阵保持一致。)
With 1 <= x <= 5 and 1 <= y <= 7:
+---------------------+
| - - 1 2 1 4 3 |
| 1 2 4 5 1 4 3 |
p[x][y] = | 2 4 2 4 3 2 4 |
| - - - - 3 2 4 |
| - - - - 5 3 3 |
+---------------------+
第 2 步:对解决方案进行评分
对于所有个地方p[x][y]
,使用邻接矩阵计算得分。例如,第一名1
有2
和4
为邻居,所以得分为11:
score(p[1][3]) = m[1][2] + m[1][4] = 11
所有个人分数的总和将是解决方案分数。
第 3 步:通过交换位置优化当前解决方案
对于每一对地方p[x1][y1], p[x2][y2]
,交换它们并再次评估解决方案,如果得分更好,则保留新解决方案。在任何情况下重复步骤 3,直到没有排列能够改进解决方案。
例如,如果您将 p[1][4]
与 p[2][1]
交换:
+---------------------+
| - - 1 1 1 4 3 |
| 2 2 4 5 1 4 3 |
p[x][y] = | 2 4 2 4 3 2 4 |
| - - - - 3 2 4 |
| - - - - 5 3 3 |
+---------------------+
您会找到得分更高的解决方案:
交换前
score(p[1][3]) = m[1][2] + m[1][4] = 11
score(p[2][1]) = m[1][2] + m[1][2] = 12
交换后
score(p[1][3]) = m[1][1] + m[1][4] = 15
score(p[2][1]) = m[2][2] + m[2][2] = 20
所以保留它并继续交换位置。
一些笔记
- 请注意,鉴于在迭代的某个时刻您将无法交换 2 个位置并获得更好的分数,因此算法将始终最终确定。
- 在一个有
N
个位置的矩阵中,有 N x (N-1)
个可能的交换,并且可以通过有效的方式完成(因此,不需要蛮力)。
希望对您有所帮助!
我需要帮助来实现允许生成建筑计划的算法,这是我最近在阅读 Kostas Terzidis 教授的最新出版物时偶然发现的:Permutation Design: Buildings, Texts and Contexts (2014)。
上下文
- 考虑划分为网格系统 (a) 的站点 (b)。
- 我们还考虑要放置在站点范围内的空间列表 (c) 和邻接矩阵以确定这些空间的放置条件和相邻关系 (d)
引用 Terzidis 教授的话:
"A way of solving this problem is to stochastically place spaces within the grid until all spaces are fit and the constraints are satisfied"
上图显示了这样的问题和示例解决方案 (f)。
算法(如书中简要描述)
1/"Each space is associated with a list that contains all other spaces sorted according to their degree of desirable neighborhood."
2/"Then each unit of each space is selected from the list and then one-by-one placed randomly in the site until they fit in the site and the neighboring conditions are met. (If it fails then the process is repeated)"
九个随机生成计划的示例:
我要补充一点,作者稍后会解释这个算法不依赖于暴力破解技术。
问题
如您所见,解释相对含糊,步骤 2 相当不清楚(在编码方面)。到目前为止我只有 "pieces of a puzzle":
- a "site"(选定整数列表)
- 邻接矩阵(嵌套列表)
- "spaces"(列表字典)
每个单元:
- 一个函数 returns 它的直接邻居
- 其理想邻居的列表及其索引按排序顺序
基于其实际邻居的适应度得分
from random import shuffle n_col, n_row = 7, 5 to_skip = [0, 1, 21, 22, 23, 24, 28, 29, 30, 31] site = [i for i in range(n_col * n_row) if i not in to_skip] fitness, grid = [[None if i in to_skip else [] for i in range(n_col * n_row)] for e in range(2)] n = 2 k = (n_col * n_row) - len(to_skip) rsize = 50 #Adjacency matrix adm = [[0, 6, 1, 5, 2], [6, 0, 1, 4, 0], [1, 1, 0, 8, 0], [5, 4, 8, 0, 3], [2, 0, 0, 3, 0]] spaces = {"office1": [0 for i in range(4)], "office2": [1 for i in range(6)], "office3": [2 for i in range(6)], "passage": [3 for i in range(7)], "entry": [4 for i in range(2)]} def setup(): global grid size(600, 400, P2D) rectMode(CENTER) strokeWeight(1.4) #Shuffle the order for the random placing to come shuffle(site) #Place units randomly within the limits of the site i = -1 for space in spaces.items(): for unit in space[1]: i+=1 grid[site[i]] = unit #For each unit of each space... i = -1 for space in spaces.items(): for unit in space[1]: i+=1 #Get the indices of the its DESIRABLE neighbors in sorted order ada = adm[unit] sorted_indices = sorted(range(len(ada)), key = ada.__getitem__)[::-1] #Select indices with positive weight (exluding 0-weight indices) pindices = [e for e in sorted_indices if ada[e] > 0] #Stores its fitness score (sum of the weight of its REAL neighbors) fitness[site[i]] = sum([ada[n] for n in getNeighbors(i) if n in pindices]) print 'Fitness Score:', fitness def draw(): background(255) #Grid's background fill(170) noStroke() rect(width/2 - (rsize/2) , height/2 + rsize/2 + n_row , rsize*n_col, rsize*n_row) #Displaying site (grid cells of all selected units) + units placed randomly for i, e in enumerate(grid): if isinstance(e, list): pass elif e == None: pass else: fill(50 + (e * 50), 255 - (e * 80), 255 - (e * 50), 180) rect(width/2 - (rsize*n_col/2) + (i%n_col * rsize), height/2 + (rsize*n_row/2) + (n_row - ((k+len(to_skip))-(i+1))/n_col * rsize), rsize, rsize) fill(0) text(e+1, width/2 - (rsize*n_col/2) + (i%n_col * rsize), height/2 + (rsize*n_row/2) + (n_row - ((k+len(to_skip))-(i+1))/n_col * rsize)) def getNeighbors(i): neighbors = [] if site[i] > n_col and site[i] < len(grid) - n_col: if site[i]%n_col > 0 and site[i]%n_col < n_col - 1: if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1]) if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1]) if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col]) if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col]) if site[i] <= n_col: if site[i]%n_col > 0 and site[i]%n_col < n_col - 1: if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1]) if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1]) if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col]) if site[i]%n_col == 0: if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1]) if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col]) if site[i] == n_col-1: if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1]) if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col]) if site[i] >= len(grid) - n_col: if site[i]%n_col > 0 and site[i]%n_col < n_col - 1: if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1]) if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1]) if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col]) if site[i]%n_col == 0: if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1]) if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col]) if site[i]%n_col == n_col-1: if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1]) if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col]) if site[i]%n_col == 0: if site[i] > n_col and site[i] < len(grid) - n_col: if grid[site[i]+1] != None: neighbors.append(grid[site[i]+1]) if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col]) if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col]) if site[i]%n_col == n_col - 1: if site[i] > n_col and site[i] < len(grid) - n_col: if grid[site[i]-1] != None: neighbors.append(grid[site[i]-1]) if grid[site[i]+n_col] != None: neighbors.append(grid[site[i]+n_col]) if grid[site[i]-n_col] != None: neighbors.append(grid[site[i]-n_col]) return neighbors
如果有人能帮我解释一下,我将不胜感激:
- 如何根据理想邻域的程度对单元重新排序?
编辑
你们中的一些人已经注意到,该算法基于某些空间(由单元组成)相邻的可能性。按照逻辑,每个单元都将随机放置在站点范围内:
- 我们事先检查它的直接邻居(上、下、左、右)
- 如果至少有 2 个邻居,则计算适合度分数。 (=这 2+ 个邻居的权重之和)
- 如果邻接概率高,最后放置那个单元
粗略地说,它会翻译成这样:
i = -1
for space in spaces.items():
for unit in space[1]:
i+=1
#Get the indices of the its DESIRABLE neighbors (from the adjacency matrix 'adm') in sorted order
weights = adm[unit]
sorted_indices = sorted(range(len(weights)), key = weights.__getitem__)[::-1]
#Select indices with positive weight (exluding 0-weight indices)
pindices = [e for e in sorted_indices if weights[e] > 0]
#If random grid cell is empty
if not grid[site[i]]:
#List of neighbors
neighbors = [n for n in getNeighbors(i) if isinstance(n, int)]
#If no neighbors -> place unit
if len(neighbors) == 0:
grid[site[i]] = unit
#If at least 1 of the neighbors == unit: -> place unit (facilitate grouping)
if len(neighbors) > 0 and unit in neighbors:
grid[site[i]] = unit
#If 2 or 3 neighbors, compute fitness score and place unit if probability is high
if len(neighbors) >= 2 and len(neighbors) < 4:
fscore = sum([weights[n] for n in neighbors if n in pindices]) #cumulative weight of its ACTUAL neighbors
count = [1 for t in range(10) if random(sum(weights)) < fscore] #add 1 if fscore higher than a number taken at random between 0 and the cumulative weight of its DESIRABLE neighbors
if len(count) > 5:
grid[site[i]] = unit
#If 4 neighbors and high probability, 1 of them must belong to the same space
if len(neighbors) > 3:
fscore = sum([weights[n] for n in neighbors if n in pindices]) #cumulative weight of its ACTUAL neighbors
count = [1 for t in range(10) if random(sum(weights)) < fscore] #add 1 if fscore higher than a number taken at random between 0 and the cumulative weight of its DESIRABLE neighbors
if len(count) > 5 and unit in neighbors:
grid[site[i]] = unit
#if random grid cell not empty -> pass
else: pass
考虑到大部分单元不会放在第一个 运行(因为相邻概率低),我们需要反复迭代,直到所有单元都可以随机分布找到合适的。
几千次迭代后找到一个合适的并且满足所有相邻要求。
但是请注意此算法如何生成分离的组,而不是像提供的示例中那样生成未划分和统一的堆栈。我还应该补充一点,将近5000次迭代比Terzidis先生在他的书中提到的274次迭代要多得多
问题:
- 我处理这个算法的方式有问题吗?
- 如果不是,那么我缺少什么隐含条件?
我提出的解决这一挑战的解决方案是在记录有效解决方案的同时多次重复该算法。由于解决方案不是唯一的,我希望算法抛出不止 1 个解决方案。他们每个人都会有一个基于邻居亲和力的分数。
我将调用“尝试”来完成 运行 尝试找到有效的植物分布。完整脚本 运行 将包含 N
次尝试。
每次尝试都从 2 个随机(统一)选择开始:
- 网格中的起点
- 就职
一旦定义了一个点和一个办公室,就会出现一个“扩展过程”,试图将所有办公大楼放入网格中。
每个新块都按照他的程序设置:
- 第一。计算办公室每个相邻单元格的亲和力。
- 第二。随机select一个站点。选择应该由亲和力来加权。
放置完每一个办公楼后,还需要统一随机选择:下一个要放置的办公楼。
选择后,您应该再次计算每个站点的亲和力,并随机(加权)select 新办公室的起点。
0
affinity offices don't add. Probability factor should be0
for that point in the grid. Affinity function selection is an iteresting part of this problem. You could try with the addition or even the multiplication of adjacent cells factor.
扩展过程再次参与,直到办公室的每一块都被放置。
所以基本上,办公室选择遵循均匀分布,然后,加权扩展过程发生在 selected 办公室。
尝试什么时候结束?, 如果:
- 没有必要在网格中放置一个新办公室(都有
affinity = 0
) - Office 无法扩展,因为所有亲和力权重都等于 0
那么该尝试无效,应该放弃并转向全新的随机尝试。
否则,如果所有块都适合:它是有效的。
重点是办公室应该团结在一起。这是该算法的关键点,它随机尝试根据亲和力来适应每个新办公室,但仍然是一个随机过程。如果不满足条件(无效),随机过程将再次开始选择新的随机网格点和办公室。
抱歉,这里只有算法,没有代码。
注意:我相信亲和力计算过程可以改进,甚至您可以尝试一些不同的方法。这只是帮助您获得解决方案的想法。
希望对您有所帮助。
我相信 Kostas Terzidis 教授会是一位出色的计算机理论研究人员,但他的算法解释根本无济于事。
首先,邻接矩阵没有任何意义。在你说的问题评论中:
"the higher that value is, the higher the probability that the two spaces are adjecent is"
但 m[i][i] = 0
,这意味着同一 "office" 的人更喜欢其他办公室作为邻居。这与您的预期完全相反,不是吗?我建议改用这个矩阵:
With 1 <= i, j <= 5:
+----------------+
| 10 6 1 5 2 |
| 10 1 4 0 |
m[i][j] = | 10 8 0 |
| 10 3 |
| 10 |
+----------------+
有了这个矩阵,
- 最高值为 10。所以
m[i][i] = 10
正是您想要的意思:同一个办公室的人应该在一起。 - 最低值为0。(根本不应该联系的人)
算法
第一步:开始随机放置所有地方
(很抱歉基于 1 的矩阵索引,但它要与邻接矩阵保持一致。)
With 1 <= x <= 5 and 1 <= y <= 7:
+---------------------+
| - - 1 2 1 4 3 |
| 1 2 4 5 1 4 3 |
p[x][y] = | 2 4 2 4 3 2 4 |
| - - - - 3 2 4 |
| - - - - 5 3 3 |
+---------------------+
第 2 步:对解决方案进行评分
对于所有个地方p[x][y]
,使用邻接矩阵计算得分。例如,第一名1
有2
和4
为邻居,所以得分为11:
score(p[1][3]) = m[1][2] + m[1][4] = 11
所有个人分数的总和将是解决方案分数。
第 3 步:通过交换位置优化当前解决方案
对于每一对地方p[x1][y1], p[x2][y2]
,交换它们并再次评估解决方案,如果得分更好,则保留新解决方案。在任何情况下重复步骤 3,直到没有排列能够改进解决方案。
例如,如果您将 p[1][4]
与 p[2][1]
交换:
+---------------------+
| - - 1 1 1 4 3 |
| 2 2 4 5 1 4 3 |
p[x][y] = | 2 4 2 4 3 2 4 |
| - - - - 3 2 4 |
| - - - - 5 3 3 |
+---------------------+
您会找到得分更高的解决方案:
交换前
score(p[1][3]) = m[1][2] + m[1][4] = 11
score(p[2][1]) = m[1][2] + m[1][2] = 12
交换后
score(p[1][3]) = m[1][1] + m[1][4] = 15
score(p[2][1]) = m[2][2] + m[2][2] = 20
所以保留它并继续交换位置。
一些笔记
- 请注意,鉴于在迭代的某个时刻您将无法交换 2 个位置并获得更好的分数,因此算法将始终最终确定。
- 在一个有
N
个位置的矩阵中,有N x (N-1)
个可能的交换,并且可以通过有效的方式完成(因此,不需要蛮力)。
希望对您有所帮助!