prolog - Flujos de trabajo de expansión de plazos
logtalk (1)
Estoy agregando soporte de biblioteca para flujos de trabajo de expansión de términos comunes (1). Actualmente, he definido un flujo de trabajo "set", donde se prueban conjuntos de reglas de expansión de términos (2) hasta que uno de ellos tiene éxito, y un flujo de trabajo "pipeline", donde los resultados de expansión de un conjunto de reglas de expansión de términos se pasan a el siguiente conjunto en la tubería. Me pregunto si hay otros flujos de trabajo razonables de expansión de términos que, aunque sean menos comunes, tengan usos prácticos y, por lo tanto, aún valgan la asistencia de la biblioteca.
(1) Para Logtalk, las versiones actuales se pueden encontrar en:
https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/hook_pipeline.lgt https://github.com/LogtalkDotOrg/logtalk3/blob/master/library/hook_set.lgt
(2) Un conjunto de reglas de expansión se debe entender en este contexto como un conjunto de cláusulas para el term_expansion/2
definido por el term_expansion/2
(también posiblemente el goal_expansion/2
definido por el usuario goal_expansion/2
, aunque esto es menos probable dada la semántica de punto fijo utilizada para la expansión de objetivos) definida en un módulo de Prolog o un objeto de Logtalk (que no sea el pseudo-módulo / objeto del user
).
El punto fijo ya es un conjunto y una canalización en un cierto nivel durante la expansión. Su expand_term / 2 es solo el cierre transitivo de las cláusulas término_expansión / 2 de un paso. Pero esto solo funciona durante el desvío a un término, en mi opinión, también necesitamos algo al reunir el término nuevamente.
En casos raros, este cierre transitivo incluso necesita el control (==) / 2 como se encuentra en algunos sistemas Prolog. Lo más probable es que simplemente se detenga si ninguno de los términos_expansiones / 2 hace algo. Entonces, básicamente, sin la comprobación (==) / 2:
expand_term(X, Y) :- term_expansion(X, H), !, expand_term(H, Y).
expand_term(.. ..) :- /* possibly decend into meta predicate */
Pero lo que me gustaría ver es una especie de marco de simplificación agregado al marco de expansión. Entonces cuando descendemos a un meta predicado y regresemos, deberíamos llamar un gancho de simplificación.
Está de acuerdo con algunas teorías de reescritura de términos, que dicen: la forma normal (nf) de un compuesto es una función de la forma normal de sus partes. El marco de expansión, por lo tanto, no se ocuparía de las formas normales, solo ofrecería redefiniciones de los predicados, pero el marco de simplificación haría el trabajo de forma normal:
nf(f(t_1,..,t_n)) --> f''(nf(t_1),..nf(t_n))
Entonces, el gancho de simplificación tomaría f(nf(t_1), .., nf(t_n))
, suponiendo que expand_term al descennding en un meta predicado produce ya nf(t_1)
... nf(t_n)
para los meta argumentos, y luego simplemente dé f(nf(t_1), .., nf(t_n))
al simplificador.
El simplificador devolvería f''(nf(t_1), .., nf(t_n))
, es decir, haría su trabajo y devolvería una forma simplificada, basándose en la suposición de que los argumentos ya están simplificados. Tal simplificador puede ser bastante poderoso. Jekejeke Prolog ofrece una etapa tras otra.
El simplificador Jekejeke Prolog y su integración en el marco de expansión es de código abierto aquí y aquí . Se usa, por ejemplo, para reordenar la conjunción, aquí están las reglas de ejemplo para este propósito:
/* Predefined Simplifications */
sys_goal_simplification(( ( A, B), C), J) :-
sys_simplify_goal(( B, C), H),
sys_simplify_goal(( A, H), J).
Example:
(((a, b), c), d) --> (a, (b, (c, d)))
El simplificador Jekejeke Prolog es extremadamente eficiente, ya que puede funcionar con la suposición de que recibe términos ya normalizados. No innecesariamente repetirá la coincidencia de patrones durante todo el término dado.
Pero necesita alguna práctica común del sistema de reescritura para escribir reglas de simplicidad. Una regla de simplificación debería llamar simplificación cuando construya un nuevo término.
En el ejemplo anterior, estas son las dos llamadas sys_simplify_goal/2
, por ejemplo, no simplemente devolvemos un nuevo término con (B,C)
en él, como haría una regla de expansión. Dado que (B,C)
no formaba parte de los argumentos normalizados para sys_goal_simplification/2
, primero debemos normalizarlo.
Pero dado que el marco del simplificador está entrelazado con el marco de expansión, dudo que pueda llamarse arquitectura de flujo de trabajo. No hay una dirección de flujo específica, el resultado es más bien un ping pong. Sin embargo, el marco de simplfication se puede usar de forma modular.
El simplificador Jekejeke Prolog también se usa en la reescritura de la cláusula de encadenamiento directo. Allí genera a partir de una cláusula forward múltiples cláusulas de computación delta.
Adiós