Domanda

Ho simulare albero genealogico in Prolog. E ho problema di predicati simmetriche. Fatti:

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

Regole:

blood_relation mi sta dando il mal di testa. questo è quello che ho fatto:

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 sto ottenendo penso risultati soddisfacenti (ho stampe fronte - posso risolvere questo), il problema è che voglio che questo rapporto sia simmetrico. Non è ora.

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

so..is C'è un modo per risolvere questo problema. E ho bisogno di query: Tutte le coppie che non sono in blood_relation ..

Aggiornamento:

  

Che tipo di relazioni è la prima dichiarazione dovrebbe soddisfare?   blood_relation (X, Y): - blood_relation (X, Y)

.

sorry..it è una brutta copia / paste..it

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

Ora fisso sopra.

qui ci sono altre regole:

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

fratello della madre è in definizione zio. E 'un po' strano. Ho regole che ho bisogno di implementare, e non so come posso implementare regole oltre a quello. Sono solo confuso.

Qualsiasi idea di come fare blood_relation simmetrica? E not_blood_relation è una nuova regola. E ho bisogno di query. Questo è davvero mi dà il mal di testa. Forse perché relazione è scritto da schifo.

E non ci sono più fatti. È tutto. Tutte le regole e tutti i fatti.

interrogazione .. not(blood_relation(X,Y)) Non funziona, e davvero non so perché. Per esempio query:

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

funziona bene

È stato utile?

Soluzione

Un po 'si presenta come un lavoro, non è vero ...

Un trucco che la maggior parte dei principianti di Prolog non viene in mente è la lista pattern matching. Pensate ad un albero come [a1, [[a2], [b2, [[E3], [F3]]], [C2]]] come in <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]).

Penso che si può migliorare su questo, come, utilizzando le coppie come radici, l'aggiunta di generi, dando un nome alle specifiche relazioni di membri dell'albero ...

Altri suggerimenti

La soluzione ingenuo fare un particolare simmetrica predicato non è che lontano da una decente. Per motivi di generalità, diamo un'occhiata a un rapporto di amicizia così la gente non ottengono scattato sul zii e simili.

Ecco alcuni fatti che dettagliano un rapporto di amicizia (dove, ad esempio, i numeri sono gli ID utente e la particolare ordinamento degli argomenti è venuto da chi ha avviato l'amicizia).

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

Si potrebbe pensare inizialmente una regola come "friends(A,B) :- friends(B,A)." avrebbe risolto le cose a posto, ma questo porta ad una ricorsione infinita perché racconta prologo che se scambia solo l'argomento ancora una volta potrebbe funzionare. V'è un predicato chiamato "@</2" che vi dice se un termine (anche una variabile) viene prima di un altro in "ordine standard dei termini". Il significato tecnico non è poi così importante, ma ciò che ci preoccupa è che per due termini diversi è vero solo per un ordine di loro. Possiamo usare questo per rompere la ricorsione infinita!

Questa singola regola si prenderà cura di rendere simmetrico "friend/2".

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

Per quanto pulito come questo è, c'è un modo approccio dovrebbe prendere per i grandi progetti. Ricordiamo che l'ordinamento dei args nella mia lista di fatti aveva un significato vero e proprio (che ha avviato l'amicizia). Aggiunta la regola finale distrutto futuro l'accesso a queste informazioni e, per le altre persone che leggono il codice, nasconde la proprietà simmetrica in una sola riga di codice che è facile ignorare a fronte di un blocco di dati hard-coded.

Condsider la soluzione di livello industriale:

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

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

E 'più ingombrante, ma si legge in modo pulito senza usare predicati oscuri e mantiene le informazioni originali (che si potrebbe desiderare di nuovo un giorno in un'applicazione reale).

-

Per quanto riguarda trovando le coppie che non avere una proprietà specifica, assicuratevi di includere sempre qualche predicato per fornire un contesto in regola quando si utilizza la negazione di cercare persone reali.

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

Che tipo di relazioni è la prima dichiarazione dovrebbe soddisfare?

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

Questo non vi dice nulla che già non "conosce" e sta per causare la ricorsione mal di testa. Per quanto riguarda il 'no' risposta, è Sembra che tu abbia già ottenuto tutte le risposte dalla query che si sta per ottenere, e l'interprete è solo dicendo che non ci sono più.

Si dovrebbe pubblicare più fatti, e la definizione di zio / 2, e c'è una ragione per cui non si è corrispondenza il fratello di una madre, proprio sua sorella? Hai un sacco di altre questioni su cui lavorare: -).

Per tutto ciò che non è un rapporto di sangue, provate questo:

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

E chiedetevi perché funziona!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top