Пролог цель с несколькими результатами
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).
Первая цель возвращается: верно, ложно. Тогда как второй возвращает только истину.
Мой вопрос: почему в первой цели у нас есть эта дополнительная информация?
Я использую версию SWI-Prolog 7.6.4
1 ответ
Причина, по которой это происходит, заключается в том, что в первом случае все еще есть "возможность" возврата, тогда как во втором случае такой возможности нет.
Если мы назовем цель с 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/3
с runs(pc, vb, MemNeeded)
и Пролог находит первый ответ с 16
, Но это устанавливает точку возврата, чтобы искать другие runs/3
факты с runs(pc, vb, MemNeeded)
, Представьте, что позже в исходном коде есть другой факт, например 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
в противном случае: поскольку Пролог работает сверху вниз, если мы выполнили последний факт / предложение, мы знаем, что другого варианта нет.
Поскольку все другие вызовы также принимают последний предикат или с другой константой в качестве первого параметра (SWI-Prolog смотрит на первый аргумент, когда он компилирует исходный код в качестве оптимизации), других точек возврата нет, и поэтому это не способ Redo
определенный звонок.