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 load_hoa(path): with open(path, 'r') as f: lines = f.readlines() try: if lines[0].startswith('VAR_MAP: '): idx = lines[0].index(':') var_map_str = lines[0][idx + 1:].strip() var_map = ast.literal_eval(var_map_str) for k, vs in var_map.items(): for v in vs: BuchiAutomaton.update_counter(v) return BuchiAutomaton(spot.automaton('\n'.join(lines[1:])), var_map) except ValueError: pass return from_spot_aut(spot.automaton('\n'.join(lines)))
def parse_multiple_auts(hoa): l = hoa.split('--END--') a = [] cpt = 0 for x in l: if x.isspace() or x == '': continue x = x + "--END--" a.append(spot.automaton(x)) return a
def _convert_raw(property_: str, signal_by_name: Dict[str, Signal], states_prefix, timeout=None) -> Automaton: """ :param property_: in the LTL2BA format (we do NOT negate it!) """ rc, ba, err = execute_shell('{0} "{1}"'.format( LTLToAtmViaLTL3BA._execute_cmd, property_), timeout=timeout) assert rc == 0, str(rc) + ', err: ' + str(err) + ', out: ' + str(ba) assert is_empty_str(err), err logging.debug(ba) aut = spot.automaton(ba + '\n') # type: spot.twa # (when SPOT sees `\n` it treats input as the string) atm = spotAtm_to_automaton(aut, states_prefix, signal_by_name, property_) atm.name = property_ return atm
def ltl2oa(self,ltl): """Constructs and returns dictionaries and lists containing the specifications of an OA obtained by translation from the ltl property. It parses the output of ltl2ldba or ltl2dra for the ltl formula and creates a objects that store the specification of the OA. Parameters ---------- ltl : str The linear temporal logic (LTL) formula to be transformed to a OA. Returns ------- out : (q0, delta, acc, eps, shape, spot_oa) The tuple of the initial state q0, the list of dictionaries of transitions delta, the list of dictionaries of the accepting transitions, the list of lists of epsilon-moves, the pair of the number of the Rabin pairs and the number of states and the spot object of the OA. """ # Translate the LTL formula to an OA using Rabinizer 4. out=check_output(['ltl2ldba', '-d', '-e', ltl] if self.oa_type == 'ldba' else ['ltl2dra', '-c', ltl]) # Split the output into two parts: the header and the body header, body = out.decode('utf-8').split('--BODY--\n') # Parse the initial state, the atomic propositions and the number of Rabin pairs for line in header.splitlines(): if line.startswith('Start'): q0 = int(line[7:]) # The initial state elif line.startswith('AP'): char_map = {i:c for i,c in enumerate(re.sub("[^\w]", " ", line[4:]).split()[1:])} # Maps ids to atomic propositions ap_list = [tuple(ap) for ap in self.powerset(sorted(char_map.values()))] # The list of all subsets of AP. elif line.startswith('Acceptance'): n_pairs = int(line.split()[1])//2 # Zero for the Buchi condition body_lines = body.splitlines()[:-1] # Ignore the last line # Get the number of states n_qs = 0 # The number of states for line in reversed(body_lines): # Loop over all states because the states might not be ordered. if line.startswith('State'): n_qs = max(int(line[7:]),n_qs) # Get the maximum of them n_qs += 2 # +1 because the index origin is 0 and +1 for the trap state n_i = max(1,n_pairs) # Because n_pairs is zero for the Buchi condition shape = n_i, n_qs # The transition function delta[q][label] stores the next state The OA makes a transition when the it consumes 'label' at state 'q'. delta = [{ap:n_qs-1 for ap in ap_list} for i in range(n_qs)] # The default target of a transition is the trap state whose index is n_qs-1 acc = [{ap:[None]*n_i for ap in ap_list} for i in range(n_qs)] # The default acceptance value is None, meaning the transition does not belong to any acceptance set. eps = [[] for i in range(n_qs)] # The epsilon moves in the OA. eps[q] is the list of states can be reached from `q` by making an epsilon-transition. # Parse the transitions, acceptance values q=-1 # The state to be parsed for line in body_lines: if line.startswith('State'): q = int(line[7:]) # Update the state to be parsed else: # Parse the transition into three parts _, _label, _dst, _, _acc_set = re.findall('(\[(.*)\])? ?(\d+) ?(\{(.*)\})?',line)[0] dst = int(_dst) # Get the destination if not _label: # If there is no label then the transition is an epsilon-move eps[q].append(dst) else: # Get the acceptance status of the transition acc_set = set([int(a) for a in _acc_set.split()]) # The set of acceptance states that the transition belongs to if not n_pairs: # acc_name == 'Buchi': t_acc = [True if 0 in acc_set else None] # If it is an Buchi set, then it is True and None otherwise else: t_acc = [None]*n_pairs for i in range(n_pairs): # For each Rabin pairs if 2*i+1 in acc_set: t_acc[i] = True # True if it belongs to the second set of the Rabin pair if 2*i in acc_set: t_acc[i] = False # False if it belongs to the first set of the Rabin pair labels = [''] _labels = re.compile('[()]').split(_label) # The transitions might have subformulas for _l in _labels: labels = [l+_ll for l in labels for _ll in _l.split('|')] # Add all the combinations for label in labels: if label == 't': # Means all the transitions label_acc, label_rej = set(()), set(()) else: ls = list(filter(None,re.compile('[\s&]').split(label))) # Get the atoms label_acc = set([char_map[int(l)] for l in ls if not l.startswith('!')]) # Transitions having these atoms label_rej = set([char_map[int(l[1:])] for l in ls if l.startswith('!')]) # Transitions that doesn't have these for ap in delta[q]: # Find all the matching transitions # If matches, update the transition properties if not(label_acc-set(ap)) and (label_rej-set(ap))==label_rej: delta[q][ap] = dst acc[q][ap] = t_acc # Construct a spot object for visualization if spot: filename = self.random_hoa_filename() with open(filename,'wb') as f: f.write(check_output(['ltl2ldba', '-d', ltl] if self.oa_type == 'ldba' else ['ltl2dra', '-c', ltl])) spot.setup() spot_oa = spot.automaton(filename) spot_oa.merge_edges() # For better visualization os.remove(filename) else: spot_oa=None return q0, delta, acc, eps, shape, spot_oa
# 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 from sys import exit aut = spot.automaton(""" HOA: v1 States: 2 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1 Inf(0) --BODY-- State: 0 [t] 1 {0} State: 1 [t] 1 {0} --END-- """) aut2 = spot.simulation(aut) assert aut2.to_str() == """HOA: v1 States: 1 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1 Inf(0) properties: trans-labels explicit-labels state-acc colored complete
# 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 aut = spot.automaton(""" HOA: v1 States: 3 Start: 0 AP: 2 "a" "b" Acceptance: 4 Inf(0) & Inf(1) | Fin(3) properties: trans-labels explicit-labels trans-acc --BODY-- State: 0 [0] 1 {0 1} State: 1 [0] 1 {2 3} [1] 2 {0 1 2 3} State: 2 [1] 0 {2 3} --END--""") spot.simplify_acceptance_here(aut) hoa = aut.to_str('hoa') assert hoa == """HOA: v1 States: 3 Start: 0 AP: 2 "a" "b" Acceptance: 2 Fin(1) | Inf(0)
a = spot.automaton(""" HOA: v1 States: 8 Start: 0 AP: 3 "b" "a" "c" Acceptance: 5 (Fin(0) | Inf(1)) & (Fin(2) | Inf(3)) & Inf(4) properties: trans-labels explicit-labels state-acc --BODY-- State: 0 [!0&!2] 1 [0&!2] 2 [2] 3 State: 1 [0&2] 4 [0&1&2] 5 State: 2 [!0&!2] 1 [!0&2] 3 State: 3 [!0&!2] 1 [!0&2] 3 [0&2] 4 [0&1&2] 5 State: 4 [2] 4 [0&1&2] 5 [!0&!2] 6 State: 5 {4} [1&2] 5 [!0&1&!2] 7 State: 6 [0&2] 4 [0&1&2] 5 State: 7 {1 3 4} [0&1&2] 5 --END-- """)
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} [!0&!1] 1&4 {0 1} State: 2 [1] 2 {0 1} [0&!1] 3 {0 1} [!0&!1] 4 {0 1} State: 3 [1] 2 {0 1} [0&!1] 3 {1} [!0&!1] 4 {1} State: 4 [0&1] 2 {0 1} [0&!1] 3 {1} [!0&!1] 4 {1} [!0&1] 5 {0 1} State: 5 [0&1] 2 {0 1} [0&!1] 3 {0 1} [!0&1] 5 {0} [!0&!1] 6 {0} State: 6 [0&1] 2 {0 1} [0&!1] 3 {1} [!0&1] 5 {0} [!0&!1] 6 --END-- """)
# # 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 # This test used to trigger an assertion (or a segfault) # in scc_filter_states(). aut = spot.automaton(""" HOA: v1 States: 3 Start: 1 AP: 1 "a" Acceptance: 1 Inf(0) --BODY-- State: 0 {0} [t] 0 State: 1 [!0] 0 [0] 2 State: 2 [t] 2 --END-- """) aut.prop_inherently_weak(True) aut = spot.dualize(aut) aut1 = spot.scc_filter_states(aut) assert (aut1.to_str('hoa') == """HOA: v1 States: 2 Start: 0 AP: 1 "a" acc-name: co-Buchi
# 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 from sys import exit aut = spot.automaton(""" HOA: v1 States: 2 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1 Inf(0) --BODY-- State: 0 [0] 0 {0} [!0] 0 [1] 1 State: 1 [1] 1 {0} --END-- """) aut2 = spot.degeneralize(aut) assert aut2.to_str() == """HOA: v1 States: 3 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1 Inf(0)
def hoa_to_spot(hoa): print(hoa, file=open('tmp_aut.hoa', 'w')) a = spot.automaton('tmp_aut.hoa') subprocess.call(['rm', 'tmp_aut.hoa']) return a
# 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 a = spot.automaton("""HOA: v1 States: 1 Start: 0 AP: 2 "a" "b" Acceptance: 2 Inf(0)|Inf(1) --BODY-- State: 0 [0&1] 0 {0 1} [0&!1] 0 {0} [!0&1] 0 {1} [!0&!1] 0 --END--""") p = spot.to_parity(a) assert spot.are_equivalent(a, p) for f in spot.randltl(4, 400): d = spot.translate(f, "det", "G") p = spot.to_parity(d) assert spot.are_equivalent(p, d) for f in spot.randltl(5, 2000): n = spot.translate(f)
# 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/>. # Test that the spot.gen package works, in particular, we want # to make sure that the objects created from spot.gen methods # are usable with methods from the spot package. import spot a1 = spot.automaton(''' HOA: v1 name: "aut" States: 4 Start: 0 AP: 0 Acceptance: 4 Fin(0) & (Inf(1) | (Fin(2) & Inf(3))) --BODY-- State: 0 [t] 0 {0} [t] 1 {0 2} State: 1 [t] 2 State: 2 [t] 1 [t] 0 {0} [t] 3 {3} State: 3 [t] 2 {1} [t] 0 --END--''') a2 = spot.automaton(''' HOA: v1 States: 7 Start: 0 AP: 3 "a" "b" "c" Acceptance: 3 Fin(0) & Fin(2) & Inf(1) properties: trans-labels explicit-labels trans-acc --BODY-- State: 0 [2] 1 [!0&!2] 2 [0&!2] 3 [0&!2] 4 State: 1 [!0 | 1] 1 {1 2} [0&!1] 5 {1} State: 2 [t] 2 {0} State: 3 [!0&!2] 2 [0&!2] 3 State: 4 [0&!1&2] 1 [!0&2 | 1&2] 1 {2} [!0&!2] 6 {2} [0&!1&!2] 4 [0&1&!2] 4 {2} State: 5 [!0 | 1] 1 {2} [0&!1] 5 State: 6 [0&!1] 6 {0} [!0 | 1] 6 {0 2} --END--''') a3 = spot.automaton('''
# 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 aut = spot.automaton(""" HOA: v1 States: 3 Start: 0 AP: 2 "a" "b" Acceptance: 4 Inf(0) & Inf(1) | Fin(3) properties: trans-labels explicit-labels trans-acc --BODY-- State: 0 [0] 1 {0 1} State: 1 [0] 1 {2 3} [1] 2 {0 1 2 3} State: 2 [1] 0 {2 3} --END--""") spot.simplify_acceptance_here(aut) hoa = aut.to_str('hoa') assert hoa == """HOA: v1 States: 3 Start: 0 AP: 2 "a" "b" acc-name: parity min even 2
# # 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 from buddy import bddfalse, bddtrue a = spot.automaton(""" HOA: v1 States: 2 Start: 1 AP: 2 "p0" "p1" acc-name: Buchi Acceptance: 1 Inf(0) --BODY-- State: 0 [!0 | 1] 0 {0} [0&!1] 1 State: 1 /* we want this edge to be false, but the parser would ignore it if we wrote it here */ [0] 0 {0} [!1] 1 --END-- """) # Make the false edge. for e in a.out(1): if e.dst == 0: e.cond = bddfalse assert a.accepting_run() is None assert a.is_empty()
State: 1 [0] 0 [!0] 2 State: 2 [t] 2 --END--""" aut = spot.automaton(""" HOA: v1 States: 3 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1 Inf(0) properties: trans-labels explicit-labels state-acc --BODY-- State: 0 [0] 1 [0] 2 State: 1 {0} [0] 1 State: 2 {0} [1] 2 --END--""") test_assert(aut) dual = spot.dualize(aut) h = dual.to_str('hoa') assert h == """HOA: v1 States: 4
import spot # This test used to trigger an assertion (or a segfault) # in scc_filter_states(). aut = spot.automaton(""" HOA: v1 States: 3 Start: 1 AP: 1 "a" Acceptance: 1 Inf(0) --BODY-- State: 0 {0} [t] 0 State: 1 [!0] 0 [0] 2 State: 2 [t] 2 --END-- """) aut.prop_inherently_weak(True) aut = spot.dualize(aut) aut1 = spot.scc_filter_states(aut) assert(aut1.to_str('hoa') == """HOA: v1 States: 2 Start: 0 AP: 1 "a" acc-name: co-Buchi Acceptance: 1 Fin(0) properties: trans-labels explicit-labels state-acc deterministic properties: inherently-weak
#!/usr/bin/python3 # -*- mode: python; coding: utf-8 -*- # Copyright (C) 2018 Laboratoire de Recherche et Développement de # l'EPITA. # # 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 <http://www.gnu.org/licenses/>. import spot aut = spot.translate('GF(a <-> Xa) & GF(b <-> XXb)') si = spot.scc_info(aut) s = "" for aut2 in si.split_on_sets(0, [0]): # This call to to_str() used to fail because split_on_sets had not # registered the atomic propositions of aut s += aut2.to_str() assert spot.automaton(s).num_states() == 8
Start: 0 AP: 2 "p1" "p2" acc-name: Buchi Acceptance: 1 Inf(0) properties: trans-labels explicit-labels trans-acc univ-branch --BODY-- State: 0 [0] 1&2 {0} [1] 0&1 State: 1 [0&1] 0&2&1 State: 2 [0 | 1] 2 --END--""" aut2 = spot.automaton(h) h2 = aut2.to_str('hoa') print(h2) assert h != h2 # This will sort destination groups aut.merge_univ_dests() h = aut.to_str('hoa') assert h == h2 aut2.set_univ_init_state([0, 1]) h3 = aut2.to_str('hoa') print(h3) assert h3 == """HOA: v1 States: 3 Start: 0&1
# 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 # Test 1. aut = spot.automaton(""" HOA: v1 States: 2 Start: 0 AP: 2 "a" "b" Acceptance: 2 (Fin(0) & Inf(1)) --BODY-- State: 0 [!0] 0 {1} [0] 1 State: 1 [0] 1 {0} --END-- """) exp = """HOA: v1 States: 2 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1 Inf(0) properties: trans-labels explicit-labels trans-acc deterministic --BODY--
# Make sure scc_filter preserves state-names (suggested by Juraj # Major) import spot a = spot.automaton(""" HOA: v1.1 States: 3 Start: 1 AP: 1 "a" acc-name: Buchi Acceptance: 1 Inf(0) spot.highlight.states: 0 0 2 3 --BODY-- State: 0 "baz" [t] 0 State: 2 "foo" {0} [0] 0 [0] 2 [!0] 2 State: 1 "bar" [0] 2 --END-- """) assert (spot.scc_filter(a, True).to_str('hoa', '1.1') == """HOA: v1.1 States: 2 Start: 0 AP: 1 "a" acc-name: Buchi
def hoa_to_spot(hoa): return spot.automaton(hoa + "\n")
assert transi == [(0, 0, 1), (0, 3, 4), (3, 0, 7), (3, 3, 9), (1, 1, 5), (2, 2, 6), (4, 4, 12)] assert not spot.is_weak_automaton(a, si) a = spot.automaton(""" HOA: v1 States: 4 Start: 0 AP: 1 "a" Acceptance: 2 Inf(0)&Fin(1) --BODY-- State: 0 [t] 0 {1} [t] 1 {0} State: 1 [t] 1 {1} [t] 0 {1} [t] 2 State: 2 [t] 2 {1} [t] 3 {0} State: 3 [t] 3 {1} [t] 2 --END-- """) si = spot.scc_info(a) si.determine_unknown_acceptance() assert si.scc_count() == 2 assert si.is_accepting_scc(0) assert not si.is_rejecting_scc(0)
assert spot.is_colored(a3) a = spot.translate('GFa & GFb') try: spot.change_parity_here(a, spot.parity_kind_same, spot.parity_style_even) except RuntimeError as e: assert 'input should have parity acceptance' in str(e) else: exit(2) a = spot.automaton(""" HOA: v1 States: 1 Start: 0 AP: 1 "a" Acceptance: 2 Fin(0) & Inf(1) --BODY-- State: 0 [t] 0 {0} --END-- """) spot.cleanup_parity_here(a) assert a.to_str() == """HOA: v1 States: 1 Start: 0 AP: 1 "a" acc-name: none Acceptance: 0 f properties: trans-labels explicit-labels state-acc complete properties: deterministic --BODY--
States: 3 Start: 0 AP: 1 "p0" acc-name: Streett 1 Acceptance: 2 Fin(0) | Inf(1) properties: trans-labels explicit-labels state-acc deterministic --BODY-- State: 0 "2#0" [0] 1 State: 1 "0#0" {0 1} [0] 2 State: 2 "1#0" {1} [0] 1 --END--""" c = spot.automaton("randaut -A'(Fin(0)&Inf(1)&Inf(2))|Fin(2)' 1 |") assert spot.is_partially_degeneralizable(c) == [1, 2] dc = spot.partial_degeneralize(c, [1, 2]) assert dc.equivalent_to(c) assert str(dc.get_acceptance()) == '(Fin(0) & Inf(2)) | Fin(1)' assert spot.is_partially_degeneralizable(d) == [] dd = spot.partial_degeneralize(d, []) assert dd.equivalent_to(d) assert dd.num_states() == 1 assert str(dd.get_acceptance()) == 'Inf(1) & Fin(0)' e = spot.dualize(b) de = spot.partial_degeneralize(e, [0, 1]) assert de.equivalent_to(e) assert de.num_states() == 4
(3, 3, 9), (1, 1, 5), (2, 2, 6), (4, 4, 12)] assert not spot.is_weak_automaton(a, si) a = spot.automaton(""" HOA: v1 States: 4 Start: 0 AP: 1 "a" Acceptance: 2 Inf(0)&Fin(1) --BODY-- State: 0 [t] 0 {1} [t] 1 {0} State: 1 [t] 1 {1} [t] 0 {1} [t] 2 State: 2 [t] 2 {1} [t] 3 {0} State: 3 [t] 3 {1} [t] 2 --END-- """) si = spot.scc_info(a) si.determine_unknown_acceptance() assert si.scc_count() == 2 assert si.is_accepting_scc(0) assert not si.is_rejecting_scc(0)
import spot # This test used to trigger an assertion (or a segfault) # in scc_filter_states(). aut = spot.automaton(""" HOA: v1 States: 3 Start: 1 AP: 1 "a" Acceptance: 1 Inf(0) --BODY-- State: 0 {0} [t] 0 State: 1 [!0] 0 [0] 2 State: 2 [t] 2 --END-- """) aut.prop_inherently_weak(True) aut = spot.dualize(aut) aut1 = spot.scc_filter_states(aut) assert (aut1.to_str('hoa') == """HOA: v1 States: 2 Start: 0 AP: 1 "a" acc-name: co-Buchi Acceptance: 1 Fin(0) properties: trans-labels explicit-labels state-acc deterministic properties: inherently-weak
# Test case reduced from a report by Reuben Rowe <*****@*****.**> # sent to the Spot mailing list on 2016-10-31. import spot a = spot.automaton(""" HOA: v1 States: 5 Start: 4 AP: 3 "p_0" "p_1" "p_2" Acceptance: 1 Inf(0) --BODY-- State: 0 [0&!1&2] 1 [!0&!1&2] 2 State: 1 {0} [0&!1&2] 1 State: 2 {0} [!0&!1&2] 2 State: 3 {0} [0&1&!2] 0 [!0&1&!2] 3 State: 4 [!0&1&!2] 3 --END-- """) b = spot.automaton(""" HOA: v1 States: 8 Start: 0
aut = spot.translate('GFa') assert aut.num_states() == 1 assert not aut.prop_state_acc().is_true() aut = spot.sbacc(aut) assert aut.num_states() == 2 assert aut.prop_state_acc().is_true() aut = spot.automaton("""HOA: v1 States: 3 Start: 0 AP: 2 "a" "b" Acceptance: 2 Inf(0) | Inf(1) properties: trans-labels explicit-labels trans-acc --BODY-- State: 0 [0&1] 1 [0&!1] 2 State: 1 [t] 1 {0} [0] 0 State: 2 [t] 2 {1} [0] 1 --END--""") s = spot.sbacc(aut) h = s.to_str('hoa') assert h == """HOA: v1 States: 2 Start: 0
Start: 0 AP: 2 "p1" "p2" acc-name: Buchi Acceptance: 1 Inf(0) properties: univ-branch trans-labels explicit-labels trans-acc --BODY-- State: 0 [0] 1&2 {0} [1] 0&1 State: 1 [0&1] 0&2&1 State: 2 [0 | 1] 2 --END--""" aut2 = spot.automaton(h) h2 = aut2.to_str('hoa') print(h2) assert h != h2 # This will sort destination groups aut.merge_univ_dests() h = aut.to_str('hoa') assert h == h2 aut2.set_univ_init_state([0, 1]) h3 = aut2.to_str('hoa') print(h3) assert h3 == """HOA: v1 States: 3 Start: 0&1
test(spot.automaton("""HOA: v1 name: "(FGp0 & ((XFp0 & F!p1) | F(Gp1 & XG!p0))) | G(F!p0 & (XFp0 | F!p1) & F(Gp1 | G!p0))" States: 14 Start: 0 AP: 2 "p1" "p0" Acceptance: 6 (Fin(0) & Fin(1)) | ((Fin(4)|Fin(5)) & (Inf(2)&Inf(3))) properties: trans-labels explicit-labels trans-acc complete properties: deterministic --BODY-- State: 0 [!0] 1 [0] 2 State: 1 [!0&!1] 1 {0 1 2 3 5} [0&!1] 3 [!0&1] 4 [0&1] 5 State: 2 [0&!1] 2 {1} [!0&1] 4 [!0&!1] 6 [0&1] 7 State: 3 [0&!1] 3 {1 3} [!0&1] 4 [!0&!1] 6 {0 1 2 3 5} [0&1] 8 State: 4 [!0&!1] 4 {1 2 3 5} [!0&1] 4 {2 4 5} [0&!1] 5 {1 3} [0&1] 5 {4} State: 5 [!0&1] 4 {2 4 5} [0&!1] 5 {1 3} [0&1] 8 {2 4} [!0&!1] 9 {1 2 3 5} State: 6 [0&!1] 3 {1 3} [!0&1] 4 [0&1] 5 [!0&!1] 10 State: 7 [!0&1] 4 [0&!1] 7 {1 3} [!0&!1] 11 [0&1] 12 {0 4} State: 8 [!0&1] 4 {2 4 5} [0&1] 5 {4} [0&!1] 8 {1 3} [!0&!1] 11 {1 3 5} State: 9 [!0&1] 4 {2 4 5} [0&!1] 5 {1 3} [0&1] 5 {4} [!0&!1] 11 {1 3 5} State: 10 [!0&1] 4 [0&1] 8 [!0&!1] 10 {0 1 2 3 5} [0&!1] 13 {1 2 3} State: 11 [!0&1] 4 {2 4 5} [0&!1] 8 {1 2 3} [0&1] 8 {2 4} [!0&!1] 11 {1 2 3 5} State: 12 [!0&1] 4 [0&1] 7 {0 2 4} [!0&!1] 9 [0&!1] 12 {1 3} State: 13 [!0&1] 4 [0&1] 5 [!0&!1] 10 {0 1 3 5} [0&!1] 13 {1 3} --END--"""), [35, 28, 23, 30, 29, 25, 22])
import spot # Test 1. aut = spot.automaton(""" HOA: v1 States: 2 Start: 0 AP: 2 "a" "b" Acceptance: 2 (Fin(0) & Inf(1)) --BODY-- State: 0 [!0] 0 {1} [0] 1 State: 1 [0] 1 {0} --END-- """) exp = """HOA: v1 States: 2 Start: 0 AP: 2 "a" "b" acc-name: Buchi Acceptance: 1 Inf(0) properties: trans-labels explicit-labels trans-acc deterministic --BODY-- State: 0 [!0] 0 {0} [0] 1 State: 1 [0] 1