Skip to content

Commit 9dbf2bc

Browse files
committed
update leakage detection
1 parent b7ad038 commit 9dbf2bc

13 files changed

+879
-299
lines changed

AlgorithmComparison.py

Lines changed: 62 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ def astar_search(g, position, ur):
115115

116116
# One row in the table means one graph, but some rows are different but have same edges to remove because some different nodes may locate in the same
117117
# edge, so the length of final graph list may longer than the table
118-
def VeSpAGraphGenerator(table, nodes_group_list, vcofe, g):
118+
def VespaGraphGenerator(table, nodes_group_list, vcofe, g):
119119
g_list = []
120120
edge_remove_listall = []
121121
for row in table:
122-
g_VeSpA = g.copy()
122+
g_Vespa = g.copy()
123123
edge_remove_list = []
124124
# cut the edges when there are valves onside be set to 0 in a row
125125
for i in range(len(row)):
@@ -153,10 +153,10 @@ def VeSpAGraphGenerator(table, nodes_group_list, vcofe, g):
153153
continue
154154
# remove edges involved
155155
for e in edge_remove_list:
156-
for edge in g_VeSpA.edges():
156+
for edge in g_Vespa.edges():
157157
if Counter(e) == Counter(edge):
158-
g_VeSpA.remove_edge(e[0], e[1])
159-
g_list.append(g_VeSpA)
158+
g_Vespa.remove_edge(e[0], e[1])
159+
g_list.append(g_Vespa)
160160
edge_remove_listall.append(edge_remove_list)
161161
return g_list
162162

@@ -166,55 +166,82 @@ def VeSpAGraphGenerator(table, nodes_group_list, vcofe, g):
166166
# All node[0] node[1] here will be totally same or different at all. If they have intersection node, they will be
167167
# connected by the findallConnectedNodes() function. So, we can transfer the current d to a list of tuples consists
168168
# of two node groups, all nodes in the group should be open or close together.
169-
def enumerateVeSpAgraphs(g, d, vcofe, listlen):
170-
conflict = 0
169+
def enumerateVespagraphs(g, d, vcofe, listlen):
170+
171171
# creat node group constraint list
172172
conflict, ConstraintNGList, nodes_group_list = Node_NG_Constraint_translater(d)
173173
if conflict == 1:
174174
return 1, []
175175
# create a truth table including all node groups according to the ConstraintGroupList
176-
conflict, table, fp = NodeGroupTruthTableBuilder(nodes_group_list, ConstraintNGList, listlen)
177-
I_best = len(table)
176+
conflict, table, NotAllGraph = NodeGroupTruthTableBuilder(nodes_group_list, ConstraintNGList, listlen)
177+
NumOfGraph = len(table)
178178
# Use the table to generate graphs which lose some edges compared with the original graph.
179-
g_list = VeSpAGraphGenerator(table, nodes_group_list, vcofe, g)
180-
return conflict, g_list, fp, I_best
179+
g_list = VespaGraphGenerator(table, nodes_group_list, vcofe, g)
180+
return conflict, g_list, NotAllGraph, NumOfGraph
181+
181182

183+
def get_ports (G):
184+
ports = []
185+
for node in G:
186+
if 'o' not in node:
187+
ports.append(node)
188+
return ports
182189

183-
def VeSpA_search(g, g_c, position, ConstraintList, VCO2FEdictionary, ur, listlen):
190+
191+
def Vespa_search(g, g_c, position, ConstraintList, VCO2FEdictionary, ur, listlen):
184192
global pos
185193
pos = position
186194
start = time.time()
195+
ports = get_ports(g)
196+
leakage_fail = 0
187197

188198
# Create a constraint dictionary list represents the constraint equation:
189199
# Data structure: {'Type': 2, 'TruthTable': [[0, 0]], 'Nodes': [['co1'...], ['co3'...]]}
190-
Conflict, NGConstraintDict = NodeGroupConstraintDictBuilder(ConstraintList, g, g_c)
200+
Conflict, NGConstraintDict = NodeGroupConstraintDictBuilder(ConstraintList, g_c)
191201

192202
# update graph with removing the edges in constraint type 1
193203
g, NGConstraintDictNew = updateGraphByNGConstraint(VCO2FEdictionary, g, NGConstraintDict)
194204
# generate all graphs satisfy the constraint type 2 as a list
195-
Conflict, g_list, flagFalseNegative, I_best = enumerateVeSpAgraphs(g, NGConstraintDictNew, VCO2FEdictionary, listlen)
205+
Conflict, g_list, NotAllGraph, NumOfGraph = enumerateVespagraphs(g, NGConstraintDictNew, VCO2FEdictionary, listlen)
196206
if Conflict == 1:
197-
print("Constraint conflict 2!", ConstraintList)
207+
print("Constraint conflict!", ConstraintList)
198208
end = time.time()
199-
return end - start, [], -2, -1, I_best
200-
VeSpAPathMin = []
201-
VeSpALengthMin = 0
209+
return end - start, [], -2, -1, NumOfGraph, leakage_fail
210+
VespaPathMin = []
211+
VespaLengthMin = 0
202212
# If the list is too big, we can randomly choose 1000 graphs from the big list to speedup the procedure. (random way)
203213
# Here we choose graphs in order from truth table elements are all 1 to all 0. (Our way)
204214
# if len(g_list) > listlen:
205215
# flagFalseNegative = 1
206216
# g_list = random.sample(g_list, listlen)
207217
for gb in g_list:
208-
_, VeSpAPath, VeSpALength = netxsp_search(gb, ur)
209-
if len(VeSpAPathMin) == 0 or VeSpALengthMin > VeSpALength > 0:
210-
VeSpAPathMin = VeSpAPath
211-
VeSpALengthMin = VeSpALength
218+
_, VespaPath, VespaLength = netxsp_search(gb, ur)
219+
if len(VespaPathMin) == 0 or VespaLengthMin > VespaLength > 0:
220+
if VespaLength > 0:
221+
flag_leakage = False
222+
for p in ports:
223+
if p in ur[0]:
224+
continue
225+
ur_new = [ur[0], p]
226+
_, _, l = netxsp_search(gb, ur_new)
227+
228+
# leakage issue arise
229+
if l > 0:
230+
if p not in ur[1]:
231+
flag_leakage = True
232+
break
233+
# if current graph have leakage issue, skip it
234+
if flag_leakage:
235+
leakage_fail += 1
236+
continue
237+
VespaPathMin = VespaPath
238+
VespaLengthMin = VespaLength
212239
end = time.time()
213-
if not VeSpAPathMin:
214-
# print(f"No such a path from {ur[0]} to {ur[1]} using VeSpA I={listlen} searching algorithm")
215-
return end - start, [], -1, flagFalseNegative, I_best
216-
VeSpATime = end - start
217-
return VeSpATime, VeSpAPathMin, VeSpALengthMin, flagFalseNegative, I_best
240+
if not VespaPathMin:
241+
# print(f"No such a path from {ur[0]} to {ur[1]} using Vespa I={listlen} searching algorithm")
242+
return end - start, [], -1, NotAllGraph, NumOfGraph, leakage_fail
243+
VespaTime = end - start
244+
return VespaTime, VespaPathMin, VespaLengthMin, NotAllGraph, NumOfGraph, leakage_fail
218245

219246

220247
def control_search(path, dictionary):
@@ -275,8 +302,8 @@ def simulateControlPathway(time, path, filepath, j, graph, GraphListInfo):
275302
pass
276303

277304

278-
def simulate(NodeInfo, NetxSPTime, NetxSPPath, NCP, DijkstraTime, DijkstraPath, DCP, AstarTime, AstarPath, ACP, VeSpATime,
279-
VeSpAPath, BCP, i, j, g, g_c, gli):
305+
def simulate(NodeInfo, NetxSPTime, NetxSPPath, NCP, DijkstraTime, DijkstraPath, DCP, AstarTime, AstarPath, ACP, VespaTime,
306+
VespaPath, BCP, i, j, g, g_c, gli):
280307
# NetxSP simulate flow pathway
281308
outputfolderpath = f"TestCaseFiles/NetxSP_result/Section_{i}/{NodeInfo}"
282309
simulateFlowPathway(NetxSPTime, NetxSPPath, outputfolderpath, j, g, gli)
@@ -289,9 +316,9 @@ def simulate(NodeInfo, NetxSPTime, NetxSPPath, NCP, DijkstraTime, DijkstraPath,
289316
outputfolderpath = f"TestCaseFiles/A*_result/Section_{i}/{NodeInfo}"
290317
simulateFlowPathway(AstarTime, AstarPath, outputfolderpath, j, g, gli)
291318

292-
# VeSpA simulate flow pathway
293-
outputfolderpath = f"TestCaseFiles/VeSpA_result/Section_{i}/{NodeInfo}"
294-
simulateFlowPathway(VeSpATime, VeSpAPath, outputfolderpath, j, g, gli)
319+
# Vespa simulate flow pathway
320+
outputfolderpath = f"TestCaseFiles/Vespa_result/Section_{i}/{NodeInfo}"
321+
simulateFlowPathway(VespaTime, VespaPath, outputfolderpath, j, g, gli)
295322

296323
# NetxSP simulate control layer pathway
297324
outputfolderpath = f"TestCaseFiles/NetxSP_result/Section_{i}/{NodeInfo}"
@@ -305,6 +332,6 @@ def simulate(NodeInfo, NetxSPTime, NetxSPPath, NCP, DijkstraTime, DijkstraPath,
305332
outputfolderpath = f"TestCaseFiles/A*_result/Section_{i}/{NodeInfo}"
306333
simulateControlPathway(AstarTime, AstarPath, outputfolderpath, j, g, gli)
307334

308-
# VeSpA simulate control pathway
309-
outputfolderpath = f"TestCaseFiles/VeSpA_result/Section_{i}/{NodeInfo}"
310-
simulateControlPathway(VeSpATime, VeSpAPath, outputfolderpath, j, g, gli)
335+
# Vespa simulate control pathway
336+
outputfolderpath = f"TestCaseFiles/Vespa_result/Section_{i}/{NodeInfo}"
337+
simulateControlPathway(VespaTime, VespaPath, outputfolderpath, j, g, gli)

ConstraintFunctions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def OriginalConstraintTablebuilder(type, node, t):
3434
# "[vi, vj]": {Type: 2, Nodes: [[vi, ci, vj], [vj, cj, vi]], TruthTable: [[0,0]]}, vi cannot be opened and closed at the same time
3535
# If we cannot generate a constraint dictionary, (not type1 and type2, may some other type)
3636
# then that means the constraint is incorrect, show warning!!!!!
37-
def NodeGroupConstraintDictBuilder(ConstraintList, g, g_c):
37+
def NodeGroupConstraintDictBuilder(ConstraintList, g_c):
3838
d = []
3939
conflict = 0
4040
for c in ConstraintList:
@@ -164,8 +164,8 @@ def NodeGroupTruthTableBuilder(nl, cl, listlen):
164164
listlen = min(listlen, 2**table_col)
165165
else:
166166
listlen = 2**table_col
167-
d, tab, flagFalseNegative = createTruthTable(d, keys, 0, [], cl, listlen, 0)
167+
d, tab, NotAllGraph = createTruthTable(d, keys, 0, [], cl, listlen, 0)
168168
if len(tab) == 0 and len(cl) != 0:
169169
conflict = 1
170-
return conflict, tab, flagFalseNegative
170+
return conflict, tab, NotAllGraph
171171

HeatMapBioDesignFixed.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from ConstraintMaker import createRandomConstraint
88
from MetricsGenerator import calculate_false_pos
9-
from AlgorithmComparison import VeSpA_search, control_search, netxsp_search, astar_search, findall_control_path
9+
from AlgorithmComparison import Vespa_search, control_search, netxsp_search, astar_search, findall_control_path
1010
import random
1111
import csv
1212
import networkx as nx
@@ -142,21 +142,21 @@ def locateValveAndCOonFE(vco_path):
142142
PathLength = [NetxSPLength, AstarLength]
143143
CtrlNodeLists = [NetxSPControlNodeList, AstarControlNodeList]
144144

145-
# Update the flow edge info after we get RandomConstraintList and use it in VeSpA_search
145+
# Update the flow edge info after we get RandomConstraintList and use it in Vespa_search
146146
VespaTime = []
147147
flagFN = []
148148
for ii in a:
149-
g_VeSpA = g.copy()
150-
VeSpATimeii, VeSpAPathii, VeSpALengthii, flag, _ = VeSpA_search(g_VeSpA, g_c, pos, ConstraintList, VCO2FEdictionary, ur, ii)
149+
g_Vespa = g.copy()
150+
VespaTimeii, VespaPathii, VespaLengthii, flag, _, _ = Vespa_search(g_Vespa, g_c, pos, ConstraintList, VCO2FEdictionary, ur, ii)
151151
# Find all valves and other control components which may be involved giving the searched path
152-
VeSpAVCOList = control_search(VeSpAPathii, FE2VCOdictionary)
153-
VeSpAControlNodeList, VeSpAControlEdgeList = findall_control_path(VeSpAVCOList, g_c)
152+
VespaVCOList = control_search(VespaPathii, FE2VCOdictionary)
153+
VespaControlNodeList, VespaControlEdgeList = findall_control_path(VespaVCOList, g_c)
154154

155155
# add middle products into list
156-
VespaTime.append(format(VeSpATimeii, '.5f'))
157-
PathLength.append(VeSpALengthii)
156+
VespaTime.append(format(VespaTimeii, '.5f'))
157+
PathLength.append(VespaLengthii)
158158
flagFN.append(flag)
159-
CtrlNodeLists.append(VeSpAControlNodeList)
159+
CtrlNodeLists.append(VespaControlNodeList)
160160

161161
# Calculate the false positive for each algorithm
162162
l, t, nodeslist = calculate_false_pos(PathLength, ConstraintList, CtrlNodeLists, g_c, flagFN)

MetricsGenerator.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from ConstraintFunctions import findallConnectedNodes
22
from collections import Counter
3+
from AlgorithmComparison import get_ports, NodeGroupConstraintDictBuilder, updateGraphByNGConstraint
34

45

56
def fp_flag(a, b):
@@ -25,22 +26,36 @@ def checkandappend(nodeslist, b):
2526
return nodeslist
2627

2728

28-
def VeSpA_checker(t, l, flag):
29-
# true negative for VeSpA, because it scanned all the possible graphs
29+
def Vespa_checker(t, l, flag):
30+
# true negative for Vespa, because it scanned all the possible graphs
3031
t = fp_flag(t, l)
3132
if flag == 1 and t == 2:
3233
t = 23
3334
return t, l
3435

3536

36-
def calculate_false_pos(p, cl, c, g_c, flag):
37+
# calculate_false_pos([NetxSPLength, AstarLength, VespaLength1, VespaLength2, VespaLength], ConstraintList,
38+
# [NetxSPControlNodeList, AstarControlNodeList, VespaControlNodeList1, VespaControlNodeList2,
39+
# VespaControlNodeList], g_c, [flagFalseNegative1, flagFalseNegative2, flagFalseNegative])
40+
def calculate_false_pos(p, cl, c, g_c, flag, g, ur):
3741
# l means the result of predict value, t means [0-false, 1-true] in the beginning and fp value in the end.
3842
l = [1] * len(p)
3943
t = [1] * len(p)
4044
for i in range(len(p)):
4145
if p[i] == -1:
4246
l[i] = 0
4347
nodeslist = []
48+
49+
# check leakage in two naive algorithms
50+
# transfer control protocol list to constraint list by labeling all un-mentioned control ports as type 1 constraint.
51+
# feed that to NodeGroupConstraintDictBuilder() and updateGraphByNGConstraint(), we can get a residual graph without any edges blocked by the
52+
# control ports not in the control protocol list.
53+
# remove all the edges if they are not in the control list, then search the other ports.
54+
# If find an "other" port can be reached, assign t[i]=0
55+
ports = get_ports(g)
56+
57+
58+
# check the constraints again, make sure the target path follow all constraints.
4459
for cc in cl:
4560
if cc[0] == 1:
4661
nodes = findallConnectedNodes([cc[1]], g_c.edges())
@@ -59,13 +74,14 @@ def calculate_false_pos(p, cl, c, g_c, flag):
5974
t[i] = 0
6075
nodeslist = checkandappend(nodeslist, nodes1)
6176
nodeslist = checkandappend(nodeslist, nodes2)
62-
# true positive = 1, false positive = 0, true negative= = 2, false negative = 3
77+
78+
# true positive = 1, false positive = 0, true negative = 2, false negative = 3
6379
t[0] = fp_flag(t[0], l[0])
6480
t[1] = fp_flag(t[1], l[1])
6581
for i in range(2, len(p)):
66-
t[i], l[i] = VeSpA_checker(t[i], l[i], flag[i-2])
82+
t[i], l[i] = Vespa_checker(t[i], l[i], flag[i-2])
6783

68-
# other algorithm can find a path without breaking the constraint, that means VeSpA is false negative
84+
# other algorithm can find a path without breaking the constraint, that means Vespa is false negative
6985
if t[0] == 1 or t[1] == 1:
7086
for i in range(2, len(p)):
7187
if t[i] in [23, 2]:

0 commit comments

Comments
 (0)