do-while循环足以满足图灵完整性吗?


22

我知道,在命令式编程语言中,while-do循环足以构成使图灵完成的语言的控制流构造(就控制流而言,当然,我们还需要无限制的内存和某些运算符...) 。我的问题的要点是:do-while循环是否具有与while-do-循环相同的计算能力?换句话说,如果不可能完全跳过指令,那么一种语言可以是图灵完备的吗?

我意识到这里的某些语义可能有点模棱两可,所以让我用一个特定的例子来表达实际问题:

Brainfuck(BF)是一个图灵tarpit,其中唯一的控制流是while-do循环,表示为[...](问题的底部有一个完整的语言规范,以防您不熟悉Brainfuck。让我们定义一种新的语言BF *,它,.+-<>的语义与BF中的语义相同,但是代替它的[]{},它具有do-while循环。也就是说,与BF的唯一区别是每个循环至少可以执行一次,然后才能跳过进一步的迭代。

BF *图灵完成了吗?如果是这样,我会对如何将BF转换为BF *感兴趣。如果不是,我该如何证明?

我自己的一些观察:

  • 并非每个BF程序都可以转换为BF *。例如,不可能用BF *编写可能会或可能不会读取或打印值的程序-如果该程序可能打印一个或多个值,它将始终打印至少一个。但是,可能存在BF的图灵完备子集,可以将其转换为BF *。
  • 我们不能简单地将[f]f仅由组成的任意Brainbrauck程序翻译成+-[]<>)(以消除第一次迭代的效果),因为a)并非每个可计算的函数都具有可计算的逆,并且b)即使有,循环次数不一定会比因此少,因此不能保证首先递归地执行此步骤。f-1{f}f-1f

这是Brainfuck语言的快速概述。Brainfuck在无限磁带上操作,其中每个单元包含一个字节值,最初为零。溢出会回绕,因此增加255可得到0,反之亦然。该语言包含8条指令:

+   Increment the current cell.
-   Decrement the current cell.
>   Move tape head to the right.
<   Move tape head to the left.
,   Input a character from STDIN into the current cell.
.   Output the current cell as a character to STDOUT.
[   If the current cell is zero, jump past the matching ].
]   If the current cell is non-zero, jump back to just behind the matching [.


有趣,但认为它没有完全精心构造。[]在BF中未完全定义“ while do”循环。如表中所示,左括号和右括号将当前单元格评估为零/非零。那么相应的{}括号评估逻辑的确切描述是什么?建议进一步的对话/讨论计算机科学聊天”中。同样,您的“观察”更像是没有证据的“假设”或“命题”。
vzn

@vzn这些都是好点。我认为明显的定义{}将是使{所有,什么也不做}一样]。接下来的几天我不会有很多时间,但是如果有时间,我会和您聊天。
马丁·恩德

a,这似乎有些微妙,这里似乎有两个完全不同的问题。(1)给定任何带有while-do循环的图灵完整语言(和“其他东西”),可以将其转换为仅带有do-while循环的Turing完整语言。但是接下来,您需要更多地了解“其他内容”才能回答。(2)给定BF和给定的定义{}并带走的新BF * [],BF *图灵完成。理解BF []是一种构造,仅类似于图灵完整语言中的while-do循环。
vzn

1
@vzn部分(1)只是我的问题的TL; DR部分。我完全意识到,对于“某种语言”,这可能是不可能的。这就是为什么我措辞的实际问题,在一个非常简单的玩具语言(BF)的条款,以真正缩小它的循环的行为(因为我想如果 BF *可以被证明是TC,将使其更简单以将其显示给只有do-while循环的其他语言)。我不确定您认为BF循环与其他语言的while-do循环有何不同。
马丁·恩德

Answers:


10

我不知道Brainfuck,所以您必须从我的伪代码中进行一些翻译。但是,假设Brainfuck表现得很明智(ha!),则以下所有内容均适用。

do-while等同于while-do。 do X while Y等同于,X; while Y do X并且假设您有条件,while Y do X等同于if Y then (do X while Y)

如果没有条件,生活会更艰难。如果您有边做边做的事,则可以if Y then X使用以下方式进行模拟:

B := true
while (Y and B) do
    X
    B := false
endwhile

但是,如果您只有一段时间,该怎么办?我声称以下模拟if Y then X,假设在X给定变量当前值的情况下终止。(这不能保证:即使对变量的任何值进行循环,该程序也会在if y=0 then loopforever终止时终止)。让,...,y != 0XV1Vn为被修改的变量,XX'对其进行X修改,以使... Vi'代替Vi变量。swap(A,B)表示交换变量A和的显而易见的代码B

V1' := V1; ...; Vn' := Vn
V1'' := V1; ...; Vn'' := Vn
C := 0
do
    X'
    swap (V1',V1''); ...; swap (Vn',Vn'')
    C := C+1
while Y and C<2
V1 := V1'; ...; Vn := Vn'

这个想法如下。首先,假设这Y是错误的。我们模拟X一次,然后将结果存储在V1''...中Vn''V1',...,Vn'保留的原始值V1,...Vn。然后,我们分配V1 := V1'; ...; Vn := Vn',它什么都不做。因此,如果Y为假,我们什么也没做。现在,假设这Y是真的。现在,我们将模拟X 两次,并将结果存储在“ primed”和“ double-primed”变量中。因此,现在,循环末尾的分配具有X只计算一次的效果。请注意,它Y仅取决于“未准备好的”变量,因此其值不受重复运行循环的影响。

好的,如果X变量的当前值不终止怎么办?(感谢Martin Ender指出了这种可能性。)在这种情况下,我们需要X使用与上述类似的思想来模拟逐条指令。每条指令肯定会终止,因此我们可以使用if上面的模拟来进行指令解码,即“如果操作码为foo,请执行此操作;如果它是bar,请执行此操作……”。因此,现在,我们使用循环来迭代,的指令X,使用指令的指针等,以便我们知道接下来要执行的指令。在循环的每次迭代结束时,检查Y并检查是否X已停止。如果Y为假,则交换技术使我们可以消除X的第一条指令。


1
这是一个好主意,但我认为这里有一个问题:考虑以下情况Y:假,但X不终止于当前变量值集。if Y then X终止,但您的翻译不会终止,因为它总是需要X'至少执行一次。
马丁·恩德

1
@MartinBüttnerUrgh。你是对的。因此,我们需要使用循环来模拟逐条X指令,并Y在每条指令之后进行检查。保证每条指令都会终止,因此一切正常。但是写下来是很痛苦的。
David Richerby

1
我不确定如果X以while循环/条件本身开始,是否可以像这样进行解构。我将不得不再考虑一下。
马丁·恩德

同样,“因此,现在,我们使用循环来迭代X的指令,使用指令指针等等,以便我们知道接下来要执行哪条指令。” 我觉得这本身可能需要某种条件。
马丁·恩德

1
我仍然不完全确定如果X'是非线性的,您如何定义“每个指令” 。您介意为一个简单但不平凡的玩具提供更多细节X吗?例如do (while A do B) while C?(外部do while来自while do我们当前正在翻译的外部)
Martin Ender
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.