prolog arguments clpfd instantiation-error

prolog - Prólogo-Los argumentos no están suficientemente ejemplificados



arguments clpfd (3)

Estoy escribiendo esta respuesta, porque la mejor respuesta fue en un comment de lurker . Quiero que aparezca como una respuesta real.

Su código no funciona, porque está haciendo que R1 is R+1 cuando R no se not_number([X|T], R) instancia en el caso no not_number([X|T], R) . Su caso recursivo se encadena un poco hacia atrás. Quieres hacer esto:

not_number([X|T],R):- not(number(X)), not_number(T,R1), R is R1+1.

Ahora el lado derecho de la unidad se crea una instancia cuando se llama.

Estoy escribiendo un pequeño programa que cuenta cuántos elementos en una lista no son números. Aquí está mi código:

not_number([],0). not_number([X|T],R):- not(number(X)), R1 is R+1, not_number(T,R1). not_number([_|Tail],Result):- not_number(Tail,Result).

Si ejecuto código como este:

?- not_number([1,2,3,5], R).

Estoy obteniendo que R = 0 (como debería ser)

R = 0.

Pero si pongo un personaje en la lista:

?- not_number([1,2,3,5,a], R).

entonces estoy recibiendo este error:

ERROR: not_number/2: Arguments are not sufficiently instantiated Exception: (10) not_number([a], _G247) ?

¿Puede alguien explicar qué está mal con el código? Soy nuevo en prólogo.


La solución general a tales problemas es usar restricciones .

Por ejemplo, su programa funciona exactamente como se espera si solo usa clpfd restricciones clpfd . Simplemente reemplace (is)/2 por (#=)/2 para obtener una aritmética de enteros que funcione en todas las direcciones :

:- use_module(library(clpfd)). not_number([],0). not_number([X|T],R):- /+ number(X), R1 #= R+1, not_number(T,R1). not_number([_|Tail],Result):- not_number(Tail,Result).

Consulta de muestra y su resultado:

?- not_number([1,2,3,5], R). R = 0.

Tenga en cuenta también que he cambiado el código para usar el predicado ISO (/+)/1 lugar de not/1 .


Su problema es que en cálculos aritméticos como este:

A es B

Todo en el lado derecho (B) ya tiene que ser conocido. No hay variables allí.

Puedes hacer algo como esto:

not_number(X, Y) :- not_number(X, Y, 0). not_number([], Y, Y). not_number([H|T], Y, Z) :- /+ (number(H)), Z1 is Z+1, not_number(T, Y, Z1). not_number([H|T], Y, Z) :- number(H), not_number(T, Y, Z).

(probado este código ahora, funciona).

Ahora el tercer argumento es un acumulador. Cuenta cuántos no-números hay. Cuando la lista está vacía, este tercer argumento se unifica con el segundo y se convierte en la respuesta correcta.

Prólogo, cuando se le dé la oportunidad, pasará por todas las rutas posibles. Si haces algo como esto:

cat(adam). cat(eve).

y luego preguntar:

?- cat(X).

Podrías obtener ambas respuestas: X = adam y X = eve. También se aplica a su código: observe que cuando el encabezado de la lista no es un número, aún puede hacer esto:

not_number([_|Tail],Result):- not_number(Tail,Result).

Lo que no da la respuesta que te gustaría. Tienes que cortar las rutas que no te interesan. En este caso, yo añadiría

number(Head).

para asegurarnos de que omitimos un elemento en una lista sin aumentar el contador en 1 solo cuando este elemento no es un número.

Para hacer que Prolog encuentre otros resultados, debe presionar ";" en su teclado (como en este ejemplo de adam y eve).