Пролог - Операция внутри находки

Используя findall в Прологе, как я могу выполнять операции внутри цели, не влияя на возврат?

Следующий пример объясняет, чего я пытаюсь достичь:

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

Проблема здесь в том, что когда я запускаю "запустить", он печатает:

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

Принимая во внимание, что если я бегу "run2." (это тот же код без вызова sumValue и "+ F"), он печатает только

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

Из моей отладки кажется, что проблема в том, что когда findall заканчивает первую цель и возвращается, sumValue влияет на его поведение.

Поэтому мой главный вопрос - как суммировать значения (из другого предиката) в переменную "C" при определенных условиях (в данном случае, когда "M_1" отличается от "M"), не влияя на обратное отслеживание findall.

Я целый день пытался найти способ обойти это, я уже пытался использовать "!" но безрезультатно.

1 ответ

Решение

Причина, по которой вы получаете различное поведение при запросах run. а также run2. потому что цель sumValue('M1', _, F) удовлетворяется дважды:

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

Я бы также рекомендовал вам использовать format/2 вместо всех тех write/1 предикаты. Это помогает для читабельности кода.

debug_t(H, X, C, F, M):-
    format("<~w> to <~w> @ ~w> total=~w e freq=~w~n", [H, X, M, C, F]).
Другие вопросы по тегам