Ваша проблема была похожа на weighted minimum vertex cover problem (которая NP-полная). Спасибо @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
Re: все точки решения на выпуклой оболочке: Это не так, к сожалению, как выпуклая оболочка может иметь меньше, чем 'к 'вершины. – us2012
Тогда это правда, если _k_ <_h_, с _h_ количеством точек в корпусе? – Nathan
Часто «самый дальний»/«самый длинный» сложнее, чем «ближайший» с графиками. Do * not * думайте, что если вы можете найти самые близкие точки/минимум чего-то, чем вы также можете найти самые дальние точки/максимум чего-то с главным образом тем же кодом и тем же самым временем. – Bakuriu