Prolog - findall 内部操作
Prolog - Operation inside findall
在 Prolog 中使用 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).
这里的问题是,当我运行 "run." 时,它会打印:
<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 会影响它的行为。
所以我的主要问题是 如何在特定条件下(在这种情况下,当 "M_1" 不同于 "M") 不影响 findall 回溯.
我整天都在尝试解决这个问题,我已经尝试过使用“!”但无济于事。
查询 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]).
在 Prolog 中使用 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).
这里的问题是,当我运行 "run." 时,它会打印:
<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 会影响它的行为。
所以我的主要问题是 如何在特定条件下(在这种情况下,当 "M_1" 不同于 "M") 不影响 findall 回溯.
我整天都在尝试解决这个问题,我已经尝试过使用“!”但无济于事。
查询 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]).