Можно рассчитать оптимальную полную сетку некоторых графов из других вычисленных графов.Для данной полной сетки, если мы отметим узлы, которые были вырезаны из исходного графа для создания текущего подграфа, мы обнаружим, что любые другие ребра, соединяющиеся с этими узлами разреза, могут свободно, но без последствий вырезать.Используя эту информацию, мы можем взять декартово произведение узлов разреза и всех других узлов, удалить любые эквивалентные дубликаты и получить набор всех ребер, которые мы можем свободно вырезать.Затем мы берем powerset всех этих ребер и соединяем каждый с нашим текущим списком ломаных ребер, чтобы определить другие подграфы, которые неизбежно приведут к той же оптимальной полной сетке.Модифицированный класс FullMesh, который реализует это поведение, можно увидеть ниже:
class FullMesh:
def __init__(self, weights, pairs=[]):
self.weights = weights
self.elements = set(range(len(weights)))
self.set_pairs(pairs)
def set_pairs(self, pairs):
self.pairs = pairs
self.skips = {e:set() for e in self.elements}
for i, (a, b) in enumerate(pairs):
self.skips[a].add(i)
self.skips[b].add(i)
def powerset(self, elements):
return chain.from_iterable(combinations(elements, r) for r in range(len(elements)+1))
def find_all(self):
to_search = self.powerset(list(combinations(self.elements, 2)))
pairs_searched = dict()
for pairs in to_search:
if pairs in pairs_searched: continue
self.set_pairs(pairs)
val, nums = self.find_max()
new_pairs = set(product(set(self.elements) - set(nums), set(self.elements))) - set(pairs)
new_pairs = self.powerset({(x, y) for x, y in new_pairs if x < y})
pairs_searched.update({tuple(sorted(pairs + np)):(val,nums) for np in new_pairs})
return pairs_searched
def find_max(self):
max_score = sum(self.weights)
val, nums = self.exclude(0, max_score + 1, set(range(len(self.pairs))))
return max_score - val, sorted(self.elements - set(nums))
def exclude(self, curr_score, min_score, search):
if not search or min_score <= curr_score:
return curr_score, []
min_nums = []
for e in self.pairs[next(iter(search))]:
score, nums = self.exclude(curr_score + self.weights[e], min_score, search - self.skips[e])
if score < min_score:
min_score, min_nums = score, nums + [e]
return min_score, min_nums
Этот код занял ~ 50 секунд для создания всех оптимальных полных сеток для всех подграфов случайно взвешенного 7-узлового полностью связного графа.