图灵机,Random Access Machine,和算法的几个基本要素
图灵机
学过计算机课程的人,大概第一节课老师就会讲图灵,图灵也被成为计算机之父。他是英国计算机科学家、数学家、逻辑学家、密码分析学家和理论生物学家。他还提出了一种数学模型,图灵机模型;图灵机(Turing Machine,TM)又称确定型图灵机,它是一种抽象的计算模型。其更抽象的意义为一种数学逻辑机,可以看作等价于任何有限逻辑数学过程的终极强大逻辑机器。1
他的基本思想就是来,模拟人们用纸和笔进行数学计算的过程,我们可以把这样的过程定义为以下的两个步骤:
- 在纸上写上或者擦出一个记号,
- 把标志从一个记号移动到另一个记号中。
… | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | … |
---|
现在来给图灵机模型增加一些定义:
- Tape:在一个无限长的纸带中,均匀地分为单元格,各又某一字符
- Alphabet:字符的种类有限:这里我们就把种类归为0,1,#默认的为#
- Head,总是对准某一单元格,并可读取和改写其中的字符,没经过一个字符,它也可以左转或者右转
- State:TM总是处于有限状态中的一种,每经过一个单元格,可以(按照规则)转向另一种状态
- Transition Function:(q,c; d; L/R/N; p); 这个表达式的意思就是:如果当前状态为q字符为c,则将当前字符改为d,转向左侧/右侧/停止;转入p状态,一旦转入特定的状态‘h’,则停机
上述的这些定义就构成可图灵机模型的所有场景了;图灵机是强大的。Church–Turing thesis认为:“ 任何在算法上可计算的问题同样可以由图灵机计算“
图灵机的一个简单例子
上面简单介绍了以下图灵机的基本概念,我们也使用了Church–Turing thesis来说明图灵机的强大,既然他这么强大,说骡子是马拉出来遛遛,所以这里我们就把图灵机应用到一个例子中。
Example 1: 把纸带上存储的值加1(使用二进制来表示的无符号整数):
… | # | 1 | 1 | 1 | 1 | 1 | # | … |
---|
现在我们来定义我们的算法:
- 初始状态:head指向纸带上的数值的最左边那为紧挨着的那个“#”;
- 向左移动head,如果该位为1 则把这位变为0,head再向左移动,如果为0的话把这位变成1,head再向右移动,如果该位为#则把这位变成1 head向右移动
- 当head向右移动的时候不改变单元格上的数值。
- 最终状态:head向右移动,知道head指向 # 的单元格结束
接下来我们就用一个表格来表示这样的一个移动状态(表达式的状态放到第三列和第四列了):
步数 | 转换函数表达式 | 纸带(执行前 ) | 纸带(执行后) |
---|---|---|---|
1 | (#,#,L) | #11111# | #11111# |
2 | (1, 0, L) | #11111# | #11110# |
3 | (1, 0, L) | #11110# | #11100# |
4 | (1, 0, L) | #11100# | #11000# |
5 | (1, 0, L) | #11000# | #10000# |
6 | (1, 0, L) | #10000# | #00000# |
7 | (#,1,R) | #00000# | 100000# |
9 | (0,0,R) | 100000# | 100000# |
10 | (0,0,R) | 100000# | 100000# |
11 | (0,0,R) | 100000# | 100000# |
12 | (0,0,R) | 100000# | 100000# |
13 | (0,0,R) | 100000# | 100000# |
14 | (#,#,N | 100000# | 100000# |
在这里我们可能会有这样的疑问,当我们在第七步的时候我们已经完成了数值加一的操作为什么还要去进行后面的步骤呢,这个就涉及到算法的初态和终态的概念,当我们下次再去这样运行加一操作的时候,就可以在上一次的终态的基础上进行操作了。这样就方便了算法的复用性
Random Access Machine
在计算复杂性理论内,随机存取图灵机(random-access Turing machines)是一种变版的图灵机,用来处理大小较小的复杂度类,特别是使用对数时间的复杂度类.在随机存取图灵机上,多了一个特殊的指针磁带,大小是对数空间,字母是二进位单字(0和1)。图灵机有一个特殊的状态(state),当指到这个状态而指针磁带的数字(二进位)是’p’时,图灵机会将工作磁带上面的指针移动到输入的第p个符号。
这特性让图灵机可以直接读取输入的特定字母,而不需要花时间去处理整条输入。这对使用少于线性时间的复杂度类来说,是必要的(因为处理整个输入的时间是线性时间)2
RAM模型的定义:
R[i] <- c | R[i] <-R[R[j]] | R[i]<-R[j] + R[k] |
---|---|---|
R[i] <- R[j] | R[R[i]] <- R[j] | R[i] <- R[j] - R[k] |
IF R[i] = 0 GOTO 1 | IF R[i] >0 GOTO 1 | GOTO 1 |
算法的几个基本要素
所谓的算法,即特定计算模型下,旨在解决特定问题的指令序列:
- 输入 待处理的信息(问题)
- 输出 经处理的信息 (答案)
算法的特性:
- 正确性, 的确可以解决指定的问题
- 确定性,任意算法可以描述为一个由基本操作的序列(TM,RAM中的基本操作)
- 可行性,每一个基本操作都可以实现,且在常数时间内完成
- 有穷行,对于任何输入,经过有穷次的基本操作,都可以得到输出
上面的这些特性都是一个算法该有的特性。下面的这个特性是一个好算法一个具有的特点:
- 健壮性,能辨别不合法的输入并做适当的处理,而不是非正常的退出
- 可读性, 结构化 +准确性 + 注释 +…
- 效率性,它的速度尽可能快,存储的空间尽可能小;
这三个特性的前两个特性都是主观意向的,不适合有客观的标尺来衡量。但是第三个就可以用数学公式来把它大体上衡量出来。
在计算机行业中有这样的 一个公式:
Algorithm + Data Structures = Program; //N. Wirth ,1976
其中的算法就可以表示为效率的代表。 那么我们怎么样来用客观的标尺来表示主观上的快慢呢? 在这里就要使用到我们这篇文章开始提到的TM ,Church–Turing thesis可以知道我们能解决的问题都可以替代到图灵机的模型中,我们就可以用它在图灵机模型上运动的步数来表示它的快慢,但是我们上面的7-14步计算机是在一步的时间内做完的,所以这里就用RAM模型来衡量(它从根本上模拟来计算机的操作), 我们知道它是变版本的图灵机模型所以图灵机上能解决的,它都可以解决。所以这样的话我们就把这个算法的时间效率等价为在RAM上的执行步数。
在计算机的时间中一般用大O时间来表示一个算法的上界,它可以表示一个算法的效率。分别有:
常数时间 | 对数时间 | 多项式时间 | 指数时间 |
---|---|---|---|
O(1) | O(logn) | O(n^c) | O(c^n) |
把指数时间的算法变成多项式时间复杂度就是NP hard问题来。