所以基本上我正在尝试编写一个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_0
,J01
都已分配给5
时,它将在J01 is 0
失败。
但我无法找到解决这个问题的方法......
有人能给我一些帮助吗?
答案 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)和简单状态(
)我真的应该补充一点:这样的一对一翻译可能很有意思,但不会对特定问题给出很多见解。