Основываясь на ответе CapelliC, поскольку, по-видимому, его ответ был недостаточно ясным. Что касается синтаксиса if-else и его использования, см. В конце ответа.
Во-первых, в вашей постановке проблемы содержится информация, которую вы хотите представить в форме программы на Прологе. В Prolog у вас есть предикаты, которые могут описывать отношения между их аргументами или утверждать известные истины об их аргументах. Вот, например, таблица фактов; в нем говорится, что мы знаем о существовании семи человек:
person(john).
person(fred).
person(harry).
person(mary).
person(julie).
person(susan).
person(anne).
Хорошо. Теперь мы хотим констатировать, что некоторые из них - мужчины, а некоторые - женщины.
% John, Fred and Harry are men, Mary, Julie, Susan and Anne are women.
male(john).
male(fred).
male(harry).
female(mary).
female(julie).
female(susan).
female(anne).
Это еще две таблицы фактов. Теперь вы хотите добавить в свою базу данных информацию об их цвете волос:
% John has blonde hair while Fred and Harry have dark hair.
% Julie and Susan are blonde, Mary and Anne are brunette.
person_hair(john, blond).
person_hair(fred, dark).
person_hair(harry, dark).
person_hair(julie, blond).
person_hair(susan, blond).
person_hair(mary, dark).
person_hair(anne, dark).
Это таблица с двумя столбцами, если хотите: первый - это человек, второй - описание цвета волос. Слово «брюнетка» обычно используется для описания темноволосой женщины, поэтому мы могли бы добавить правило, которое гласит:
% A brunette is a female with dark hair
brunette(X) :-
female(X),
person_hair(X, dark).
У некоторых людей есть золото, и владение золотом в нашей программе делает человека богатым:
person_owns(fred, gold).
person_owns(julie, gold).
is_rich(X) :-
%person(X),
person_owns(X, gold).
В нашей строго гетеросексуальной программе мужчинам нравятся женщины, а женщинам нравятся мужчины:
person_likes(M, F) :-
male(M),
female(F).
person_likes(F, M) :-
female(F),
male(M).
Как вы можете подсчитать, это дает нам 3 x 4 + 4 x 3 = 24 возможных решения для person_likes(A, B)
без каких-либо дополнительных ограничений:
?- bagof(A-B, person_likes(A, B), R), length(R, Len).
R = [john-mary, john-julie, john-susan, john-anne, fred-mary, fred-julie, fred-susan, fred-anne, ... - ...|...],
Len = 24.
Это очень общее правило: оно описывает отношения между свободными переменными, что отличает его, например, от нашего отношения person_owns/2
. Это действительно полезно? Почему нет:
is_heterosexual(H) :-
person(H).
Но это только говорит о том, что каждый человек в нашей программе гетеросексуален; это не позволяет нам вывести правило, согласно которому гетеросексуал - это тот, кому нравится противоположный пол. Может быть, даже лучше переименовать его, чтобы лучше выразить его значение (и я буду использовать конструкцию if-then-else, чтобы показать, как это обычно делается):
opposite_sex(X, Y) :-
( male(X)
-> female(Y)
; female(X)
-> male(Y)
).
Для наших целей это могло быть так же хорошо, как и выше:
opposite_sex(M, F) :-
male(M), female(F).
opposite_sex(F, M) :-
male(M), female(F).
Таким образом, мы можем написать правило person_likes/2
с общим предварительным условием, гласящим, что другой должен быть противоположного пола:
person_likes(X, Y) :-
opposite_sex(X, Y),
fits_personal_taste(X, Y).
Теперь мы можем устанавливать правила для личных вкусов каждого человека. Для Джули:
fits_personal_taste(julie, X) :-
is_rich(X),
person_hair(X, dark).
Однако это создает небольшую проблему. Вы должны убедиться, что для каждого человека, о котором знает программа, существует правило в этой форме. Мы не знаем каких-либо предпочтений для Анны, поэтому у нас должно быть правило:
% Anyone (male) would fit Anne's tastes
fits_personal_taste(anne, _).
Было бы лучше, если бы вместо этого у нас была таблица с записями для каждого человека, у которого есть есть предпочтения, например:
person_preferences(julie, [is_rich, person_hair(dark)]).
person_preferences(harry, [is_rich]).
% and so on
Это позволило бы нам написать fits_personal_taste/2
что-то вроде этого:
fits_personal_taste(X, Y) :-
( person_preferences(X, Ps)
-> maplist(fits_preference(Y), Ps)
; true
).
Это предполагаемое использование конструкции if-else в Прологе: исключающее ИЛИ.
Если у человека есть предпочтения, проверьте, подходит ли кандидат им всем; в противном случае - успешно.
Но как бы fits_preference/2
выглядело? В качестве первого аргумента он принимает человека, термин с предпочтением во втором, и должен как-то проверять, удовлетворяется ли это предпочтение для этого человека. Одним из хакерских решений было бы использовать так называемый оператор Univ =..
, чтобы взять член в форме person_hair(Color)
, создать член в форме person_hair(Person, Color)
и назвать его:
fits_preference(Person, Preference) :-
Preference =.. [F|Args],
Preference1 =.. [F,Person|Args],
call(Preference1).
Может быть, лучше, если person_preferences
будет напрямую сопоставлять человека с вызываемыми терминами:
person_preferences(julie, P, [is_rich(P), person_hair(P, dark)]).
person_preferences(harry, P, [is_rich(P)]).
% and so on
При этом fits_personal_taste/2
становится:
fits_personal_taste(X, Y) :-
( person_preferences(X, Y, Ps)
-> maplist(call, Ps)
; true
).
Когда person_preferences/3
вызывается в части условия оператора, каждое предпочтение в списке предпочтений привязано к конкретному человеку; Затем мы звоним каждому, чтобы проверить, можно ли доказать, что это соответствует действительности в нашей программе.
Наконец, вспомогательный предикат possible_pair/2
, который утверждает, что оба человека должны нравиться друг другу:
possible_pair(X, Y) :-
person_likes(X, Y),
person_likes(Y, X),
X @< Y.
Последняя строка гарантирует, что мы не получим одну и ту же пару дважды, постулируя, что эти два человека должны быть в строгом порядке.
Таким образом я получаю:
?- bagof(A-B, possible_pair(A, B), R).
R = [fred-mary, anne-fred].
Или, для списка однонаправленных лайков,
?- bagof(A-B, person_likes(A, B), R), write(R).
[john-julie,fred-mary,fred-anne,harry-julie,susan-john,anne-john,mary-fred,julie-fred,susan-fred,anne-fred,mary-harry,susan-harry,anne-harry]
R = [john-julie, fred-mary, fred-anne, harry-julie, susan-john, anne-john, mary-fred, julie-fred, ... - ...|...].
person
Community
schedule
21.07.2015