Пример #1
0
    def sift(self, sequence):
        cur_dtree_node = self.DTree.root
        prev_dtree_node = None

        while not cur_dtree_node is None and not cur_dtree_node.isLeaf:
            # Figure out which branch we should follow
            seq = sequence + cur_dtree_node.suffix
            response = self.query(seq)
            prev_dtree_node = cur_dtree_node
            if response in cur_dtree_node.children:
                cur_dtree_node = cur_dtree_node.children[response]
            else:
                cur_dtree_node = None

        # If we end up on an empty node, we can add a new leaf pointing to the
        # state accessed by the given sequence
        if cur_dtree_node is None:
            new_acc_seq = sequence
            new_state = DFAState(f's{len(self.S)}')
            new_dtree_node = self.DTree.createLeaf(new_state)
            self.S[new_acc_seq] = new_state
            prev_dtree_node.add(response, new_dtree_node)
            cur_dtree_node = new_dtree_node

        assert cur_dtree_node is not None, "Oof this shouldn't happen"
        assert cur_dtree_node.isLeaf, "This should always be a leaf node"
        assert cur_dtree_node.state is not None, "Leaf nodes should always represent a state"

        return cur_dtree_node.state
Пример #2
0
    def build_dfa(self):
        # Gather states from S
        S = self.S

        # The rows can function as index to the 'state' objects
        state_rows = set([tuple(self._get_row(s)) for s in S])
        initial_state_row = tuple(self._get_row(tuple()))
        accepting_states_rows = set(
            [tuple(self._get_row(s)) for s in S if self.query(s)])

        # Generate state names for convenience
        state_names = {
            state_row: f's{n + 1}'
            for (n, state_row) in enumerate(state_rows)
        }

        # Build the state objects and get the initial and accepting states
        states = {
            state_row: DFAState(state_names[state_row])
            for state_row in state_rows
        }
        initial_state = states[initial_state_row]
        accepting_states = [states[a_s] for a_s in accepting_states_rows]

        # Add the connections between states
        A = [a for (a, ) in self.A]
        # Keep track of states already visited
        visited_rows = []
        for s in S:
            s_row = tuple(self._get_row(s))
            if s_row not in visited_rows:
                for a in A:
                    sa_row = tuple(self._get_row(s + (a, )))
                    if sa_row in states.keys():
                        try:
                            states[s_row].add_edge(a, states[sa_row])
                        except:
                            # Can't add the same edge twice
                            pass
            else:
                visited_rows.append(s_row)

        return DFA(initial_state, accepting_states)
Пример #3
0
    def process_counterexample(self, counterexample):

        u, a, v = self.decompose(counterexample)

        # This state q_old needs to be split:
        q_old_state = self.get_state_from_sequence(u + a)
        q_old_acc_seq = self.get_access_sequence_from_state(q_old_state)

        # Store new state and access sequence
        q_new_acc_seq = self.get_access_sequence(u) + a
        q_new_state = DFAState(f's{len(self.S)}')

        assert q_new_acc_seq not in self.S

        self.S[q_new_acc_seq] = q_new_state

        ### update the DTree:
        # find the leaf corresponding to the state q_old
        q_old_leaf = self.DTree.getLeaf(q_old_state)
        # and create a new inner node,
        new_inner = self.DTree.createInner(v, temporary=True)

        # replace the old leaf node with the new inner node
        q_old_leaf.replace(new_inner)

        # check what branch the children should go
        response_q_old = self.query(q_old_acc_seq + v)
        response_q_new = self.query(q_new_acc_seq + v)
        # response_q_old = self.query(u + v)
        # response_q_new = self.query(q_new_acc_seq + v)
        assert response_q_new != response_q_old, "uh oh this should never happen"

        # prepare leaf node for the new state
        q_new_leaf = self.DTree.createLeaf(q_new_state)

        # Add the children to the corresponding branch of the new inner node
        new_inner.add(response_q_new, q_new_leaf)
        new_inner.add(response_q_old, q_old_leaf)

        print("splitty boi", q_old_state.name, q_new_state.name)
Пример #4
0
 def setUp(self):
     s1 = DFAState('s1')
     s2 = DFAState('s2')
     s3 = DFAState('s3')
     s1.add_edge('a', s2)
     s1.add_edge('b', s1)
     s2.add_edge('a', s2)
     s2.add_edge('b', s3)
     s3.add_edge('a', s3)
     s3.add_edge('b', s3)
     self.dfa = DFA(s1, [s3])
Пример #5
0
    def __init__(self, teacher: Teacher):
        # Access sequences S + state bookkeeping
        self.S = {tuple(): DFAState("s0")}

        super().__init__(teacher)
Пример #6
0
import tempfile

from stmlearn.equivalencecheckers import BFEquivalenceChecker
from stmlearn.learners import TTTDFALearner
from stmlearn.suls import DFA, DFAState
from stmlearn.teachers import Teacher

# Set up a simple state machine (S1) =a> (S2) =b> ((S3))

s1 = DFAState('s1')
s2 = DFAState('s2')
s3 = DFAState('s3')

s1.add_edge('a', s2)
s2.add_edge('b', s3)

sm = DFA(s1, [s3])

# Since we are learning a DFA, we need edges for the whole alphabet in every state
s1.add_edge('b', s1)
s2.add_edge('a', s2)
s3.add_edge('a', s3)
s3.add_edge('b', s3)

# We are using the brute force equivalence checker
eqc = BFEquivalenceChecker(sm)

# Set up the teacher, with the system under learning and the equivalence checker
teacher = Teacher(sm, eqc)

# Set up the learner who only talks to the teacher
Пример #7
0
    def setUp(self):
        # Set up an example mealy machine
        s1 = DFAState('1')
        s2 = DFAState('2')
        s3 = DFAState('3')

        s1.add_edge('a', s2)
        s1.add_edge('b', s1)
        s2.add_edge('a', s3)
        s2.add_edge('b', s1)
        s3.add_edge('a', s3)
        s3.add_edge('b', s1)

        self.dfa = DFA(s1, [s3])
Пример #8
0
 def setUp(self):
     # Set up an example mealy machine
     s1 = DFAState('1')
     s1.add_edge('a', s1)
     s1.add_edge('b', s1)
     self.dfa = DFA(s1, [])