-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgraph_methods.py
119 lines (93 loc) · 3.62 KB
/
graph_methods.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import time
import random
import networkx as nx
from statistics import mean
from collections import defaultdict
import os
def getSupports(g):
leaves = set()
supports = set()
for node in g:
if node in supports or node in leaves:
continue
if g.degree(node) == 0:
supports.add(node)
elif g.degree(node) == 1:
leaves.add(node)
supports.add(next(g.neighbors(node)))
return supports
def pruneSet(currSolution, g):
assert nx.algorithms.dominating.is_dominating_set(g, currSolution), "Initial solution is not a dominating set"
for i in range(len(currSolution) - 1, -1, -1):
remNode = currSolution[i]
isDominated = False
neighborsDominated = True
for neigh in g.neighbors(remNode):
if neigh in currSolution and neigh != remNode:
# At least one neighbor must be in the solution if we are removing this node
isDominated = True
else:
# If neighbor not in solution, one of the neighbor's neighbors (other than the node being removed) must be in the solution
currDominated = False
for neigh2 in g.neighbors(neigh):
if neigh2 == remNode:
continue
if neigh2 in currSolution:
currDominated = True
break
if not currDominated:
neighborsDominated = False
break
if isDominated and neighborsDominated:
currSolution[i], currSolution[-1] = currSolution[-1], currSolution[i]
currSolution.pop()
def getBestMDS(g, predictions):
bestSolution = list(g)
for prediction in predictions.transpose():
potentialSolution = buildMDS(g, prediction, set())
bestSolution = potentialSolution if len(potentialSolution) < len(bestSolution) else bestSolution
return bestSolution
def buildMDS(g, prediction, supportNodes):
sortedNodes = sorted(zip(list(g), prediction), key=lambda x: x[1], reverse=True)
nodeOrder = list(supportNodes)
for x in sortedNodes:
if x not in supportNodes:
nodeOrder.append(x[0])
# Build minimum dominating set using binary search
min = len(supportNodes)
max = len(nodeOrder) - 1
while min < max:
mid = (max + min) // 2
currSolution = nodeOrder[:mid+1]
if nx.algorithms.dominating.is_dominating_set(g, currSolution):
max = mid
else:
min = mid + 1
currSolution = nodeOrder[:min+1]
assert min == max
assert nx.algorithms.dominating.is_dominating_set(g,currSolution)
pruneSet(currSolution, g)
return sorted(currSolution)
def buildComboMDS(g, currNodes, prediction):
sortedNodes = sorted(enumerate(prediction), key=lambda x: x[1], reverse=True)
currNodeSet = set(currNodes)
nodeOrder = []
for x in sortedNodes:
if x[0] not in currNodeSet:
nodeOrder.append(x[0])
# Build minimum dominating set using binary search
min = 0
max = len(nodeOrder) - 1
while min < max:
mid = (max + min) // 2
currSolution = nodeOrder[:mid+1] + currNodes
if nx.algorithms.dominating.is_dominating_set(g, currSolution):
max = mid
else:
min = mid + 1
currSolution = nodeOrder[:min+1] + currNodes
assert min == max, f"min is {min} and max is {max}"
assert nx.algorithms.dominating.is_dominating_set(g,currSolution)
# Prune the dominating set
pruneSet(currSolution, g)
return sorted(currSolution)