def test_spot_substitute_tt_ff(): """ Test AP subsitution only. """ # Define true and false formula tt = spot.formula("true") ff = spot.formula("false") # Try substituting true with true/false (nothing should happen) new_f = tt.substitute(formula=tt, new_formula=tt) assert new_f == tt new_f = tt.substitute(formula=tt, new_formula=ff) assert new_f == tt new_f = tt.substitute(formula=ff, new_formula=tt) assert new_f == tt new_f = tt.substitute(formula=ff, new_formula=ff) assert new_f == tt # Try substituting true with true/false (nothing should happen) new_f = ff.substitute(formula=tt, new_formula=tt) assert new_f == ff new_f = ff.substitute(formula=tt, new_formula=ff) assert new_f == ff new_f = ff.substitute(formula=ff, new_formula=tt) assert new_f == ff new_f = ff.substitute(formula=ff, new_formula=ff) assert new_f == ff
def isGeneral(self, bc1, bc2): if type(bc1) is str: bc1 = spot.formula(bc1) if type(bc2) is str: bc2 = spot.formula(bc2) if not sat_check(spot.formula_And([bc2, spot.formula_Not(bc1)]).to_str('spin')): return True else: return False
def isWitness(self, bc1, bc2): if type(bc1) is str: bc1 = spot.formula(bc1) if type(bc2) is str: bc2 = spot.formula(bc2) # if self.isGeneral(bc1, bc2): # print('just genral') # return False if not self.isBC(spot.formula_And([bc2, spot.formula_Not(bc1)])): return True else: return False
def compute_results(formulas, toolnames, tools): '''Runs each tool from `toolnames` on each formula from `formulas` and stores the results in a pandas DataFrame, which is returned.''' data = [ [i,str(spot.formula(formula)),is_interesting(str(spot.formula(formula))) ] +\ [get_states_number(tools[name],formula) for name in toolnames] for i,formula in enumerate(formulas) ] return pd.DataFrame.from_records( data, columns=['form_id', 'formula', 'interesting'] + toolnames, index='form_id')
def isBC(self, bc, show_reason = False): if type(bc) is str: bc = spot.formula(bc) c = spot.language_containment_checker() #non-triviality if not sat_check(bc.to_str('spin')) or not sat_check(spot.formula_Not(bc).to_str('spin')): if show_reason: print('bc is true or false') return False not_g = spot.formula_Not(spot.formula_And(self.goals)) if not sat_check(spot.formula_And([not_g, spot.formula_Not(bc)]).to_str('spin')) and not sat_check(spot.formula_And([spot.formula_Not(not_g), bc]).to_str('spin')): if show_reason: print('trivial') return False #logical incosistency if sat_check(spot.formula_And(self.doms + self.goals + [bc,]).to_str('spin')): if show_reason: print('consistency') return False else: #minimality for i in range(len(self.goals)): if not sat_check(spot.formula_And(self.doms + [goal for goal in self.goals if goal != self.goals[i]] + [bc,]).to_str('spin')): if show_reason: print('not minimality') print(i, self.goals[i].to_str()) return False return True
def get_pbcs_from_aut(aut): pbcs = [] acc = [] for s in range(0, aut.num_states()): if aut.state_is_accepting(s): acc.append(s) for acc_i in acc: aut_temp = spot.automaton(aut.to_str('hoa', '1.1')) for acc_j in acc: if acc_j != acc_i: for t in aut_temp.out(acc_j): t.cond = buddy.bddfalse run = aut_temp.accepting_run() plist = [p for p in run.prefix] pbct = spot.formula_tt() step = 0 for p in plist: p_step = spot.bdd_format_formula(aut.get_dict(), p.label) p_step = spot.formula(p_step) for i in range(step): p_step = spot.formula_X(p_step) pbct = spot.formula_And([pbct, p_step]) step += 1 pbcs.append(pbct) return pbcs
def get_automaton(): input = request.forms.get('query') spot.setup() f = spot.formula(input) a = f.translate('monitor') output = a.to_str('dot') return output
def rewrite_weakuntil(input_line): formula = spot.formula(input_line.strip()) newformula = "{0:[W]}".format(formula).replace('1', 'true').replace( '0', 'false') print('{:10}'.format("Original:"), input_line.strip()[2:-2]) print('{:10}'.format("Spot:"), newformula) return newformula
def do_split(f, in_list): aut = spot.translate(f) inputs = spot.buddy.bddtrue for a in in_list: inputs &= spot.buddy.bdd_ithvar(aut.get_dict().varnum(spot.formula(a))) s = spot.split_2step(aut, inputs) return aut, s
def spotify(ltl_formula): ltl_spot = _get_spot_format(ltl_formula) f = spot.formula(ltl_spot) f = spot.simplify(f) ltl_spot = f.__format__("l") # return ltl_spot return f #.to_str('latex')
def test(): input = '(Ga -> Gb) W c' spot.setup() f = spot.formula(input) a = f.translate('tgba') output = a.to_str('dot') return output
def selector_for_ltl(self, formula, init_states=None, cap=inf, SolverClass=GoalLeaningES, keep_product=False): """ Get selector for almost surely satisfaction of specification given as ltl formula. Currently, only the recurrence fragment is supported. Translate the formula into equivalent deterministic Büchi automaton, build a product of the lCMDP with the automaton and synthesise strategy for Büchi objective with targets in states of the product with accepting state in the automaton component. If `init_states` are given, only consider these states as possible initial states. This can save the algorithm from building parts of the product that would never be used. After the product is analyzed, it is discarded and no longer available, unless `keep_product` is `True`. In this case, the product MDP object is accessible by `selector.product_mdp`. The returned selector is intended to be passed to DBACounterStrategy that work directly on top of this LabeledConsMDP. Parameters ========== * formula: formula from the recurrence fragment of LTL in format that is readable by Spot's Python binding. * init_states: iterable of ints, the set of initial states of the LabeledConsMDP `self`. The product will be started from these states only. If `None`, all states are considered initial. At least one state must be declared as initial. * SolverClass of energy solvers to be used for analysis of the product (GoalLeaningES by default) * keep_product: Bool, default False. Keep the product MDP associated to the returned selector. Returns: `ProductSelector` for Büchi objective given by determinstic Büchi automaton `aut`. """ f = spot.formula(formula) if f.mp_class() not in "SRPOBG": raise ValueError( "The formula must be from the recurrence fragment" "of LTL. See https://spot.lrde.epita.fr/hierarchy.html" f"for more details. The formula {f} was given.") dba = spot.translate(f, "BA", "deterministic", "complete") return self.selector_for_dba(aut=dba, init_states=init_states, cap=cap, SolverClass=SolverClass, keep_product=keep_product)
def progress_and_clean(ltl_formula, truth_assignment): ltl = progress(ltl_formula, truth_assignment) # I am using spot to simplify the resulting ltl formula ltl_spot = _get_spot_format(ltl) f = spot.formula(ltl_spot) f = spot.simplify(f) ltl_spot = f.__format__("l") ltl_std, r = _get_std_format(ltl_spot.split(' ')) assert len(r) == 0, "Format error" + str(ltl_std) + " " + str(r) return ltl_std
def test_spot_substitute_ap(): """ Test AP subsitution only. """ a = spot.formula("a") b = spot.formula("b") tt = spot.formula("true") ff = spot.formula("false") # Substitute a new_f = a.substitute(formula=a, new_formula=tt) assert new_f == tt new_f = a.substitute(formula=a, new_formula=ff) assert new_f == ff new_f = a.substitute(formula=a, new_formula=a) assert new_f == a new_f = a.substitute(formula=a, new_formula=b) assert new_f == b
def spot_get_trace(formula_str, simplify): spot_formula = spot.formula(formula_str) automaton = spot_formula.translate() automaton.merge_edges() acc_run = automaton.accepting_run() if acc_run is None: return False, None else: trace = spot.twa_word(acc_run) if simplify: trace.simplify() return True, str(trace)
def test_spot_substitute_pl(): """ Test AP subsitution only. """ a = spot.formula("a") b = spot.formula("b") tt = spot.formula("true") ff = spot.formula("false") phi0 = spot.formula("!a") phi1 = spot.formula("a & b") # Substitute phi0 new_f = phi0.substitute(formula=a, new_formula=tt) assert new_f == ff new_f = phi0.substitute(formula=a, new_formula=ff) assert new_f == tt new_f = phi0.substitute(formula=a, new_formula=b) assert new_f == spot.formula("!b") new_f = phi0.substitute(formula=phi0, new_formula=b) assert new_f == spot.formula("b") # Substitute phi1 new_f = phi1.substitute(formula=a, new_formula=tt) assert new_f == spot.formula("b") new_f = new_f.substitute(formula=b, new_formula=tt) assert new_f == tt new_f = phi1.substitute(formula=a, new_formula=ff) assert new_f == ff # Substitute a with b new_f = phi1.substitute(formula=a, new_formula=b) assert new_f == spot.formula("b")
def form_of_id(self, form_id, spot_obj=True): """For given form_id returns the formula Parameters ---------- form_id : int id of formula to return spot_obj : Bool If ``True``, returns Spot formula object (uses Latex to print the formula in Jupyter notebooks) """ f = self.values.index[form_id][1] if spot_obj: return spot.formula(f) return f
def explain_stut(f): f = spot.formula(f) pos = spot.translate(f) neg = spot.translate(spot.formula.Not(f)) word = spot.product(spot.closure(pos), spot.closure(neg)).accepting_word() if word is None: print(f, "is stutter invariant") return word.simplify() # This line used to be missing, causing issue #388. word.use_all_aps(pos.ap_vars()) waut = word.as_automaton() aut = neg if waut.intersects(pos) else pos word2 = spot.sl2(waut).intersecting_word(aut) word2.simplify() return(word, word2)
def translate(inp): """Translate input to polish pred Logic. input: ltl no matter what form. output: ltl in polish notation >>> from LTL.tools.ltlToPred import translate >>> translate('[]<>p0') 'G F p0' >>> translate('p1 U (p2 & GFp3)') 'U p1 & p2 G F p3' """ f = spot.formula(inp) lbt = f.to_str('lbt') return lbt
def _to_automaton(self): self._spot_formula = spot.formula(self._formula) # Follow https://spot.lrde.epita.fr/tut12.html to convert to finite semantics aut = spot.from_ltlf(self._formula).translate('low', 'sbacc') rem = spot.remove_ap() rem.add_ap('alive') aut = rem.strip(aut) aut = spot.postprocess(aut, 'low', 'sbacc') self._spot_automaton = aut init_states = [d for d in aut.univ_dests(aut.get_init_state_number())] bdd_dict = aut.get_dict() for s in range(aut.num_states()): is_init = s in init_states is_accepting = aut.state_is_accepting(s) self.add_state(str(s), init=is_init, accept=is_accepting) state_id = aut.num_states() for ed in aut.edges(): label = spot.bdd_to_formula(ed.cond, bdd_dict) if self._add_flexible_state and str(ed.src) != str(ed.dst): state_name = 'e_' + str(state_id) self.add_state(state_name) # add transition to the new state self.add_transition(str(ed.src), state_name, label='1') # add transition of the self loop self.add_transition(state_name, state_name, label='1') # add transition from the new state to destination self.add_transition(state_name, str(ed.dst), label=str(label)) state_id += 1 else: self.add_transition(str(ed.src), str(ed.dst), label=str(label)) if self._alphabets is None: self._alphabets = set() for ap in spot.atomic_prop_collect(self._spot_formula): self._alphabets.add(str(ap)) # replace all '1' labels to be all possible alphabets for src, dst, label in self._graph.edges(data='label'): if self._graph[src][dst]['label'] == '1': self._graph[src][dst]['label'] = self._get_alphabet_str() self._graph[src][dst]['print_label'] = '1' elif self._graph[src][dst]['label'] == '0': self._graph[src][dst]['label'] = self._get_neg_alphabet_str() self._graph[src][dst]['print_label'] = '0' else: self._graph[src][dst]['print_label'] = self._graph[src][dst][ 'label']
def isBC_t(self, bc, no_relation_gi): if type(bc) is str: bc = spot.formula(bc) #logical incosistency if sat_check(spot.formula_And(self.doms + self.goals + [bc,]).to_str('spin')): return -1 else: #minimality no_relation_g = [] for i in range(len(self.goals)): if i in no_relation_gi: no_relation_g.append(self.goals[i]) for i in range(len(self.goals)): if i in no_relation_gi: continue if not sat_check(spot.formula_And(self.doms + [goal for goal in self.goals if goal != self.goals[i] and goal not in no_relation_g] + [bc,]).to_str('spin')): return i return -2
def test_spot_substitute_error(): a = spot.formula("a U b") with pytest.raises(ValueError): a.substitute(formula=a, new_formula=spot.formula("true"))
try: a = r.replay(spot.get_cout()) except RuntimeError as e: assert "empty cycle" in str(e) else: report_missing_exception() try: a = r.reduce() except RuntimeError as e: assert "empty cycle" in str(e) else: report_missing_exception() f = spot.formula('GF(a | Gb)') try: spot.gf_guarantee_to_ba(f, spot._bdd_dict) except RuntimeError as e: assert "guarantee" in str(e) else: report_missing_exception() f = spot.formula('FG(a | Fb)') try: spot.fg_safety_to_dca(f, spot._bdd_dict) except RuntimeError as e: assert "safety" in str(e) else: report_missing_exception()
def test_graph_tool(): import spot spot.formula('a')
# + import spot spot.setup() from spot.jupyter import display_inline from math import inf from fimdp.labeled import DBAWrapper, LabeledConsMDP from fimdp.energy_solvers import BasicES from fimdp.objectives import BUCHI # - # ### Test DBAWrapper f = spot.formula("GF b & GF a") aut = spot.translate(f, "BA", "deterministic", "complete") aut # + AP = ["a", "b"] wrapper = DBAWrapper(aut, AP) a = AP.index("a") b = AP.index("b") assert wrapper.succ(2, [a]) == 1 assert wrapper.succ(2, [a, b]) == 2 assert wrapper.succ(2, [b]) == 0 assert wrapper.succ(2, []) == 1
#!/usr/bin/python3 import spot from functools import reduce ltl = spot.formula( "G(trigger -> X(policy W (!trigger & terminate & callback)))") GR1 = ([ "!triggered", # Init "G((trigger | (triggered & !terminate))<-> X(triggered))", # Keeps Triggering "G(triggered -> policy)", # Current State "G((!trigger & terminate ) -> callback)" # Callback Action ]) translated_gr1 = (reduce(lambda x, y: spot.product(x, y), map(spot.translate, map(spot.formula, GR1)))) ltl_n = spot.formula.Not(ltl).translate() ans = spot.product(translated_gr1, ltl_n) print(ans.is_empty()) print(ans.accepting_word())
# along with this program. If not, see <http://www.gnu.org/licenses/>. import spot lcc = spot.language_containment_checker() formulas = ['GFa', 'FGa', '(GFa) U b', '(a U b) U c', 'a U (b U c)', '(a W b) W c', 'a W (b W c)', '(a R b) R c', 'a R (b R c)', '(a M b) M c', 'a M (b M c)', '(a R b) U c', 'a U (b R c)', '(a M b) W c', 'a W (b M c)', '(a U b) R c', 'a R (b U c)', '(a W b) M c', 'a M (b W c)', ] # The rewriting assume the atomic proposition will not change # once we reache the non-alive part. cst = spot.formula('G(X!alive => ((a <=> Xa) && (b <=> Xb) && (c <=> Xc)))') for f in formulas: f1 = spot.formula(f) f2 = f1.unabbreviate() f3 = spot.formula_And([spot.from_ltlf(f1), cst]) f4 = spot.formula_And([spot.from_ltlf(f2), cst]) print("{}\t=>\t{}".format(f1, f3)) print("{}\t=>\t{}".format(f2, f4)) assert lcc.equal(f3, f4) print()
# 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 <http://www.gnu.org/licenses/>. import spot f = spot.formula('GF(a & b) -> (FG(a & b) & Gc)') m = spot.relabeling_map() g = spot.relabel_bse(f, spot.Pnn, m) res = "" for old, new in m.items(): res += "#define {} {}\n".format(old, new) res += str(g) print(res) assert(res == """#define p0 a & b #define p1 c GFp0 -> (FGp0 & Gp1)""") autg = g.translate() spot.relabel_here(autg, m) assert str(autg.ap()) == '(a, b, c)'
T = spot.formula.tt() F = spot.formula.ff() f1 = spot.formula.Equiv(c, a) f2 = spot.formula.Implies(a, b) f3 = spot.formula.Xor(b, c) f4 = spot.formula.Not(f3) del f3 f5 = spot.formula.Xor(F, c) del a, b, c, T, F, f1, f2, f4, f5 assert spot.fnode_instances_check() #---------------------------------------------------------------------- assert str([x for x in spot.formula('a &b & c')]) == '[a, b, c]' def switch_g_f(x): if x._is(spot.op_G): return spot.formula.F(switch_g_f(x[0])) if x._is(spot.op_F): return spot.formula.G(switch_g_f(x[0])) return x.map(switch_g_f) f = spot.formula('GFa & XFGb & Fc & G(a | b | Fd)') assert str(switch_g_f(f)) == 'FGa & XGFb & Gc & F(a | b | Gd)' x = 0
if not j.startswith('DRA'): if s < mins: mins = s if a < mina: mina = a else: hl = False; if s < mins: val = '\\textbf{' + val + '}' hl = True if a < mina: a = '\\textbf{' + str(a) + '}' hl = True if hl: val = '\\E ' + val val += ' (' + str(a) + ')' except KeyError: val = 'na' print("&", val, end=' ') for i in l: mins = 999999 mina = 999999 print('$' + spot.formula(i).to_str('latex') + '$', end=' ') print_half_line(i, csv_s, ts) print_half_line(i, csv_t, tt) print("\\\\") print("""\end{tabular} \end{document}""")
import spot import pdb ltl = "(a U b) & GFc & GFd" safety = spot.formula("!a U b") safety_aut = spot.translate(safety, "deterministic", "BA", "sbacc") ra = spot.to_generalized_rabin(safety_aut) ra = spot.split_edges(ra) def get_edges_labels(a): bddict = a.get_dict() edges = [] labels = [] for s in range(0, a.num_states()): print("State :{}".format(s)) for t in a.out(s): ud = a.is_univ_dest(t) if not ud: for dest in a.univ_dests(t): print("adding edge {}".format((int(t.src), int(dest)))) print("with label {}".format( spot.bdd_to_formula(t.cond, bddict))) edges.append((int(t.src), int(dest))) labels.append(spot.bdd_to_formula(t.cond, bddict)) edges, labels = get_edges_labels(ra) for e in ra.edges(): print("edge {}".format((int(e.src), int(e.dst))))
def test_phi(phi): a = spot.translate(phi, 'TGBA', 'SBAcc') res = spot.to_weak_alternating(spot.dualize(a)) assert equivalent(res, spot.formula.Not(spot.formula(phi)))
c = spot.formula.ap('c') T = spot.formula.tt() F = spot.formula.ff() f1 = spot.formula.Equiv(c, a) f2 = spot.formula.Implies(a, b) f3 = spot.formula.Xor(b, c) f4 = spot.formula.Not(f3); del f3 f5 = spot.formula.Xor(F, c) del a, b, c, T, F, f1, f2, f4, f5 assert spot.fnode_instances_check() #---------------------------------------------------------------------- assert str([x for x in spot.formula('a &b & c')]) == '[a, b, c]' def switch_g_f(x): if x._is(spot.op_G): return spot.formula.F(switch_g_f(x[0])) if x._is(spot.op_F): return spot.formula.G(switch_g_f(x[0])) return x.map(switch_g_f) f = spot.formula('GFa & XFGb & Fc & G(a | b | Fd)') assert str(switch_g_f(f)) == 'FGa & XGFb & Gc & F(a | b | Gd)' x = 0 def count_g(f): global x
def equivalent(a, phi): negphi = spot.formula.Not(phi) nega = spot.dualize(a) return not (spot.translate(negphi).intersects(a) or spot.translate(phi).intersects(nega)) def test_phi(phi): a = spot.translate(phi, 'TGBA', 'SBAcc') res = spot.to_weak_alternating(spot.dualize(a)) assert equivalent(res, spot.formula.Not(spot.formula(phi))) for p in phi1.split('\n'): print(p) test_phi(p) phi2 = spot.formula("(G((F a) U b)) W a") a2 = spot.automaton(""" HOA: v1 States: 7 Start: 1 AP: 2 "a" "b" acc-name: generalized-Buchi 2 Acceptance: 2 Inf(0)&Inf(1) properties: trans-labels explicit-labels trans-acc complete univ-branch --BODY-- State: 0 [t] 0 {0 1} State: 1 [0] 0 {0 1} [1] 1&2 {0 1} [0&!1] 1&3 {0 1}
#!/usr/bin/python3 import spot precede = spot.formula(" ((F after) -> ( (!after) U ((!after) & before) ))") gr1 = spot.formula( " (!before & !s & !after) & G( (!s & !before)->X(!s) ) &G(before->X(s)) & G((!s)->(!after)) & G(s->X(s))" ) def implies(f, g): a_f = f.translate() a_ng = spot.formula.Not(g).translate() return spot.product(a_f, a_ng) r1 = (implies(precede, gr1)) print(r1.is_empty()) print(r1.accepting_word()) r2 = (implies(gr1, precede)) print(r2.is_empty()) print(r2.accepting_word())
def calculate_accuracy(formulas_file, traces_file, targets_file, log_file, sat_prob_file, polish, sem_desp_syn, per_size, validator, log_level, **kwargs): with nice_open(formulas_file, 'r') as formulas, nice_open( traces_file, 'r') as traces, nice_open(targets_file, 'r') as targets, nice_open( log_file, 'w') as log, nice_open(sat_prob_file, 'w') as sat_prob: line_num = 0 tictoc = TicToc() if per_size: res = { 'syntactically correct': {}, 'only semantically correct': {}, 'incorrect': {}, 'invalid': {}, 'unknown': {} } def increment(key, formula_obj): size = formula_obj.size() if size in res[key]: res[key][size] += 1 else: res[key][size] = 1 else: res = { 'syntactically correct': 0, 'only semantically correct': 0, 'incorrect': 0, 'invalid': 0, 'unknown': 0 } def increment(key, formula_obj): res[key] += 1 if validator == 'spot' or validator == 'both': import spot for formula_str, trace_str in zip(formulas, traces): formula_str, trace_str = formula_str.strip(), trace_str.strip() line_num += 1 target_str = next(targets).strip() if targets else None if target_str == '-': # no trace target_str = None formula_format = 'network-' + ('polish' if polish else 'infix') formula_obj = ltl_parser.ltl_formula(formula_str, format=formula_format) # trace valid syntactically? try: trace_obj = ltl_parser.ltl_trace(trace_str, format=formula_format) except ltl_parser.ParseError as e: increment('invalid', formula_obj) if log and log_level >= 1: log.write( "INVALID {:d}\ninput (raw): {}\noutput (raw): {}\ntarget (raw): {}\nerror: {}\n\n" .format(line_num, formula_str, trace_str, target_str, e)) continue # trace equal to target (if available)? if target_str: # target available target_obj = ltl_parser.ltl_trace(target_str, format=formula_format) if trace_obj.equal_to(target_obj, extended_eq=True): increment('syntactically correct', formula_obj) syntactically_correct = True if log and log_level >= 4: log.write( "SYNTACTICALLY CORRECT {:d}\ninput : {}\noutput: {}\n\n" .format(line_num, formula_obj.to_str('spot'), trace_obj.to_str('spot'))) if not sem_desp_syn: continue else: syntactically_correct = False else: target_obj = None syntactically_correct = None # sat problem sat_obj = encode_for_satisfiability(trace_obj, formula_obj) sat_formula = sat_obj.to_str('spot', spacing='all ops', full_parens=True) if sat_prob: sat_formula_conv = sat_formula.replace('1', 'True').replace( '0', 'False').replace('!', '~') sat_prob.write(sat_formula_conv) # aalta trace check if validator == 'aalta' or validator == 'both': tictoc.tic() try: aalta_result = aalta_wrapper.sat(sat_formula, timeout=20) aalta_holds = not aalta_result if aalta_result is not None else None except RuntimeError as e: aalta_holds = None tictoc.toc('aalta check') else: aalta_holds = None # spot trace check if validator == 'spot' or validator == 'both': formula_spot = spot.formula(formula_obj.to_str('spot')) trace_spot = spot.parse_word(trace_obj.to_str('spot')) tictoc.tic() formula_automaton = formula_spot.translate() trace_automaton = trace_spot.as_automaton() tictoc.toc('spot translate') tictoc.tic() try: spot_holds = spot.contains( formula_automaton, trace_automaton ) # spot.contains checks whether language of its right argument is included in language of its left argument except RuntimeError: spot_holds = None tictoc.toc('spot contains') else: spot_holds = None # compare, evaluate trace checks trace_holds = aalta_holds if aalta_holds is not None else spot_holds # if both, same, else the one that is there or both None if validator == 'both' and aalta_holds != spot_holds: print('Formula ', formula_obj.to_str('spot')) print('Trace ', trace_obj.to_str('spot')) print('Sat form', sat_formula) print('MISMATCH aalta: {} -- spot: {}\n'.format( aalta_holds, spot_holds)) trace_holds = spot_holds # trust spot more if trace_holds is None: if log: log.write( "UNKNOWN {:d}\ninput : {}\noutput: {}\ntarget: {}\n\n". format( line_num, formula_obj.to_str('spot'), trace_obj.to_str('spot'), target_obj.to_str('spot') if target_obj else None)) increment('unknown', formula_obj) elif trace_holds: if not sem_desp_syn or (not syntactically_correct): if log and log_level >= 3: log.write( "SEMANTICALLY CORRECT {:d}\ninput : {}\noutput: {}\ntarget: {}\n\n" .format( line_num, formula_obj.to_str('spot'), trace_obj.to_str('spot'), target_obj.to_str('spot') if target_obj else None)) increment('only semantically correct', formula_obj) else: # dosen't hold increment('incorrect', formula_obj) if log and log_level >= 2: log.write( "INCORRECT {:d}\ninput : {}\noutput: {}\ntarget: {}\n\n" .format( line_num, formula_obj.to_str('spot'), trace_obj.to_str('spot'), target_obj.to_str('spot') if target_obj else None)) if sem_desp_syn and syntactically_correct: raise RuntimeError( 'Trace is said to be syntactically correct, but does not fulfil formula!' ) tictoc.histogram(show=False) # evaluation if per_size: res = per_size_analysis(res, **kwargs) res['total'] = line_num res['correct'] = res['syntactically correct'] + res[ 'only semantically correct'] assert res['total'] == res['correct'] + res['incorrect'] + res[ 'invalid'] + res['unknown'] res_str = "Correct: {:f}%, {correct:d} out of {total:d}\nSyntactically correct: {:f}%, {syntactically correct:d} out of {total:d}\n"\ "Semantically correct, but not syntactically: {:f}%, {only semantically correct:d} out of {total:d}\n"\ "Incorrect: {:f}%, {incorrect:d} out of {total:d}\nInvalid: {:f}%, {invalid:d} out of {total:d}\n"\ "Unknown: {unknown:d} out of {total:d}\n"\ "".format(res['correct'] / res['total'] * 100, res['syntactically correct'] / res['total'] * 100, res['only semantically correct'] / res['total'] * 100, res['incorrect'] / res['total'] * 100, res['invalid'] / res['total'] * 100, **res) if log and not (log is sys.stdout): log.write(res_str) return res, res_str