【问题标题】:Repeat until predicate evaluates to true in prolog重复直到谓词在序言中评估为真
【发布时间】:2020-05-23 09:18:33
【问题描述】:

所以,我对 prolog 很陌生,并且在做一些非常基本的事情时遇到了麻烦。我希望能够重复对谓词的评估,直到 in 评估为 True

do(Goals, Frontier, Explored):-
    repeat, bfs(Goals, Frontier, Explored).

基本上,谓词bfs 将在大多数情况下评估为False(由于一些随机路径搜索,它采用不同的值)。一旦评估为True,我想停止查找。谓词do 基本上在这里充当while 循环。当谓词计算结果为 True 时,我希望循环结束。

虽然 stackoverflow 上还有其他一些帖子解决了这个问题,但我发现它们很难理解,因为它们详细介绍了自己的问题。所以也许有人可以向我展示这个场景的一般配方。

【问题讨论】:

  • 虽然当谓词成功时循环没有结束,但循环确实停止了——结果产生了,然后“循环”暂停,准备继续从它停止的地方开始搜索。如果您不希望它继续,请不要要求它。如果您不希望它能够继续,请在调用后添加剪切 !,甚至在 do 中添加作为最后一个目标,在 bfs 调用之后。

标签: prolog


【解决方案1】:

嗯,你已经写好了解决方案!

这是一个“失败驱动的循环”。

Prolog 的行为就像有一个光标从左向右移动(好吧,这里是从上到下,由于格式化)通过该行,当谓词调用失败时,光标被发送回左侧,并弹回在repeat/0 右侧:

do(X) :-                                 % X will take on the value of success
  repeat ,                               % The cursor bounces off here
                                         % ...to try again!                  
  format("Now trying something\n",[]) ,     
  random(0.0,1.0,X) ,                    % Try something
  format("Obtained ~q\n",[X]) ,            
  X < 0.2 ,                              % Test whether success
  format("Done!\n").                     % On success, we end up here.
                                         % On failure, we redo in order
                                         % Redo X < 0.5 - There is no redo here
                                         % Redo format/2 - There is no redo here 
                                         % Redo random/3 - There is no redo here  
                                         % Redo format/2 - There is no redo here 
                                         % Redo repeat/1 - Redo means cursor bounce

所以:

?- do(X).
Now trying something
Obtained 0.9837293974501616
Now trying something
Obtained 0.7031039796418066
Now trying something
Obtained 0.5838475489280747
Now trying something
Obtained 0.7179787440277113
Now trying something
Obtained 0.14040275695848495
Done!
X = 0.14040275695848495 

由于没有“cut”,Prolog 顶层会询问您是否需要更多解决方案。如果您输入;,该过程将继续,在format("Done!\n") 重新输入。

这是一个替代方案

  • 使用between/3 最多尝试 4 次
  • 在第一次成功时,使用“!”切断进一步的解决方案/重试,因此永远不会要求用户进行第二次尝试。
do(X) :-  
  between(1,4,K) ,            
  format("Now trying something, K = ~q\n",[K]) ,     
  random(0.0,1.0,X) ,
  format("Obtained ~q\n",[X]) ,            
  X < 0.2 ,                   
  format("Done!\n"),
  !.

由于between/3 的“重做限制”性质,这实际上可能在有限数量的重做后失败:

?- do(X).
Now trying something, K = 1
Obtained 0.823698968756448
Now trying something, K = 2
Obtained 0.8617406555236128
Now trying something, K = 3
Obtained 0.7718447437621774
Now trying something, K = 4
Obtained 0.6010951752269867
false.

奖励脑筋急转弯

当“光标向左移动”时,这个谓词也会打印一些东西。

它的工作原理可能并不直接明显。

do(X) :-  
  between(1,4,K) ,            
  (true ; (format("Going to hit between/3 coming from the 'right' with K = ~q\n",[K]),fail) ), 
  format("Now trying something, K = ~q\n",[K]) ,     
  random(0.0,1.0,X) ,
  format("Obtained ~q\n",[X]) ,            
  (true ; (format("NOPE! ~q doesn't cut it\n",[X]),fail) ), 
  X < 0.2,                   
  format("Done!\n"),
  !.

样本输出:

?- do(X).
Now trying something, K = 1
Obtained 0.25501790245795947
NOPE! 0.25501790245795947 doesn't cut it
Going to hit between/3 coming from the 'right' with K = 1
Now trying something, K = 2
Obtained 0.2778042792426882
NOPE! 0.2778042792426882 doesn't cut it
Going to hit between/3 coming from the 'right' with K = 2
Now trying something, K = 3
Obtained 0.042750567384520134
Done!
X = 0.042750567384520134.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多