Exemple #1
0
    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
Exemple #2
0
    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
Exemple #3
0
    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
Exemple #4
0
def _minimize(mm: MealyMachine):
    dset = get_distinguishing_set(mm)
    dset_outputs = get_dset_outputs(mm, dset)

    # Find non-unique states:
    state_map = {}
    for state, outputs in dset_outputs.items():
        if outputs not in state_map:
            state_map[outputs] = [state]
        else:
            state_map[outputs].append(state)

    for outputs, states in state_map.items():
        if len(states) > 1:
            og_state = states[0]
            rest_states = states[1:]

            states = mm.get_states()
            for state in states:
                for action, (other_state, output) in state.edges.items():
                    if other_state in rest_states:
                        state.edges[action] = og_state, output

    return mm
Exemple #5
0
    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
Exemple #6
0
    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
Exemple #7
0
 def test_simple_moore(self):
     dset = get_distinguishing_set(self.dfa, method="Moore")
     self.assertTrue(check_distinguishing_set(self.dfa, dset))
     self.assertEqual({tuple(), ('b', )}, dset)
Exemple #8
0
    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
Exemple #9
0
 def test_m182_moore(self):
     dset = get_distinguishing_set(self.m182, method="Moore")
     self.assertTrue(check_distinguishing_set(self.m182, dset))
Exemple #10
0
 def test_simple_hopcroft(self):
     dset = get_distinguishing_set(self.dfa, method="Hopcroft")
     self.assertTrue(check_distinguishing_set(self.dfa, dset))
     self.assertEqual({('a', ), tuple()}, dset)
Exemple #11
0
 def test_m182_hopcroft(self):
     dset = get_distinguishing_set(self.m182, method="Hopcroft")
     self.assertTrue(check_distinguishing_set(self.m182, dset))
Exemple #12
0
 def test_deterministic_hopcroft(self):
     for i in range(10):
         dset1 = get_distinguishing_set(self.m54, method="Hopcroft")
         dset2 = get_distinguishing_set(self.m54, method="Hopcroft")
         self.assertEqual(dset1, dset2)
Exemple #13
0
 def test_at_least_one_moore(self):
     dset = get_distinguishing_set(self.dfa, method="Moore")
     self.assertTrue(check_distinguishing_set(self.dfa, dset))
     self.assertEqual({tuple()}, dset)
Exemple #14
0
 def test_single_long_moore(self):
     dset = get_distinguishing_set(self.mm, method="Moore")
     self.assertEqual({('a', )}, dset)
Exemple #15
0
 def test_single_long_hopcroft(self):
     dset = get_distinguishing_set(self.mm, method="Hopcroft")
     self.assertEqual({('a', )}, dset)