@@ -35,6 +35,15 @@ def latex_escape(s: str) -> str:
3535 s = s .replace (k , v )
3636 return s
3737
38+ def html_escape (s : str ) -> str :
39+ # minimal escaping for LaTeX special chars
40+ replace = {
41+ '\\ ' : ' '
42+ }
43+ for k , v in replace .items ():
44+ s = s .replace (k , v )
45+ return s
46+
3847def format_time (t ):
3948 # compact formatting: up to 3 significant digits
4049 try :
@@ -68,7 +77,13 @@ def main(inp_path, out_path):
6877 if model not in model_nr_rules :
6978 model_nr_rules [model ] = nr_rules
7079
71- total_step_count = 4
80+ # sort by number of rules in the model
81+ sorted_data = sorted (data .keys (), key = lambda k : int (model_nr_rules .get (k , "0" )))
82+
83+ step_names = [r"analysis" , r"initial\\analysis" , r"disable\\rules" , r"add\\a rule" ]
84+ analysis_items = [("1_full" ,["1_init" ]), ("2_decremental" ,["1_init" , "4_disable" ]), ("3_incremental" ,["1_init" ])]
85+
86+ total_step_count = len (step_names )
7287 col_spec = "l c " + " " .join (["c" ] * total_step_count )
7388
7489 # Build LaTeX
@@ -82,14 +97,14 @@ def main(inp_path, out_path):
8297 lines .append (r"\cmidrule(lr){3-3}" )
8398 lines .append (r"\cmidrule(lr){4-6}" )
8499 # Second header row
85- lines .append (r"& & \bfseries\shortstack{analysis} & \bfseries\shortstack{initial\\analysis} & \bfseries\shortstack{disable\\rules} & \bfseries\shortstack{add\\a rule}\\" )
100+ header = r"& & \bfseries\shortstack{" + r"} & \bfseries\shortstack{" .join (step_names ) + r"}\\"
101+ lines .append (header )
86102 lines .append (r"\midrule" )
87103
88- for model in sorted ( data . keys (), key = lambda k : int ( model_nr_rules . get ( k , "0" ))): # sort by number of rules in the model
104+ for model in sorted_data :
89105 row_elems = []
90106 row_elems .append (r"\texttt{" + latex_escape (model ) + "}" )
91107 row_elems .append (latex_escape (model_nr_rules .get (model , "" )))
92- analysis_items = [("1_full" ,["1_init" ]), ("2_decremental" ,["1_init" , "4_disable" ]), ("3_incremental" ,["1_init" ])]
93108 for a , steps in analysis_items :
94109 for s in steps :
95110 val = data [model ].get (a , {}).get (s , "" )
@@ -100,11 +115,41 @@ def main(inp_path, out_path):
100115 lines .append (" & " .join (row_elems ) + r" \\" )
101116 lines .append (r"\bottomrule" )
102117 lines .append (r"\end{tabular}" )
103-
104118 # write output
105119 with open (out_path , "w" ) as outf :
106120 outf .write ("\n " .join (lines ))
107121
122+ # Build HTML
123+ lines = []
124+ lines .append ("<table>" )
125+ # First header row
126+ lines .append (" <tr>" )
127+ lines .append (" <th rowspan=\" 2\" >Model</th>" )
128+ lines .append (" <th rowspan=\" 2\" >Nr. of rules</th>" )
129+ lines .append (" <th colspan=\" 1\" >non-incremental</th>" )
130+ lines .append (" <th colspan=\" 3\" >incremental</th>" )
131+ lines .append (" </tr>" )
132+ # Second header row
133+ header = " <tr>\n <th>" + "</th>\n <th>" .join ([html_escape (step ) for step in step_names ]) + "</th>\n </tr>"
134+ lines .append (header )
135+
136+ for model in sorted_data :
137+ row_elems = []
138+ row_elems .append (model )
139+ row_elems .append (model_nr_rules .get (model , "" ))
140+ for a , steps in analysis_items :
141+ for s in steps :
142+ val = data [model ].get (a , {}).get (s , "" )
143+ if val == "" :
144+ row_elems .append ("" ) # empty cell if missing
145+ else :
146+ row_elems .append (format_time (val ))
147+ lines .append (" <tr>\n <td>" + "</td>\n <td>" .join (row_elems ) + "</td>\n </tr>" )
148+ lines .append ("</table>" )
149+ # write output
150+ with open (out_path [:- 4 ] + ".html" , "w" ) as outf :
151+ outf .write ("\n " .join (lines ))
152+
108153if __name__ == "__main__" :
109154 if len (sys .argv ) < 3 :
110155 print ("Usage: python3 latex_table_of_runtimes.py input.csv output.tex" )
0 commit comments