Вопрос

Я должен смоделировать генеалогическое древо в prolog.И у меня есть проблема с симметричными предикатами.Факты:

parent(x,y).
male(x).
female(y).
age(x, number).

Правила:

blood_relation у меня от этого болит голова.это то, что я сделал:

blood_relation(X,Y):-ancestor(X,Y).
blood_relation(X,Y):-uncle(X,Y);brother(X,Y);sister(X,Y);(mother(Z,Y),sister(X,Z));(father(Z,Y),sister(X,Z));(father(Z,Y),brother(X,Z)).
blood_relation(X,Y):-uncle(X,Z),blood_relation(Z,Y).

и я получаю, я думаю, удовлетворительные результаты (у меня двойные отпечатки - могу ли я это исправить), проблема в том, что я хочу, чтобы это отношение было симметричным.Это не сейчас.

blood_relation(johns_father, joh):yes 
blood_relation(john,johns_father): no

so..is есть способ это исправить.И мне нужен запрос:Все пары, которые не находятся в blood_relation..

Обновить:

Каким типам отношений должно удовлетворять первое утверждение?blood_relation(X,Y):-blood_relation(X,Y).

sorry..it это плохое копирование / вставка .. это

blood_relation(X,Y):-ancestor(X,Y).

Теперь исправлено выше.

вот другие правила:

father(X,Y):-parent(X,Y),male(X).  
mother(X,Y):-parent(X,Y),female(X).  
brother(X,Y):-parent(Z,X),parent(Z,Y),male(X).  
sister(X,Y):-parent(Z,X),parent(Z,Y),female(X).  
grandFather(X,Y):-parent(Z,Y),parent(X,Z),male(X).  
grandMother(X,Y):-parent(Z,Y),parent(X,Z),female(X).  
uncle(X,Y):-mother(Z,Y),brother(X,Z).  
ancestor(X,Y):-ancestor(X,Y).  
ancestor(X,Y):-parent(X,Z),ancestor(Z,Y).

Брат матери находится в определении дяди.Это немного странно.У меня есть правила, которые мне нужно реализовать, и я не знаю, как я могу реализовать правила помимо этого.Я просто в замешательстве.

Есть идеи, как сделать blood_relation симметричный?И not_blood_relation это новое правило.И мне нужен запрос.От этого у меня действительно болит голова.Может быть, потому, что relation написано как дерьмо.

И больше никаких фактов нет.Вот и все.Все правила и все факты.

запрос.. not(blood_relation(X,Y)) не работает, и я действительно не знаю почему.Например, запрос:

age(X,Y), Y>18,  
not(parent(X,Z)),write(X),nl,fail.

работает просто отлично

Это было полезно?

Решение

Немного похоже на домашнее задание, не так ли?..

Один из трюков, о котором большинство новичков в prolog не задумываются, - это сопоставление списка с шаблоном.Подумайте о дереве типа [a1,[[a2], [b2, [[e3], [f3]]],[c2]]] как в <tree>=[корень,[<tree1>,<tree2>,...]]:

%Y is immediate child of X?
child(X,Y,[X|S]) :- member([Y|_],S).

%pick one tree in S and check
child(X,Y,[X|S]) :- member([Z|SS],S),child(Z,Y,[Z|SS]).

%X and Y end up with same root?
sib(X,Y,[R|T]) :- child(R,X,[R|T]), child(R,Y,[R|T]).

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

Другие советы

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

Вот некоторые факты, подробно описывающие дружеские отношения (где, скажем, цифры являются идентификаторами пользователей, а конкретный порядок аргументов был задан тем, кто инициировал дружбу).

friends(1,2).
friends(5,2).
friends(7,4).

Изначально вы могли бы подумать, что такое правило, как "friends(A,B) :- friends(B,A)." исправил бы все правильно, но это приводит вас к бесконечной рекурсии, потому что это сообщает prolog, что если он просто поменяет местами аргумент еще раз, это может просто сработать.Существует предикат , называемый "@</2" это говорит вам, стоит ли один термин (даже переменная) перед другим в "стандартном порядке терминов".Техническое значение здесь не так уж важно, но что нас волнует, так это то, что для двух разных терминов это верно только для одного их порядка.Мы можем использовать это, чтобы прервать бесконечную рекурсию!

Это единственное правило позаботится о том, чтобы "friend/2" симметричный.

friends(A,B) :- A @< B, friends(B,A).

Каким бы аккуратным это ни было, существует подход, которым вы следует берите для больших проектов.Напомним, что порядок аргументов в моем списке фактов имел некоторое реальное значение (кто инициировал дружбу).Добавление последнего правила уничтожило будущий доступ к этой информации и для других людей, читающих код, скрыло свойство symmetric в одной строке кода, которое легко проигнорировать перед лицом блока жестко закодированных данных.

Рассмотрим решение промышленной прочности:

friended(1,2).
friended(5,2).
friended(7,4).

friends(A,B) :- friended(A,B).
friends(A,B) :- friended(B,A).

Он более объемный, но читается чисто, без использования непонятных предикатов, и сохраняет исходную информацию (которая вам может понадобиться когда-нибудь снова в реальном приложении).

--

Что касается поиска пар, которые не надо обладая определенным свойством, убедитесь, что вы всегда включаете какой-либо предикат для обеспечения контекста в свое правило, когда используете отрицание для поиска реальных пользователей.

potential_enemies(A,B) :- user(A), user(B), \+ friends(A,B).

Каким типам отношений должно удовлетворять первое утверждение?

blood_relation(X,Y):-blood_relation(X,Y).

Это не говорит вам ничего такого, чего вы еще не "знаете", и вызовет у вас головную боль от рекурсии.Что касается ответа "нет", похоже, что вы уже получили все ответы из запроса, которые собираетесь получить, и интерпретатор просто сообщает вам, что их больше нет.

Вам действительно следует опубликовать больше фактов и определение дяди / 2, и есть ли причина, по которой вы подходите не к брату матери, а только к ее сестре?У вас есть много других проблем, над которыми нужно поработать :-).

Для всего, что не является кровным родственником, попробуйте это:

not_blood_relation(X, Y) :- blood_relation(X, Y), !, fail.
not_blood_relation(X, Y).

И спросите себя, почему это работает!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top