我选了一门中,我学到了一些序言。 我无法弄清楚如何/时使用的削减。 即使我得到削减的总体思路,我似乎无法正确地使用它们。 任何人都可以简单介绍一下它,或者提供“切”一个很好的教程(这不是learnprolognow.org),他们可以推荐?
Answer 1:
TL; DR:不要。
切割修剪的Prolog的搜索树。 也就是说,由于没有切断一个纯粹的Prolog程序,并削减相同的程序,唯一的区别是,与削减计划可能会花无果而终中的分支更短的时间,从而更有效; 可能有较少的答案; 它也可能终止,而原来的程序没有。
听起来很无害......甚至是有用的,不是吗? 嗯,大部分的时间事情比较复杂。
红削减
切口通常的方式使得在不裁员的程序有没有合理的意义使用的。 这样的裁员被称为红色的削减。 在较好的情况下,它被用来实现非单调否定的原始形式。 而在其他一些情况下,它是半否定,半数一些程序上的意义,这是非常难以理解。 不仅对节目的读者也为它的作家。 事实上,往往这样的用途无意缺乏坚定性 。 在任何情况下:这些削减不会被放置到现有程序。 他们是为了在从一开始就计划的权利。
对于这样的红色切口的更结构化的用途中,更好地利用once/1
, (\+)/1
,或(;)/2
-如果-则-否则像( If -> Then ; Else )
代替。 更妙的是,试图通过发行防范意外的用途,结构instantiation_error
秒。 或者使用iwhen/2
产生实例错误或when/2
,其延迟目标(在SWI,YAP,SICStus提供)。
绿色削减
即删除无用choicepoints(也是多余的答案)削减被称为绿色削减。 但要注意:你不能把它们放入你的程序只需按下! 有的#00ff00
。 大多数时候,你需要一个干净的只读后卫,以确保有没有办法切断这种轮流#ff0000
。 还有一个简单的方法来安全地删除一些吃剩的choicepoints: call_semidet/1
。 下面是一些相关案例:
什么是SLD树此查询?
Prolog的追加与切割操作
什么是最佳的绿色削减接班人算术总和?
实施“最后”的序言
切不能犯
最后,我想指出的是切不提交运营商。 有时候行为有点像,但需要大量的限制是一个。 一个提交的操作员不能(AB)用于实现(\+)/1
。 一个提交要求每个子句彼此独立地试过。 因此,每一个条款,需要一个完整的后卫; 它不能只依赖于经过其他一些条款已首次尝试受审。 此外,承诺将有谓词的每个子句中出现。 切口可以在任何地方发生。
Answer 2:
的切口承诺 Prolog的目标而被证明所做的选择。
必须然后使用时的程序员都知道 ,任何可用的替代不能受审。
最突出的应用是否定的故障实施。
fact(a).
fact(b).
/* 1 */ neg(X) :- call(X), !, fail.
/* 2 */ neg(_).
在这里,我(重新)定义的标准否定操作符,通常这是( \ + )/ 1
?- neg(fact(c)).
true.
call(fact(c))
第1条规则不能被证明,和备选规则2然后成功。
?- neg(fact(a)).
false.
因为fact(a)
可以证明,切割失效之前丢弃的备选方案。
?- neg(fact(X)).
false.
至少存在一个未知的X这样的事实(X)取得成功。
?- neg(neg(fact(X))).
true.
双重否定有变量没有得到约束的效果。 做元编程时,在不改变其“结构”来获取条款这可能是有用的。 从操作角度来看,很明显(?)这是怎么回事,但该程序确实失去其声明属性。
另一种用途,只有在基本的解释是有用的,是指导进行最后一次通话的优化系统,附加了一个切递归调用。 然后该系统能够避免分配通常需要跟踪替代点的堆栈空间。 一个虚拟的例子:
print_list([E|Es]) :- print_element(E), !, print_list(Es).
print_list([]).
编辑有关的教程:我发现,由威廉Clocksin“条款和效果”包含削减相关的详细调查:第4章“选择和承诺”这是完全致力于削减利弊。 在底线,主要是利弊...
Answer 3:
使用切割之前,我需要我的谓词满足这两个标准:
- 它给出正确的答案不切
- 它给出正确的答案,如果条款进行重新排序
一旦我的谓词的行为这种方式,我有时加割伤剪掉不需要确定性。
例如,谓词来测试数是否为正,负或零。
sign(N, positive) :-
N > 0.
sign(N, negative) :-
N < 0.
sign(N, zero) :-
N =:= 0.
每个子句代表完全独立于其他人。 我可以重新排列这些条款或删除条款,其余条款仍然得到所需要的答案。 在这种情况下,我可能把切在年底positive
和negative
的条款只是告诉Prolog的系统,它不会通过检查其他条款找到更多的解决方案。
人们可以写一个类似的断言不削减使用-> ;
,但有些不喜欢它的外观:
sign(N, Sign) :-
( N > 0 -> Sign=positive
; N < 0 -> Sign=negative
; Sign=zero
).
Answer 4:
切谓语防止backtracking.Cut谓词被指定为一个感叹号(!)。 切修剪搜索树,并缩短了序言interpreter.Semantically路径跟踪它总是成功。
read(a).
read(b).
color(p, red) :- red(p).
color(p,black) :- black(p),!.
color(p,unknown).
?-color(X,Y).
X = a,
Y = red;
X = b,
Y = black;
如果不削减目标显示Y =黑后,Y =未知。
有两种类型的切谓词:
绿色剪切:剪切绿色是一种切断这对声明的含义没有影响。 它只是用来提高效率,同时避免不必要的计算。 绿色切削从程序中去除不改变程序的含义。
红切:红切是一个这不会对声明的意义作用。 红切从程序去除改变程序的含义。
Answer 5:
削减几乎从我的代码消失了,一旦我找到了once
断言。 在内部,它就像
once(X) :- X, !.
我发现负责就如何我做的东西之前做一些果断的决定是非常有用的。
例如,这里是我的标准元解释。 该maybe1/1
条在其参数独特的仿函数所以一旦他们知道,再右边maybe1/1
可以选择,非常完美。
发现独特功能的作业给予maybe0/2
预处理器,设置Y
到“做什么声明”约X
。
如果没有once
,这可能将不得不削减与百病。 例如在maybe1
,有三个/两种不同的解释X/Y
,而且or
我们需要一个自上而下的方式进行检查。 但检查OUT-没有削减。
maybe(X) :-
once(maybe0(X,Y)), maybe1(Y).
maybe0(true, true).
maybe0((X,Y), (X,Y)).
maybe0((X;Y), or(L)) :- o2l((X;Y),L).
maybe0(X, calls(X)) :- calls(X).
maybe0(X/Y, fact(X/Y)) :- clause(X/_, true).
maybe0(X/Y, rule(X/Y)) :- clause(X/_,_).
maybe0(X/Y, abducible(X/Y)).
maybe0(or([H|T]), or([H|T])).
maybe0(or([]), true).
maybe1(true).
maybe1((X,Y)) :- maybe(X),maybe(Y).
maybe1((X;Y)) :- maybe(X);maybe(Y).
maybe1(abducible(X)) :- assume(X,0).
maybe1(fact(X)) :- assume(X,1), one(X).
maybe1(rule(X)) :- assume(X,2), one(clause(X,Y)), maybe(Y).
maybe1(calls(X)) :- one(clause(X,Y)), maybe(Y).
maybe1(or([H|T])) :- any(One,Rest,[H|T]), ignore(maybe(One)), maybe(or(Rest)).