Skip to content

Commit e2d94d3

Browse files
committed
WIP: result parsing and false positivity analysis script
1 parent 589f824 commit e2d94d3

File tree

4 files changed

+100
-5
lines changed

4 files changed

+100
-5
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import os
2+
3+
import yaml
4+
from run_exp_for_class import EXPS, get_checker_output_dir, get_setup_key
5+
6+
from mldaikon.checker import parse_checker_results
7+
from mldaikon.invariant.base_cls import read_inv_file
8+
9+
10+
def discover_checker_results() -> dict:
11+
"""Requires changing to the directory where the checker output files are stored."""
12+
13+
with open("setups.yml", "r") as f:
14+
setups = yaml.load(f, Loader=yaml.FullLoader)
15+
16+
results = {} # setup: [(program, results), ...]
17+
valid_programs = [
18+
f
19+
for f in os.listdir("validset")
20+
if os.path.isdir(os.path.join("validset", f)) and f != "data"
21+
]
22+
# for setup in setups['setups']:
23+
for setup in setups["setups"]:
24+
for program in valid_programs:
25+
checker_output_dir = get_checker_output_dir(setup, program)
26+
if os.path.exists(checker_output_dir):
27+
if get_setup_key(setup) not in results:
28+
results[get_setup_key(setup)] = []
29+
results[get_setup_key(setup)].append((program, checker_output_dir))
30+
else:
31+
print(
32+
f"Warning: checker output directory for {program} in {setup} does not exist, skipping. {checker_output_dir}"
33+
)
34+
return results
35+
36+
37+
if __name__ == "__main__":
38+
all_results = {}
39+
for bench in EXPS:
40+
os.chdir(bench)
41+
results = discover_checker_results()
42+
if results:
43+
all_results[bench] = results
44+
os.chdir("..")
45+
46+
# for each bench, for each setup, for each program, parse the results
47+
for bench, setups in all_results.items():
48+
os.chdir(bench)
49+
for setup, programs in setups.items():
50+
for program, checker_output_dir in programs:
51+
# find the results files
52+
result_and_inv_files = os.listdir(checker_output_dir)
53+
assert "invariants.json" in result_and_inv_files
54+
inv_file = os.path.join(checker_output_dir, "invariants.json")
55+
failed_results = [
56+
f for f in result_and_inv_files if f.startswith("failed")
57+
][0]
58+
failed_file = os.path.join(checker_output_dir, failed_results)
59+
passed_results = [
60+
f for f in result_and_inv_files if f.startswith("passed")
61+
][0]
62+
passed_file = os.path.join(checker_output_dir, passed_results)
63+
not_triggered_results = [
64+
f for f in result_and_inv_files if f.startswith("not_triggered")
65+
][0]
66+
not_triggered_file = os.path.join(
67+
checker_output_dir, not_triggered_results
68+
)
69+
# analyzing the results
70+
failed = parse_checker_results(failed_file)
71+
passed = parse_checker_results(passed_file)
72+
non_triggered = parse_checker_results(not_triggered_file)
73+
invariants = read_inv_file(inv_file)
74+
assert len(failed) + len(passed) + len(non_triggered) == len(invariants)
75+
76+
print(
77+
f"Results for {program} in {setup} in {bench}, failed: {len(failed)} ({len(failed) / len(invariants)}), passed: {len(passed)} ({len(passed) / len(invariants)}), non_triggered: {len(non_triggered)} ({len(non_triggered) / len(invariants)})"
78+
)
79+
os.chdir("..")

eval_scripts/false_positive/run_exp_for_class.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55

66
import yaml
77

8-
EXPS = os.listdir(".")
9-
EXPS = [exp for exp in EXPS if os.path.isdir(exp)]
8+
EXPS = ["CNN", "RNN", "Transformers"]
109

1110
# get the current time (just date and HH:MM)
1211
READY_TRACES: list[str] = []

mldaikon/checker.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,23 @@
1313
register_custom_excepthook()
1414

1515

16+
def parse_checker_results(file_name: str):
17+
with open(file_name, "r") as f:
18+
lines = f.readlines()
19+
20+
all_results: list[dict] = []
21+
current_res_str = ""
22+
for line in lines:
23+
if line.startswith("{") and current_res_str:
24+
all_results.append(json.loads(current_res_str))
25+
current_res_str = ""
26+
current_res_str += line
27+
28+
if current_res_str:
29+
all_results.append(json.loads(current_res_str))
30+
return all_results
31+
32+
1633
def check_engine(
1734
traces: list[Trace], invariants: list[Invariant], check_relation_first: bool
1835
) -> list[CheckerResult]:

mldaikon/invariant/base_cls.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def load_function_obj(func_name: str) -> Any:
6969
return func_obj
7070
except Exception as e:
7171
logger = logging.getLogger(__name__)
72-
logger.warning(
72+
logger.debug(
7373
f"Failed to load the object for the function: {func_name}, error: {e}"
7474
)
7575
return None
@@ -89,7 +89,7 @@ def load_function_signature(func_name: str) -> inspect.Signature | None:
8989
return FUNC_SIGNATURE_OBJS[func_name]
9090
except Exception as e:
9191
logger = logging.getLogger(__name__)
92-
logger.warning(
92+
logger.debug(
9393
f"Failed to load the signature for the function: {func_name}, error: {e}"
9494
)
9595
FUNC_SIGNATURE_OBJS[func_name] = (
@@ -129,7 +129,7 @@ def __init__(
129129
self.signature = load_function_signature(func_name)
130130
if self.signature is None:
131131
logger = logging.getLogger(__name__)
132-
logger.warning(
132+
logger.debug(
133133
f"Failed to load the signature for the function: {func_name}, can only work on kwargs."
134134
)
135135
self.arguments = kwargs.copy()

0 commit comments

Comments
 (0)