【问题标题】:Please explain the cut in the Bubblesort Prolog program?请解释 Bubblesort Prolog 程序中的削减?
【发布时间】:2013-12-03 11:46:39
【问题描述】:

我目前正在阅读 Bratko Prolog 书,并且正在研究冒泡排序程序。我似乎无法弄清楚为什么 cut(!) 是必要的。假设剪辑不存在,Prolog 会回溯,它怎么可能找到错误的答案?因为如果我把它删掉,Prolog 会先给我正确的答案,然后也会给出替代的错误答案。

在我看来,swap 怎么会返回一个未排序的列表?一个未排序的列表怎么可能达到目标bubblesort(Sorted, Sorted)

当然,除非第一个列表也被更改...无法理解它。

Prolog BubbleSort 程序:

gt(X,Y) :- X > Y.

bubblesort(List, Sorted) :-
  swap(List, List1), !,           % A useful swap in List?
  bubblesort(List1, Sorted).
bubblesort(Sorted, Sorted).       % Otherwise list is already sorted

swap([X,Y|Rest], [Y,X|Rest]) :-   % Swap first two elements
  gt(X,Y).
swap([Z|Rest], [Z|Rest1]) :-      % Swap elements in tail
  swap(Rest, Rest1).

留下它给我的切口:

?- bubblesort([5,7,3,6,8,9,2,6], Sorted).

Sorted = [2, 3, 5, 6, 6, 7, 8, 9] ;

Sorted = [2, 3, 5, 6, 7, 6, 8, 9] ;

Sorted = [2, 3, 5, 6, 7, 8, 6, 9] ;

Sorted = [2, 3, 5, 6, 7, 8, 9, 6] ;

我想我明白了,但我不确定。是不是在某个时刻,它回溯到swap(List, List1) 去第二个冒泡排序谓词并达到目标,这意味着两个列表排序相等?

在英语中,这是否意味着冒泡排序需要继续进行交换,直到无法再进行交换,然后才需要终止?或者这是否意味着每次成功的交换完成后,回溯该成功是没有用的?

【问题讨论】:

  • 我认为你关于它为什么存在的第二个概念基本上是正确的。如果gt(X,Y) 失败,swap 将提供替代方案。即使gt(X,Y) 成功,该替代方案也将被退回。 bubblesort 谓词的结构方式,bubblesort 的每次迭代只是寻找swap 以找到下一次出现的必要交换并执行它。如果没有剪辑,您会从 swap 获得不符合所需条件的回溯。

标签: prolog bubble-sort prolog-cut


【解决方案1】:

有几种可能使目标swap(List, List1) 失败。 List 是长度为 0 或 1 的列表;或者它不包含两个紧随其后的元素,其中第二个小于第一个。

剪切的放置方式既剪切swap/2,又剪切bubblesort/2

这是一个很好的例子,“深切”(切入swap/2)仍然可以很好地工作。但是,这种情况非常罕见。大多数时候,削减太多。大多数此类程序使用起来非常脆弱,如果已经给出了第二个参数,则更是如此。他们往往不是坚定的

啊,我差点错过了:即使在这个程序中,我们也有 bubblesort(nonlist,L) 成功,或者 bubblesort([1|nonlist],L) 这可能不是故意的,会导致细微的编程错误。

这个程序没有呈现理想的逻辑编程风格还有另一个原因:bubblesort/2 的第二条规则单独阅读时说:一切都是排序列表`。要理解这一点,我们必须同时阅读这两个规则并将其缩小到Everything but ...

在英语中,这是否意味着冒泡排序需要继续进行交换,直到无法再进行交换,然后才需要终止?或者这是否意味着每次成功的交换完成后,回溯该成功是没有用的?

这是适用于此的第一个程序含义。当然,将成功回溯到bubblesort/2 的第二个子句将是一个错误。

另一个非常不直观的细节不是特定于剪辑的,即除了数字之外,该程序还可以成功处理 bubblesort([1,1+1],L) 这样的表达式,这又可能导致细微的差异。

【讨论】:

    【解决方案2】:

    我只想补充一点,if-then-else 是一种比 !/0 更合适的语言结构来表达意图(而且我知道你没有自己选择 !/0这里):

    bubblesort(List0, List) :-
            (   swap(List0, List1) ->
                bubblesort(List1, List)
            ;   List0 = List
            ).
    

    您也可以将-> 更改为*-> 以查看swap/2 的替代解决方案,即,如果您将其更改为:

    bubblesort(List0, List) :-
            (   swap(List0, List1) *->
                bubblesort(List1, List)
            ;   List0 = List
            ).
    

    然后你得到例如:

    ?- bubblesort([5,7,3,6,8,9,2,6], Ascending).
    Ascending = [2, 3, 5, 6, 6, 7, 8, 9] ;
    Ascending = [2, 3, 5, 6, 6, 7, 8, 9] ;
    Ascending = [2, 3, 5, 6, 6, 7, 8, 9] .
    

    如您所见,所有这些列表都没有减少,正如您已经预料到的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-11
      • 2018-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多