如何在Prolog中处理这个“多循环”?

时间:2014-06-01 15:19:38

标签: prolog

所以基本上我正在尝试编写一个Prolog代码,模拟这个多循环:

int foo()
{
   int i, j, m;
   m = 1;
   i = 0;
   for (; i < 5; i++)
   {
      j = 0;
      for (; j < 5; j++)
         m = i + j + m;
   }

   return m;
}

我的Prolog代码是这样的:

foo(M02) :-
   M01 is 1,
   I01 is 0,
   loop_entry_1(M01, J01, I01, M02, J02, I02).

loop_entry_1(M01, J01, I01, FinalM, FinalJ, FinalI) :-
   I01 < 5, !,
   J01 is 0,                    %%  I failed here!!
   loop_entry_0(M01, J01, I01, M02, J02, I01),
   I02 is I01 + 1,
   loop_entry_1( M02, J02, I02 , FinalM, FinalJ, FinalI).
loop_entry_1( M01, J01, I01,  M01, J01, I01).

loop_entry_0(M01, J01, I01, FinalM, FinalJ, FinalI) :-
   J01 < 5, !,
   M02 is (I01 + J01) + M01,
   J02 is J01 + 1,
   loop_entry_0(M02, J02, I01 , FinalM, FinalJ, FinalI).
loop_entry_0(M01, J01, I01,  M01, J01, I01). 

所以问题在于,每次执行退出loop_entry_0J01都已分配给5时,它将在J01 is 0失败。

但我无法找到解决这个问题的方法......

有人能给我一些帮助吗?

1 个答案:

答案 0 :(得分:3)

您正在尝试模拟Prolog中的状态。而且你已经弄清楚如何做到这一点:基本上,通过一系列逻辑变量,你可以模拟一个(非逻辑)变量。这种模拟通常被称为差异&#34;。常见的惯例是将这样的变量命名为:S0, S1, S2, ... S。所以&#34; final&#34;州没有任何号码。通过这种方式,您可以在不知道需要多少中间状态的情况下启动规则,例如:

p(S0, S) :-
   ...

因此,每次为变量赋值时,都需要一个新的逻辑变量。但是,你说J01 is 0!等等,我们说:新状态意味着新变量!因此,您必须在此处引入新的中间变量,或者只需在J01中替换下一个目标中的0

与差异相关的另一个常见惯例是将相关的参数紧跟在彼此之后。

然后,虽然这种做法并不常见,但你可能会省略这些论点之间的空间,这样就可以更清楚地看到它们彼此属于。

哦,我忘记了:在循环中碰巧保持不变的变量不需要复制。

因此,在所有这些约定中,foo/1将被写入(注意不同的参数顺序!):

foo(M) :-
   loop_entry_1(1,M, 0,_).

loop_entry_1(M0,M, I0,I) :-
   I0 < 5, !,
   loop_entry_0(M0,M1, 0,_, I0),
   I1 is I0+1,
   loop_entry_1(M1,M, I1,I).
loop_entry_1(M,M, I,I).

loop_entry_0(M0,M, J0,J, I) :-
   J0 < 5, !,
   M1 is I + J0 + M0,
   J1 is J0 + 1,
   loop_entry_0(M1,M, J1,J, I).
loop_entry_0(M,M, J,J, _).

B-but:我意识到,我们可以完全删除一些状态变量。事实上:

foo(M) :-
   loop_entry_1(1,M, 0).

loop_entry_1(M0,M, I0) :-
   I0 < 5, !,
   loop_entry_0(M0,M1, 0, I0),
   I1 is I0+1,
   loop_entry_1(M1,M, I1).
loop_entry_1(M,M, _).

loop_entry_0(M0,M, J0, I) :-
   J0 < 5, !,
   M1 is I + J0 + M0,
   J1 is J0 + 1,
   loop_entry_0(M1,M, J1, I).
loop_entry_0(M,M, _, _). 

所以这是另一个技巧:如果你只需要一个简单的仅尾递归函数的状态,那么你可以忽略第二个参数!参数之间的空格并不重要,以区分复杂状态(M)和简单状态(


我真的应该补充一点:这样的一对一翻译可能很有意思,但不会对特定问题给出很多见解。