Skip to content

Commit f996da4

Browse files
committed
Support kotgll evaluation
1 parent 814ab7f commit f996da4

File tree

2 files changed

+109
-1
lines changed

2 files changed

+109
-1
lines changed

cfpq_eval/runners/all_pairs_cflr_tool_runner_facade.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
GigascaleAllPairsCflrToolRunner)
77
from cfpq_eval.runners.graspan_algo_all_pairs_cflr_tool_runner import (
88
GraspanAllPairsCflrToolRunner)
9+
from cfpq_eval.runners.kotgll_all_pairs_cflr_tool_runner import (
10+
KotgllAllPairsCflrToolRunner)
911
from cfpq_eval.runners.pearl_algo_all_pairs_cflr_tool_runner import (
1012
PearlAllPairsCflrToolRunner)
1113
from cfpq_eval.runners.pocr_algo_all_pairs_cflr_tool_runner import (
@@ -24,7 +26,8 @@ def run_appropriate_all_pairs_cflr_tool(
2426
"pocr": PocrAllPairsCflrToolRunner,
2527
"pearl": PearlAllPairsCflrToolRunner,
2628
"gigascale": GigascaleAllPairsCflrToolRunner,
27-
"graspan": GraspanAllPairsCflrToolRunner
29+
"graspan": GraspanAllPairsCflrToolRunner,
30+
"kotgll": KotgllAllPairsCflrToolRunner,
2831
}.get(algo_settings, PyAlgoAllPairsCflrToolRunner)(
2932
algo_settings, graph_path, grammar_path, timeout_sec
3033
).run()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import os
2+
import subprocess
3+
import uuid
4+
import warnings
5+
from pathlib import Path
6+
from typing import Optional
7+
8+
import pandas as pd
9+
10+
from cfpq_eval.runners.all_pairs_cflr_tool_runner import (
11+
AbstractAllPairsCflrToolRunner,
12+
CflrToolRunResult
13+
)
14+
from cfpq_model.cnf_grammar_template import CnfGrammarTemplate
15+
from cfpq_model.label_decomposed_graph import LabelDecomposedGraph
16+
from cfpq_model.model_utils import explode_indices
17+
18+
19+
class KotgllAllPairsCflrToolRunner(AbstractAllPairsCflrToolRunner):
20+
@property
21+
def base_command(self) -> Optional[str]:
22+
grammar = CnfGrammarTemplate.read_from_pocr_cnf_file(self.grammar_path)
23+
graph = LabelDecomposedGraph.read_from_pocr_graph_file(self.graph_path)
24+
25+
grammar_path = self.grammar_path.parent / "kotgll" / (self.grammar_path.stem + ".rsm")
26+
if not os.path.isfile(grammar_path):
27+
grammar_path = grammar_path.with_suffix(".cfg")
28+
if not os.path.isfile(grammar_path):
29+
warnings.warn(
30+
"Skipping kotgll evaluation, because RSM/CFG is missing. "
31+
"To fix this error write RSM/CFG to "
32+
f"'{grammar_path.with_suffix('.rsm')}'/'{grammar_path.with_suffix('.cfg')}'. "
33+
"See https://github.com/vadyushkins/kotgll?tab=readme-ov-file#rsm-format-example"
34+
)
35+
return None
36+
if graph.block_matrix_space.block_count > 1:
37+
exploded_grammar_path = (
38+
self.grammar_path.parent / "kotgll" / self.grammar_path.stem /
39+
self.graph_path.stem / (self.grammar_path.stem + grammar_path.suffix)
40+
)
41+
self._explode_grammar(
42+
grammar_path,
43+
exploded_grammar_path,
44+
graph.block_matrix_space.block_count
45+
)
46+
grammar_path = exploded_grammar_path
47+
48+
# kotgll doesn't support indexed symbols, we need to concat labels and indices
49+
graph, grammar = explode_indices(graph, grammar)
50+
graph_path = self.graph_path.parent / "kotgll" / self.graph_path.stem / self.graph_path.name
51+
os.makedirs(graph_path.parent, exist_ok=True)
52+
# kotgll requires its own graph formatting, so we need to save the graph in a custom format
53+
self._write_kotgll_graph(graph, graph_path)
54+
55+
out_folder = self.graph_path.parent / "kotgll" / 'out' / str(uuid.uuid4())
56+
os.makedirs(out_folder)
57+
58+
return (
59+
'java -cp kotgll.jar org.kotgll.benchmarks.BenchmarksKt '
60+
f'--grammar {grammar_path.suffix[1:]} --sppf off '
61+
f'--inputPath {graph_path.parent} --grammarPath {grammar_path} '
62+
f'--outputPath {out_folder} '
63+
'--warmUpRounds 1 --benchmarkRounds 1'
64+
)
65+
66+
@property
67+
def work_dir(self) -> Optional[Path]:
68+
return Path(os.environ['KOTGLL_DIR'])
69+
70+
def parse_results(self, process: subprocess.CompletedProcess[str]) -> CflrToolRunResult:
71+
for line in process.stdout.split('\n'):
72+
if line.startswith('benchmark::'):
73+
parts = line.split()
74+
return CflrToolRunResult(
75+
s_edges=int(parts[-2]),
76+
time_sec=float(parts[-1]),
77+
ram_kb=self.parse_ram_usage_kb(process)
78+
)
79+
raise Exception(f"No results are found in stdout {process.stdout}")
80+
81+
@staticmethod
82+
def _write_kotgll_graph(graph: LabelDecomposedGraph, graph_path: Path) -> None:
83+
with open(graph_path, 'w', encoding="utf-8") as output_file:
84+
for symbol, matrix in graph.matrices.items():
85+
edge_label = symbol.label
86+
(rows, columns, _) = matrix.to_coo()
87+
edges_df = pd.DataFrame({
88+
'source': rows,
89+
'destination': columns,
90+
'label': edge_label
91+
})
92+
csv_string = edges_df.to_csv(sep=' ', index=False, header=False)
93+
output_file.write(csv_string)
94+
95+
@staticmethod
96+
def _explode_grammar(rsm_path: Path, exploded_grammar_path: Path, block_count: int) -> None:
97+
os.makedirs(exploded_grammar_path.parent, exist_ok=True)
98+
with open(rsm_path, 'r') as infile, open(exploded_grammar_path, 'w') as outfile:
99+
for line in infile:
100+
if '{' in line and '}' in line:
101+
for i in range(block_count + 1):
102+
expanded_line = eval(f"f'{line.strip()}'")
103+
outfile.write(expanded_line + '\n')
104+
else:
105+
outfile.write(line)

0 commit comments

Comments
 (0)