你的问题似乎与
weighted minimum vertex cover problem(这是NP-complete)相似.感谢@Gareth Rees的下面的评论,澄清了我不明白顶点封面与你正在寻找的集合的关系.但是,您仍然可以调查顶点覆盖问题和文献,因为您的问题可能会在旁边讨论,因为它们仍然具有一些功能.
如果您愿意使用直径而不是总和图重量,则可以使用您在问题中链接的最小直径集的方法.如果您当前的距离测量称为d(您希望距离彼此最远的点),则只需定义d’= 1 / d,并用d’求解最小距离问题.
某些形式的图形切割算法(例如normalized cut)与您寻求的子集之间也可能存在关系.如果您的距离度量用作节点之间的图形权重或亲和度,您可能可以修改现有的图形切割目标函数以匹配您的目标函数(查找具有最大相加权重的k个节点组).
这似乎是一个组合困难的问题.你可以考虑一些简单的模拟退火.提议函数可以随机选择当前在k子集中的点,并用当前不在k子集中的点随机地替换它.
您将需要一个很好的温度计划,并可能需要使用再热作为成本的函数.但这样做真的很简单.只要n相当小,就可以随机地随机选择k个子集,并且朝向具有非常大的总距离的k子集退火.
这只会给你一个近似值,但即使是确定性的方法也许会大概解决这个问题.
以下是模拟退火代码可能出现的第一个错误.请注意,我没有对此做出保证.如果计算距离太大或者问题实例大小增加太大,这可能是一个低效的解决方案.我使用非常幼稚的几何冷却与固定的冷却速度,你可能还想修补一个鸽友的建议,而不仅仅是随机交换节点.
all_nodes = np.asarray(...) # Set of nodes
all_dists = np.asarray(...) # Pairwise distances
N = len(all_nodes)
k = 10 # Or however many you want.
def calculate_distance(node_subset, distances):
# A function you write to determine sum of distances
# among a particular subset of nodes.
# Initial random subset of k elements
shuffle = np.random.shuffle(all_nodes)
current_subset = shuffle[0:k]
current_outsiders = shuffle[k:]
# Simulated annealing parameters.
temp = 100.0
cooling_rate = 0.95
num_iters = 10000
# Simulated annealing loop.
for ii in range(num_iters):
proposed_subset = current_subset.copy()
proposed_outsiders = current_outsiders.copy()
index_to_swap = np.random.randint(k)
outsider_to_swap = np.random.randint(N - k)
tmp = current_subset[index_to_swap]
proposed_subset[index_to_swap] = current_outsiders[outsider_to_swap]
proposed_outsiders[outsider_to_swap] = tmp
potential_change = np.exp((-1.0/temp)*
calculate_distance(proposed_subset,all_dists)/
calculate_distance(current_subset, all_dists))
if potential_change > 1 or potential_change >= np.random.rand():
current_subset = proposed_subset
current_outsiders = proposed_outsiders
temp = cooling_rate * temp