def test_equivalence(self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]: print("Starting EQ test") depth = self.m print('Attempting to determine distinguishing set') W = get_distinguishing_set(fsm) if len(W) < 1: W.add(tuple()) print('distinguishing:', W) P = get_state_cover_set(fsm) print('state cover:', P) X = fsm.get_alphabet() #set([(x,) for x in fsm.get_alphabet()]) equivalent = True counterexample = None order = sorted(range(1, depth + 1), reverse=self.longest_first) for i in order: print(i, '/', depth) for p in P: for x in product(X, repeat=i): for w in W: test_sequence = p + x + w #print(test_sequence) equivalent, counterexample = self._are_equivalent(fsm, test_sequence) #print("Test sequence: ", test_sequence) if not equivalent: print("COUNTEREXAMPLE:", counterexample) return equivalent, counterexample return equivalent, None
def test_equivalence(self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]: print("[info] Starting equivalence test") if self.m is not None: n = len(fsm.get_states()) m = self.m assert m >= n, "hypothesis has more states than w-method bound" depth = m - n else: depth = self.horizon print("Depth:", depth) print("[info] Calculating distinguishing set") W = get_distinguishing_set(fsm, check=False) P = get_state_cover_set(fsm) print("[info] Got state cover set") # Ensure all access sequences have a counter for p in P: if p not in self.acc_seq_ce_counter: self.acc_seq_ce_counter[p] = 0 A = sorted([(x,) for x in fsm.get_alphabet()]) equivalent = True counterexample = None for access_sequence in self.acc_seq_order(P): print("[info] Trying access sequence:", access_sequence) to_visit = deque() to_visit.extend(A) while len(to_visit) > 0: cur = to_visit.popleft() # Grow the testing tree where possible self.sul.reset() sul_output_pre = self.sul.process_input(access_sequence + cur) if sul_output_pre in self.stop_on or any([sul_output_pre.startswith(x) for x in self.stop_on_startswith]): self.stopping_set.add(access_sequence + cur) continue elif len(cur) <= depth: for a in A: if access_sequence + cur + a not in self.stopping_set: to_visit.append(cur + a) # Perform the standard W-method tests for w in W: equivalent, counterexample = self._are_equivalent(fsm, access_sequence + cur + w) if not equivalent: self.acc_seq_ce_counter[access_sequence] += 1 return equivalent, counterexample # Nothing found for this access sequence: self.acc_seq_ce_counter[access_sequence] = min(0, self.acc_seq_ce_counter[access_sequence]) self.acc_seq_ce_counter[access_sequence] -= 1 return equivalent, counterexample
def test_statecover(self): for name, system in self.systems.items(): states = system.get_states() p = get_state_cover_set(system) reached_by_statecover = [] for acc_seq in p: system.reset() system.process_input(acc_seq) reached_by_statecover.append(system.state) self.assertCountEqual(states, reached_by_statecover)
def test_equivalence(self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]: print("Starting EQ test") n = len(fsm.get_states()) m = self.m assert m >= n, "hypothesis has more states than w-method bound" depth = m - n print('Attempting to determine distinguishing set') W = get_distinguishing_set(fsm) # We shouldn't forget to check without distinguishing sequence, or we may miss some differences in some cases if tuple() not in W: W.add(tuple()) print('distinguishing:', W) P = get_state_cover_set(fsm) print('state cover:', P) X = fsm.get_alphabet() #set([(x,) for x in fsm.get_alphabet()]) equivalent = True counterexample = None order = sorted(range(1, depth + 2), reverse=self.longest_first) for i in order: for x in product(X, repeat=i): for p in P: for w in W: test_sequence = p + x + w equivalent, counterexample = self._are_equivalent(fsm, test_sequence) if not equivalent: return equivalent, counterexample return equivalent, None
def test_equivalence(self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]: print("[info] Starting equivalence test") if self.m is not None: n = len(fsm.get_states()) m = self.m assert m >= n, "hypothesis has more states than w-method bound" depth = m - n else: depth = self.horizon print("Depth:", depth) print("[info] Calculating distinguishing set") W = get_distinguishing_set(fsm) print("Dset: ", W) # We shouldn't forget to check without distinguishing sequence, or we may miss some differences in some cases if tuple() not in W: W.add(tuple()) P = get_state_cover_set(fsm) print("[info] Got state cover set") # Ensure all access sequences have a counter for p in P: if p not in self.acc_seq_ce_counter: self.acc_seq_ce_counter[p] = 0 A = sorted([(x,) for x in fsm.get_alphabet()]) equivalent = True counterexample = None for access_sequence in self.acc_seq_order(P): # Get state name reached by acc seq fsm.reset() fsm.process_input(access_sequence) _acc_seq_state_name = fsm.state.name fsm.reset() print("[info] Trying access sequence:", access_sequence, "State:", _acc_seq_state_name) to_visit = deque() to_visit.extend(A) while len(to_visit) > 0: cur = to_visit.popleft() # Grow the testing tree where possible self.sul.reset() sul_output_pre = self.sul.process_input(access_sequence + cur) if sul_output_pre in self.stop_on or any([sul_output_pre.startswith(x) for x in self.stop_on_startswith]): self.stopping_set.add(access_sequence + cur) #continue elif len(cur) <= depth: for a in A: if access_sequence + cur + a not in self.stopping_set\ and access_sequence + cur + a not in P: to_visit.append(cur + a) # Perform the standard W-method tests for w in W: equivalent, counterexample = self._are_equivalent(fsm, access_sequence + cur + w) if not equivalent: # find longest access sequence which overlaps with the current query longest_acc_seq = None cur_query = access_sequence + cur + w for acc_seq in P: if cur_query[0:len(acc_seq)] == acc_seq: if longest_acc_seq is None or len(acc_seq) > len(longest_acc_seq): longest_acc_seq = acc_seq print("Counterexample:", counterexample) print("Longest acc seq:", longest_acc_seq) self.acc_seq_ce_counter[longest_acc_seq] += 1 return equivalent, counterexample # Nothing found for this access sequence: self.acc_seq_ce_counter[access_sequence] = min(0, self.acc_seq_ce_counter[access_sequence]) self.acc_seq_ce_counter[access_sequence] -= 1 return equivalent, counterexample
def test_equivalence(self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]: print("[info] Starting equivalence test") if self.m is not None: n = len(fsm.get_states()) m = self.m assert m >= n, "hypothesis has more states than w-method bound" depth = m - n else: depth = self.horizon print("Depth:", depth) print("[info] Calculating distinguishing set") W = get_distinguishing_set(fsm, check=False) P = get_state_cover_set(fsm) print("[info] Got state cover set") A = sorted([(x,) for x in fsm.get_alphabet()]) equivalent = True counterexample = None acc_seq_tasks = deque( zip( self.acc_seq_order(P), [deque([a for a in A if a not in self.stopping_set]) for x in range(len(P))] ) ) while len(acc_seq_tasks) > 0: access_sequence, to_visit = acc_seq_tasks.popleft() # bprint("[info] Trying access sequence:", access_sequence) assert len(to_visit) > 0 cur = to_visit.popleft() # Test without distinguishing sequence, important for early stopping equivalent, counterexample = self._are_equivalent(fsm, access_sequence + cur) if not equivalent: return equivalent, counterexample if access_sequence + cur not in self.stopping_set: # Basically the usual W-method tests: for w in W: equivalent, counterexample = self._are_equivalent(fsm, access_sequence + cur + w) if not equivalent: return equivalent, counterexample # If not, keep building if len(cur) <= depth: for a in A: if access_sequence + cur + a not in self.stopping_set: to_visit.append(cur + a) if len(to_visit) > 0: acc_seq_tasks.append((access_sequence, to_visit)) #else: #print(access_sequence) return equivalent, counterexample
def test_equivalence(self, fsm: Union[DFA, MealyMachine]) -> Tuple[bool, Iterable]: print("[info] Starting equivalence test") if self.m is not None: n = len(fsm.get_states()) m = self.m assert m >= n, "hypothesis has more states than w-method bound" depth = m - n else: depth = self.horizon print("Depth:", depth) print("[info] Calculating distinguishing set") W = get_distinguishing_set(fsm) P = get_state_cover_set(fsm) print("[info] Got state cover set") # Ensure all access sequences have a counter for p in P: if p not in self.acc_seq_ce_counter: self.acc_seq_ce_counter[p] = 0 A = sorted([(x,) for x in fsm.get_alphabet()]) equivalent = True counterexample = None for access_sequence in self.acc_seq_order(P): print("[info] Trying access sequence:", access_sequence) to_visit = deque() to_visit.extend(A) while len(to_visit) > 0: cur = to_visit.popleft() # Basically the usual W-method tests: for w in W: equivalent, counterexample = self._are_equivalent(fsm, access_sequence + cur + w) if not equivalent: self.acc_seq_ce_counter[access_sequence] += 1 return equivalent, counterexample # Also test without distinguishing sequence, important for early stopping equivalent, counterexample = self._are_equivalent(fsm, access_sequence + cur) if not equivalent: self.acc_seq_ce_counter[access_sequence] += 1 return equivalent, counterexample # Cut this branch short? if access_sequence + cur in self.stopping_set: continue # If not, keep building #else: if len(cur) <= depth: for a in A: if access_sequence + cur + a not in self.stopping_set: to_visit.append(cur + a) # Nothing found for this access sequence: self.acc_seq_ce_counter[access_sequence] = min(0, self.acc_seq_ce_counter[access_sequence]) self.acc_seq_ce_counter[access_sequence] -= 1 return equivalent, counterexample