-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathNetShieldSolver.py
95 lines (81 loc) · 3.12 KB
/
NetShieldSolver.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
import networkx as nx
import numpy as np
import time
import sys
import itertools
from scipy.linalg import eigh
import os
from heapq import *
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from Solver import *
class PriorityQueue:
def __init__(self, initlist):
self.counter = itertools.count() # unique sequence count
self.entry_finder = {} # mapping of tasks to entries
self.pq = []
for el in initlist:
entry = [-el[0], next(self.counter), el[1]]
self.pq.append(entry)
self.entry_finder[el[1]] = entry
heapify(self.pq) # list of entries arranged in a heap
self.REMOVED = '<removed-task>' # placeholder for a removed task
def update_task_add(self, task, add_value):
priority = 0
if task in self.entry_finder:
entry = self.entry_finder.pop(task)
entry[-1] = self.REMOVED
priority = entry[0]
count = next(self.counter)
entry = [priority-add_value, count, task]
self.entry_finder[task] = entry
heappush(self.pq, entry)
def add_task(self, task, priority=0):
'Add a new task or update the priority of an existing task'
if task in self.entry_finder:
self.remove_task(task)
count = next(self.counter)
entry = [-priority, count, task]
self.entry_finder[task] = entry
heappush(self.pq, entry)
def remove_task(self, task):
'Mark an existing task as REMOVED. Raise KeyError if not found.'
entry = self.entry_finder.pop(task)
entry[-1] = self.REMOVED
def pop_task(self):
'Remove and return the lowest priority task. Raise KeyError if empty.'
while self.pq:
priority, count, task = heappop(self.pq)
if task is not self.REMOVED:
del self.entry_finder[task]
return task
raise KeyError('pop from an empty priority queue')
class NetShieldSolver(Solver):
def net_shield(self):
G = self.G.to_undirected()
nodelist = [n for n in G.nodes()]
inverse_index = {}
for i in range(len(nodelist)):
inverse_index[nodelist[i]] = i
t1 = time.time()
A = nx.to_numpy_matrix(G, nodelist=nodelist, weight=None)
M = len(G)
W, V = eigh(A, eigvals=(M-1, M-1), type=1, overwrite_a=True)
max_eig = W[0]
max_eigvec = V[:,0].reshape((V.shape[0],))
self.log["Eigenvalue"] = max_eig
scores = 2*max_eig*(max_eigvec**2)
pk = PriorityQueue(zip(scores.tolist(), list(range(len(G)))))
S = set()
for it in range(self.k):
next_best = pk.pop_task()
S.add(next_best)
for n in G.neighbors(nodelist[next_best]):
j = inverse_index[n]
if j not in S:
pk.update_task_add(j, -2 * max_eigvec[next_best] * max_eigvec[j])
t2 = time.time()
self.log['Total time'] = t2-t1
return [nodelist[i] for i in S]
def run(self):
blocked = self.net_shield()
self.log['Blocked nodes'] = [int(node) for node in blocked]