Prolog - Operation inside findall

旧时模样 提交于 2019-12-23 22:11:21

问题


Using a findall in Prolog how can I perform operations inside the goal without affecting backtracking?

The following example explains what I'm trying to achieve:

value('M1', 11, 3).
value('M2', 11, 3).

connection('M1',1, 'A', 'B').
connection('M1',1, 'B', 'C').
connection('M1',2, 'C', 'D').
connection('M1',2, 'D', 'E').
connection('M2',1, 'D', 'F').

run :- bbR('C',[(0,'X',['A'])],_,_).

run2 :- bbR2('C',[(0,['A'])],_,_).

bbR(Destination,[(Cost,_,[Destination|T])|_],Result,Cost):-
   reverse([Destination|T],Result).
bbR(Destination,[(Cost,M_1,[H|T])|Rest],Result,CostSol):-
   write('----'), nl,
   findall( (C, M, [X,H|T]),
            (  Destination\==H,
               connection(M, CX, H, X),
               not(member(X,[H|T])),
               sumValue(M, M_1, F),
               C is CX+Cost+F,
               debug_t(H, X, C, F, M)
            ),
            New),
   append(New,Rest,All),
   sort(All,LS),
   bbR(Destination,LS,Result,CostSol).

sumValue(M, M_1, F):-M_1\==M,value(M, 11, F);F is 0.

debug_t(H, X, C, F, M):-
   write('<'),write(H),
   write('> to <'),write(X),
   write('> @ '), write(M),
   write('> total='),write(C),
   write(' e freq='), write(F),
   nl.

bbR2(Destino,[(Cost,[Destino|T])|_],Result,Cost):-
   reverse([Destino|T],Result).
bbR2(Destino,[(Cost,[H|T])|Rest],Result,CostSol):-
   write('----'), nl,
   findall((C,[X,H|T]),
           (  Destino\==H,
              connection(M, CX, H, X),
              \+ member(X,[H|T]),
              C is CX+Cost,
              debug_t(H, X, C, 0, M)
           ),
           New),
   append(New,Rest,All),
   sort(All,LS),
   bbR2(Destino,LS,Result,CostSol).

The problem here is, when I run "run.", it prints:

    <A> to <B> @ M1> total=4 e freq=3
    <A> to <B> @ M1> total=1 e freq=0

Whereas if I run "run2." (which is the same code without the call to sumValue and the "+ F") it only prints

    <A> to <B> @ M1> total=1 e freq=0

From my debugging it seems the problem is when findall finishes the first goal and backtracks, the sumValue affects it's behavior.

So my main question is How to sum values (from another predicate) to the variable "C" under certain conditions (in this case, when "M_1" is different to "M") without affecting the findall backtracking.

I have been trying all day to find a way around this, I already tried using "!" but to no avail.


回答1:


The reason you get different behaviours when querying run. and run2. is because the goal sumValue('M1', _, F) is being satisfied twice:

?- sumValue('M1', _, F).
F = 3 ;
F = 0.

I would also recommend you to use format/2 instead of all those write/1 predicates. It helps for code readability.

debug_t(H, X, C, F, M):-
    format("<~w> to <~w> @ ~w> total=~w e freq=~w~n", [H, X, M, C, F]).


来源:https://stackoverflow.com/questions/27848142/prolog-operation-inside-findall

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!