#!/usr/bin/env python3 ## -*- coding: utf-8 -*- ## Copyright (C) 2013 Laboratoire de Recherche et Développement de ## l'Epita (LRDE). ## ## This file is part of Spot, a model checking library. ## ## Spot is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## Spot is distributed in the hope that it will be useful, but WITHOUT ## ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ## or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public ## License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program. If not, see . import json import argparse def latex_escape_char(ch): if ch in '#$%&_{}': return '\\' + ch elif ch in '~^': return '\\' + ch + '{}' elif ch == '\\': return '\\textbackslash' else: return ch def latex_escape(x): if type(x) == str: return ''.join(latex_escape_char(ch) for ch in x) return map(latex_escape, x) def rot(x): if type(x) == str: return '\\rot{' + x + '}' return map(rot, x) def process_file(filename): data = json.load(open(filename)) ncols = len(data['fields']) ntools = len(data['tool']) datacols = range(4, ncols) fields = { name:index for index,name in enumerate(data["fields"]) } toolcol = fields['tool'] inputcol = fields['formula'] statescol = fields['states'] inputs = data["inputs"] # Index results by tool, then input results = { t:{} for t in range(0, ntools) } for l in data["results"]: if l[statescol] == None: continue results[l[toolcol]][l[inputcol]] = l for i in range(0, ntools): # Remove any leading directory, and trailing %... name = data["tool"][i] name = name[name.rfind('/', 0, name.find(' ')) + 1:] data["tool"][i] = latex_escape(name[0:(name+'%').find('%')]) timecol = fields['time'] print(r''' \section*{\texttt{%s}} \subsection*{Cumulative summary}''' % latex_escape(filename)) print('\\noindent\\begin{tabular}{l' + ('r' * (ncols - 1)) + '}\n', " & ".join(rot(latex_escape(["tool", "count"] + data["fields"][4:]))), "\\\\") for i in range(0, ntools): # Compute sums over each column. sums = [("%6.2f" if j == timecol else "%6d") % (sum([x[j] for x in results[i].values()])) for j in datacols] print("\\texttt{%-18s} & %3d & " % (data["tool"][i], len(results[i])), " & ".join(sums), "\\\\") print(r'\end{tabular}') print(r'''\subsection*{Cross comparison} How many times did the left tool produce an automaton strictly bigger than the top tool? Bigger means more states, or equal number of states and more transitions. ''') header = '\\noindent{\\small\\begin{tabular}{l' for i in data["tool"]: header += 'c' header += '}' transcol = fields['transitions'] print(header) for left in data["tool"]: print("&", rot("\\texttt{%s}" % left), end=' ') print(r'\\') for left in range(0, ntools): print("\\texttt{%-18s}" % data["tool"][left], end=' ') for top in range(0, ntools): x = 0 for k,ct in results[top].items(): if k in results[left]: cl = results[left][k] if (cl[statescol] > ct[statescol] or (cl[statescol] == ct[statescol] and cl[transcol] > ct[transcol])): x += 1 print("&", x, end=' ') print(r"\\") print(r'\end{tabular}}') def main(): p = argparse.ArgumentParser(description="Process ltlcross' output", epilog="Report bugs to .") p.add_argument('filenames', help="name of the JSON file to read", nargs='+') p.add_argument('--intro', help="introductory text for the LaTeX output", default='') args = p.parse_args() print(r'''\documentclass{article} \usepackage[a4paper,landscape,margin=1cm]{geometry} \usepackage{adjustbox} \usepackage{array} \newcolumntype{R}[2]{% >{\adjustbox{angle=#1,lap=\width-(#2)}\bgroup}% l% <{\egroup}% } \newcommand*\rot{\multicolumn{1}{R{90}{0em}}}% no optional argument here, please! \begin{document} ''') print(args.intro) for filename in args.filenames: process_file(filename) print(r'\end{document}') main()