suspected_bugs_detector.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. """
  2. # Part of localization phase
  3. # suspected bug detection:
  4. # 1. Tensorflow,Theano,CNTK
  5. # 2. Tensorflow,Theano,MXNET
  6. #
  7. # voting process
  8. # -> a. inconsistency -> error backend,error layer.
  9. # b. check error backend in new container(whether inconsistency disappears).
  10. # """
  11. #
  12. import numpy as np
  13. import os
  14. import sys
  15. import configparser
  16. from scripts.tools.filter_bugs import filter_bugs
  17. import pickle
  18. import pandas as pd
  19. from itertools import combinations,product
  20. from datetime import datetime
  21. #np.random.seed(20200501)
  22. def get_model_inputs(idntfrs):
  23. idntfrs_set = set()
  24. for idntfr in idntfrs:
  25. idntfr_splits = idntfr.split("_")
  26. model_input = "{}_{}_{}".format(idntfr_splits[0], idntfr_splits[1], idntfr_splits[-1])
  27. idntfrs_set.add(model_input)
  28. return idntfrs_set
  29. def voted_by_inconsistency(res_dict):
  30. votes = {}
  31. for back_pair,incon_value in res_dict.items():
  32. if incon_value >= threshold:
  33. back1,back2 = back_pair.split("_")
  34. votes[back1] = votes.setdefault(back1, 0) + 1
  35. votes[back2] = votes.setdefault(back2, 0) + 1
  36. for bk, cnt in votes.items():
  37. if cnt == 2:
  38. return bk
  39. def get_metrics_of_exp(exp_id,exp_dir):
  40. res_dict = dict()
  41. metrics_dir = os.path.join(exp_dir, "metrics_result")
  42. file_name = f"{exp_id}_D_MAD_result.csv"
  43. with open(os.path.join(metrics_dir, file_name), "r") as fr:
  44. fr.readline()
  45. for line in fr.readlines():
  46. line = line.rstrip("\n").split(",")
  47. res_dict[line[0]] = float(line[1])
  48. return res_dict
  49. def get_metrics_of_model_input(model_input,backend_pairs,exp_metrics_dict):
  50. mis = model_input.split("_")
  51. res_dict = dict()
  52. for backend_pair in backend_pairs:
  53. model_idntfr = f"{mis[0]}_{mis[1]}_{backend_pair}_{mis[-1]}"
  54. res_dict[backend_pair] = exp_metrics_dict[model_idntfr]
  55. return res_dict
  56. def choose_error_layer(localize_res: dict):
  57. def get_common_layer(res, error_layer):
  58. bk_dict = {}
  59. for bk_pair, tu in res.items():
  60. if tu[0] == error_layer:
  61. bk1, bk2 = bk_pair.split("_")[0], bk_pair.split("_")[1]
  62. bk_dict[bk1] = bk_dict.setdefault(bk1, 0) + 1
  63. bk_dict[bk2] = bk_dict.setdefault(bk2, 0) + 1
  64. for bk, cnt in bk_dict.items():
  65. if cnt == 2:
  66. return bk
  67. layers_list = list(localize_res.values())
  68. unique_layer_dict = dict()
  69. for layer_tuple in layers_list:
  70. unique_layer_dict[layer_tuple[0]] = unique_layer_dict.setdefault(layer_tuple[0], 0) + 1
  71. unique_layer_dict = list(unique_layer_dict.items())
  72. if len(unique_layer_dict) == 1:
  73. return unique_layer_dict[0][0], "-".join(backends)
  74. if len(unique_layer_dict) == 2:
  75. error_layer = unique_layer_dict[0][0] if unique_layer_dict[0][1] == 2 else unique_layer_dict[1][0]
  76. return error_layer, get_common_layer(localize_res, error_layer)
  77. if len(unique_layer_dict) == 3:
  78. return None, None
  79. def get_layer_values(bk_res: dict, layer_name):
  80. values = list()
  81. for bk_p in backend_pairs:
  82. df = bk_res[bk_p]
  83. select_row = df[df['current_layer'].isin([layer_name])]
  84. values.append("{}:{}".format(bk_p, select_row['Rl'].values[0]))
  85. return "|".join(values)
  86. def get_rate(value:str):
  87. """
  88. v:values:'tensorflow_theano:325317.28125-tensorflow_cntk:325317.28125-tensorflow_mxnet:325317.28125-theano_cntk:0.07708668-theano_mxnet:0.09217975-cntk_mxnet:0.0887682'
  89. rate: max_Rl
  90. """
  91. if 'inf' in value:
  92. return 'inf'
  93. else:
  94. try:
  95. value_splits = value.split("|")
  96. value_list = [abs(float(val.split(":")[1])) for val in value_splits]
  97. except ValueError as e:
  98. print(value)
  99. raise e
  100. max_rl,min_rl = max(value_list),min(value_list)
  101. return max_rl / (min_rl + 1e-10)
  102. def update_suspected_bugs(res_dict:dict, row:dict):
  103. """
  104. select suspected bugs from inconsistencies by their rate
  105. rate: max_Rl / min_Rl
  106. row is like: {error_backend:theano,error_layer:conv2d_copy_LA1,
  107. model_input:'alexnet-cifar10_origin0-NAI1-LS6-WS4-NS1-ARep8_input228',
  108. values:'tensorflow_theano:325317.28125-tensorflow_cntk:325317.28125-tensorflow_mxnet:325317.28125-theano_cntk:0.07708668-theano_mxnet:0.09217975-cntk_mxnet:0.0887682'}
  109. """
  110. # if not exists;add
  111. # else update
  112. error_bk,layer_name = row['error_backend'],simplify_layer_name(row['error_layer'])
  113. if (error_bk,layer_name) not in res_dict.keys():
  114. res_dict[(error_bk,layer_name)] = set()
  115. res_dict[(error_bk,layer_name)].add(row['model_input'])
  116. # print(row['error_layer'],simplify_layer_name(row['error_layer']))
  117. return res_dict
  118. def simplify_layer_name(layer_name:str):
  119. """
  120. simplify layer name 'conv2d_copy_LA' -> conv2d
  121. """
  122. if 'copy' in layer_name:
  123. layer_name = layer_name.split("_copy_")[0]
  124. if 'insert' in layer_name:
  125. layer_name = layer_name.split("_insert_")[0]
  126. # '_' in str and str doesn't endwiths '_'
  127. if "_" in layer_name:
  128. last_chr = layer_name.rfind("_")
  129. if last_chr == len(layer_name) -1 or layer_name[last_chr+1].isdigit():
  130. layer_name = layer_name[:last_chr]
  131. return layer_name
  132. def get_inconsistency_value(bk_values):
  133. res_list = []
  134. for bk,values in bk_values.items():
  135. res_list.append(f"{bk}:{values}")
  136. return "|".join(res_list)
  137. def get_largest_error_layer(error_bk,bk_local_res,top_layers):
  138. def get_layer_value_other_bkp(layer_name,layer_stacks):
  139. for idx, row in layer_stacks.iterrows():
  140. if row['current_layer'] == layer_name:
  141. return float(row['Rl'])
  142. layerset = set()
  143. layer_value_dict = dict()
  144. error_bk_pairs = [bkp for bkp in backend_pairs if error_bk in bkp]
  145. # length == 1
  146. other_pair = [bkp for bkp in backend_pairs if error_bk not in bkp]
  147. for bkp in error_bk_pairs:
  148. layerset.add(top_layers[bkp][0])
  149. layer_value_dict[bkp] = (top_layers[bkp][0],get_layer_value_other_bkp(top_layers[bkp][0],bk_local_res[other_pair[0]]))
  150. if len(layerset) == 1:
  151. return list(layerset)[0]
  152. else:
  153. if layer_value_dict[error_bk_pairs[0]][1] < layer_value_dict[error_bk_pairs[1]][1]:
  154. return layer_value_dict[error_bk_pairs[0]][0]
  155. else:
  156. return layer_value_dict[error_bk_pairs[1]][0]
  157. def get_higher_value_count(l):
  158. higher_cnt = 0
  159. for val in l:
  160. if val >= threshold:
  161. higher_cnt += 1
  162. return higher_cnt
  163. def get_another_tuple(idntfr,unique_incon_dict:list):
  164. """unique_incon_dict is list of ('theano_cntk','O&M',('lenet5-mnist_origin0_theano_cntk_input1',0.35))"""
  165. idntfr_splits = idntfr.split("_")
  166. bkp = f"{idntfr_splits[2]}_{idntfr_splits[3]}"
  167. if idntfr_splits[1] == 'origin0':
  168. # mutated should be added
  169. for iu in unique_incon_dict:
  170. iu_idntfr = iu[2][0]
  171. iu_idntfr_splits = iu_idntfr.split("_")
  172. if iu[0] == bkp and iu[1] =='O&M' and idntfr_splits[0] == iu_idntfr_splits[0] and iu_idntfr_splits[1] != 'origin0' and idntfr_splits[-1] == iu_idntfr_splits[-1]:
  173. return iu[2]
  174. else:
  175. raise Exception(f"Can't find equivalent mutated inconsistency for {idntfr}")
  176. else:
  177. # origin should be added
  178. origin_idntfr = f"{idntfr_splits[0]}_origin0_{idntfr_splits[2]}_{idntfr_splits[3]}_{idntfr_splits[-1]}"
  179. for iu in unique_incon_dict:
  180. if iu[0] == bkp and iu[1] == 'O&M' and origin_idntfr == iu[2][0]:
  181. return iu[2]
  182. else:
  183. print(origin_idntfr)
  184. raise Exception(f"Can't find equivalent origin inconsistency for {idntfr}")
  185. def is_all_original(model_inputs):
  186. for mi in model_inputs:
  187. mi_splits = mi.split("_")
  188. if mi_splits[1] != 'origin0':
  189. return False
  190. else:
  191. return True
  192. def is_all_original_on_exp(model_inputs,exp):
  193. for mi in model_inputs:
  194. mi_splits = mi.split("_")
  195. if mi_splits[0] == exp and mi_splits[1] != 'origin0':
  196. return False
  197. else:
  198. return True
  199. def is_all_mutant(model_inputs):
  200. for mi in model_inputs:
  201. mi_splits = mi.split("_")
  202. if mi_splits[1] == 'origin0':
  203. return False
  204. else:
  205. return True
  206. def is_all_mutant_on_exp(model_inputs,exp):
  207. for mi in model_inputs:
  208. mi_splits = mi.split("_")
  209. if mi_splits[0] == exp and mi_splits[1] == 'origin0':
  210. return False
  211. else:
  212. return True
  213. def is_exp_bug(model_inputs,exp):
  214. for mi in model_inputs:
  215. mi_splits = mi.split("_")
  216. if mi_splits[0] == exp:
  217. return True
  218. else:
  219. return False
  220. if __name__ == '__main__':
  221. start_time = datetime.now()
  222. config_name = sys.argv[1]
  223. lemon_cfg = configparser.ConfigParser()
  224. lemon_cfg.read(f"./config/{config_name}")
  225. parameters = lemon_cfg['parameters']
  226. output_dir = parameters['output_dir']
  227. output_dir = output_dir[:-1] if output_dir.endswith("/") else output_dir
  228. threshold = parameters.getfloat('threshold')
  229. current_container = output_dir.rstrip("/").split("/")[-1]
  230. backend_choices = [1, 2, 3]
  231. print("current_container",current_container)
  232. exps = parameters['exps'].lstrip().rstrip().split(" ")
  233. exps.sort(key=lambda x:x)
  234. global_backend_pairs = [f"{pair[0]}_{pair[1]}" for pair in combinations(['tensorflow', 'theano', 'cntk','mxnet'], 2)]
  235. pd_exps = list()
  236. success_cnt = fail_cnt = 0
  237. fail_model_inputs = list()
  238. reduced_bugs = dict()
  239. columns_cnt = int(3*(len(exps) + 1))
  240. content = np.zeros((6,columns_cnt),dtype='int64')
  241. # create an empty DataFrame
  242. dict_exps = list()
  243. for e in exps:
  244. dict_exps.append(f"{e}+O-M")
  245. dict_exps.append(f"{e}+M-O")
  246. dict_exps.append(f"{e}+O&M")
  247. pd_exps.append(f"{e}+LE")
  248. pd_exps.append(f"{e}+Mu")
  249. pd_exps.append(f"{e}+In")
  250. pd_exps.append(f"Total+LE")
  251. pd_exps.append(f"Total+Mu")
  252. pd_exps.append(f"Total+In")
  253. bug_analysis_keys = list(product(dict_exps, global_backend_pairs))
  254. exp_bkp_tuples = list(product(pd_exps, global_backend_pairs))
  255. bug_analysis = {t:set() for t in bug_analysis_keys}
  256. bug_df = pd.DataFrame(content,columns=pd_exps,index=global_backend_pairs)
  257. model_input_localize = {}
  258. for backend_choice in backend_choices:
  259. if backend_choice == 1:
  260. backends = ['tensorflow', 'theano', 'cntk']
  261. elif backend_choice == 2:
  262. backends = ['tensorflow', 'theano', 'mxnet']
  263. else:
  264. backends = ['tensorflow', 'cntk', 'mxnet']
  265. backend_str = "-".join(backends)
  266. backend_pairs = [f"{pair[0]}_{pair[1]}" for pair in combinations(backends, 2)]
  267. """Get all exps"""
  268. unsolved_columns = backend_pairs.copy()
  269. unsolved_columns.insert(0,'model_input')
  270. unsolved_df = pd.DataFrame(columns=unsolved_columns)
  271. solved_df = pd.DataFrame(columns=['error_layer', "error_backend", "model_input"])
  272. with open(os.path.join(output_dir, f"localize_model_inputs-{backend_str}.pkl"), "rb") as fr:
  273. localize_model_inputs:dict = pickle.load(fr)
  274. for exp,model_inputs in localize_model_inputs.items():
  275. exp_dir = os.path.join(output_dir, exp)
  276. # get model_inputs:
  277. localize_res_dir = os.path.join(output_dir,exp, "localization_result")
  278. exp_metrics_dict = get_metrics_of_exp(exp, exp_dir)
  279. for model_input in model_inputs:
  280. # get metrics of model_input
  281. top_layers = dict()
  282. bk_local_res = dict()
  283. second_layers = dict()
  284. third_layers = dict()
  285. model_input_split = model_input.split("_")
  286. tmp_store = dict()
  287. for bk_p in backend_pairs:
  288. local_file_name = "{}_{}_{}_{}.csv".format(model_input_split[0], model_input_split[1], bk_p,
  289. model_input_split[-1])
  290. try:
  291. df = pd.read_csv(os.path.join(localize_res_dir, local_file_name), error_bad_lines=False,
  292. usecols=[0, 1, 2])
  293. df = df.sort_values(by=['Rl'], ascending=False)
  294. bk_local_res[bk_p] = df.copy()
  295. top_layers[bk_p] = (df.iloc[0]['current_layer'], float(df.iloc[0]['Rl']))
  296. second_layers[bk_p] = (df.iloc[1]['current_layer'], float(df.iloc[1]['Rl']))
  297. third_layers[bk_p] = (df.iloc[2]['current_layer'], float(df.iloc[2]['Rl']))
  298. tmp_store[bk_p] ={'first':(df.iloc[0]['current_layer'], float(df.iloc[0]['Rl'])),
  299. 'second':(df.iloc[1]['current_layer'], float(df.iloc[1]['Rl'])),
  300. 'third':(df.iloc[2]['current_layer'], float(df.iloc[2]['Rl']))}
  301. except:
  302. print(f"{os.path.join(localize_res_dir, local_file_name)} doesn't exists")
  303. print(f"No localization result of {model_input} for {backends}")
  304. fail_cnt += 1
  305. break
  306. # raise Exception(local_file_name)
  307. else:
  308. if model_input not in model_input_localize.keys():
  309. model_input_localize[model_input] = tmp_store
  310. else:
  311. model_input_localize[model_input].update(tmp_store)
  312. success_cnt += 1
  313. metrics_dict = get_metrics_of_model_input(model_input=model_input, backend_pairs=backend_pairs,exp_metrics_dict=exp_metrics_dict)
  314. higher_cnt = get_higher_value_count(metrics_dict.values())
  315. # localization result exist
  316. if higher_cnt == 3:
  317. error_layer, error_backend = choose_error_layer(top_layers)
  318. if error_layer is not None:
  319. # error backend may be like 'tensorflow-theano-cntk'
  320. error_backends = error_backend.split("-")
  321. for eb in error_backends:
  322. solved_row = dict()
  323. solved_row['model_input'] = model_input
  324. solved_row['error_layer'] = error_layer
  325. solved_row['error_backend'] = eb
  326. solved_row['values'] = get_inconsistency_value(metrics_dict)
  327. # solved_df = solved_df.append([solved_row], ignore_index=True)
  328. reduced_bugs = update_suspected_bugs(reduced_bugs, solved_row)
  329. else:
  330. unsolve_row = dict()
  331. unsolve_row['model_input'] = model_input
  332. for bk_pair, tu in top_layers.items():
  333. unsolve_row[bk_pair] = "{}-{}".format(tu[0], tu[1])
  334. unsolved_df = unsolved_df.append([unsolve_row], ignore_index=True)
  335. elif higher_cnt == 2:
  336. voted_backend = voted_by_inconsistency(metrics_dict)
  337. solved_row = dict()
  338. solved_row['model_input'] = model_input
  339. solved_row['error_layer'] = get_largest_error_layer(voted_backend,bk_local_res,top_layers)
  340. solved_row['error_backend'] = voted_backend
  341. solved_row['values'] = get_inconsistency_value(metrics_dict)
  342. # solved_df = solved_df.append([solved_row], ignore_index=True)
  343. reduced_bugs = update_suspected_bugs(reduced_bugs, solved_row)
  344. else:
  345. fail_model_inputs.append([backend_str,model_input])
  346. print(f"{success_cnt} model_inputs vote successfully!")
  347. print(f"{fail_cnt} model_inputs fail to vote !")
  348. bug_list = list(reduced_bugs.items())
  349. bug_list.sort(key= lambda t:f"{t[0][0]}+{t[0][1]}") # sort by 'tensorflow+conv2d'
  350. bug_list = filter_bugs(bug_list=bug_list, output_dir=output_dir)
  351. with open(os.path.join(output_dir, f"unique_inconsistencies.pkl"), "rb") as fw:
  352. unique_inconsistencies_dict = pickle.load(fw)
  353. incon_bugs = dict()
  354. bug_incons = {idx:set() for idx in range(len(bug_list))}
  355. for incon_tuple in unique_inconsistencies_dict:
  356. "incon_tuple is like ('theano-cntk','O-M',('lenet5-mnist_origin0_theano-cntk_input1',0.35))"
  357. bkp,incon_idntfr = incon_tuple[0],incon_tuple[2][0]
  358. incon_idntfr_splits = incon_idntfr.split("_")
  359. incon_mi = f"{incon_idntfr_splits[0]}_{incon_idntfr_splits[1]}_{incon_idntfr_splits[-1]}"
  360. cur_exp = incon_idntfr_splits[0]
  361. for idx,bug_item in enumerate(bug_list):
  362. error_bk = bug_item[0][0]
  363. if error_bk in bkp and incon_mi in bug_item[1]:
  364. if incon_idntfr not in incon_bugs.keys():
  365. incon_bugs[incon_idntfr] = set()
  366. incon_bugs[incon_idntfr].add(idx)
  367. bug_incons[idx].add(incon_tuple[2])
  368. bug_store = {"O-M":set(),'M-O':set(),"O&M":set()}
  369. # bug_list like [ (('tensorflow', 'conv2d_1'),['mi1,mmi2,..']), ]
  370. for idx,bug_item in enumerate(bug_list):
  371. # check if it's O-bug or M-bug
  372. error_bk,layer_name = bug_item[0][0], bug_item[0][1]
  373. mis = bug_item[1]
  374. if is_all_mutant(mis):
  375. bug_store['M-O'].add(idx)
  376. elif is_all_original(mis):
  377. bug_store['O-M'].add(idx)
  378. else:
  379. bug_store['O&M'].add(idx)
  380. for incon_tuple in unique_inconsistencies_dict:
  381. "incon_tuple is like ('theano_cntk','O-M',('lenet5-mnist_origin0_theano_cntk_input1',0.35))"
  382. bkp, incon_idntfr = incon_tuple[0], incon_tuple[2][0]
  383. incon_idntfr_splits = incon_idntfr.split("_")
  384. incon_mi = f"{incon_idntfr_splits[0]}_{incon_idntfr_splits[1]}_{incon_idntfr_splits[-1]}"
  385. cur_exp = incon_idntfr_splits[0]
  386. if error_bk in bkp and incon_mi in mis:
  387. if incon_idntfr not in incon_bugs.keys():
  388. incon_bugs[incon_idntfr] = set()
  389. incon_bugs[incon_idntfr].add(idx)
  390. bug_incons[idx].add(incon_tuple[2])
  391. if is_all_mutant_on_exp(model_inputs=mis,exp=cur_exp):
  392. cluster = 'M-O'
  393. elif is_all_original_on_exp(model_inputs=mis,exp=cur_exp):
  394. cluster = 'O-M'
  395. else:
  396. cluster = 'O&M'
  397. exp_bkp_tuple = (f"{cur_exp}+{cluster}", bkp)
  398. if exp_bkp_tuple not in bug_analysis.keys():
  399. bug_analysis[exp_bkp_tuple] = set()
  400. bug_analysis[exp_bkp_tuple].add(idx)
  401. exp_bkps = list(product(exps, global_backend_pairs))
  402. total_bugs_dict = {p:set() for p in list(product(['Total+LE','Total+Mu','Total+In'], global_backend_pairs))}
  403. all_bug_O_M = set()
  404. all_bug_M_O = set()
  405. all_bug_O_and_M = set()
  406. for tu in exp_bkps:
  407. O_M_str,M_O_str,O_and_M_str = f"{tu[0]}+O-M",f"{tu[0]}+M-O",f"{tu[0]}+O&M"
  408. bkp = tu[1]
  409. le_set = (bug_analysis[(O_M_str,bkp)] | bug_analysis[(M_O_str,bkp)] | bug_analysis[(O_and_M_str,bkp)])
  410. mu_set = bug_analysis[(M_O_str,bkp)]
  411. in_set = bug_analysis[(O_and_M_str,bkp)]
  412. bug_df[f"{tu[0]}+LE"][bkp] = str(le_set)
  413. bug_df[f"{tu[0]}+Mu"][bkp] = str(mu_set)
  414. bug_df[f"{tu[0]}+In"][bkp] = str(in_set)
  415. total_bugs_dict[('Total+LE',bkp)].update(le_set)
  416. total_bugs_dict[('Total+Mu',bkp)].update(mu_set)
  417. total_bugs_dict[('Total+In',bkp)].update(in_set)
  418. final_bug_O_M = bug_store['O-M']
  419. final_bug_M_O = bug_store['M-O']
  420. final_bug_O_and_M = bug_store['O&M']
  421. final_LE = final_bug_O_M | final_bug_M_O | final_bug_O_and_M
  422. final_bug_O = final_bug_O_M | final_bug_O_and_M
  423. bug_df[f"Bug+Mu"] = str(final_bug_M_O)
  424. bug_df[f"Bug+In"] = str(final_bug_O_M)
  425. bug_df[f"Bug+origin"] = str(final_bug_O)
  426. bug_df[f"Bug+LE"] = str(final_LE)
  427. print("Original",sorted(list(final_bug_O)))
  428. print("M-O",sorted(list(final_bug_M_O)))
  429. print("O-M",sorted(list(final_bug_O_M)))
  430. print("O&M",sorted(list(final_bug_O_and_M)))
  431. for k,v in total_bugs_dict.items():
  432. bug_df[k[0]][k[1]] = str(v)
  433. bug_df['Total'] = len(bug_list)
  434. with open(os.path.join(output_dir,"bug_list.txt"),"w") as fw:
  435. for bug_id,incon_set in bug_incons.items():
  436. print("###############")
  437. print(f"# {bug_id} Bug: {bug_list[bug_id][0][0]}-{bug_list[bug_id][0][1]}")
  438. fw.write("###############\n")
  439. fw.write(f"# {bug_id} Bug: {bug_list[bug_id][0][0]}-{bug_list[bug_id][0][1]}\n")
  440. origin_max = 0
  441. mutated_max = 0
  442. for incon_tuple in incon_set:
  443. incon_idntfr,incon_value = incon_tuple[0],incon_tuple[1]
  444. if incon_idntfr.split("_")[1] == 'origin0':
  445. origin_max = incon_value if incon_value > origin_max else origin_max
  446. else:
  447. mutated_max = incon_value if incon_value > mutated_max else mutated_max
  448. print(f"{len(incon_set)} inconsistencies!")
  449. print(f"Max original value:{origin_max}")
  450. print(f"Max mutated value:{mutated_max}")
  451. fw.write(f"{len(incon_set)} inconsistencies!\n")
  452. fw.write(f"Max original value:{origin_max}\n")
  453. fw.write(f"Max mutated value:{mutated_max}\n")
  454. if bug_id in final_bug_O_M:
  455. print(f"Type:Only Initial can found\n")
  456. fw.write(f"Type:Only Initial can found\n")
  457. if bug_id in final_bug_M_O:
  458. print(f"Type:Only Mutated can found\n")
  459. fw.write(f"Type:Only Mutated can found\n")
  460. if bug_id in final_bug_O_and_M:
  461. print(f"Type:O&M can found\n")
  462. fw.write(f"Type:O&M can found\n")
  463. ordered_mi_set = sorted(list(bug_list[bug_id][1]))
  464. for idx,mi in enumerate(ordered_mi_set):
  465. print(f"{idx}.{mi}")
  466. fw.write(f"{idx}.{mi}\n")
  467. local_res:dict = model_input_localize[mi]
  468. for bkp,res in local_res.items():
  469. print(bkp,res['first'],res['second'],res['third'])
  470. fw.write(f"{bkp} {res['first']} {res['second']} {res['third']}\n")
  471. print("------------")
  472. fw.write("------------\n")
  473. print("###############\n\n")
  474. fw.write("###############\n\n")
  475. endtime = datetime.now()
  476. print("Time cost:",endtime - start_time)