Pergunta

Eu tenho que árvore genealógica simular no prólogo. E eu tenho problema de predicados simétricas. Factos:

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

Regras:

blood_relation está me dando dor de cabeça. isto é o que eu fiz:

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

e eu estou começando eu acho resultados satisfatórios (i têm estampas duplas - posso corrigir isso), problema é que eu quero que essa relação ser simétrico. Não é agora.

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

so..is Existe uma maneira de corrigir isso. E eu preciso de consulta: Todos os pares que não estão em blood_relation ..

Update:

Que tipos de relacionamentos é a primeira declaração deveria satisfazer? blood_relation (X, Y): -. blood_relation (X, Y)

sorry..it é uma cópia ruim / paste..it

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

Agora fixo acima.

aqui estão outras regras:

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

irmão da mãe está em definição tio. É meio estranho. Eu tenho regras que eu preciso para implementar, e eu não sei como eu pode implementar regras além disso. Eu só estou confuso.

Qualquer idéia de como fazer blood_relation simétrica? E not_blood_relation é uma nova regra. E eu preciso de consulta. Este é realmente me dando dor de cabeça. Talvez porque relação é escrito como lixo.

E não há mais fatos. Isso é tudo. Todas as regras e todos os fatos.

consulta .. not(blood_relation(X,Y)) não funcionar, e eu realmente não sei por que. Por exemplo consulta:

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

funciona muito bem

Foi útil?

Solução

Um pouco parece um dever de casa, não é ...

Um truque que a maioria dos iniciantes de prólogo não pensar é a lista padrão de correspondência. Pense em uma árvore como [a1, [[a2], [b2, [[E3], [F3]]], [c2]]] como em <tree> = [root, [<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]).

Eu acho que você pode melhorar em cima deste tipo, usando pares como raízes, acrescentando sexos, dando nomes às relações específicas de membros da árvore ...

Outras dicas

A solução ingênua de fazer uma simétrica predicado particular não é que, longe de um decente. Por uma questão de generalidade, vamos olhar para uma relação de amizade para que as pessoas não tropeçar em tios e similares.

Aqui estão alguns fatos detalhando uma relação de amizade (onde, por exemplo, os números são IDs de usuário e a ordem particular dos argumentos veio de quem iniciou a amizade).

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

Você iria pensar inicialmente uma regra como "friends(A,B) :- friends(B,A)." iria corrigir as coisas direito, mas Isso leva você a recursividade infinita porque diz prólogo que, se ele simplesmente troca o argumento mais uma vez que só poderia trabalhar. Há um predicado chamado "@</2" que indica se um prazo (até mesmo uma variável) vem antes de outra na "ordem padrão de termos". O significado técnico não é tão importante aqui, mas o que importa é que por dois termos diferentes que só é verdade para uma ordenação deles. Podemos usar isso para quebrar a recursividade infinita!

Esta única regra vai cuidar de fazer "friend/2" simétrica.

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

Como puro como este é, há uma maneira abordagem que você deve levar para grandes projetos. Lembre-se que a ordem dos argumentos na minha lista de fatos tinha algum significado real (que iniciou a amizade). Adicionando a regra destruiu o futuro acesso final a esta informação e, para outras pessoas que lêem o código, esconde a propriedade simétrica em uma única linha de código que é fácil ignorar em face de um bloco de dados codificados.

condsider a solução de força industrial:

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

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

É mais volumoso, mas ele lê de forma limpa sem o uso de predicados obscuros e retém a informação original (que você pode querer de novo algum dia em uma aplicação real).

-

Como para encontrar pares que não tem uma propriedade específica, certifique-se sempre incluir algum predicado para fornecer o contexto em sua regra quando você usa a negação de olhar para os indivíduos reais.

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

Que tipos de relacionamentos é a primeira declaração supostamente para satisfazer?

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

Isso não está dizendo nada que você ainda não "sabe" e vai causar-lhe dores de cabeça de recursão. Quanto à resposta 'não', é Parece que você já tenha obtido todas as respostas da consulta que você está indo para chegar, e o intérprete está apenas dizendo a você que não há mais nada.

Você realmente deve postar mais fatos, e a definição de tio / 2, e há uma razão por que você não está combinando irmão de uma mãe, apenas sua irmã? Você tem muitas outras questões para os trabalhos sobre: ??-)

.

Para tudo o que não é uma relação de sangue, tente o seguinte:

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

E se perguntar por que ela funciona!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top