Пролог - объяснение шагов трассировки на английском языке

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).

так что ответ да, они могут сделать комбо.

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

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

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

    1. говорит (аллен, русский).
    2. говорит (боб, английский).
    3. говорит (Мария, русский).
    4. говорит (мэри, английский).
  2. На самом деле 1, первый слот не боб, так что это не сработает. На самом деле 2, первый слот это Боб, так что давайте попробуем L = englishв speaks(allen,L), bob \= allen. Теперь мы спрашиваем speaks(allen,english), bob\= allen.

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

1 ответ

Решение

заменить каждый случай Person1 с Бобом

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


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

За эти факты

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и arity, в этом случае 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)

Это только завершение портов модели коробки Пролог. Это показывает результат 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, Так как у Дрю есть два факта для 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 не играют на свинцовой гитаре, барабанах и базовой гитаре.

Другие вопросы по тегам