annotate tools/myTools/bin/FVS_python3/FVS_localsearch_10_python.py @ 1:7e5c71b2e71f draft default tip

Uploaded
author laurenmarazzi
date Wed, 22 Dec 2021 16:00:34 +0000
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
1 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
2 This file contains functions used to calculate feedback vertex set for directed graph
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
3
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
4 The major function is the FVS_local_search(), which calculate maximum sub topological ordering of a graph
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
5 The algorithm is given by "Applying local search to feedback vertex set problem"
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
6 Author of the paper Philippe Galinier, Eunice Lemamou, Mohamed Wassim Bouzidi
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
7 The code mimic the pseudocode given in Page 805 in that paper
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
8 The code is written by Gang Yang, Penn State University
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
9 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
10
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
11
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
12 import networkx as nx
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
13 import random
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
14 import math
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
15 import array
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
16
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
17
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
18
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
19 #the following two function calculate the position for the candidate given the existing topological ordering S
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
20 def get_position_minus(candidate_incoming_neighbour, S):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
21 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
22 get_position_minus return position as just after its numbered in-coming neighbours
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
23 As in the paper, the function return i_minus(v)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
24 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
25 position = 1
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
26 for x in range(len(S)-1,-1,-1): #we loop through index from the end as we try to find the largest index of numbered incoming neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
27 if S[x] in candidate_incoming_neighbour:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
28 position = x+2 #2 comes from we need to put candidate after the incoming neighbour and also the position count from 1 instead of 0
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
29 return position
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
30 return position #put the candidate in the first position if there is no numbered incoming neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
31
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
32
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
33
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
34 def get_position_plus(candidate_outgoing_neighbour, S):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
35 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
36 get_position_plus return position as just before its numbered out-going neighbours
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
37 As in the paper, the function return i_plus(v)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
38 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
39 position = 1+len(S)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
40 for x in range(len(S)): #we loop through index from the beginning as we try to find the smallest index of numbered outgoing neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
41 if S[x] in candidate_outgoing_neighbour:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
42 position = x+1 #1 comes from the fact position count from 1 instead of 0
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
43 return position
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
44 return position #put the candidate in the first position if there is no numbered outgoing neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
45
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
46
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
47
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
48 def FVS_local_search(G_input, T_0, alpha, maxMvt, maxFail, randomseed=None):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
49 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
50 Returns an maximum sub topological ordering of a DiGraph G.
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
51 FVS is G_input \ the topological ordering
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
52 A topological ordering of a graph is an ordering of vertices such that
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
53 the starting point of every arc occurs earlier in the ordering than
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
54 the endpoint of the art.
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
55
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
56 This algorithm is a fast approximation based on simulating annealing(SA) of a noval local search strategy [1]_.
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
57 The code follows the pseudocode given in Page 805 in that paper.
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
58
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
59
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
60 Parameters
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
61 ----------
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
62 G : NetworkX Graph/DiGraph, result for MultiGraph is not tested
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
63 T_0 : the initial temperature in SA
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
64 alpha : the cooling multiplier for temperatue in the geometric cooling regime
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
65 maxMvt_factor : maxMvt_factor times network size is the number of iterations for the inner loop given a fixed temperatue
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
66 maxFail : FVS_local_search stops when maxFail number of outloops (temperatue) fail to improve the result
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
67 randomseed: random seed for generating random numbers
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
68
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
69 Returns
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
70 -------
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
71 An approximation of the maximum ordering of the given graph as a list.
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
72
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
73
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
74 Notes
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
75 -----
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
76 The code is written by Gang Yang, Department of Physics, Penn State University
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
77
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
78
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
79 References
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
80 ----------
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
81 ..[1] Galinier, P., Lemamou, E. & Bouzidi, M.W. J Heuristics (2013) 19: 797. doi:10.1007/s10732-013-9224-z
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
82
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
83 '''
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
84 #set a random seed
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
85 random.seed(randomseed)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
86 G=G_input.copy()
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
87 N= len(G.nodes()) #number of nodes in the graph
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
88 edges=G.edges()
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
89
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
90
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
91 #Initialization
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
92 T = T_0 #set initial temperatue
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
93 nbFail = 0 #Outer loop counter to record failure times
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
94 S = [] #list to record the ascending ordering
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
95 S_optimal = [] #list to record the optimal ordering
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
96
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
97
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
98 #calculate parent and child node for each node
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
99 parent = [{} for i in range(N)]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
100 child = [{} for i in range(N)]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
101
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
102 for edge in edges:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
103 child[int(edge[0])][int(edge[1])]=None
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
104 parent[int(edge[1])][int(edge[0])]=None
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
105
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
106 #all the nodes that are self_loops
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
107 self_loops = [edge[0] for edge in edges if edge[0]==edge[1]]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
108 print(self_loops)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
109 #all the nodes that is not in S
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
110 unnumbered=[x for x in range(N) if x not in self_loops]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
111 N_unnumbered = len(unnumbered)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
112 while nbFail< maxFail:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
113 nbMvt = 0 #Inner loop counter to record movement times
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
114 failure = True #if cardinal of S increase after one inner loop, failure will be set to false
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
115 while nbMvt < maxMvt:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
116 candidate_index = random.randint(0, N_unnumbered-1)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
117 candidate = unnumbered[candidate_index] #random pick a node from all unnumbered node
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
118 position_type = random.randint(0,1) #random choose a position type
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
119 #calculate incoming/outgoing neighbour for the candidate node, store as keys in the dict
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
120 candidate_incoming_neighbour = parent[candidate]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
121 candidate_outgoing_neighbour = child[candidate]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
122 #see how to find the position on Page 803 of the paper
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
123 #position_type=1 means just after incoming neighbours
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
124 if position_type==1:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
125 position = get_position_minus(candidate_incoming_neighbour,S)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
126 #position_type=0 means just before outgoint neighbours
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
127 elif position_type==0:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
128 position = get_position_plus(candidate_outgoing_neighbour,S)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
129
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
130 #first, insert the candidate to the given position
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
131 S_trail = S[:] #copy the list
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
132 S_trail.insert(position-1,candidate)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
133
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
134 #second remove all the conflict
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
135 #break the sequence into two parts: before and after the candidate node and
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
136 S_trail_head= S_trail[:position-1]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
137 S_trail_tail= S_trail[position:]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
138 #determine conflict node See page 801
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
139 if position_type==1:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
140 CV_pos=[] #conflict before the newly inserted node in the topological ordering
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
141 for x in range(len(S_trail_head)):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
142 nodetemp=S_trail_head[x]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
143 #print nodetemp,candidate_outgoing_neighbour,nodetemp in candidate_outgoing_neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
144 if nodetemp in candidate_outgoing_neighbour:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
145 CV_pos.append(nodetemp)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
146 conflict=CV_pos #there won't be conflict after the inserted node as the node inserted after its incoming neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
147 elif position_type==0:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
148 CV_neg=[] #conflict after the newly inserted node in the topological ordering
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
149 for x in range(len(S_trail_tail)):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
150 nodetemp=S_trail_tail[x]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
151 #print nodetemp,candidate_incoming_neighbour,nodetemp in candidate_incoming_neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
152 if nodetemp in candidate_incoming_neighbour:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
153 CV_neg.append(nodetemp)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
154 conflict=CV_neg #there won't be conflict before the inserted node as the node inserted before its outgoing neighbour
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
155 #finally remove the conflict node
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
156 N_conflict=len(conflict)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
157 if N_conflict>0:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
158 for i in range(N_conflict):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
159 S_trail.remove(conflict[i])
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
160
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
161 #third, evaluate the move
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
162 #delta_move=-len(S_trail)+len(S)
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
163 delta_move=N_conflict-1
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
164 #accept all the move that is not harmful, otherwise use metrospolis algorithm
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
165 if delta_move<=0 or math.exp(-delta_move/float(T))>random.random():
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
166 S = S_trail[:]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
167 #update unnumbered nodes
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
168 unnumbered.remove(candidate) #remove the node just inserted
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
169 if N_conflict>0: #add all the conflict node just removed
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
170 for i in range(N_conflict):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
171 unnumbered.append(conflict[i])
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
172 N_unnumbered+=delta_move
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
173 nbMvt = nbMvt+1
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
174 #update S_optimal only when there is increase in cardinal of the sequence
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
175 if len(S)>len(S_optimal):
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
176 S_optimal = S[:]
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
177 failure = False
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
178 if N_unnumbered==0:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
179 return S_optimal
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
180
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
181 #Increment the failure times if no progress in size of the sequence
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
182 if failure==True:
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
183 nbFail+=1
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
184 else: #otherwise reset the num of failure times
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
185 nbFail=0
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
186 #shrink the temperatue by factor alpha
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
187 T=T*alpha
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
188 #print T
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
189 #print nbFail
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
190 return S_optimal
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
191
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
192
7e5c71b2e71f Uploaded
laurenmarazzi
parents:
diff changeset
193