Esempio n. 1
0
    def applyTransition(self, t):
        """Apply the given transition to the current configuration.

        This implements one computational step of the Turing machine,
        following the given transition to its destination state,
        writing a symbol onto the tape if necessary, and moving the
        head if necessary.

        Args:

            t (Transition): the Transition to be followed. If t is
                None and implicit rejection is permitted, the machine
                will transition into the project state.

        """
        if TuringMachine.verbose: print('Applying transition', t)
        self.steps = self.steps + 1
        if not t:
            if self.allowImplicitReject:
                self.state = TuringMachine.rejectState
            else:
                message = '***Error***: No valid transition was found, and implicit rejects are disabled.\n' + \
                              'Current configuration:\n' + str(self)
                raise utils.WcbcException(message)
        else:
            self.state = t.destState
        if self.isAHaltingState(self.state):
            self.halted = True
        if t:
            if t.writeSymbol:
                self.writeSymbol(t.writeSymbol)
            if t.direction == TuringMachine.leftDir:
                if self.headPos > 0:
                    self.headPos = self.headPos - 1
                elif self.allowLeftFromCell0:
                    pass # we remain in cell 0
                else:
                    message = '***Error***: Tried to move left ' + \
                              'from cell 0, which is disallowed by ' + \
                              'this Turing machine.\n' + \
                              'Current configuration:\n' + str(self)
                    raise utils.WcbcException(message)
            elif t.direction == TuringMachine.rightDir:
                self.headPos = self.headPos + 1
                if self.headPos == len(self.tape):
                    self.tape.append(TuringMachine.blank)
        if self.keepHistory:
            self.history.append(str(self))
    def __init__(self, description = None, tapeStr = '', name = None, \
                 keepHistory = False):
        """Initialize NDTuringMachine object.

        Args:

            description (str): A string describing the states and
                transitions of the nondeterministic Turing machine,
                according to the specification described in the
                textbook. For examples, see the files containsGAGA.tm
                and binaryIncrementer.tm.

            tapeStr (str): The initial content of the Turing machine's
                tape.

            name (str): A string that gives a meaningful name to the
                machine, e.g. 'binary incrementer'. This can be used
                for debugging and meaningful output.

            keepHistory (bool): If True, keep a complete record of the
                history of this machine's computation. This is useful
                for certain experiments, but costly in terms of
                storage.

        """

        self.rootClone = self.createRootClone(description, tapeStr, 'root', \
                                              keepHistory)
        """TuringMachine object: The root clone of this nondeterministic
        Turing machine, which is itself a (deterministic) Turing
        machine.

        """

        if len(self.rootClone.blocks) > 0:
            msg = "Sorry, blocks aren't supported for nondeterministic machines"
            raise utils.WcbcException(msg)

        self.clones = set([self.rootClone])
        """set of TuringMachine objects: the set of clones that comprise this
        nondeterministic Turing machine.

        """

        self.steps = 0
        """int: The number of computational steps taken so far in the computation."""

        self.nextCloneID = 1
        """int: Each clone is assigned an ID number sequentially, beginning
        with zero for the root clone. This stores the ID that will be
        assigned to the next clone created.

        """

        self.name = name
        self.keepHistory = keepHistory

        self.acceptingClone = None
        """TuringMachine object: mostly for debugging, remember which clone
Esempio n. 3
0
 def step(self):
     """Perform one computational step for this Turing machine."""
     ts = self.getValidTransitions()
     if len(ts) > 1:
         message = '***Error***: multiple valid transitions in deterministic Turing machine.\n' + \
                   'Current state:' + self.state + '\n' + \
                   'Valid transitions:' + str(ts)
         raise utils.WcbcException(message)
     if len(ts) == 0:
         t = None
     else:
         t = ts[0]
     self.applyTransition(t)
     if self.state in self.blocks:
         self.runBlock()
Esempio n. 4
0
    def checkSymbolIsValid(self, t, c):
        """Check if a given symbol is permitted in Turing machines.

        Nothing is returned, but a WcbcException is raised if the
        symbol is invalid.

        Args:

            t (Transition): the Transition in which c is used.

            c (str): a single character which is the symbol to be
                checked

        """
        if c not in TuringMachine.validSymbols:
            message = '''***Error***: The symbol {0} (ASCII value {1}) is not permitted in Turing machine alphabets. The full transition containing this error is:\n{2}'''.format(c, ord(c), t)
            raise utils.WcbcException(message)
def revertSolution(cliqueSoln):
    if cliqueSoln == 'no':
        return 'no'
    nodes = cliqueSoln.split(',') if cliqueSoln != '' else []
    # Remove everything after the 'C' in each node name
    nodes = [n[:n.index('C')] for n in nodes]
    # build truth assignment
    truthAssignment = dict()
    for node in nodes:
        variableName = node[:-1]
        posNeg = node[-1:]
        if posNeg == 'p':
            truthAssignment[variableName] = True
        elif posNeg == 'n':
            truthAssignment[variableName] = False
        else:
            raise utils.WcbcException('Unexpected node name' + node)

    return truthAssignment
Esempio n. 6
0
    def write(self):
        """Convert the current Turing machine into description format.

        Returns:

            str: description format of the current machine, suitable
                for storing in a .tm file.

        """

        if len(self.blocks)>0:
            raise utils.WcbcException("Error: writing Turing machines is not implemented for blocks.")
        if self.transitions == None: 
            return '[No transitions]'
        lines = []
        for tList in self.transitions.values():
            for t in tList:
                line = self.writeTransition(t)
                lines.append(line)
        lines.sort()
        return '\n'.join(lines)
    def run(self):
        """Run the nondeterministic Turing machine until it halts.

        For practical reasons, the machine will also stop once it
        exceeds its maximum number of steps.

        """
        while True:
            if NDTuringMachine.verbose:
                print(self)
                print()
            self.step()
            allReject = True
            retVal = None
            for tm in self.clones:
                if tm.state != TuringMachine.rejectState:
                    allReject = False
                if tm.state == TuringMachine.acceptState:
                    retVal = 'yes'
                elif tm.state == TuringMachine.haltState:
                    retVal = ''.join(tm.tape)
                # Mostly for debugging, remember which clone accepted
                # (if any). Also, we break so that the first clone to
                # accept is the one whose return value is used.
                if tm.state == TuringMachine.acceptState or \
                   tm.state == TuringMachine.haltState:
                    self.acceptingClone = tm
                    break
            if allReject:
                retVal = 'no'
            if retVal != None:
                return retVal
            if self.steps >= NDTuringMachine.maxSteps:
                self.rootClone.raiseExceededMaxSteps()
                # return NDTuringMachine.exceededMaxStepsMsg
            if len(self.clones) > self.maxClones:
                raise utils.WcbcException(NDTuringMachine.exceededMaxClonesMsg)
Esempio n. 8
0
 def raiseExceededMaxSteps(self):
     """Raise an exception indicating that the maximum number of steps was exceeded.
     """
     
     raise utils.WcbcException(TuringMachine.exceededMaxStepsMsg + \
                               '.  Current output: ' + self.getOutput())