Пролог цель с несколькими результатами - PullRequest
0 голосов
/ 02 декабря 2018
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, false.Тогда как второй возвращает только true.
Мой вопрос заключается в том, почему в первой цели у нас есть эта дополнительная информация.
Я использую версию SWI-Prolog 7.6.4

1 Ответ

0 голосов
/ 02 декабря 2018

Причина, по которой это происходит, заключается в том, что в первом случае все еще есть " возможность " для возврата, тогда как во втором случае такой возможности нет.

Если мы назовем цельс помощью 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
   <b>Call: (10) runs(pc, vb, _2970) ? creep</b>
   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 ;
   <b>Redo: (10) runs(pc, vb, _2970)</b> ? 

Мы, таким образом, делаем вызов 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
   <b>Call: (10) runs(mac, prolog, _3728) ? creep</b>
   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 определенного вызова.

...