spec(comp1, pc, 32). /* Fact 1 */
spec(comp2, mac, 128). /* Fact 2 */
spec(comp3, pc, 64). /* Fact 3 */
runs(pc, movie_edit, 96). /* Fact 4 */
runs(pc, vb, 16). /* Fact 5 */
runs(pc, cpp, 28). /* Fact 6 */
runs(mac, vb, 24). /* Fact 7 */
runs(mac, prolog, 128). /* Fact 8 */
access(judy, comp1). /* Fact 9 */
access(peter, comp3). /* Fact 10 */
access(david, comp1). /* Fact 11 */
access(david, comp2). /* Fact 12 */
can_use(P, SW) :- access(P, Comp), can_run(Comp, SW). /* Rule 1 */
can_run(Comp, SW) :- spec(Comp, CompType, MemAvail),
runs(CompType, SW, MemNeeded),
MemAvail >= MemNeeded. /* Rule 2 */
?- can_use(judy, vb).
?- can_use(david, prolog).
第一个目标返回:真,假。而第二个只返回true
我的问题是,为什么在第一个进球中我们有额外的信息
我使用的是SWI Prolog 7.6.4版本
发生这种情况的原因是,在前一种情况下,仍然有">机会"进行回溯,而在后一种情况中,没有这样的机会。
如果我们用trace
调用目标,我们会看到:
[trace] ?- can_use(judy, vb).
Call: (8) can_use(judy, vb) ? creep
Call: (9) access(judy, _2968) ? creep
Exit: (9) access(judy, comp1) ? creep
Call: (9) can_run(comp1, vb) ? creep
Call: (10) spec(comp1, _2968, _2970) ? creep
Exit: (10) spec(comp1, pc, 32) ? creep
Call: (10) runs(pc, vb, _2970) ? creep
Exit: (10) runs(pc, vb, 16) ? creep
Call: (10) 32>=16 ? creep
Exit: (10) 32>=16 ? creep
Exit: (9) can_run(comp1, vb) ? creep
Exit: (8) can_use(judy, vb) ? creep
true ;
Redo: (10) runs(pc, vb, _2970)?
因此,我们用runs(pc, vb, MemNeeded)
调用runs/3
,Prolog用16
找到第一个答案。但它设置了一个回溯点,用runs(pc, vb, MemNeeded)
查找其他runs/3
事实。想象一下,在源代码后面还有另一个事实,例如末尾的runs(pc, vb, 14)
,那么这可以产生另一个答案。
然而,如果我们称之为第二个目标,我们会看到:
[trace] ?- can_use(david, prolog).
Call: (8) can_use(david, prolog) ? creep
Call: (9) access(david, _3726) ? creep
Exit: (9) access(david, comp1) ? creep
Call: (9) can_run(comp1, prolog) ? creep
Call: (10) spec(comp1, _3726, _3728) ? creep
Exit: (10) spec(comp1, pc, 32) ? creep
Call: (10) runs(pc, prolog, _3728) ? creep
Fail: (10) runs(pc, prolog, _3728) ? creep
Fail: (9) can_run(comp1, prolog) ? creep
Redo: (9) access(david, _3726) ? creep
Exit: (9) access(david, comp2) ? creep
Call: (9) can_run(comp2, prolog) ? creep
Call: (10) spec(comp2, _3726, _3728) ? creep
Exit: (10) spec(comp2, mac, 128) ? creep
Call: (10) runs(mac, prolog, _3728) ? creep
Exit: (10) runs(mac, prolog, 128) ? creep
Call: (10) 128>=128 ? creep
Exit: (10) 128>=128 ? creep
Exit: (9) can_run(comp2, prolog) ? creep
Exit: (8) can_use(david, prolog) ? creep
true.
这里我们调用runs(mac, prolog, MemNeeded).
,这是runs/3
的最后一个事实,因此没有其他可能满足runs/3
:由于Prolog从上到下运行,如果我们满足了最后一个fact/子句,我们知道没有其他选择。
由于所有其他调用也采用最后一个谓词,或者使用不同的常量作为第一个参数(SWI-Prolog在编译源代码作为优化时会查看第一个参数(,因此没有其他回溯点,因此无法对某个调用进行Redo
。