sencillos reglas predicados operadores listas fuente ejemplos ejemplo conocimiento codigo prolog

reglas - prolog pdf



¿Cómo contar el número de hijos de padres en prolog(sin usar listas) en prolog? (2)

Tengo el siguiente problema. Tengo un cierto número de hechos tales como: padre (jane, dick). padre (michael, dick). Y quiero tener un predicado como: numberofchildren (michael, X) para que si lo llamo así, muestre X = 1.

He buscado en la web y todos ponen a los niños en las listas, ¿hay alguna manera de no usar listas?


Solo puedo ver dos formas de resolver esto.

El primero, que parece más fácil, es obtener todas las soluciones en una lista y contarlas. No estoy seguro de por qué no le gusta esta opción. ¿Estás preocupado por la eficiencia o algo así? ¿O solo una tarea?

El problema es que sin usar un predicado meta-lógico como setof/3 , tendrá que permitir que Prolog vincule los valores de la forma habitual. La única forma de hacer bucles si está dejando que Prolog lo haga es con fallas, como en algo como esto:

numberofchildren(Person, N) :- parent(Person, _), N is N+1.

Esto no va a funcionar sin embargo; primero vas a obtener arguments not sufficiently instantiated . Entonces vas a arreglar eso y obtener algo como esto:

?- numberofchildren(michael, N) N = 1 ; N = 1 ; N = 1 ; no.

La razón es que necesitas que Prolog retroceda si va a revisar los hechos uno por uno, y cada vez que retrocede, desvincula lo que sea que esté vinculado desde el último punto de elección. La única forma que conozco de pasar datos a través de esta barrera es con la tienda dinámica:

:- dynamic(numberofchildrensofar/1). numberofchildren(Person, N) :- asserta(numberofchildrensofar(0)), numberofchildren1(Person), numberofchildrensofar(N), !. numberofchildren1(Person) :- parent(Person, _), retract(numberofchildrensofar(N)), N1 is N + 1, asserta(numberofchildrensofar(N1), !, fail. numberofchildren1(_).

No lo he probado, porque creo que es bastante desagradable, pero probablemente podría funcionar si no lo hace. :)

De todos modos, te recomiendo que tomes la opción de la lista si es posible.


Contar el número de soluciones requiere alguna herramienta lógica adicional (es intrínsecamente no monótono). Aquí una posible solución:

:- dynamic count_solutions_store/1. count_solutions(Goal, N) :- assert(count_solutions_store(0)), repeat, ( call(Goal), retract(count_solutions_store(SoFar)), Updated is SoFar + 1, assert(count_solutions_store(Updated)), fail ; retract(count_solutions_store(T)) ), !, N = T.