Prólogo: una persona es un hermano de sí mismo?

Tengo problemas para entender por qué mi código en prolog hace algo basado en el orden en el que puse mis reglas.

Aquí está mi base de datos:

parent(tom, bob). parent(tom, liz). parent(mary, bob). parent(mary, liz). male(tom). male(bob). female(mary). female(liz). 

Y aquí están las reglas:

 %difference(X, Y) ==> Predicate to check if two people X and Y are not the same person. difference(X, Y) :- \==(X, Y). father(X, Y) :- male(X), parent(X, Y), difference(X, Y). mother(X, Y) :- female(X), parent(X, Y), difference(X, Y). sibling(X, Y) :- difference(X, Y), mother(M, X), mother(M, Y), father(F, X), father(F, Y). 

El problema es que cuando hago esto,

 ?- sibling(bob, X). 

yo obtengo

 X = bob ; X = liz ; false. 

Pero cuando cambio el orden (puse la diferencia (X, Y) en la última parte)

 sibling(X, Y) :- mother(M, X), mother(M, Y), father(F, X), father(F, Y), difference(X, Y). 

y yo llamo

 ?- sibling(bob, X). 

yo obtengo

 X = liz; false. 

que es lo que quiero

Hasta ahora, solo he visto que el orden de las reglas importa cuando se realiza la recursión. Así que no entiendo cómo Bob todavía es un hermano de sí mismo solo porque primero hice la verificación de diferencia.

¡Gracias por cualquier ayuda!

    Esto se debe a la forma en que funciona la unificación. Si coloca la diferencia primero, los valores de X e Y aún no están unificados a ningún valor. Considera el rastro:

      goal list: [sibling(bob, Z)] goal: sibling(bob, Z). X-> bob, Y -> Z goal list: [difference(bob, Y), mother(M, bob), mother(M, Y), father(F, bob), father(F, Y).] goal: difference(bob, Y) --SUCCESS goal list: [mother(M, bob), mother(M, Y), father(F, bob), father(F, Y).] goal: mother(M, bob) ... 

    Cuando pone la diferencia en la última llamada, tanto X como Y se han unificado y la diferencia fallará si tienen el mismo valor. Luego se producirá un retroceso.

    Use la función de rastreo de su entorno de prólogo para ver qué sucede paso a paso durante la ejecución.

    La razón real de su problema es (\==)/2 dentro de different/2 . Tiene éxito simplemente con demasiada frecuencia. Reemplázalo con dif/2 y obtendrás el comportamiento esperado. dif/2 está disponible en muchos sistemas Prolog como SICStus, YAP, B, SWI. También puede definir una aproximación segura en ISO-Prolog así:

     iso_dif(X, Y) :- X \== Y, ( X \= Y -> true ; throw(error(instantiation_error,iso_dif/2)) ). 

    Ahora, si los argumentos no se han instanciado lo suficiente, obtendrá un Error de instanciación. Prolog aborta el cálculo y dice: ¡No tengo idea! Lo cual es mucho mejor que pretender que tiene una idea, mientras que no tiene ninguna.

    Usando iso_dif/2 aún tendrás que colocarlo al final de la regla. Pero esta vez, Prolog vigilará su uso correcto.

     | ?- iso_dif(a,b). yes | ?- iso_dif([a,_],[b,_]). (8 ms) yes | ?- iso_dif([a,X],[X,b]). yes | ?- iso_dif([a,X],[a,X]). no | ?- iso_dif([a,X],[X,X]). uncaught exception: error(instantiation_error,iso_dif/2)