sistema - manual de prolog
Variables atribuidas: interfaces de biblioteca/implementaciones/portabilidad (4)
Cuando estaba hojeando algunas preguntas relacionadas con Prolog recientemente, tropecé con esta respuesta de @mat para preguntar Cómo representar el gráfico cíclico dirigido en Prolog con acceso directo a las verticidades vecinas .
Hasta ahora, mi experiencia personal con variables atribuidas en Prolog ha sido muy limitada. Pero el caso de uso dado por @mat despertó mi interés. Así que traté de usarlo para responder a otra pregunta, ordenando listas con programación de lógica de restricción .
Primero, la buena noticia: mi primer uso de las variables atribuidas funcionó como yo quería.
Luego, las noticias no tan buenas: cuando publiqué por respuesta, me di cuenta de que había varias API e implementaciones para las variables atribuidas en Prolog.
Siento que estoy por encima de mi cabeza aquí ... En particular, quiero saber lo siguiente:
- ¿Qué API son de amplio uso? Hasta ahora, encontré dos: SICStus y SWI.
- ¿Qué características ofrecen las diferentes implementaciones de variables atribuidas? ¿Los mismos? ¿O uno subsume al otro?
- ¿Hay diferencias en semántica?
- ¿Qué hay de la implementación real? ¿Son algunos más eficientes que otros?
- ¿Puede (o es) usar variables atribuidas un problema de portabilidad?
Muchos signos de interrogación, aquí ... ¿Comparte tu experiencia / postura? ¡Gracias de antemano!
Editar 2015-04-22
Aquí hay un fragmento de código de la respuesta mencionada anteriormente:
init_att_var(X,Z) :-
put_attr(Z,value,X).
get_att_value(Var,Value) :-
get_attr(Var,value,Value).
Hasta ahora, "solo" uso put_attr/3
y get_attr/3
, pero --- de acuerdo con la documentación de SICStus Prolog sobre variables atribuidas --- SICStus ofrece put_attr/2
y get_attr/2
.
Así que incluso este caso de uso muy superficial requiere alguna capa de emulación (de una forma u otra).
Una perspectiva adicional sobre las bibliotecas de variables atribuidas es cuántos atributos se pueden definir por módulo. En el caso de SWI-Prolog / YAP y citando la documentación de SWI:
Cada atributo está asociado a un módulo, y el
attr_unify_hook/2
(attr_unify_hook/2
) se ejecuta en este módulo.
Esta es una limitación grave para los implementadores de bibliotecas, como CLP (FD), ya que obliga a utilizar módulos adicionales con el único propósito de tener múltiples atributos en lugar de poder definir tantos atributos como sea necesario en el módulo que implementa su biblioteca. Esta limitación no existe en la interfaz SICStus Prolog, que proporciona un attribute/1
directiva attribute/1
que permite la declaración de un número arbitrario de atributos por módulo.
Puede encontrar una de las implementaciones más antiguas y más elaboradas de variables atribuidas en ECLiPSe , donde forma parte de la infraestructura más amplia para implementar solucionadores de restricciones.
Las principales características de este diseño son:
- atributos deben ser declarados, y a cambio el compilador admite un acceso eficiente
- una sintaxis para las variables atribuidas, para que puedan leerse y escribirse
- un conjunto más completo de manejadores para las operaciones de atributos, de modo que los atributos no solo se tengan en cuenta para la unificación, sino también para otras operaciones genéricas como la copia de términos y las pruebas de subsunción
- una separación clara entre los conceptos de atributo variable y objetivos suspendidos
- utilizado en más de una docena de bibliotecas de ECLiPSe
Este documento (sección 4) y la documentación de ECLiPSe tienen más detalles.
Me gustaría centrarme en un punto general importante que noté al trabajar con diferentes interfaces para variables de atributos: Al diseñar una interfaz para variables atribuidas, un implementador también debe tener en cuenta lo siguiente:
- ¿Es posible tener en cuenta los atributos al razonar sobre unificaciones simultáneas , como en
[X,Y] = [0,1]
?
Esto es posible, por ejemplo, en SICStus Prolog, porque tales enlaces se deshacen antes de verify_attributes/3
. En la interfaz proporcionada por hProlog ( attr_unify_hook/2
, llamada después de la unificación y con todos los enlaces ya establecidos) es difícil tener en cuenta los atributos (previos) de Y
al razonar sobre la unificación de X
en attr_unify_hook/2
, porque Y
ya no es una variable en este punto! Esto puede ser suficiente para los solucionadores que pueden tomar decisiones basadas solo en los valores del terreno, pero es una gran limitación para los solucionadores que necesitan datos adicionales, generalmente almacenados en atributos, para ver si una unificación debería tener éxito y cuáles ya no están disponibles. . Un ejemplo obvio: unificación booleana con diagramas de decisión.
A partir de 2016, la rama de atributos de verificación de SWI-Prolog también es compatible con verify_attributes/3
, gracias al gran trabajo de implementación de Douglas Miles . La sucursal está lista para ser probada e intenta fusionarse en maestra tan pronto como funcione de manera correcta y eficiente. Para la compatibilidad con hProlog, la rama también admite attr_unify_hook/2
: lo hace reescribiendo dichas definiciones a los verify_attributes/3
más generales verify_attributes/3
en tiempo de compilación.
En lo que verify_attributes/3
al rendimiento, está claro que puede haber un inconveniente para verify_attributes/3
, ya que hacer que verify_attributes/3
varias variables al mismo tiempo puede permitirle ver antes (en attr_unify_hook/2
) que una unificación no puede tener éxito. Sin embargo, con mucho gusto y en cualquier momento cambiaré esta ventaja normalmente despreciable por la confiabilidad mejorada, facilidad de uso y mayor funcionalidad que la interfaz más general le brinda, y que en cualquier caso ya es el comportamiento estándar en SICStus Prolog que está en la parte superior de su generalidad también es uno de los sistemas Prolog más rápidos que existen.
SICStus Prolog también presenta un predicado importante llamado project_attributes/2
: es usado por el toplevel para proyectar restricciones para consultar variables. SWI-Prolog también es compatible con esto en versiones recientes.
También hay una gran ventaja de la interfaz SWI: los objetivos residuales que attribute_goals//1
y por copy_term/3
tanto copy_term/3
dan son siempre una lista . Esto ayuda a los usuarios a evitar el carácter predeterminado en su código y fomenta una interfaz más declarativa, ya que una lista de objetivos de restricción pura no puede contener estructuras de control .
Curiosamente, ninguna interfaz le permite interpretar unificaciones distintas de sintácticamente . Personalmente, creo que hay casos en los que es posible que desee interpretar las unificaciones de forma diferente que sintácticamente, sin embargo, también puede haber buenos argumentos en contra de eso.
Los otros predicados de interfaz para variables atribuidas son en su mayoría fácilmente intercambiables con predicados de contenedor simple para diferentes sistemas.
Jekejeke Minlog tiene variables de atributos delgadas o sin estado. Bueno, no exactamente, una variable de atributo puede tener cero, uno o muchos ganchos, que pueden ser cierres, y por lo tanto pueden llevar un pequeño estado.
Pero típicamente una implementación administra el estado elsewere. Para este propósito, Jekejeke Minlog permite crear tipos de referencia a partir de variables, de modo que puedan usarse como índices en tablas.
Se libera todo el potencial si esto se combina con el encadenamiento final y / o posterior. Como ejemplo, hemos implementado CLP (FD). También hay un pequeño tutorial de solucionador.
Los ingredientes primitivos en nuestro caso son:
1) Variables de atributo sin estado
2) Teclas finales y variables
3) Cola de continuación
Los ganchos de variables de atributo pueden tener efectos de enlace hasta extender la cola de continuación, pero solo se ejecutan una vez. Los objetivos de la cola de continuación pueden ser no deterministas.
Hay algunas capas adicionales antes de realizar aplicaciones, que son en su mayoría agregaciones de las primitivas para realizar cambios de forma temporal.
Las principales aplicaciones hasta ahora son de código abierto aquí y aquí :
a) Solucionador de restricción de dominio finito
b) Restricciones Herbrand
c) Suspensión de objetivos
Adiós