La notación sucesora del Prolog produce un resultado incompleto y un bucle infinito


Empiezo a aprender Prolog y primero aprendí sobre la notación sucesora.

Y aquí es donde me entero de escribir axiomas Peano en Prolog.

Ver página 12 del PDF :

sum(0, M, M).
sum(s(N), M, s(K)) :-
    sum(N,M,K).

prod(0,M,0).
prod(s(N), M, P) :-
    prod(N,M,K),
    sum(K,M,P).

Pongo las reglas de multiplicación en Prolog. Entonces hago la consulta:

?- prod(X,Y,s(s(s(s(s(s(0))))))).

Lo que significa encontrar el factor de 6 básicamente.

Aquí están los resultados.

X = s(0),
Y = s(s(s(s(s(s(0)))))) ? ;
X = s(s(0)),
Y = s(s(s(0))) ? ;
X = s(s(s(0))),
Y = s(s(0)) ? ;
infinite loop

Este resultado tiene dos problemas:

  1. No se muestran todos los resultados, tenga en cuenta que el resultado X = 6, Y = 1 falta.
  2. No se detiene a menos que yo Ctrl+C elija abortar.

So... mis preguntas son:

  1. ¿POR qué es eso? Intenté cambiar " prod "y" sum". El código resultante me da todos los resultados. Y de nuevo, ¿por qué es eso? Sin embargo, sigue sin funcionar.
  2. CÓMO resolver eso?

Leí la otra respuesta en bucle infinito. Pero agradecería que alguien respondiera basándose en este escenario. Me ayuda mucho.

Author: false, 2012-04-13

2 answers

Si desea estudiar las propiedades de terminación en profundidad, los programas que utilizan sucesor-aritmética son un objeto de estudio ideal: Usted sabe a priori lo que deben describir, por lo que puede concentrarse en los detalles más técnicos. Usted tendrá que entender varias nociones.

Terminación universal

La forma más fácil de explicarlo, es considerar Goal, false. Esto termina iff Goal termina universalmente. Es decir: Mirar trazadores es el más ineficaz way-te mostrarán una única ruta de ejecución. ¡Pero tienes que entenderlos todos a la vez! Además, nunca mires las respuestas cuando quieres una terminación universal, solo te distraerán. Usted lo ha visto arriba: Usted consiguió tres respuestas ordenadas y correctas, solamente entonces sus bucles del programa. Así que mejor" desactivar " respuestas con false. Esto elimina toda distracción.

Corte de falla

La siguiente noción que necesita es la de un corte de falla . Tome una lógica monótona pura programa y lanza algunos goles false. Si el segmento de falla resultante no termina (universalmente), tampoco lo hará el programa original. En su ejemplo, considere:

prod(0,M,0) :- false.
prod(s(N), M, P) :-
    prod(N,M,K), false,
    sum(K,M,P).

Estos objetivos false ayudan a eliminar adornos irrelevantes en su programa: La parte restante le muestra claramente, por qué prod(X,Y,s(s(s(s(s(s(0))))))). no termina. ¡No termina, porque a ese fragmento no le importa P en absoluto! Usted está esperando que el tercer argumento ayudará a hacer prod/3 terminar, pero el fragmento te muestra que todo es en vano, ya que P no ocurre en ninguna meta. No hay necesidad de rastreadores parlanchines.

A menudo no es tan fácil encontrar cortes de falla mínimos. Pero una vez que encontró uno, es casi trivial determinar sus propiedades de terminación o más bien no terminación. Después de algún tiempo puedes usar tu intuición para imaginar una rebanada, y luego puedes usar tu razón para verificar si esa rebanada es relevante o no.

Lo que es tan notable sobre la noción de un corte de falla es esto: Si desea mejorar el programa, tiene que modificar su programa en la parte visible en el fragmento anterior! Mientras no lo cambies, el problema persistirá. Por lo tanto, un corte de falla es una parte muy relevante de su programa.

Inferencia de terminación

Eso es lo último que necesita: Un inferencer (o analizador) de terminación como cTI le ayudará a identificar la condición de terminación rápidamente. Mira las condiciones de terminación inferidas de prod/3 y la mejora prod2/3 aquí!


Editar: Y ya que esta era una pregunta de tarea no he publicado la solución final. Pero para dejarlo claro, aquí están las condiciones de terminación obtenidas hasta ahora:

    prod(A,B,C)terminates_if b(A),b(B).
    prod2(A,B,C)terminates_if b(A),b(B);b(A),b(C).

Así que el nuevo prod2/3 es estrictamente mejor que el programa original!

Ahora, depende de usted encontrar el programa final. Su condición de terminación es:

   prod3(A,B,C)terminates_if b(A),b(B);b(C).

Para empezar, trate de encontrar el segmento de falla para prod2(A,B,s(s(s(s(s(s(0)))))))! Esperamos que terminar, pero todavía no lo hace. Así que tome el programa y añadir manualmente false objetivos! La parte restante le mostrará la clave!

Como sugerencia final: Necesitas agregar un objetivo extra y un hecho.


Editar: A petición, aquí está el segmento de falla para prod2(A,B,s(s(s(s(s(s(0))))))):

prod2(0,_,0) :- false.
prod2(s(N), M, P) :-
   sum(M, K, P),
   prod2(N,M,K), false.

sum(0, M, M).
sum(s(N), M, s(K)) :- false,
    sum(N,M,K).

Tenga en cuenta la definición significativamente simplificada de sum/3. Sólo dice: 0 más cualquier cosa es cualquier cosa. No más. Como consecuencia, incluso los más especializados prod2(A,0,s(s(s(s(s(s(0))))))) se repetirán mientras queprod2(0,X,Y) elegantemente termina ...

 30
Author: false,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-23 14:22:06

La primera pregunta (POR QUÉ) es bastante fácil de detectar, especialmente si se sabe acerca de recursión izquierda. sum(A,B,C) se une A y B cuando C está enlazado, pero el programa original prod(A,B,C) no usa esas vinculaciones, y en su lugar recurse con still A,B unbound.

Si intercambiamos sum, prod obtenemos 2 enlaces útiles de sum para la llamada recursiva:

sum(M, K, P)

Ahora M está enlazado, y será usado para terminar la recursión izquierda. Podemos intercambiar N y M, porque sabemos que el producto es conmutativo.

sum(0, M, M).
sum(s(N), M, s(K)) :-
    sum(N, M, K).

prod3(0, _, 0).
prod3(s(N), M, P) :-
    sum(M, K, P),
    prod3(M, N, K).

Tenga en cuenta que si intercambiamos M,K (es decir,sum(K,M, P)), cuando se llama a prod3 con P desconocido, nuevamente tenemos un bucle no terminal, pero en suma.

?- prod3(X,Y,s(s(s(s(s(s(0))))))).
X = s(s(s(s(s(s(0)))))),
Y = s(0) ;
X = s(s(s(0))),
Y = s(s(0)) ;
X = s(s(0)),
Y = s(s(s(0))) ;
X = s(0),
Y = s(s(s(s(s(s(0)))))) ;
false.

OT estoy perplejo por el cTI informe: prod3(a,B,C)terminates_if b(A) b(B);b(A) b(C).

 16
Author: CapelliC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-18 17:20:19