Example #1
0
class CountertraceFinder(object):
    """
    Heuristically searches for a countertrace.

    This module is able to heuristically search for a countertrace, i.e.,
    for a FIXED sequence of input values, so that the system is not able
    to fulfill the specification no matter how it behaves. Of course
    such a fixed sequence of inputs is a much simpler explanation for
    unrealizability than a sequence of inputs which is dependent on
    previous outputs.

    Computing a countertrace is expensive. We could existentially
    quantify all outputs in the automaton representing the specification,
    complement the automaton and check for emptyness. However,
    complementing a nondeterministic automaton causes an exponential
    blow up of the state space. Thus we define a heuristic. If no
    countertrace could be found with this heuristic, this does not mean,
    that no such trace exists. If a countertrace could be found, it is
    written into the file 'spec_debug_results/countertrace.txt'.

    @author: Robert Koenighofer <*****@*****.**>
    @version: 1.0.0
    """
    def __init__(self, utils):
        """
        Constructor

        @param utils: A module containing a lot of utility-functions as
               well as data which is needed almost everywhere.
        @type utils: L{SpecDebugUtils}
        """

        #: A module containing a lot of utility-functions.
        #: @type: L{SpecDebugUtils}
        self.__utils = utils

        #: A utility class that allows us to print the countertrace.
        #: @type: L{Writer}
        self.__writer = Writer(utils)

    def compute_countertrace(self, counterstrategy, abort = 100):
        """
        Heuristically searches for a countertrace.

        This method is able to heuristically search for a countertrace, i.e.,
        for a FIXED sequence of input values, so that the system is not able
        to fulfill the specification no matter how it behaves. Of course
        such a fixed sequence of inputs is a much simpler explanation for
        unrealizability than a sequence of inputs which is dependent on
        previous outputs.

        The heuristic works in the following way:
        For every time step, we compute a set of states which might be
        visited in exactly this time step:
         - set0 = all states which might be visited in step 0 (initial states)
         - set1 = all states which might be visited in step 1, so
           all possible successors of set0
         - and so on
        For every set we now try to find one next input which is winning for
        the environment from all states of the set (which is conforming to
        the counterstrategy from all states of the set). If no next input
        could be found for at least one of the sets, our heuristic gives up.

        @param counterstrategy: the (interactive, system dependent)
               counterstrategy.
        @type counterstrategy: L{BDD}
        @param abort: The number of iterations after which the heuristic aborts
               without success. The default value is 100.
        @type abort: 100
        @return: A countertrace.
        @rtype: L{InfiniteTraceOfBdds}
        """

        utils = self.__utils

        if utils.init.isZero() or utils.trans.isZero():
            # we won't find a countertrace in these cases:
            return None

        itcount = 0
        list_of_sets = []
        countertrace = []
        repeat_index = None
        irrelevant_output_cube = BDD.ONE(self.__utils.dd_mgr)
        for out in utils.output_vars:
            irrelevant_output_cube *= out.ps * out.ns
        for out in utils.relevant_out_vars:
            irrelevant_output_cube = irrelevant_output_cube.exists(out.ps)
            irrelevant_output_cube = irrelevant_output_cube.exists(out.ns)

        current_states = utils.all_present_vars_cube

        # we start in the initial state:
        current_set_of_states = utils.init_ix_jx

        countertrace.append(utils.keep_only_present_inputs(utils.init))

        # while we did not already examine a superset of the current set of
        # states:
        while not self.get_index_of_superset_in_list(list_of_sets, \
                                                     current_set_of_states):
            list_of_sets.append(current_set_of_states)
            #print "------------   iteration %d  ------------------" % itcount
            itcount += 1
            if abort != None and abort > 0 and itcount >= abort:
                return None

            # computing all next inputs conforming to the counterstrategy:
            state_plus_input_ix_jx = current_set_of_states * counterstrategy
            state_plus_input_ix_jx = \
                      state_plus_input_ix_jx.exists(irrelevant_output_cube)
            state_plus_input = \
                      utils.remove_next_ix_jx_outputs(state_plus_input_ix_jx)

            # now we compute all next inputs, which are OK (winning for the
            # environment) for all states of current_set_of_states:
            state_occurs = utils.keep_only_present(state_plus_input)
            system_indep_next_inputs = \
                   ((~state_occurs) + state_plus_input).forall(current_states)

            if system_indep_next_inputs.isZero():
                # if we could not find one, we give up
                # TODO: maybe try something else in a previous step to
                # avoid this certain current_set_of_states.
                return None

            # we choose one of these inputs:
            concrete_next_input = \
                        utils.choose_all_next_inputs(system_indep_next_inputs)

            trace_elem = utils.swap_present_next(concrete_next_input)
            countertrace.append(utils.keep_only_present_inputs(trace_elem))

            # the new current_set_of_states is the set of next states (if
            # concrete_next_input is used as input):
            state_plus_input_ix_jx *= concrete_next_input
            next_states = state_plus_input_ix_jx * utils.sys_trans
            next_states = utils.swap_present_next(next_states)
            current_set_of_states = utils.keep_only_present(next_states)


        # If we are here, we found an input for every time step.
        repeat_index = self.get_index_of_superset_in_list(list_of_sets, \
                                                     current_set_of_states) + 1
        trace = InfiniteTraceOfBdds(utils, countertrace, repeat_index)

        return trace
        
    def print_trace(self, countertrace):
        """
        Prints a countertrace into the file
        ./spec_debug_results/countertrace.txt.

        @param countertrace: A sequence of inputs so that the system is forced
               to violate its specification.
        @type countertrace: L{InfiniteTraceOfBdds}
        """

        # write the inputs according to the countertrace:
        for input_bdd in countertrace.get_trace():
            for var in self.__utils.input_vars:
                symb = self.__utils.get_val_as_string(input_bdd, var, False)
                self.__writer.set_chosen_input(var.name, symb)
            self.__writer.start_next_time_step()

        # finally we define where the trace repeats:
        self.__writer.set_repeat_indices(countertrace.repeat_index, \
                                     countertrace.length_stem_plus_loop - 1)

        # and write the file:
        self.__writer.write_to_file("./spec_debug_results/countertrace.txt")
        self.__writer.clear()

    def is_graph_system_independent(self, graph_nodes):
        """
        Checks if the inputs in a graph are system independent.

        This method checks if the inputs in the graph computed by the class
        L{PathFinder} are system independent. If this is the case, a
        countertrace can be read directly from this graph. If the graph was
        generated from a countertrace, the inputs in this graph will always
        be system independent (i.e., independent of the moves of the system).

        This method is only used to check if the methods compute_countertrace
        and make_strategy_system_independent work correctly.

        @param graph_nodes: A set of graph nodes.
        @type graph_nodes: list<L{GraphNode}>
        @return: True if the graph is system independent, False otherwise
        @rtype: bool
        """

        # The first current state is the initial state:
        current_nodes = [graph_nodes[0]]
        current_nodes_bdd = graph_nodes[0].bdd
        list_of_sets = []
        while list_of_sets.count(current_nodes_bdd) == 0:
            list_of_sets.append(current_nodes_bdd)

            # check if all inputs are equal:
            input_intersection = BDD.ONE(self.__utils.dd_mgr)
            for node in current_nodes:
                inputs = self.__utils.keep_only_present_inputs(node.bdd)
                input_intersection *= inputs
            
            if input_intersection.isZero():
                print "Graph is NOT system independent !\n"
                return False

            # compute list of successor states:
            next_nodes = []
            for node in current_nodes:
                next_nodes.extend(node.successors)
            # we remove multiple elements:
            current_nodes = list(set(next_nodes))

            # compute a bdd that contains all nodes:
            current_nodes_bdd = BDD.ZERO(self.__utils.dd_mgr)
            for node in current_nodes:
                current_nodes_bdd += node.bdd

        # If we are here, the graph is system independent, i.e., the inputs
        # used in the graph are independent of the moves of the system.
        print "graph IS system independent!!!"
        return True


    def make_strategy_system_independent(self, counterstrategy):
        """
        Heuristically tries to make a counterstrategy system independent.

        A counterstrategy is system independent if choices on
        next inputs do not depend on previous choices of outputs in all time
        steps. Hence, a system independent counterstrategy can be used to
        compute a countertrace, i.e. a FIXED sequence of inputs, so that the
        system is always forced to violate its specification no matter how it
        behaves. Basically a system independent counterstrategy is a
        countertrace in the shape of a counterstrategy (in the shape of a
        relation rather than a list of inputs).

        This method is never used, it is just experimental. Use the method
        compute_countertrace instead. compute_countertrace will find
        countertraces in more cases, since there is no restriction that the
        result has to be in the shape of a counterstrategy. So in the method
        compute_countertrace, different behaviours from the same state
        (inputs,outputs,ix,jx content) are possible dependent on the step
        count while this is not the case for make_strategy_system_independent.

        The heuristic works in the following way:
        For every time step, we compute a set of states which might be
        visited in exactly this time step:
         - set0 = all states which might be visited in step 0 (initial states)
         - set1 = all states which might be visited in step 1, so
           all possible successors of set0
         - and so on
        For every set we now try to find one next input which is winning for
        the environment from all states of the set (which is conforming to
        the counterstrategy from all states of the set). If such an input is
        found, the counterstrategy must take this next input from all states
        of the set. In the counterstrategy we disallow all other inputs from
        these states. When the counterstrategy changes, we restart the
        computation (we perform another iteration) as the change might affect
        previous time steps as well. If no next input could be found for at
        least one of the sets, our heuristic gives up.

        @param counterstrategy: The (interactive, system dependent)
               counterstrategy.
        @type counterstrategy: L{BDD}
        @return: A system independent counterstrategy or None if no system
                independent counterstrateg could be found with the heuristic.
        @rtype: L{BDD}
        """

        # The initial system independent counterstrategy (=SIC) is the
        # interactive counterstrategy:
        sic = counterstrategy.copy()

        continue_iterating = 1
        while continue_iterating:
            (sic, continue_iterating) = self._make_sic_iteration(sic)

        return sic


    def _make_sic_iteration(self, counterstrategy):
        """
        Implements one iteration to make a counterstrategy system independent.

        It works in the following way:
        For every time step, we compute a set of states which might be
        visited in exactly this time step:
         - set0 = all states which might be visited in step 0 (initial states)
         - set1 = all states which might be visited in step 1, so
           all possible successors of set0
         - and so on
        For every set we now try to find one next input which is winning for
        the environment from all states of the set (which is conforming to
        the counterstrategy from all states of the set). If such an input is
        found, the counterstrategy must take this next input from all states
        of the set. In the counterstrategy we disallow all other inputs from
        these states. When the counterstrategy changes, we abort the iteration
        and request another one (with continue_iterating=0).

        @param counterstrategy: A counterstrategy which is not yet fully
               system independent.
        @type counterstrategy: L {BDD}
        @return: A tuple (sic, continue_iterating) where:
                 - sic is the counterstrategy which is a bit more system
                   independent than the passed one.
                 - continue_iterating is True, if another iteration has to be
                   performed to make the sic fully system independent.
        @rtype: (L{BDD}, bool)
        """
        sic = counterstrategy.copy()

        itcount = 0
        list_of_sets = []
        list_of_chosen_next_inputs = []
        current_states = self.__utils.all_present_vars_cube

        # we start in the initial state:
        current_set_of_states = self.__utils.init_ix_jx

        # while we did not already examine the current set of states:
        while list_of_sets.count(current_set_of_states) == 0:
            list_of_sets.append(current_set_of_states)
            print "------------   iteration %d  ------------------" % itcount
            itcount += 1

            # computing all next inputs conforming to the counterstrategy:
            state_plus_input_ix_jx = current_set_of_states * counterstrategy
            state_plus_input = \
                self.__utils.remove_next_ix_jx_outputs(state_plus_input_ix_jx)

            # now we compute all next inputs, which are OK (winning for the
            # environment) for all states of current_set_of_states:
            state_occurs = self.__utils.keep_only_present(state_plus_input)
            system_indep_next_inputs = \
                   ((~state_occurs) + state_plus_input).forall(current_states)

            if system_indep_next_inputs.isZero():
                # if we could not find one, we give up
                # TODO: maybe try something else in a previous step to avoid
                # this certain current_set_of_states.
                print "Failed!"
                return (None, False)


            # Whenever we are in a state of current_set_of_states, the next
            # input must be a system_indep_next_inputs:
            forbidden_transitions = current_set_of_states * \
                                    (~system_indep_next_inputs)
            new_sic = sic * (~forbidden_transitions)
            if new_sic != sic:
                # whenever the counterstrategy changed, we start again, because
                # the change might effect one of the previous sets of states as
                # well. Hence it might be the case, that not all states of
                # current_set_of_states are reachable any more.
                return (new_sic, True)


            # now we choose a concrete next input and compute all next states
            # again in current_set_of_states:
            concrete_next_input = \
                  self.__utils.choose_all_next_inputs(system_indep_next_inputs)
            list_of_chosen_next_inputs.append(concrete_next_input)
            state_plus_input_ix_jx *= concrete_next_input
            next_states = state_plus_input_ix_jx * self.__utils.sys_trans
            next_states = self.__utils.swap_present_next(next_states)
            current_set_of_states = self.__utils.keep_only_present(next_states)

        # We now know, that applying the counterstrategy in sic together
        # with the heuristic for choosing inputs as implementd in
        # choose_all_next_inputs() leads to complete system independence. Thus
        # we finally add the heuristic for choosing inputs as implementd in
        # choose_all_next_inputs() to the counterstrategy to really have a
        # system independent counterstrategy.
        for i in range(0, len(list_of_chosen_next_inputs)):
            set_of_states = list_of_sets[i]
            next_input = list_of_chosen_next_inputs[i]
            forbidden_transitions = set_of_states * (~next_input)
            sic *= ~forbidden_transitions
        return (sic, False)

    def get_index_of_superset_in_list(self, list, bdd):
        """
        Searches for a superset in a list.

        This method searches through a list of bdds to find a superset of
        a specific bdd and returns the index of the superset in the
        list or None if the list does not contain a superset of the bdd.

        @param list: A list of bdds.
        @type list: list<L{BDD}>
        @param bdd: A bdd where we want to find a superset for.
        @type bdd: L{BDD}
        @return: the index of a superset of in the list or None
        @rtype: int
        """
        for i in range(0,len(list)):
            if bdd <= list[i]:
                return i
        return None
Example #2
0
class InteractiveGame(object):
    """
    Implements an interactive debugging game.

    This class implements an interactive game between the computer in
    the role of the environment and the user in the role of the system.
    In every time step, the environment first gives next inputs to the
    system. Then the user is asked to choose the next values of the
    output variables. The play is won for the user if she manages to
    fulfill all the fairness conditions of the system infinitely often
    or if the environment does not fulfill all its fairness constraints.
    The play is won for the environment if the user looses, so if the
    environment manages to find inputs to the system, so that the user is
    not able to fulfill all fairness conditions infinitely often while
    the environment is able to do so.

    If the specification is not realizable a strategy to determine the
    next inputs to the system so that the system loses every play
    exists. This strategy is called a 'counterstrategy'. In the game
    implemented in this class, this counterstrategy is used to find the
    inputs for the system. To make it easier for the user to find outputs
    of the system which are feasible according to the transition relation of
    the system, the possible values for all output variables are calculated.
    The computer will also print the index of the fairness constraint of the
    system it tries to evade. Thus the user can concentrate on fulfilling this
    constraint only. A summary of all input variables and all output
    variables in all steps is finally written into the file
    'spec_debug_results/log.txt'.

    @author: Robert Koenighofer <*****@*****.**>
    @version: 1.0.0
    """
    def __init__(self, utils, counterstrategy, z_array, countertrace):
        """
        Constructor

        @param utils: A module containing a lot of utility-functions as
               well as data which is needed almost everywhere.
        @type utils: L{SpecDebugUtils}
        @param counterstrategy: A counterstrategy, i.e., a strategy for the
               environment to find inputs so that the system is forced to
               violate the specification.
        @type counterstrategy: L{BDD}
        @param z_array: z_array[a] contains the intermediate results of the
               fixpoint computation in the variable Z of the computation of
               the winning region for the environment. 'a' counts the
               iterations of the fixpoint computation in Z. It is used to
               figure out how often the value of jx might still change in the
               future of the play. (If the play is in z_array[a], jx might
               change at most a-1 times.)
        @type z_array: list<L{BDD}>
        @param countertrace: A sequence of inputs so that the system is forced
               to violate its specification.
        @type countertrace: L{InfiniteTraceOfBdds}
        """

        #: A module containing a lot of utility-functions.
        #: @type: L{SpecDebugUtils}
        self.__utils = utils

        #: A winning strategy for the environment.
        #: @type: L{BDD}
        self.__counterstrategy = counterstrategy

        #: Intermediate results of the fixpoint computation in the variable Z.
        #: @type: list<L{BDD}>
        self.__z_array = z_array

        #: A sequence of inputs so that the system is forced to violate its
        #: specification.
        #: @type: L{InfiniteTraceOfBdds}
        self.__countertrace = countertrace

        #: A utility class that allows us to print the summary of the play.
        #: @type: L{Writer}
        self.__writer = Writer(utils)

    def interact(self):
        """
        Implements an interactive debugging game.

        This method implements an interactive game between the computer in
        the role of the environment and the user in the role of the system.
        In every time step, the environment first gives next inputs to the
        system. Then the user is asked to choose the next values of the
        output variables. The play is won for the user if she manages to
        fulfill all the fairness conditions of the system infinitely often
        or if the environment does not fulfill all its fairness constraints.
        The play is won for the environment if the user looses, so if the
        environment manages to find inputs to the system, so that the user is
        not able to fulfill all fairness conditions infinitely often while
        the environment is able to do so. The counterstrategy is used to find
        the inputs for the system.

        To make it easier for the user to find outputs of the system which
        are feasible according to the transition relation of the system, the
        possible values for all output variables are calculated. The computer
        will also print the index of the fairness constraint of the system
        it tries to evade. Thus the user can concentrate on fulfilling this
        constraint only. A summary of all input variables and all output
        variables in all steps is finally written into the file
        'spec_debug_results/log.txt'.
        """

        # The first current state is the initial state:
        current_state = self.__utils.init_ix_jx

        step_count = 0
        while True:

            # We now print the current state:
            # (The method _print_current_state also logs the current state to
            # the file 'spec_debug_results/log.txt'.)
            self._print_current_state(current_state)
            #current_state.print_minterm()

            # a concrete next input is chosen either according to the
            # counterstrategy or according to the countertrace:
            next_input = self.__utils.get_next_inputs(current_state, \
                                             step_count, \
                                             self.__counterstrategy, \
                                             self.__countertrace)

            # print the next inputs:
            self._print_next_inputs(next_input)

            # Choose the next jx variables (rho2 may allow more than one):
            for jx_var in self.__utils.jx_variables:
                (val, next_input) = self.__utils.choose_val( \
                                        next_input, jx_var, True)

            # computing all possible next outputs:
            possible_next_outputs = next_input * self.__utils.sys_trans

            # we read the next output variables (entered by the user):
            (outvar_bdd, quit) = self._read_out_vars(possible_next_outputs)
            if quit:
                return
            next_state = possible_next_outputs * outvar_bdd

            # and assign the next state to current_state:
            next_state = self.__utils.swap_present_next(next_state)
            current_state = self.__utils.keep_only_present(next_state)
            step_count += 1

    def _print_current_state(self, current_state):
        """
        Prints the current state.

        This method prints the current state in the interactive game between
        the environment and the system to STDOUT. In addition to that, the
        state is written to the log file 'spec_debug_results/log.txt' with
        the help of the L{Writer}.

        @param current_state: The state to print.
        @type current_state: L{BDD}
        """

        print "current state:"

        # print the input variables:
        for in_var in self.__utils.input_vars:
            symb = self.__utils.get_val_as_string(current_state, in_var, False)
            print "current " + in_var.name + " is: " + symb
            self.__writer.set_chosen_input(in_var.name, symb)

        # print the output variables:
        for out_var in self.__utils.relevant_out_vars:
            symb = self.__utils.get_val_as_string(current_state, out_var, False)
            print "current " + out_var.name + " is: " + symb
            self.__writer.set_chosen_output(out_var.name, symb);

        # print the ix-variables:
        ix_value = self.__utils.get_decimal_ix_val(current_state, False)
        if ix_value != None:
            print "The environment tries to fulfill fairness condition nr",
            print str(ix_value) + " next";
            self.__writer.set_chosen_aux("ix", str(ix_value))
        else:
            print "The environment has not decided yet which fairness",
            print "condition it will try to reach next"
            self.__writer.set_chosen_aux("ix","?")

        # print the jx-variables:
        nr_changes = self.__utils.how_often_may_jx_change(current_state, \
                                                          self.__z_array)
        self.__writer.set_chosen_aux("jx changes", str(nr_changes))
        jx_value = self.__utils.get_decimal_jx_val(current_state, False);
        if jx_value != None:
            print "I try to keep the system from fulfilling fairness",
            print "condition nr: " + str(jx_value)
            print "I reserve the right to change my opinion on that at most",
            print str(nr_changes) + " times from now"
            self.__writer.set_chosen_aux("jx", str(jx_value))
        else:
            print "I have not decided yet which fairness condition of the",
            print "system I will try to evade";
            self.__writer.set_chosen_aux("jx","?")

        self.__writer.start_next_time_step()


    def _print_next_inputs(self, next_inputs):
        """
        Prints all next inputs in a bdd.

        @param next_inputs: A bdd containing the next inputs.
        @type next_inputs: L{BDD}
        """

        for in_var in self.__utils.input_vars:
            symb = self.__utils.get_val_as_string(next_inputs, in_var, True)
            print "next " + in_var.name + " is: " + symb

    def _read_out_vars(self, possible_outputs):
        """
        Reads all next output values from STDIN.

        This method asks the user to enter the next values of the output
        variables of the system. It also resolves all restrictions on the
        variables (due to the transition relation of the system and previously
        entered variables) and displays possible values for the variable
        in brackets:
         - enter next hgrant0 (1): means only 1 is allowed for the next hgrant0
         - enter next hgrant0 (0): means only 0 is allowed for the next hgrant0
         - enter next hgrant0 (0,1): means that you can pick whatever you want

        The user is only allowed to enter '0', '1' or 'Q' if she wants to
        quit the game.

        @param possible_outputs: A bdd with all possible next outputs.
        @type possible_outputs: L{BDD}
        @return: A tuple (outvar_bdd, quit) where:
                  - outvar_bdd is a bdd with all next output variables set to
                    the values entered by the user
                  - quit is True if the user wants to quit and False otherwise.
        @rtype: (L{BDD}, bool)
        """

        # While the user enters variable values that are not allowed by
        # the transition relation of the system (if valid values are entered,
        # we jump out of the loop with a return):
        while True:
            all_outvars_bdd = BDD.ONE(self.__utils.dd_mgr)
            for out_var in self.__utils.relevant_out_vars:
                (out_bdd, quit) = self._read_single_out_var(out_var, \
                                           all_outvars_bdd * possible_outputs)
                if quit:
                    return (None, True)
                all_outvars_bdd *= out_bdd

            # check if the entered values are possible according to the
            # transition relation of the system (which is already part of
            # $possible_outputs)

            if (possible_outputs * all_outvars_bdd).isNotZero():
                return (all_outvars_bdd, False)
            print "this is not possible according to the transition relation"
            print "try again"
   

    def _read_single_out_var(self, out_var, possible_next_outputs):
        """
        Reads one single next output value from STDIN.

        This method asks the user to enter the next value of one single output
        variables of the system. It also resolves all restrictions on the
        variable (due to the transition relation of the system and previously
        entered variables) and displays possible values for the variable
        in brackets:
         - enter next hgrant0 (1): means only 1 is allowed for the next hgrant0
         - enter next hgrant0 (0): means only 0 is allowed for the next hgrant0
         - enter next hgrant0 (0,1): means that you can pick whatever you want

        The user is only allowed to enter '0', '1' or 'Q' if she wants to
        quit the game.

        @param out_var: The output variable to choose.
        @type out_var: L{Variable}
        @param possible_next_outputs: A bdd with all possible next outputs.
        @type possible_next_outputs: L{BDD}
        @return: A tuple (outvar_bdd, quit) where:
                  - outvar_bdd is a bdd with all next output variables set to
                    the values entered by the user
                  - quit is True if the user wants to quit and False otherwise.
        @rtype: (L{BDD}, int)
        """

        # while the user enteres invalid values (otherwise we jump out of
        # the loop with the return):
        while True:
            print "enter next " + out_var.name,
            self._print_possible_values_for(out_var, possible_next_outputs)
            input_line = sys.stdin.readline()

            if input_line == "Q\n" or input_line == "q\n":
                print "quit by user";
                self.__writer.write_to_file("./spec_debug_results/log.txt")
                self.__writer.clear()
                return (None, True)
            if input_line == "1\n":
                return (out_var.ns, False)
            elif input_line == "0\n":
                return (~out_var.ns, False)
            print "enter '1' or '0' or 'Q' to quit"

    def _print_possible_values_for(self, out_var, restrictions):
        """
        Prints all values which are possible for a certain output.

        This method prints all possible values for a certain output variable
        to STDOUT and also writes the values to a file
        'spec_debug_results/log.txt'.
        Writing to the file is done with the L{Writer} which formats
        the output in a nice way.

        @param out_var: The variable to print the possible values for.
        @type out_var: L{Variable}
        @param restrictions: A bdd with all restrictions on the next output
               variables.
        @type restrictions: L{BDD}
        """

        (can_be_1, can_be_0) = self.__utils.get_val(restrictions, out_var, True)

        if can_be_1 and can_be_0:
            sys.stdout.write(" (0,1): ")
            self.__writer.set_possibilities(out_var.name, "(0,1)")
        elif can_be_1:
            sys.stdout.write(" (1): ")
            self.__writer.set_possibilities(out_var.name, "( 1 )")
        elif can_be_0:
            sys.stdout.write(" (0): ")
            self.__writer.set_possibilities(out_var.name, "( 0 )")
        else:
            sys.stdout.write(" (): ")
            self.__writer.set_possibilities(out_var.name, "(   )")