有限存储的计算机等价于有限自动机(DFA、NFA)

$B=\{0^n1^n|n\ge0\}$

  • Michael Sipser 的 Introduction to the Theory of Computation 的1.4提到一个非正则语言的例子,$B=\{0^n1^n|n\ge0\}$ ,并用Pumping lemma证明了其是非正则的,无法被DFA识别
  • 但是我们的计算机似乎可以识别以上语言,所以,为什么我们的计算机还是DFA呢
  • 事实上,我们的计算机只能识别n处于一定范围的B,而不能识别n为任意值的B。如果n过大,我们的计算机的存储单元无法表达,则会发生溢出,导致识别了另一个语言 $C=\{0^n1^m|n\ mod\ max=m\ mod\ max\}$ ,其中,max是我们的计算机的存储单元可以表达的最大值
  • 如果是n处于一定范围内,容易构造出一台DFA识别B:
    • 设有两个变量a、b,a、b都可以取值$[0,1000]$ ,a表示0的数量,b表示1的数量
    • 那么,a、b的所有笛卡尔积组成的集合的一个子集就是该DFA的状态集
    • 转移方程为
      • 首先: $<0,0>\rightarrow<1,0>\rightarrow<2,0>\rightarrow…\rightarrow<1000,0>$
      • 然后:从任意$<n,0>$ 都可以转移到 $<n,1>$
      • 然后:一旦转移到 $<n,1>$ ,就不能转移到 $<n+k,m>, (k>0)$ ,也就是不能增长n的值
      • 最后:一旦转移到 $<n, n>$ 就accept

为什么现实中的计算机有可能是DFA

  • 计算机只有有限存储,such as,某计算机有$2^{32}$ 个8bit的cell,每个cell有 $2^8$ 种取值,所以,所有存储的取值有 $(2^8)^{2^{32}}$ 种,也就是,这台计算机的存储只能有 $(2^8)^{2^{32}}$ 种状态,这就使得把计算机转为DFA变为可能

对任意一段代码构造等价的NFA

NFA构造方法描述
  • 假设该段代码的运行过程会改变的存储cell有c1、c2、c3、c4、c5,其中,c1到c5的取值范围都是[0,0xFF],那么就可以构造$(2^8)^5$ 个$<c1,c2,c3,c4,c5>$ ,作为该NFA的状态集合。(注意,cs:ip 寄存器的值必然是这五个cell中的一个)
  • 输入字符表是$\{0,1\}$ ,将所有计算机接受的输入全部编码成bit 串后读入该DFA,每次读一个0或者一个1。
  • 假设该代码起始时,c1到c5的取值为$0,0,0,0,0$ ,则$<0,0,0,0,0>$ 就是起始态
  • 假设该段代码处于accept状态时,c1到c5的取值分别为$1,2,3,4,5$ ,那么,$<1,2,3,4,5>$ 就是该NFA的accept state
  • 该代码可以有输入,也可以无输入,可以在多个时候输入,也可以只在一个时候输入。假设其某次输入处于$<d1,d2,d3,d4,d5>$ ,输入后处于 $<d6,d7,d8,d9,d10>$ ,则在从$<d1,d2,d3,d4,d5>$ 到 $<d6,d7,d8,d9,d10>$ 是一个转移,转移使用的字符就是读入的字符。该代码也可以在无输入情况下由cpu作用,从一个状态转移到另一个状态,则在这两个状态之间使用$\varepsilon$
为什么该NFA只接受允许的字符串,而不会接受多余的字符串
  • 首先,可以使用以上方法对于每个接受的字符串都构造NFA,则该NFA只接受允许的那个字符串
  • 设置一个新的起始态,该起始态有$\varepsilon$ 到所有为每个字符串构造的NFA
  • 则最终的NFA只接受允许的字符串
是否会出现情况:代码两次处于某状态但是行为不一样
  • 答案是肯定不会
  • 计算机的行为由当前状态决定——下一步要执行什么代码,取决于正在被执行的代码段,以及ip寄存器的值,如果text段的内容相同,cs:ip寄存器的相同,指令使用的值也相同,那么下一步的行为就是确定的

对任意一台计算机构造等价的DFA

  • 对于一台确定的计算机可以构造出确定的DFA,执行该计算机可以做的任何计算
  • 先说明一些前置情况:
    • 现实中计算机使用源码处理特定的输入
    • 把现实中计算机处理该输入的源码编码成确定长度(统一取最大长度M——M是该计算机可以存储的最长比特串长度,比如$2^{40}$比特)的字符串,每个字符表示一个指令——这个其实等价于把源码编译成机器码(每个机器指令由一样的长度的比特串表示),然后把这个比特串补全成统一长度M
  • 因为源码是M比特长,所以最多有$2^M$ 种不同的源码,根据上文,可以为每种源码构造一个DFA
  • 然后开始构造DFA
    • 该DFA分为两个部分:第一个部分解释输入的源码字符串,第二个部分实际运行输入的源码来跑输入的数据——即实际运行$2^M$ 个不同的DFA中的一个
    • DFA第一个部分,其读入长度M的字符串(也就是源码),从而把该台DFA导向某个状态,这个状态是$2^M$ 个实际运行代码的DFA中的一个的起始态
    • 第二部分就是那$2^M$ 台DFA,其接受输入,并最终停在某个状态——accept态或者是其他状态
  • 从而该DFA接受$\cup A_i$ ,其中$A_i$ 是该计算机可以运行的任意一段代码接受的字符串集合

计算机可以死循环,DFA不会死循环,为什么

  • consider that,死循环指的是无输入情况下,不停机,而不是无限输入导致的不停机。
  • 因为计算机的状态是有限的,所以,如果计算机死循环,那么其必然会重复处于某个状态,进而导致行为的重复——因为计算机的当前状态唯一确定了以后的行为。

  • 在NFA,这种情况死循环的状况也会发生——一组状态以$\varepsilon$ 连接在一起形成环,从而导致无限读入$\varepsilon$ ,无限循环

  • 截断导致NFA死循环的那个环,并不会影响接受的语言。假设该环是s1、s2、s3、s1,那么我们可以把其变成三条路:“s1、s2、s3”,“s2、s3、s1”,“s3、s1、s2” ,非形式化来说,因为这不会改变该图的连通性,所以接受的字符串集合不变

  • 而按照Introduction to the Theory of Computation 的1.2节的EQUIVALENCE OF NFAS AND DFASDFA 描述的方法,其正是去掉了这种$\varepsilon$ 环,所以不会死循环,具体去掉的方法如下(截图来自书本英文第三版P56):

    $E(R)$ 是一个集合,集合中元素不重复,而$\varepsilon$ 环所到达的状态必然是重复的,所以就把$\varepsilon$ 环断开了