有两种
剪枝; 绿色剪枝和红色剪枝。绿色剪枝仅用于提高效率,不改变程序的语义。而红色剪枝则会改变。根据定义,绿色剪枝不会引起任何问题。
那么,如果没有剪枝,行为会改变吗?
让我们看看;为了使第一个子句匹配,L1应该与[]可统一,L2与L可统一,L3与L可统一,或者换句话说,L2可统一与L3。
当L1为[]时,第二个子句无法匹配;因此,剪枝没有任何影响。
当L1未实例化时:
如果此时L2和L3的长度已知,则它们必须相等,否则第一个子句将无法匹配;因此,第二个子句无法匹配,因为在每个步骤中,L3的长度都会减少1,而唯一终止的方法需要L2=L3。
如果L3或L2的长度未知:
那么我们就有了一个问题,因为第二个子句可能会产生解决方案。
确实:
3 ?- append2(L1,L2,[1,2,3]).
L1 = [],
L2 = [1, 2, 3].
4 ?- append2(L1,[1,2,3],L3).
L1 = [],
L3 = [1, 2, 3].
5 ?- append2(L1,L2,L3).
L1 = [],
L2 = L3.
6 ?- append2(L1,[E1,E2],L3).
L1 = [],
L2 = [E1, E2].
7 ?- append2(L1,L2,[E1,E2]).
L1 = [],
L2 = [E1, E2].
当我们期望时:
8 ?- append(L1,L2,[1,2,3]).
L1 = [],
L2 = [1, 2, 3] ;
L1 = [1],
L2 = [2, 3] ;
L1 = [1, 2],
L2 = [3] ;
L1 = [1, 2, 3],
L2 = [] ;
false.
9 ?- append(L1,[1,2,3],L3).
L1 = [],
L3 = [1, 2, 3] ;
L1 = [_G24],
L3 = [_G24, 1, 2, 3] ;
L1 = [_G24, _G30],
L3 = [_G24, _G30, 1, 2, 3] ;
L1 = [_G24, _G30, _G36],
L3 = [_G24, _G30, _G36, 1, 2, 3] ;
L1 = [_G24, _G30, _G36, _G42],
L3 = [_G24, _G30, _G36, _G42, 1, 2, 3] ;
...
10 ?- append(L1,L2,L3).
L1 = [],
L2 = L3 ;
L1 = [_G22],
L3 = [_G22|L2] ;
L1 = [_G22, _G28],
L3 = [_G22, _G28|L2] ;
....
11 ?- append(L1,[E1,E2],L3).
L1 = [],
L3 = [E1, E2] ;
L1 = [_G78],
L3 = [_G78, E1, E2] ;
L1 = [_G78, _G84],
L3 = [_G78, _G84, E1, E2] ;
L1 = [_G78, _G84, _G90],
L3 = [_G78, _G84, _G90, E1, E2] ;
...
12 ?- append(L1,L2,[E1,E2]).
L1 = [],
L2 = [E1, E2] ;
L1 = [E1],
L2 = [E2] ;
L1 = [E1, E2],
L2 = [] ;
false.
append3(Xs,Ys,[])
。额外的剪枝符是否有助于消除选择点?您用哪个Prolog来运行它? - Will Nesscall((!,fail;true))
失败,而call((G=!,G,fail;true))
成功,因为实际上执行的是call((G=!,call(G),fail;true))
。对于append3(Xs,Ys,[])
,我所知道的所有Prologs都可以工作:它们具有第一个参数索引,但没有或弱索引其他参数。 - falseappend(Xs,Ys,[])
不会留下任何选择点。你为什么认为它不会呢?它执行了Zs == []
,因此有了!
。 - falseappend([], Ys, Zs).
也会重试,我总是不得不按;
键)。 - Will Ness(->)/2
的第一个参数。 - false