Prolog-在findall中进行操作 [英] Prolog - Operation inside findall

查看:384
本文介绍了Prolog-在findall中进行操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Prolog中使用 findall 如何在目标内执行操作而不影响回溯?

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

这里的问题是,当我运行"run."时,它会打印:

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

如果我运行"run2". (这是相同的代码,没有调用 sumValue 和"+ F"键)仅打印

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

从我的调试看来,问题出在 findall 完成第一个目标并回溯时, sumValue 影响了它的行为.

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

所以我的主要问题是如何在某些条件下(在这种情况下,当"M_1"不同于"M"时)将值(来自另一个谓词)求和到变量"C",而不影响 findall 回溯.

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.

推荐答案

查询run.run2.时得到不同行为的原因是因为两次满足了目标sumValue('M1', _, F):

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.


我还建议您使用format/2而不是所有那些write/1谓词.它有助于提高代码的可读性.


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

这篇关于Prolog-在findall中进行操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆