Prolog - predicados symetrical
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
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!