Beispiel #1
0
    def __computesP(self, hypothesis):
        if hypothesis is None:
            raise Exception("Hypothesis cannot be None")
        self._logger.debug("Computing P")

        P = []

        empty_word = Word([EmptyLetter()])
        current_query = OutputQuery(empty_word)
        P.append(current_query)

        open_queries = deque([current_query])
        close_queries = []

        seen_states = set([hypothesis.initial_state])
        while len(open_queries) > 0:
            query = open_queries.popleft()
            tmp_seen_states = set()

            for letter in self.input_letters:
                new_word = query.input_word + Word([letter])
                query_z = OutputQuery(new_word)
                (output_word, visited_states) = hypothesis.play_query(query_z)
                close_queries.append(query_z)

                if visited_states[-1] not in seen_states:
                    tmp_seen_states.add(visited_states[-1])
                    open_queries.append(query_z)

            seen_states.update(tmp_seen_states)

        P.extend(close_queries)

        return P
Beispiel #2
0
    def __is_prefixes_equivalent(self, eq_words_in_S):
        """This method checks that the specified prefixes are equivalent.

        It returns None, if all the prefixes share the same row value given any
        input letters it get suffixed with
        Returns the letter that makes the eq_words_in_S not equivalent

        """

        if len(eq_words_in_S) < 2:
            raise Exception("At least two words must be provided")

        self._logger.debug("Checking if words '{}' are equivalents".format(
            ','.join([str(s) for s in eq_words_in_S])))

        for input_letter in self.input_letters:
            initial_suffixed_word = Word(eq_words_in_S[0].letters +
                                         [input_letter])
            for eq_word_in_S in eq_words_in_S[1:]:
                eq_suffixed_word = Word(eq_word_in_S.letters + [input_letter])
                for word_in_D in self.D:
                    self._logger.debug(type(word_in_D))
                    if self.ot_content[word_in_D][
                            eq_suffixed_word] != self.ot_content[word_in_D][
                                initial_suffixed_word]:
                        return (input_letter, word_in_D)

        return None
Beispiel #3
0
    def __add_word_in_S(self, word):
        """Add the specified word in S. In details, it does the following:
        - add the specified word in the list of words in S
        - executes the output queries (word + word_in_D) and store the results in DxS
        - recomputes new SAs made with the specified word + word_in_D        


        >>> from pylstar.ObservationTable import ObservationTable
        >>> from pylstar.KnowledgeBase import KnowledgeBase
        >>> from pylstar.Letter import Letter
        >>> from pylstar.Word import Word
        >>> kbase = KnowledgeBase()
        >>> ot = ObservationTable(input_letters = [], knowledge_base = kbase)
        >>> ot.initialize()
        >>> w = Word([Letter("a")])
        >>> ot._ObservationTable__add_word_in_S(w)

        """

        if word is None:
            raise Exception("Word cannot be None")

        if word in self.S:
            raise Exception(
                "Word '{}' is already registered in S".format(word))

        if word in self.SA:
            raise Exception(
                "Word '{}' is already registered in SA".format(word))

        self._logger.debug("Registering word '{}' in S".format(word))

        self.S.append(word)

        for word_in_D in self.D:

            cel = self.ot_content[word_in_D]
            # if word in cel.keys():
            #     raise Exception("Word '{}' already exists in observation table with D='{}'".format(word, word_in_D))
            # formulates a new OutputQuery and execute it
            output_query = OutputQuery(word + word_in_D)
            self._logger.debug("Execute query : {}".format(output_query))
            self.__execute_query(output_query)
            if not output_query.is_queried():
                raise Exception(
                    "Query '{}' could not be queried".format(output_query))

            cel[word] = output_query.output_word.last_letter()

        for input_letter in self.input_letters:
            if isinstance(word.letters[0], EmptyLetter):
                new_word = Word([input_letter])
            else:
                new_word = word + Word([input_letter])
            self._logger.debug("Adding word: {}".format(new_word))
            if new_word not in self.S:
                self.__add_word_in_SA(new_word)
 def isCounterExample(self, r_h, r_m):
     """Return True if the two rewards r_h and r_m are different and add the counter example at the OT."""
     if r_m != r_h:
         print("CE", r_m, r_h, self.observation_seq)
         input_word = Word(
             [Letter(symbol) for symbol in self.observation_seq])
         output_word = Word(
             [Letter(symbol) for symbol in self.reward_trace])
         self.OT.add_counterexample(input_word, output_word)
         return True
     return False
Beispiel #5
0
    def initialize(self):
        self._logger.debug("Initialization of the observation table" "")

        if self.initialized:
            raise Exception("Observation table is already initialized")

        self.initialized = True

        self.D = []
        self.S = []
        self.SA = []
        self.ot_content = dict()

        # creates a word for each input letter and register it in D
        for letter in self.input_letters:
            self.__add_word_in_D(Word([letter]))

        # creates a word that contains an EmptyLetter and registers it in S
        self.__add_word_in_S(Word([EmptyLetter()]))
Beispiel #6
0
    def find_counterexample(self, hypothesis):
        if hypothesis is None:
            raise Exception("Hypothesis cannot be None")

        
        self._logger.info("Starting the RandomWalk Algorithm to search for a counter-example")
        
        i_step = 0
        first_step_after_restart = True
        current_state = hypothesis.initial_state

        input_word = Word()
        hypothesis_output_word = Word()
        force_restart = False
        while i_step < self.max_steps:

            # should we restart
            if not first_step_after_restart:
                if force_restart or random.random() < self.restart_probability:
                    current_state = hypothesis.initial_state
                    first_step_after_restart = True

                    counterexample_query = self.__check_equivalence(input_word, hypothesis_output_word)
                    if counterexample_query is not None:
                        return counterexample_query
                    
                    input_word = Word()
                    hypothesis_output_word = Word()
                    force_restart = False
            else:
                first_step_after_restart = False

            try:
                (new_state, input_letter, output_letter) = self.__walk(current_state)
                current_state = new_state
                input_word.letters.append(input_letter)
                hypothesis_output_word.letters.append(output_letter)
                
            except Exception as e:
                self._logger.warn(e)
                force_restart = True

            i_step += 1
Beispiel #7
0
    def __compute_distinguishable_string(self, hypothesis, couple):
        self._logger.debug(
            "Computes the distinguishable string for state couple '{}'".format(
                couple))
        if hypothesis is None:
            raise Exception("Hypothesis cannot be None")
        if couple is None:
            raise Exception("couple cannot be None")

        self._logger.debug(
            "Computing distinguishing strings for states {}".format(couple))
        queries_to_test = deque([])

        empty_word = Word([EmptyLetter()])
        z_query = OutputQuery(empty_word)
        for letter in self.input_letters:
            new_word = z_query.input_word + Word([letter])
            queries_to_test.append(OutputQuery(new_word))

        distinguishable_query = z_query

        done = False
        i = 0
        while not done:
            query = queries_to_test.popleft()
            if i > self.max_states * self.max_states:
                break

            if not self.__is_distinguishable_states(hypothesis, query, couple):
                done = False
                for letter in self.input_letters:
                    new_query = OutputQuery(query.input_word + Word([letter]))
                    queries_to_test.append(new_query)
            else:
                done = True
                distinguishable_query = query

            i = i + 1

        return distinguishable_query
Beispiel #8
0
    def get_output_word(self, input_word):
        if input_word is None:
            raise Exception("Input word cannot be None")

        for root in self.roots:
            try:
                w = Word(root.traverse(input_word.letters))
                self._logger.info("I = {} > O = {}".format(input_word, w))
                return w
            except Exception:
                pass

        raise Exception("No path found")
Beispiel #9
0
    def submit_word(self, word):
        """This method return the Word produced by the target while submited the specified word"""
        output_letters = []

        for letter in word.letters:
            symbols = letter.symbols
            try:
                output_symbols = []
                for symbol in symbols:
                    try:
                        self.abstraction_layer.writeSymbol(symbol)
                    except ChannelDownException as e:
                        self._logger.debug("Channel is Down")
                    (curr_output_symbols,
                     data) = self.abstraction_layer.readSymbols()
                    output_symbols.extend(curr_output_symbols)
                output_letters.append(Letter(symbols=output_symbols))
            except Exception as e:
                self._logger.fatal("An error occurred : {}".format(e))
                output_letters.append(Letter(symbols=[EmptySymbol()]))

        for i in range(len(word.letters)):
            input_letter = word.letters[i]
            output_letter = output_letters[i]
            input_str = "None"
            output_str = "None"

            if input_letter.symbols is not None:
                input_str = ','.join([s.name for s in input_letter.symbols])

            if output_letter.symbols is not None:
                output_str = ','.join([s.name for s in output_letter.symbols])

            self._logger.debug(">>> {}".format(input_str))
            self._logger.debug("<<< {}".format(output_str))

        self.write_cache()

        if self.submitted_word_cb is not None:
            try:
                self.submitted_word_cb(word.letters, output_letters)
            except Exception as e:
                self._logger.error(
                    "Error encountered while executed submitted_word_cb: {}".
                    format(e))

        return Word(output_letters, normalize=False)
    def submit_word(self, word):
        self._logger.debug(
            "Submiting word '{}' to the fake target".format(word))

        if self.automata is None:
            raise Exception("Automata cannot be None")

        current_state = self.automata.initial_state
        output_letters = []
        for letter in word.letters:
            try:
                (current_state,
                 output_letter) = self._next_state(current_state, letter)
            except Exception:
                output_letter = EmptyLetter()

            output_letters.append(output_letter)

        output_word = Word(output_letters)
        return output_word
    def submit_word(self, word):

        self._logger.debug(
            "Submiting word '{}' to the network target".format(word))

        output_letters = []

        s = socket.socket()
        # Reuse the connection
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.settimeout(self.timeout)
        s.connect((self.target_host, self.target_port))
        try:
            output_letters = [
                self._submit_letter(s, letter) for letter in word.letters
            ]
        finally:
            s.close()

        return Word(letters=output_letters)
    def _execute_word(self, word):
        # Executes the specified word.
        if word is None:
            raise Exception("Word cannot be None")
        self._logger.debug("Execute word '{}'".format(word))
        #print("Execute word '{}'".format(word))

        reward_trace = []
        self.nuof_MQs += 1

        self.world.mrm.reset()
        self.world.map.reset()

        ge = GetExperience(self.world, word, MODE)  #Create the scheduler

        i = 0
        while i < len(word):
            letter = word.letters[i]
            a = ge.getActionScheduler(self.world.map.current,
                                      i)  #ask for the next action to execute
            (obs, rew) = self.world.moveAPF(a)  #get observation and reward
            reset = False
            while Letter(obs) != letter:
                if obs == "null":  #if we observe nothing execute a new action
                    self.actionsForLearning += 1
                    a = ge.getActionScheduler(self.world.map.current, i)
                    (obs, rew) = self.world.moveAPF(a)
                else:  #if we observe something we don't want, reset
                    reset = True
                    break

            if reset:
                self.world.reset()
                i = 0
                reward_trace = []
            else:  #if we observe what we want
                i += 1
                reward_trace.append(rew)
        w = Word([Letter(r) for r in reward_trace])
        return w
Beispiel #13
0
    def __computesZ(self, hypothesis, W):
        """it follows the formula Z= W U (X^1.W) U .... U (X^(m-1-n).W) U (W^(m-n).W)

        """
        if hypothesis is None:
            raise Exception("Hypothesis cannot be None")
        if W is None:
            raise Exception("W cannot be None")

        self._logger.debug("Computing Z")

        Z = []
        Z.extend(W)

        states = hypothesis.get_states()
        v = self.max_states - len(states)
        if v < 0:
            v = 0
        self._logger.debug("V= {}".format(v))

        output_queries = []
        for input_letter in self.input_letters:
            output_query = OutputQuery(word=Word([input_letter]))
            output_queries.append(output_query)

        X = dict()
        X[0] = W
        for i in range(1, v + 1):
            self._logger.debug("Computing X^{}".format(i))
            X[i] = []
            previous_X = X[i - 1]
            for x in previous_X:
                X[i].extend(x.multiply(output_queries))
            for w in W:
                for xi in X[i]:
                    if not xi in Z:
                        Z.append(xi)

        return Z
Beispiel #14
0
    def play_word(self, input_word, starting_state=None):
        """This method can be used to play the specified word
        across the current automata.
        It returns a tuple made of the output_word and the visited state
        captured while visiting the automata

        >>> from pylstar import Letter, EmptyLetter
        >>> from pylstar import Word
        >>> from pylstar import State
        >>> from pylstar import Transition
        >>> from pylstar import Automata
        >>> l_lambda = EmptyLetter()
        >>> l_a = Letter('a')
        >>> l_b = Letter('b')
        >>> l_0 = Letter(0)
        >>> l_1 = Letter(1)
        >>> s0 = State("S0")
        >>> s1 = State("S1")
        >>> s2 = State("S2")
        >>> s3 = State("S3")
        >>> t1 = Transition("T1", s3, l_a, l_0)
        >>> t2 = Transition("T2", s1, l_b, l_0)        
        >>> s0.transitions = [t1, t2]
        >>> t3 = Transition("T3", s0, l_a, l_1)
        >>> t4 = Transition("T4", s2, l_b, l_1)        
        >>> s1.transitions = [t3, t4]
        >>> t5 = Transition("T5", s3, l_a, l_0)
        >>> t6 = Transition("T6", s0, l_b, l_0)        
        >>> s2.transitions = [t5, t6]        
        >>> t7 = Transition("T7", s3, l_a, l_1)
        >>> t8 = Transition("T8", s3, l_b, l_1)        
        >>> s3.transitions = [t7, t8]
        >>> automata = Automata(s0)
        >>> print(automata.play_word(Word([l_a, l_a, l_a]))[0])
        [Letter(0), Letter(1), Letter(1)]
        >>> print(automata.play_word(Word([l_b, l_b, l_b]))[0])
        [Letter(0), Letter(1), Letter(0)]
        >>> print(automata.play_word(Word([l_b, l_a,  l_b, l_a, l_b]))[0])
        [Letter(0), Letter(1), Letter(0), Letter(1), Letter(0)]
        
        """

        if input_word is None or len(input_word) == 0:
            raise Exception("Input word cannot be None or empty")

        if starting_state is None:
            current_state = self.initial_state
        else:
            current_state = starting_state

        self._logger.debug("Playing word '{}'".format(input_word))

        output_letters = []
        visited_states = []
        
        for letter in input_word.letters:
            (output_letter, output_state) = current_state.visit(letter)
            output_letters.append(output_letter)
            visited_states.append(output_state)

            current_state = output_state

        output_word = Word(letters=output_letters)
        return (output_word, visited_states)        
Beispiel #15
0
    def build_hypothesis(self):
        """This method returns and Automata that follows the observation table.

        If the observation table is closed and consistent, it is possible to construct
        an hypothesis automata. Each state of the automata maps to a row of S in the observation table.        

        >>> from pylstar.ObservationTable import ObservationTable
        >>> from pylstar.KnowledgeBase import KnowledgeBase
        >>> from pylstar.Letter import Letter, EmptyLetter
        >>> from pylstar.Word import Word
        >>> l_lambda = EmptyLetter()
        >>> l_a = Letter('a')
        >>> l_b = Letter('b')
        >>> l_y = Letter('y')
        >>> l_z = Letter('z')
        >>> w_lambda = Word([l_lambda])
        >>> w_a = Word([l_a])
        >>> w_b = Word([l_b])
        >>> w_aa = Word([l_a, l_a])
        >>> w_ab = Word([l_a, l_b])
        >>> w_aaa = Word([l_a, l_a, l_a])
        >>> w_aab = Word([l_a, l_a, l_b])
        >>> kbase = KnowledgeBase()
        >>> ot = ObservationTable(input_letters = [l_a, l_b], knowledge_base = kbase)
        >>> ot.D.extend([w_a, w_b, w_aa])
        >>> ot.S.extend([w_lambda, w_a, w_aa])
        >>> ot.SA.extend([w_b, w_ab, w_aaa, w_aab])
        >>> ot.ot_content[w_a] = dict()
        >>> ot.ot_content[w_a][w_lambda] = l_z
        >>> ot.ot_content[w_a][w_a] = l_y
        >>> ot.ot_content[w_a][w_aa] = l_z
        >>> ot.ot_content[w_a][w_b] = l_y
        >>> ot.ot_content[w_a][w_ab] = l_z
        >>> ot.ot_content[w_a][w_aaa] = l_z
        >>> ot.ot_content[w_a][w_aab] = l_y
        >>> ot.ot_content[w_b] = dict()
        >>> ot.ot_content[w_b][w_lambda] = l_z
        >>> ot.ot_content[w_b][w_a] = l_y
        >>> ot.ot_content[w_b][w_aa] = l_z
        >>> ot.ot_content[w_b][w_b] = l_y
        >>> ot.ot_content[w_b][w_ab] = l_z
        >>> ot.ot_content[w_b][w_aaa] = l_z
        >>> ot.ot_content[w_b][w_aab] = l_y
        >>> ot.ot_content[w_aa] = dict()
        >>> ot.ot_content[w_aa][w_lambda] = l_y
        >>> ot.ot_content[w_aa][w_a] = l_z
        >>> ot.ot_content[w_aa][w_aa] = l_z
        >>> ot.ot_content[w_aa][w_b] = l_z
        >>> ot.ot_content[w_aa][w_ab] = l_y
        >>> ot.ot_content[w_aa][w_aaa] = l_y
        >>> ot.ot_content[w_aa][w_aab] = l_z        
        >>> print(ot)
                                                | [Letter('a')] | [Letter('b')] | [Letter('a'), Letter('a')]
        --------------------------------------- | ------------- | ------------- | --------------------------
        [EmptyLetter]                           | Letter('z')   | Letter('z')   | Letter('y')               
        [Letter('a')]                           | Letter('y')   | Letter('y')   | Letter('z')               
        [Letter('a'), Letter('a')]              | Letter('z')   | Letter('z')   | Letter('z')               
        ~~~                                     | ~~~           | ~~~           | ~~~                       
        [Letter('b')]                           | Letter('y')   | Letter('y')   | Letter('z')               
        [Letter('a'), Letter('b')]              | Letter('z')   | Letter('z')   | Letter('y')               
        [Letter('a'), Letter('a'), Letter('a')] | Letter('z')   | Letter('z')   | Letter('y')               
        [Letter('a'), Letter('a'), Letter('b')] | Letter('y')   | Letter('y')   | Letter('z')               
        --------------------------------------- | ------------- | ------------- | --------------------------
        >>> print(ot.is_closed())
        True
        >>> print(ot.find_inconsistency())
        None
        >>> automata = ot.build_hypothesis()
        >>> print(automata.build_dot_code())
        digraph "Automata" {
        "0" [shape=doubleoctagon, style=filled, fillcolor=white, URL="0"];
        "1" [shape=ellipse, style=filled, fillcolor=white, URL="1"];
        "2" [shape=ellipse, style=filled, fillcolor=white, URL="2"];
        "0" -> "1" [fontsize=5, label="a / z", URL="t0"];
        "0" -> "1" [fontsize=5, label="b / z", URL="t1"];
        "1" -> "2" [fontsize=5, label="a / y", URL="t2"];
        "1" -> "0" [fontsize=5, label="b / y", URL="t3"];
        "2" -> "0" [fontsize=5, label="a / z", URL="t4"];
        "2" -> "1" [fontsize=5, label="b / z", URL="t5"];
        }
        
        """

        states = []
        transitions = []
        initial_state = None
        words_and_states = []
        long_state_name_to_states = dict()

        # find all rows in S
        rows_in_S = [(s, self.__get_row(s)) for s in self.S]

        # get all unique rows
        S_with_same_rows = collections.OrderedDict()
        for word_in_s, row_s in rows_in_S:
            key = ','.join([str(w) for w in row_s])
            if key not in S_with_same_rows.keys():
                S_with_same_rows[key] = list()
            S_with_same_rows[key].append(word_in_s)

        # build the list of states of the hypothesis (and identify the initial state)
        for long_state_name, words_in_S in S_with_same_rows.items():
            state_name = str(
                len(states)
            )  #''.join(long_state_name.replace("Letter(", "").replace(')', ''))
            state = State(name=state_name)
            states.append(state)

            words_and_states.append((words_in_S[0], state))
            long_state_name_to_states[long_state_name] = state

            # check if its the initial state
            epsilon_word_found = Word([EmptyLetter()]) in words_in_S
            self._logger.debug("state  :{} , {} / {}".format(
                long_state_name, words_in_S, epsilon_word_found))

            if initial_state is None and epsilon_word_found:
                initial_state = state
            elif epsilon_word_found and initial_state is not None:
                raise Exception("Multiple initial state found.")

        if initial_state is None:
            raise Exception("Can't find any initial state")

        # computes the transitions for each state of the automata
        for word, state in words_and_states:

            for input_letter in self.input_letters:

                # computes the output state
                new_word = word + Word([input_letter])
                row_new_word = self.__get_row(new_word)

                output_state_name = ','.join([str(w) for w in row_new_word])
                if output_state_name not in long_state_name_to_states.keys():
                    for x in long_state_name_to_states.keys():
                        self._logger.debug(x)

                    raise Exception(
                        "Cannot find a state with following name : '{}'".
                        format(output_state_name))

                output_state = long_state_name_to_states[output_state_name]
                output_letter = self.ot_content[Word([input_letter])][word]

                transition_name = "t{}".format(len(transitions))
                transition = Transition(name=transition_name,
                                        output_state=output_state,
                                        input_letter=input_letter,
                                        output_letter=output_letter)
                state.transitions.append(transition)
                transitions.append(transition)

        return Automata(initial_state=initial_state)
    def buildProductAutomaton(self, h):
        """Given a hypothesis of the angluin algo, build the product between the gird and this hypothesis and write it in a PRISM file.
		The init state is {'c1','r1','null'} with no obs already made"""

        rewards = "rewards\n"
        labels = ''
        out_file = open(TMP_MODEL_PATH, 'w')
        #module
        out_file.write("mdp\n\nmodule tmp\n\n")

        #number of state and initial state
        new_states = []
        for s in self.world.map.states:
            for o in range(len(h.get_states())):
                labels += 'label "' + s + '_' + str(o) + '" = s=' + str(
                    len(new_states)) + ' ;\n'
                new_states.append((s, o))

        out_file.write("\ts : [0.." + str(len(new_states) - 1) + "] init " +
                       str(new_states.index((self.world.map.initiales[0],
                                             0))) + ";\n\n")

        #transitions
        for s in new_states:
            state_id = self.world.map.getIdState(s[0])
            for a in self.world.map.availableActions(s[0]):
                action_id = self.world.map.getIdAction(a)
                obs = self.world.map.labelling[state_id][action_id]

                #if len(self.world.map.transitions[state_id][action_id]) > 0:
                out_file.write("\t[" + a + "] s=" + str(new_states.index(s)) +
                               "-> ")
                temp_list = []

                if obs == 'null':
                    rewards += "\t[" + a + "] (s=" + str(
                        new_states.index(s)) + ") : " + str(
                            self.world.mrm.default_reward) + ";\n"
                    for [dest, prob
                         ] in self.world.map.transitions[state_id][action_id]:
                        index_dest = str(
                            new_states.index(
                                (self.world.map.getStateFromId(dest), s[1])))
                        temp_list.append(
                            str(prob) + " : (s'=" + index_dest + ")")
                else:
                    tr_val = h.play_word(
                        Word([Letter(obs)]),
                        self.getStateInHypothesis(h.get_states(), s[1]))
                    state_in_h = int(tr_val[1][-1].name)
                    rewards += "\t[" + a + "] (s=" + str(
                        new_states.index(s)) + ") : " + str(
                            tr_val[0].last_letter().name) + ";\n"
                    for [dest, prob
                         ] in self.world.map.transitions[state_id][action_id]:
                        index_dest = str(
                            new_states.index(
                                (self.world.map.getStateFromId(dest),
                                 state_in_h)))
                        temp_list.append(
                            str(prob) + " : (s'=" + index_dest + ")")

                out_file.write(" + ".join(temp_list))
                out_file.write(";\n")

            a = "reset"
            out_file.write(
                "\t[" + a + "] s=" + str(new_states.index(s)) +
                "-> 1.0 : (s'=" +
                str(new_states.index((self.world.map.initiales[0], 0))) +
                ");\n")
            rewards += "\t[" + a + "] (s=" + str(
                new_states.index(s)) + ") : " + str(
                    self.world.mrm.reset_cost) + ";\n"

        out_file.write("\nendmodule\n\n")
        out_file.write(labels)

        rewards += "endrewards\n"
        out_file.write(rewards)
        out_file.close()
Beispiel #17
0
    def make_consistent(self, inconsistency):
        """This method makes consistent the observation table.

        >>> from pylstar.ObservationTable import ObservationTable
        >>> from pylstar.FakeActiveKnowledgeBase import FakeActiveKnowledgeBase
        >>> from pylstar.Letter import Letter, EmptyLetter
        >>> from pylstar.Word import Word
        >>> from pylstar.automata.State import State
        >>> from pylstar.automata.Transition import Transition
        >>> from pylstar.automata.Automata import Automata
        >>> l_lambda = EmptyLetter()
        >>> l_a = Letter('a')
        >>> l_b = Letter('b')
        >>> l_0 = Letter(0)
        >>> l_1 = Letter(1)
        >>> s0 = State("S0")
        >>> s1 = State("S1")
        >>> s2 = State("S2")
        >>> s3 = State("S3")
        >>> t1 = Transition("T1", s3, l_a, l_0)
        >>> t2 = Transition("T2", s1, l_b, l_0)        
        >>> s0.transitions = [t1, t2]
        >>> t3 = Transition("T3", s0, l_a, l_1)
        >>> t4 = Transition("T4", s2, l_b, l_1)        
        >>> s1.transitions = [t3, t4]
        >>> t5 = Transition("T5", s3, l_a, l_0)
        >>> t6 = Transition("T6", s0, l_b, l_0)        
        >>> s2.transitions = [t5, t6]        
        >>> t7 = Transition("T7", s3, l_a, l_1)
        >>> t8 = Transition("T8", s3, l_b, l_1)        
        >>> s3.transitions = [t7, t8]
        >>> automata = Automata(s0)
        >>> kbase = FakeActiveKnowledgeBase(automata)
        >>> ot = ObservationTable(input_letters = [l_a, l_b], knowledge_base = kbase)
        >>> ot.initialize()
        >>> print(ot)
                      | [Letter('a')] | [Letter('b')]
        ------------- | ------------- | -------------
        [EmptyLetter] | Letter(0)     | Letter(0)    
        ~~~           | ~~~           | ~~~          
        [Letter('a')] | Letter(1)     | Letter(1)    
        [Letter('b')] | Letter(1)     | Letter(1)    
        ------------- | ------------- | -------------
        >>> print(ot.is_closed())
        False
        >>> ot.close_table()
        >>> print(ot)
                                   | [Letter('a')] | [Letter('b')]
        -------------------------- | ------------- | -------------
        [EmptyLetter]              | Letter(0)     | Letter(0)    
        [Letter('a')]              | Letter(1)     | Letter(1)    
        ~~~                        | ~~~           | ~~~          
        [Letter('b')]              | Letter(1)     | Letter(1)    
        [Letter('a'), Letter('a')] | Letter(1)     | Letter(1)    
        [Letter('a'), Letter('b')] | Letter(1)     | Letter(1)    
        -------------------------- | ------------- | -------------
        >>> counter_input_word = Word([l_b, l_b, l_b])
        >>> counter_output_word = Word([l_0, l_1, l_0])
        >>> ot.add_counterexample(counter_input_word, counter_output_word)
        >>> print(ot)
                                                             | [Letter('a')] | [Letter('b')]
        ---------------------------------------------------- | ------------- | -------------
        [EmptyLetter]                                        | Letter(0)     | Letter(0)    
        [Letter('a')]                                        | Letter(1)     | Letter(1)    
        [Letter('b')]                                        | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('b')]                           | Letter(0)     | Letter(0)    
        [Letter('b'), Letter('b'), Letter('b')]              | Letter(0)     | Letter(0)    
        ~~~                                                  | ~~~           | ~~~          
        [Letter('a'), Letter('a')]                           | Letter(1)     | Letter(1)    
        [Letter('a'), Letter('b')]                           | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('a')]                           | Letter(0)     | Letter(0)    
        [Letter('b'), Letter('b'), Letter('a')]              | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('b'), Letter('b'), Letter('a')] | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('b'), Letter('b'), Letter('b')] | Letter(1)     | Letter(1)    
        ---------------------------------------------------- | ------------- | -------------
        >>> inconsistency = ot.find_inconsistency()
        >>> ot.make_consistent(inconsistency)
        >>> inconsistency = ot.find_inconsistency()
        >>> if inconsistency is not None: ot.make_consistent(inconsistency)
        >>> print(ot.find_inconsistency())
        None
        >>> print(ot.is_closed())
        True
        >>> automata = ot.build_hypothesis()
        >>> print(automata.build_dot_code())
        digraph "Automata" {
        "0" [shape=doubleoctagon, style=filled, fillcolor=white, URL="0"];
        "2" [shape=ellipse, style=filled, fillcolor=white, URL="2"];
        "3" [shape=ellipse, style=filled, fillcolor=white, URL="3"];
        "1" [shape=ellipse, style=filled, fillcolor=white, URL="1"];
        "0" -> "1" [fontsize=5, label="a / 0", URL="t0"];
        "0" -> "2" [fontsize=5, label="b / 0", URL="t1"];
        "2" -> "0" [fontsize=5, label="a / 1", URL="t4"];
        "2" -> "3" [fontsize=5, label="b / 1", URL="t5"];
        "3" -> "1" [fontsize=5, label="a / 0", URL="t6"];
        "3" -> "0" [fontsize=5, label="b / 0", URL="t7"];
        "1" -> "1" [fontsize=5, label="a / 1", URL="t2"];
        "1" -> "1" [fontsize=5, label="b / 1", URL="t3"];
        }
                


        """

        if inconsistency is None:
            raise Exception("Inconsistency cannot be None")
        # verify both words of inconsistency share the same last letter
        suffix = inconsistency[0][1]
        inconsistent_suffix = inconsistency[1]

        new_col_word = Word([suffix] + inconsistent_suffix.letters)
        self.__add_word_in_D(new_col_word)
Beispiel #18
0
    def add_counterexample(self, input_word, output_word):
        """This method register the specified counterexample in the observation table.

        In details, it insert all the prefixes of the counterexample to the upper part of the table.
        It also extend SA accordingly.

        >>> from pylstar.ObservationTable import ObservationTable
        >>> from pylstar.FakeActiveKnowledgeBase import FakeActiveKnowledgeBase
        >>> from pylstar.Letter import Letter, EmptyLetter
        >>> from pylstar.Word import Word
        >>> from pylstar.automata.State import State
        >>> from pylstar.automata.Transition import Transition
        >>> from pylstar.automata.Automata import Automata
        >>> l_lambda = EmptyLetter()
        >>> l_a = Letter('a')
        >>> l_b = Letter('b')
        >>> l_0 = Letter(0)
        >>> l_1 = Letter(1)
        >>> s0 = State("S0")
        >>> s1 = State("S1")
        >>> s2 = State("S2")
        >>> s3 = State("S3")
        >>> t1 = Transition("T1", s3, l_a, l_0)
        >>> t2 = Transition("T2", s1, l_b, l_0)        
        >>> s0.transitions = [t1, t2]
        >>> t3 = Transition("T3", s0, l_a, l_1)
        >>> t4 = Transition("T4", s2, l_b, l_1)        
        >>> s1.transitions = [t3, t4]
        >>> t5 = Transition("T5", s3, l_a, l_0)
        >>> t6 = Transition("T6", s0, l_b, l_0)        
        >>> s2.transitions = [t5, t6]        
        >>> t7 = Transition("T7", s3, l_a, l_1)
        >>> t8 = Transition("T8", s3, l_b, l_1)        
        >>> s3.transitions = [t7, t8]
        >>> automata = Automata(s0)
        >>> kbase = FakeActiveKnowledgeBase(automata)
        >>> ot = ObservationTable(input_letters = [l_a, l_b], knowledge_base = kbase)
        >>> ot.initialize()
        >>> print(ot)
                      | [Letter('a')] | [Letter('b')]
        ------------- | ------------- | -------------
        [EmptyLetter] | Letter(0)     | Letter(0)    
        ~~~           | ~~~           | ~~~          
        [Letter('a')] | Letter(1)     | Letter(1)    
        [Letter('b')] | Letter(1)     | Letter(1)    
        ------------- | ------------- | -------------
        >>> print(ot.is_closed())
        False
        >>> ot.close_table()
        >>> print(ot)
                                   | [Letter('a')] | [Letter('b')]
        -------------------------- | ------------- | -------------
        [EmptyLetter]              | Letter(0)     | Letter(0)    
        [Letter('a')]              | Letter(1)     | Letter(1)    
        ~~~                        | ~~~           | ~~~          
        [Letter('b')]              | Letter(1)     | Letter(1)    
        [Letter('a'), Letter('a')] | Letter(1)     | Letter(1)    
        [Letter('a'), Letter('b')] | Letter(1)     | Letter(1)    
        -------------------------- | ------------- | -------------
        >>> counter_input_word = Word([l_b, l_b, l_b])
        >>> counter_output_word = Word([l_0, l_1, l_0])
        >>> ot.add_counterexample(counter_input_word, counter_output_word)
        >>> print(ot)
                                                             | [Letter('a')] | [Letter('b')]
        ---------------------------------------------------- | ------------- | -------------
        [EmptyLetter]                                        | Letter(0)     | Letter(0)    
        [Letter('a')]                                        | Letter(1)     | Letter(1)    
        [Letter('b')]                                        | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('b')]                           | Letter(0)     | Letter(0)    
        [Letter('b'), Letter('b'), Letter('b')]              | Letter(0)     | Letter(0)    
        ~~~                                                  | ~~~           | ~~~          
        [Letter('a'), Letter('a')]                           | Letter(1)     | Letter(1)    
        [Letter('a'), Letter('b')]                           | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('a')]                           | Letter(0)     | Letter(0)    
        [Letter('b'), Letter('b'), Letter('a')]              | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('b'), Letter('b'), Letter('a')] | Letter(1)     | Letter(1)    
        [Letter('b'), Letter('b'), Letter('b'), Letter('b')] | Letter(1)     | Letter(1)    
        ---------------------------------------------------- | ------------- | -------------
        
        """

        if input_word is None or len(input_word) == 0:
            raise Exception("Input word cannot be None or empty")
        if output_word is None or len(output_word) == 0:
            raise Exception("Output word cannot be None or empty")
        if len(input_word) != len(output_word):
            raise Exception(
                "Output word must have the same length then input word")

        for len_prefix in range(1, len(input_word) + 1):
            prefix_input = Word(input_word.letters[:len_prefix])
            if prefix_input not in self.S:
                if prefix_input in self.SA:
                    self.remove_row(prefix_input)

                self.__add_word_in_S(prefix_input)