Пролог - объяснение шагов трассировки на английском языке - PullRequest
0 голосов
/ 25 ноября 2018
plays(alice, leadguitar).
plays(noah, drums).
plays(mike, leadguitar).
plays(mike, drums).
plays(katie, baseguitar).
plays(drew, leadguitar).
plays(drew, baseguitar).

duetwith(Person1,Person2):- 
    plays(Person1,L),
    plays(Person2,L), 
    Person1 \= Person2.

Я пишу новое правило, называемое комбо, которое определяет, могут ли три человека сделать комбо с барабанщиком, базовой гитарой и ведущей гитарой.

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

Может рисовать, Алиса, а Майк делает комбо?

combo(mike,alice,drew).

true, поэтому ответ - да, они могут создать комбо.

Мне нужна помощь в понимании шагов, которые программа выполняет для ответа на вышеуказанный запрос в прологе.Любая помощь со списком шагов очень ценится, поэтому я могу получить более глубокое понимание каждого шага, который выполняет Пролог.

Вот пример списка шагов, которые Пролог предпринимает для другого примера, просто чтобы дать представление очто я ищу.

В случае talkswith(bob,allen) двигатель предпринял следующие шаги:

  1. В

    переговоры с (Person1,Person2): - говорит (Person1, L), говорит (Person2, L), Person1 \ = Person2.

заменяет каждый случай Person1 на bob и Person2с allen чтобы получить

talkswith(bob,allen) :- 
    speaks(bob,L),
    speaks(allen,L),
    bob \= allen.

Давайте посмотрим, сможем ли мы найти значение для L, которое делает правую часть истинной.Начните с speaks(bob,L). Что может быть L?Вот наши факты:

  1. говорит (аллен, русский).
  2. говорит (боб, английский).
  3. говорит (Мэри, русский).
  4. говорит (мэри, английский).

На самом деле 1, первый слот не боб, поэтому он не будет работать.На самом деле, первый слот - это bob, поэтому давайте попробуем L = english in speaks(allen,L), bob \= allen. Теперь мы просим speaks(allen,english), bob\= allen.

Вернуться к базе знаний.speaks(allen,english) соответствует факту?Не факт 1, не факт 2, не факт 3, не факт 4. Это не удается. Теперь вернемся к шагу 2. Факт 2 не сработал, поэтому давайте попробуем факт 3. Нет, этоне бобФакт 4 тоже не боб.Мы не можем найти значение для L, которое работает, поэтому поиск не удался.

1 Ответ

0 голосов
/ 26 ноября 2018

заменяет каждое вхождение Person1 на bob

Пролог использует синтаксическое объединение , которое никогда не выполняет замену. свободная переменная может быть привязана только один раз к значению.Если похоже, что переменная изменяется более одного раза, это не так.Может быть много стековых фреймов , и для каждого стекового фрейма может быть создан новый набор переменных.


Трассировка несколько полезна, но мне нужно перевести это в форму примера выше с шагами, написанными и объясненными на простом английском языке.

Для этих фактов

plays(alice, leadguitar).
plays(noah, drums).
plays(mike, leadguitar).
plays(mike, drums).
plays(katie, baseguitar).
plays(drew, leadguitar).
plays(drew, baseguitar).

и этого предиката

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

и этого запроса

combo(mike,alice,drew).

Сначала прочитайте SWI-Prolog Программы отладки и трассировки

Запустите запрос с трассировкой, включите унифицированный порт и отключите его.

?- visible(+unify).
true.

?- leash(-all).
true.

?- trace.
true.

[trace] ?- combo(mike,alice,drew).
   Call: (8) combo(mike, alice, drew)
   Unify: (8) combo(mike, alice, drew)
   Call: (9) plays(mike, _7040)
   Unify: (9) plays(mike, leadguitar)
   Exit: (9) plays(mike, leadguitar)
   Call: (9) plays(alice, _7040)
   Unify: (9) plays(alice, leadguitar)
   Exit: (9) plays(alice, leadguitar)
   Call: (9) plays(drew, _7040)
   Unify: (9) plays(drew, leadguitar)
   Exit: (9) plays(drew, leadguitar)
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(drew, _7040)
   Unify: (9) plays(drew, baseguitar)
   Exit: (9) plays(drew, baseguitar)
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(mike, _7040)
   Unify: (9) plays(mike, drums)
   Exit: (9) plays(mike, drums)
   Call: (9) plays(alice, _7040)
   Unify: (9) plays(alice, leadguitar)
   Exit: (9) plays(alice, leadguitar)
   Call: (9) plays(drew, _7040)
   Unify: (9) plays(drew, leadguitar)
   Exit: (9) plays(drew, leadguitar)
   Call: (9) drums\=leadguitar
   Exit: (9) drums\=leadguitar
   Call: (9) leadguitar\=leadguitar
   Fail: (9) leadguitar\=leadguitar
   Redo: (9) plays(drew, _7040)
   Unify: (9) plays(drew, baseguitar)
   Exit: (9) plays(drew, baseguitar)
   Call: (9) drums\=leadguitar
   Exit: (9) drums\=leadguitar
   Call: (9) leadguitar\=baseguitar
   Exit: (9) leadguitar\=baseguitar
   Call: (9) drums\=baseguitar
   Exit: (9) drums\=baseguitar
   Exit: (8) combo(mike, alice, drew)
true.

Call: (8) combo(mike, alice, drew)

Пролог ищет предикат, которыйсоответствует запросу.Когда Пролог ищет предикат, он ищет по имени предиката, в данном случае combo, и по арности, в данном случае 3, и находит только один предикат с одним предложением.Пролог также ищет предикаты в порядке их появления в исходном коде.Это еще не все (индексация), но этот уровень детализации не нужен для объяснения этого простого запроса.


Unify: (8) combo(mike, alice, drew)

Как только Prolog обнаружил предложение / факт, основанный на имени и предикате предиката, он проверяетчто запрос и заголовок предложения или факта могут быть объединены.

mike объединяется с Person1.Person1 теперь связано с mike.
alice объединяется с Person2.Person2 теперь связан с alice.
drew объединяется с Person3.Person3 теперь связано с drew.


Call: (9) plays(mike, _7040)

Если предыдущий оператор объединяется, вызывается следующий оператор.Каждое утверждение представляет собой запрос сам по себе.Таким образом, выполнение запроса plays(mike,X). как отдельного запроса аналогично приведенному в предложении.Существует множество фактов для plays/2, и два из них совпадают с plays(mike,X).. Пролог использует первое, что находит, однако, поскольку их больше одного, делается выбор.Мы назовем эту конкретную точку выбора plays(mike,X) - cp1 и отошлем назад конкретную точку выбора при обнаружении соответствующего REDO.


Unify: (9) plays(mike, leadguitar)

Как только Prolog найдет предложение / факт на основе имени предиката и арностион проверяет, что запрос и заголовок предложения могут быть объединены.

plays объединяется с plays
mike объединяется с mike
_7040 объединяется с leadguitar._7040 привязано к leadguitar.


Exit: (9) plays(mike, leadguitar)

Это только завершение портов модели коробки Prolog .Показывает результат Call: (9) plays(mike, _7040).Никакого объединения не происходит для этого утверждения.


Call: (9) plays(alice, _7040)
Unify: (9) plays(alice, leadguitar)
Exit: (9) plays(alice, leadguitar)

Тот же шаблон для alice.У Алисы есть только один факт, поэтому для нее не генерируются очки выбора.


Call: (9) plays(drew, _7040)
Unify: (9) plays(drew, leadguitar)
Exit: (9) plays(drew, leadguitar)

То же самое для drew.Поскольку у drew есть два факта для plays(drew,X)., генерируется точка выбора.plays(drew,X) - cp1


Call: (9) leadguitar\=leadguitar

Это четвертое утверждение X \= Y с X связано с leadguitar и Y связано с leadguitar


Fail: (9) leadguitar\=leadguitar

Так как leadguitar не отличается от leadguitar, этот запрос не выполняется.В случае неудачи Пролог возвращается к последней точке выбора (Повторить) и пытается найти другое решение.


Redo: (9) plays(drew, _7040)

Запомните последнюю созданную точку выбора, plays(drew,X) - cp1.Так как что-то не удалось, запрос пытается найти другое возможное решение.Поскольку первая точка выбора для plays(drew,X) не удалась, а X была leadguitar, используется второй факт, plays(drew,baseguitar).


Unify: (9) plays(drew, baseguitar)

Просто показывает, что второй факт для plays(drew,X)используется.


Exit: (9) plays(drew, baseguitar)

Показывает результат Redo: (9) plays(drew, _7040).


Остальное - просто больше копирования / вставки того, что уже сделано, и изменение операторов, переменных, связанных значений и т. Д.


Этот ответ похож, но имеет больше деталей.


Примечательно, что этот вопрос

Я пишу новое правило, называемое комбо, которое определяет, могут ли три человека сделать комбо с барабанщиком, базовой гитарой и ведущей гитарой.

на этот запрос не ответили

combo(Person1,Person2,Person3):- 
    plays(Person1,X), 
    plays(Person2,Y), 
    plays(Person3,Z), 
    X \= Y, 
    Y \= Z, 
    X\=Z.

потому что, если эти факты будут добавлены

plays(alice, flute).
plays(noah, cello).
plays(mike, trumpet).

, этот запрос

?- combo(alice,noah,mike).
true ;
true .

ответит «истина», а alice, noah и mike - нетигра на свинцовой гитаре, ударных и базовой гитаре.

...