заменяет каждое вхождение 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
- нетигра на свинцовой гитаре, ударных и базовой гитаре.