所以基本上我试图在Prolog中模拟一些C代码。
在Prolog中很容易模拟while循环以下是这种情况:
C代码:
int a = 1;
while(N)
{
N--;
a++;
}
Prolog代码:
prolog_while(0) : !
prolog_while(N, A) :
N1 is N -1,
A1 is A + 1,
prolog_while(N1, A1).
一个问题是如何在不可改变的条件下模拟Prolog中的while循环?
情况如下:
int n = 1;
int a = 1;
while(1)
{
if (N==0)
goto while_end;
else
{
N--; A++;
}
}
或
while(1)
{
if (N==0)
break;
else
{
N--; A++;
}
}
我知道它有点奇怪,但基本上这些C代码是由源代码分析工具自动生成的,所以我必须处理它......
那么基本上我怎样才能在Prolog中模拟?它可行吗?
有人能给我一些帮助吗?
===================更新============
我尝试用这种方式编写一些Prolog代码,但基本上我还不知道如何处理测试条款。
main :- loop_entry(2, 1), write(N), nl, write(A), nl.
do(A, N, A1, N1) :- A1 is (A + 1), N1 is (N - 1).
test(N) :- ... <----- # How to write this part?
loop_entry(N, A) :-
test(N),
do(A, N, A1, N1),
loop_entry(N1,A1).
答案 0 :(得分:8)
在Prolog中进行无限循环的最明显方法是使用repeat/0
,它看起来像这样:
while(1)
do_something();
变为
repeat,
do_something.
真正的问题就是在Prolog中没有明显类似于goto
或break
的模拟。所以我倾向于寻找这样的模式:
while(1) {
if (test)
break;
do_something();
}
并将其转换为Prolog,如下所示:
loop_entry :-
test,
do_something,
loop_entry.
您当然需要将本地变量作为参数添加到loop_entry/0
并实现test
,但这样当test
失败时,循环将自然结束。
按照N和A的例子导致这种事情:
loop_entry(N, A) :-
N > 0,
succ(N0, N),
succ(A, A1),
loop_entry(N0, A1).
&#34;测试&#34;在这种情况下只是N > 0
。如果它不是真的,谓词就会失败,你可以继续Prolog的生活方式。
编辑#2。如果你想要结果(N和A),那么为你想要返回的值添加额外的参数,并添加一个子句:
loop_entry(N, A, ResultN, ResultA) :-
N > 0, !,
succ(N0, N),
succ(A, A1),
loop_entry(N0, A1, ResultN, ResultA).
loop_entry(N, A, N, A).
您可以在条件之后添加剪切,也可以在此新条款中添加反向条件。
答案 1 :(得分:3)
与你的prolog_while谓词没有什么不同:
prolog_while(N, A) :-
( N==0 ->
true
;
N1 is N -1,
A1 is A + 1,
prolog_while(N1, A1)
).
但是很可能你希望A的最终值可以被这个谓词的调用者使用,所以你必须通过一个额外的参数返回它:
prolog_while(N, A, AFinal) :-
( N==0 ->
AFinal = A
;
N1 is N -1,
A1 is A + 1,
prolog_while(N1, A1, AFinal)
).
答案 2 :(得分:1)
来自Logtalk标准库:
:- meta_predicate(whiledo(0, 0)).
whiledo(Condition, Action) :-
( call(Condition) ->
\+ \+ call(Action),
whiledo(Condition, Action)
; true
).
对于其他传统的循环结构,请参阅: https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/loopp.lgt https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/loop.lgt
答案 3 :(得分:1)
为了在Prolog中实现while循环,我为命令性语言编写了a small interpreter。
使用此解释器,可以这样编写while循环:
:- initialization(main).
:- set_prolog_flag('double_quotes','chars').
main :-
imperative_statements((
A=1,
N=0,
while(A<50,(
A=A+2,
N=N-1
))
D = increment_var(1)
)),
writeln(A),
writeln(N),
writeln(D).
increment_var(A,B) :-
imperative_statements((
B=A,
while(B<50,(
B=B*2
))
)).
print(A,true) :-
writeln(A).
imperative_statements(A) :-
term_variables(A,Names),
length(Names,L),
length(Input,L),
length(Output,L),
set_var(A,Names,Input,Output),
Names=Output.
set_var(A,Names,Input) :-
length(Input,L),
length(Output,L),
set_var(A,Names,Input,Output),
Names=Output.
set_var((A,B),Var_names,Input,Output) :-
set_var(A,Var_names,Input,Output1),
set_var(B,Var_names,Output1,Output).
set_var(Name=Value,Var_names,Input,Output) :-
get_var(Value,[Var_names,Input],Value1),
set_var_(Name=Value1,Var_names,Input,Output).
set_var_(_,[],[],[]).
set_var_(Name=Value1,[Name1|Name2],[Var1|Var2],[Output1|Output2]) :-
(Name==Name1,Output1=Value1;
Name \== Name1,Output1=Var1),
set_var_(Name=Value1,Name2,Var2,Output2).
set_var(while(A,B),Names,Vars,Result) :-
get_var(A,[Names,Vars],A1),
(((A1==true)->(set_var(B,Names,Vars,Result1),set_var(while(A,B),Names,Result1,Result)));
A1==false,Vars=Result).
get_var(Name,[[Name1],[Var1]],Output) :-
var(Name),Name==Name1,
Output=Var1.
get_var(Name,[[Name1|Name2],[Var1|Var2]],Output) :-
var(Name),(Name==Name1,get_var(Name,[[Name1],[Var1]],Output);
Name \== Name1,get_var(Name,[Name2,Var2],Output)).
get_var([],_,[]).
get_var([Name1|Name2],Vars,[Name3|Name4]) :-
get_var(Name1,Vars,Name3),
get_var(Name2,Vars,Name4).
get_var(Name,_,Name) :-
number(Name);atom(Name).
get_var(A+B,Vars,Output) :-
get_var(A,Vars,A1),
get_var(B,Vars,B1),
Output is A1+B1.
get_var(A-B,Vars,Output) :-
get_var(A,Vars,A1),
get_var(B,Vars,B1),
Output is A1-B1.
get_var(A*B,Vars,Output) :-
get_var(A,Vars,A1),
get_var(B,Vars,B1),
Output is A1*B1.
get_var(A/B,Vars,Output) :-
get_var(A,Vars,A1),
get_var(B,Vars,B1),
Output is A1/B1.
get_var(A**B,Vars,Output) :-
get_var(A,Vars,A1),
get_var(B,Vars,B1),
Output is A1**B1.
get_var((A,B),Vars,Result) :-
get_var([A,B],Vars,[A1,B1]),
(A1,B1,Result=true;([A1,B1]=[true,false];[A1,B1]=[false,true]),Result=false).
get_var((A;B),Vars,Result) :-
(get_var(A,Vars,A1),call(A1);
get_var(B,Vars,B1),call(B1)) -> (Result = true);
(get_var(A,Vars,A1),A1=false,Result=false).
get_var(A<B,Vars,Result) :-
get_var(B>A,Vars,Result).
get_var(A>B,Vars,Result) :-
%comparison of variables
get_var([A,B],Vars,[A1,B1]),
(A1>B1,Result=true;A1<B1,Result=false).
get_var(A==B,Vars,Result) :-
%comparison of variables
get_var([A,B],Vars,[A1,B1]),
(A1==B1,Result=true;A1\=B1,Result=false).
get_var(Input,Vars,Output1) :-
(\+number(Input)),
Input =.. [Name|Params],
\+member(Name,['=',==,'->',not,'[|]',',',';',+,-,*,/,**,^,writeln]),
length(Params,Params_length),
Params_length > 0,
get_var(Params,Vars,Params1),
append([Name|Params1],[Output1],Input0),
Input1 =.. Input0,
call(Input1).