使用示例(Prolog语言)理解Cut(!)运算符的问题

时间:2016-05-20 21:25:42

标签: prolog prolog-cut

我有以下规则:

noRepetition([]).
noRepetition([Elem|Rest]):- not(member(Elem,Rest)), !, noRepetition(Rest).

此规则用于确定列表中是否没有重复元素,成员规则决定特定元素是否属于列表。我的问题与此规则中的cut运算符有关,因为我不确定它的作用。

我为?-noRepetition([a,b,b,c,d])制定了以下跟踪并遇到了一个问题(可能与我对切割运算符缺乏了解有关):

?-noRepetition([a,b,b,c,d])
Unfies with the second noRepetion rule and instantiates variables to:
noRepetition([a|b,b,c,d] :- not(member(a,[b,b,c,d])), !, noRepetition([b,b,c,d]).

现在我陷入困境,因为在这种情况下,非成员返回true,因此切换被证明是真的,但是我不确定这种切割是否会阻止程序进入noRepetition(第3个目标)或者是否有其他事情。如果它确实阻止程序进入noRepetition,那么这个规则将被评估为true,而不是因为列表中有重复。

2 个答案:

答案 0 :(得分:3)

提出你的问题。我的意见:削减是不必要的。您可能想要了解剪切的内容; here is a short summary。一个好的经验法则是在切割之前查看最后一个目标并试着看它是否留下了选择点。如果确实如此,那么它们都会被丢弃(以及此子句主体中早期目标的所有选择点),并且只留下第一个解决方案。我们来看看:

\+ member(Elem, Rest) % just another way to say not...

什么时候可以留下一个选择点?如果\+ Goal为false,则Goal为true,否则为false。据我所知,\+ Goal不可能不止一次真实,也不可能不止一次。那你为什么需要削减?在这种情况下是多余的,实际上什么都不做。

(我仍然想知道你为什么把切口放在那里。是否有一个类似的谓词没有使用member/2上的否定?)

提供更好的解决方案的人不赞成,但有at least two other ways来解决这个问题。您甚至可以将它们混合在一起以进行以下定义:

all_dif_list(L) :-
    (   ground(L)
    ->  sort(L, S),
        length(L, N),
        length(S, N)
    ;   all_dif_list_nonground(L)
    ).

all_dif_list_nonground([]).
all_dif_list_nonground([X|Xs]) :-
    maplist(dif(X), Xs),
    all_dif_list_nonground(Xs).

如果您知道列表已完全实例化,则可以对其进行排序,并比较长度。 sort/2删除重复项,因此如果重复,则排序列表会更短。

如果列表包含变量,那么安全的做法就是说列表中的每对元素都是(并且将永远)不同。

请记住,member/2比其简单名称和直接定义更复杂。如果我认为我会从中受益,我可以轻松地写一篇关于member/2行为的1000字的文章。

答案 1 :(得分:0)

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.example.yahyazeid.testnotification.Jan"
    android:background="#cbbc9f">


<CalendarView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/calendarView"
    android:background="#cbbc9f"
    android:layout_marginTop="0dp" />

注意:如果Item不是基础术语,结果可能会出乎意料。例如:

noRepetition([]).
noRepetition([Item|Rest]) :- member(Item,Rest), !, fail.
noRepetition([_|Rest]) :- noRepetition(Rest).

会失败......