How to simulate a while loop in Prolog with immutable conditions?

So basically I am trying to simulate C code in Prolog.

It's easy to simulate a while loop in Prolog like this:

C code:

int a = 1;

while(N)
{
  N--;
  a++; 
}

Prolog Code:

prolog_while(0) : !
prolog_while(N, A) :
   N1 is N -1,
   A1 is A + 1,
prolog_while(N1, A1).

One problem is how to simulate a while loop in Prolog with immutable conditions?

Like this:

int n = 1;
int a = 1;

while(1)
{
   if (N==0)
     goto while_end;
   else
    {
        N--; A++;
    }       
}

Or

while(1)
{
   if (N==0)
     break;
   else
    {
        N--; A++;
    }       
}

I know this is something strange, but basically such a C code is automatically generated by a source code analysis tool, so I have to deal with it ...

Then, basically, how can I simulate in Prolog? Is this doable?

Can anyone help me?

==================== update =============

I tried to write Prolog code this way, but basically I still don't know how to handle the test sentence.

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).
+5
4

Prolog - repeat/0, :

while(1)
    do_something();

repeat,
do_something.

: goto break Prolog. :

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).

"" N > 0. , , .

# 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).

, .

+7

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

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

+1

while , .

Using this interpreter, the while loop can be written like this:

:- 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).
+1
source

Source: https://habr.com/ru/post/1535177/


All Articles