Java中的图灵机构造(Transducers Turing Machine)
先决条件——图灵机
图灵机可以大致分为两种类型,接受器和转换器。 Acceptor Turing Machine 是用于定义图灵可接受语言的自动机。这样的机器可以用来检查给定的字符串是否属于一种语言。它被定义为一个 7 元组机器。
来到换能器:通常,换能器是将一种形式的信号转换为另一种形式的设备。图灵机传感器也是如此。
转换器是一种图灵机,用于在机器执行各种读写操作后将给定的输入转换为输出。它不接受或拒绝输入,而是执行一系列操作以在同一磁带中获得正确的输出,并在完成时停止。
图灵机传感器的几个例子是:
- 加法图灵机
- 减法图灵机
- 用于乘法的图灵机
- 用于 1 和 2 补码的图灵机
执行:
现在我们将提出一个Java程序,该程序是为模拟图灵机传感器执行的构造和执行而编写的。执行时必须给出两个输入:一个定义自动机的 .txt 文件(在代码之后给出一元乘法机的示例),以及一个要通过控制台窗口输入的字符串,该字符串将作为输入自动机执行的磁带。
.txt 文件的路径必须作为输入给出。这样做是为了使相同的程序可以用于各种类型的机器,而不是对自动机进行硬编码。我们只需要编写一个不同的 txt 文件来生成不同的自动机。
之所以选择Java ,是因为它具有 OOP 结构,使用该结构为 State、Transition、Machine 等定义了一个类,以便能够将实体的各个方面封装在一个对象中。例如,转换被定义为一个类,其成员是三个字符——读、写和移位,它们分别存储读取符号、写入符号和移位方向,以及机器应该转换到的下一个状态的索引.这同样适用于 State 对象,它存储可能的传出转换列表。
例子
Java
// Java Program to Illustrate Construction of Turing Machine
// Importing package
package turing_machine;
// Importing required classes
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
// Class 1
// Helper class
class Transition {
char read;
char write;
char shift;
int nextState;
// Constructor
// This divides string into specific symbols
// and next state's number
Transition(String s)
{
read = s.charAt(0);
write = s.charAt(2);
shift = s.charAt(4);
int l = s.length();
String substr = s.substring(6, l);
nextState = Integer.parseInt(substr);
}
}
// Class 2
// Helper class
class State {
// List of transitions for a state by
// creating ArrayList object of Transaction type
ArrayList trs;
State(ArrayList ts) { trs = ts; }
}
// Class 3
// Helper class
class Machine {
// Scanner object to read input
Scanner fs;
// Number of states to be read
int stateCount;
// Initialized to start state, and then to keep track
// of current state in automaton
int currState;
// To halt the machine when reached, must not contain
// any transitions
int finalState;
// Blank symbol defined for the machine in the input
// file
char blankSym;
// TAPE is a member of machine
StringBuffer Tape = new StringBuffer();
// List of states
ArrayList states = new ArrayList<>();
// Method 1
void buildMachine(Scanner f)
{
this.fs = f;
// Printing the title in the first line of input
// file
System.out.println("\n\t" + readString());
// Reading the string of input symbols (space
// separated)
String s = readString();
System.out.println("Input symbols: " + s);
// Reading string of other tape symbols defined in
// transitions
s += " " + readString();
// Reading the blank symbol from the file
blankSym = readChar();
System.out.println("Blank symbol: " + blankSym);
s += " " + blankSym;
System.out.println("Tape symbols: " + s);
// Number of states to be defined, say N
stateCount = readInt();
System.out.println("\nNumber of States: "
+ stateCount);
// Current state variable (currState) is initialized
// to start-state
currState = readInt();
System.out.println("Start State: " + currState);
// addState() method is called N number of times
for (int i = 0; i < stateCount; i++)
addState(i);
}
// Method 2
void addState(int ind)
{
// number of transitions is read for a state and
// stored in trCount
int trCount = readInt();
// state with 0 transitions is assigned to be final
// state for the machine to halt
if (trCount == 0)
finalState = ind;
ArrayList trs = new ArrayList<>();
for (int i = 0; i < trCount; i++) {
// Each transition object is created and
// appended to list
// of transitions
String s = readString();
Transition tr = new Transition(s);
trs.add(tr);
}
// new state object is created by passing list of
// transitions with the constructor
State st = new State(trs);
states.add(st);
}
// Method 3
// To read input from file object "fs" and return it
String readString()
{
String s = fs.next();
// To ignore lines starting from '//'
while (s.startsWith("//") || s.isEmpty())
s = fs.next();
return s;
}
// Method 4
// To read input from file object as string and
// return the first character
char readChar()
{
String s = fs.next();
while (s.startsWith("//") || s.isEmpty())
s = fs.next();
return s.charAt(0);
}
// Method 5
// To read input from file object and
// return it's integer form
int readInt()
{
String s = fs.next();
while (s.startsWith("//") || s.isEmpty())
s = fs.next();
return Integer.parseInt(s);
}
// Method 6
// To perform transitions on the tape starting from
// currState
void runTuring(int index) throws InterruptedException
{
while (currState != finalState) {
// Calling makeTrans() to perform transition and
// returning the index pointed by the R/W head
index = makeTrans(index);
if (index == -1)
throw new InterruptedException(
"ERROR: Transition Not Found! Machine HALTED.");
// Tape instance printed after each transition
printTape(index);
}
}
int makeTrans(int index) throws InterruptedException
{
if (Tape.charAt(index) == '$')
throw new InterruptedException(
"ERROR: Head left the Tape boundary! Machine HALTED.");
State st = states.get(currState);
// to traverse across the list of transitions to
// match tape symbol with read symbol
for (Transition tr : st.trs) {
if (tr.read == Tape.charAt(index)) {
// to write the write-symbol onto the tape
Tape.replace(index, index + 1,
String.valueOf(tr.write));
currState = tr.nextState;
switch (tr.shift) {
case 'R':
return index + 1; // shift right on tape
case 'L':
return index - 1; // shift left on tape
default:
return -1; // unknown shift symbol
}
}
}
return -1; // transition not found
}
void printTape(int index)
{
int interval = 500; // in milliseconds
System.out.println("Tape: " + Tape);
for (int i = 0; i < index; i++)
System.out.print(" "); // to align
// to print the R/W head of machine pointing to
// particular tape index along with current state
// index
System.out.println(" ^q" + currState + "\n");
try {
// to print new instance of tape with a
// particular interval
Thread.sleep(interval);
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
// Class 4
// Helper class
class FileScanner {
Scanner scan = new Scanner(System.in);
Scanner fileScan;
String inputstr;
FileScanner() throws FileNotFoundException
{
// to read the input from .txt file
System.out.print("Enter file path: ");
String path = scan.nextLine();
fileScan = new Scanner(new File(path));
fileScan.useDelimiter("\n");
}
String buildTape(String str, char blank)
{
// str is the input string to be added to the tape
// tape defined to begin and end with '$' symbol to
// avoid indefinite transitions
String s = "$"; // begin
for (int i = 0; i < 5; i++)
s += blank; // adding few blank symbols
s = s.concat(str); // adding the input string
for (int i = 0; i < 30; i++)
s += blank; // adding few more blanks
s += '$'; // end
// this concatenated string forms a Tape and is
// returned
return s;
}
void setTape(Machine m)
{
// read input string from console
System.out.print("\nEnter input string: ");
inputstr = scan.nextLine();
// pass string as parameter to buildTape() method
m.Tape = new StringBuffer(
buildTape(inputstr, m.blankSym));
// 6 == initial index of tape that is pointed by R/W
// head
m.printTape(6);
}
}
// Class 5
// Main class
public class TuringMain {
// Main driver method
public static void main(String[] args)
{
// Display message for better readability
System.out.println(
"\n\tTRANSDUCER TURING MACHINE BUILDER\n");
// Creating new object of Machine class
Machine m = new Machine();
// Try block to check for exceptions
try {
FileScanner fileScanner = new FileScanner();
// constructing the machine using details from
// Scanner object that reads the file
m.buildMachine(fileScanner.fileScan);
fileScanner.setTape(
m); // setting tape for the machine
m.runTuring(
6); // to start execution of Turing Machine
}
catch (FileNotFoundException
| InterruptedException e) {
System.out.println(e);
System.exit(0);
}
}
}
为一元乘法自动机定义符号、状态和转换的输入文件:
//lines starting with ‘//’ are ignored by the program while reading so that the input text can be commented
//title, will be printed on console
MACHINE FOR UNARY MULTIPLICATION
//input symbols – 1’s for defining unary-number, 0 as delimiter
0 1
//tape symbols – other than inputs
Y
//blank symbol
B
//number of states
8
//start state
0
//transitions
//format – read,write,shift,next state
//for state q0, 2 transitions to be read for this state
2
1 B R 1
0 B R 6
//state q1
2
0 0 R 2
1 1 R 1
//state q2
2
0 0 L 5
1 Y R 3
//state q3
3
0 0 R 3
1 1 R 3
B 1 L 4
//state q4
3
0 0 L 4
1 1 L 4
Y Y R 2
//state q5
4
0 0 L 5
1 1 L 5
Y 1 L 5
B B R 0
//state q6
2
1 B R 6
0 B R 7
//state q7 – machine halts when it reaches this state as 0 transitions are defined
0
图灵机复制数据的文本输入在链接中给出。
注意:程序必须在本地机器或接受 I/O 文件路径的 IDE 上执行。
以下是一元乘法自动机的输出,以“1101110”作为输入(一元 2 * 一元 3):
(经过多次迭代)
稍加努力,同样的程序可以扩展为也适用于接受器类型的图灵机。鼓励任何有兴趣的人改进文章。