Programación lógica - Logic programming

La programación lógica es un paradigma de programación que se basa en gran medida en la lógica formal . Cualquier programa escrito en un lenguaje de programación lógica es un conjunto de oraciones en forma lógica, que expresan hechos y reglas sobre algún dominio de problemas. Las principales familias de lenguajes de programación lógica incluyen Prolog , programación de conjuntos de respuestas (ASP) y Datalog . En todos estos lenguajes, las reglas se escriben en forma de cláusulas :

H :- B1, …, Bn.

y se leen declarativamente como implicaciones lógicas:

H if B1 and … and Bn.

Hse llama la cabeza de la regla y , ..., se llama cuerpo . Los hechos son reglas que no tienen cuerpo y están escritas en forma simplificada: B1Bn

H.

En el caso más simple en el que H,, ..., son todas fórmulas atómicas , estas cláusulas se denominan cláusulas definidas o cláusulas de Horn . Sin embargo, hay muchas extensiones de este caso simple, siendo la más importante el caso en el que las condiciones en el cuerpo de una cláusula también pueden ser negaciones de fórmulas atómicas. Los lenguajes de programación lógica que incluyen esta extensión tienen las capacidades de representación del conocimiento de una lógica no monótona . B1Bn

En ASP y Datalog, los programas lógicos tienen solo una lectura declarativa , y su ejecución se realiza mediante un procedimiento de prueba o generador de modelos cuyo comportamiento no está destinado a ser controlado por el programador. Sin embargo, en la familia de lenguajes Prolog, los programas lógicos también tienen una interpretación procedimental como procedimientos de reducción de objetivos:

resolver H, resolver y ... y resolver .B1Bn

Considere la siguiente cláusula como ejemplo:

fallible(X) :- human(X).

basado en un ejemplo utilizado por Terry Winograd para ilustrar el lenguaje de programación Planner . Como cláusula en un programa lógico, se puede usar como un procedimiento para probar si Xes fallibleprobando si Xes human, y como un procedimiento para encontrar un Xcuál es fallibleal encontrar un Xcuál es human. Incluso los hechos tienen una interpretación procesal. Por ejemplo, la cláusula:

human(socrates).

se puede utilizar como un procedimiento para mostrar que socrateses humany como un procedimiento para encontrar un Xque es human"asignando" socratesa X.

Un programador puede utilizar la lectura declarativa de programas lógicos para verificar su corrección. Además, las técnicas de transformación de programas basadas en lógica también se pueden utilizar para transformar programas lógicos en programas lógicamente equivalentes que son más eficientes. En la familia Prolog de lenguajes de programación lógica, el programador también puede utilizar el comportamiento de resolución de problemas conocido del mecanismo de ejecución para mejorar la eficiencia de los programas.

Historia

El uso de la lógica matemática para representar y ejecutar programas de computadora también es una característica del cálculo lambda , desarrollado por Alonzo Church en la década de 1930. Sin embargo, la primera propuesta para utilizar la forma de lógica clausal para representar programas de computadora fue hecha por Cordell Green . Este utilizó una axiomatización de un subconjunto de LISP , junto con una representación de una relación de entrada-salida, para calcular la relación simulando la ejecución del programa en LISP. Absys de Foster y Elcock , por otro lado, empleó una combinación de ecuaciones y cálculo lambda en un lenguaje de programación asertivo que no impone restricciones al orden en el que se realizan las operaciones.

La programación lógica en su forma actual se remonta a los debates de finales de la década de 1960 y principios de la de 1970 sobre las representaciones declarativas frente a las procedimentales del conocimiento en la inteligencia artificial . Los defensores de las representaciones declarativas trabajaron notablemente en Stanford , asociado con John McCarthy , Bertram Raphael y Cordell Green, y en Edimburgo , con John Alan Robinson (un visitante académico de la Universidad de Syracuse ), Pat Hayes y Robert Kowalski . Los defensores de las representaciones procesales se centraron principalmente en el MIT , bajo el liderazgo de Marvin Minsky y Seymour Papert .

Aunque se basó en los métodos de prueba de la lógica, Planner , desarrollado en el MIT, fue el primer lenguaje que surgió dentro de este paradigma procedimentalista. El planificador presentó la invocación dirigida por patrones de planes de procedimiento a partir de objetivos (es decir, reducción de objetivos o encadenamiento hacia atrás ) y de afirmaciones (es decir , encadenamiento hacia adelante ). La implementación más influyente de Planner fue el subconjunto de Planner, llamado Micro-Planner, implementado por Gerry Sussman , Eugene Charniak y Terry Winograd . Se utilizó para implementar el programa de comprensión del lenguaje natural SHRDLU de Winograd , que fue un hito en ese momento. Para hacer frente a los sistemas de memoria muy limitados en ese momento, Planner utilizó una estructura de control de retroceso de modo que solo se tuviera que almacenar una ruta de cálculo posible a la vez. Planner dio origen a los lenguajes de programación QA-4, Popler, Conniver, QLISP y el lenguaje concurrente Ether.

Hayes y Kowalski en Edimburgo intentaron reconciliar el enfoque declarativo basado en la lógica para la representación del conocimiento con el enfoque procedimental de Planner. Hayes (1973) desarrolló un lenguaje de ecuaciones, Golux, en el que se podían obtener diferentes procedimientos alterando el comportamiento del demostrador de teoremas. Kowalski, por otro lado, desarrolló la resolución SLD , una variante de la resolución SL, y mostró cómo trata las implicaciones como procedimientos de reducción de objetivos. Kowalski colaboró ​​con Colmerauer en Marsella, quien desarrolló estas ideas en el diseño e implementación del lenguaje de programación Prolog .

La Asociación para la Programación Lógica se fundó para promover la Programación Lógica en 1986.

Prolog dio origen a los lenguajes de programación ALF , Fril , Gödel , Mercury , Oz , Ciao , Visual Prolog , XSB y λProlog , así como a una variedad de lenguajes de programación lógica concurrente , lenguajes de programación lógica de restricciones y Datalog .

Conceptos

Lógica y control

La programación lógica puede verse como una deducción controlada. Un concepto importante en la programación lógica es la separación de programas en su componente lógico y su componente de control. Con lenguajes de programación de lógica pura, el componente lógico determina por sí solo las soluciones producidas. El componente de control se puede variar para proporcionar formas alternativas de ejecutar un programa lógico. Esta noción es capturada por el lema

Algoritmo = Lógica + Control

donde "Lógica" representa un programa lógico y "Control" representa diferentes estrategias de demostración de teoremas.

Resolución de problemas

En el caso proposicional simplificado en el que un programa lógico y una meta atómica de nivel superior no contienen variables, el razonamiento hacia atrás determina un árbol y-o , que constituye el espacio de búsqueda para resolver la meta. El objetivo de nivel superior es la raíz del árbol. Dado cualquier nodo en el árbol y cualquier cláusula cuyo encabezado coincida con el nodo, existe un conjunto de nodos secundarios correspondientes a los subobjetivos en el cuerpo de la cláusula. Estos nodos secundarios están agrupados por una "y". Los conjuntos alternativos de hijos correspondientes a formas alternativas de resolver el nodo se agrupan mediante una "o".

Se puede utilizar cualquier estrategia de búsqueda para buscar en este espacio. Prolog utiliza una estrategia de retroceso secuencial, último en entrar, primero en salir, en la que solo se considera una alternativa y un subobjetivo a la vez. También son posibles otras estrategias de búsqueda, como la búsqueda paralela, el retroceso inteligente o la búsqueda del mejor primero para encontrar una solución óptima.

En el caso más general, donde los subobjetivos comparten variables, se pueden utilizar otras estrategias, como elegir el subobjetivo que está más instanciado o que está suficientemente instanciado para que solo se aplique un procedimiento. Tales estrategias se utilizan, por ejemplo, en programación lógica concurrente .

Negación como fracaso

Para la mayoría de las aplicaciones prácticas, así como para las aplicaciones que requieren un razonamiento no monótono en inteligencia artificial, los programas lógicos de cláusula Horn deben extenderse a programas lógicos normales, con condiciones negativas. Una cláusula en un programa lógico normal tiene la forma:

H :- A1, …, An, not B1, …, not Bn.

y se lee declarativamente como una implicación lógica:

H if A1 and … and An and not B1 and … and not Bn.

donde Hy todas las y son fórmulas atómicas. La negación en los literales negativos se conoce comúnmente como " negación como falla ", porque en la mayoría de las implementaciones, se muestra que una condición negativa se cumple al mostrar que la condición positiva no se cumple. Por ejemplo: AiBi not Bi not Bi Bi

canfly(X) :- bird(X), not abnormal(X).
abnormal(X) :- wounded(X).
bird(john).
bird(mary).
wounded(john).

Dado el objetivo de encontrar algo que pueda volar:

:- canfly(X).

hay dos soluciones candidatas, que resuelven el primer subobjetivo bird(X), a saber X = johny X = mary. El segundo subobjetivo not abnormal(john)de la primera solución candidata fracasa, porque wounded(john)tiene éxito y, por tanto, abnormal(john)tiene éxito. Sin embargo, el segundo subobjetivo not abnormal(mary)de la segunda solución candidata tiene éxito, porque wounded(mary)falla y, por lo tanto, abnormal(mary)falla. Por tanto, X = maryes la única solución del gol.

Micro-Planner tenía una construcción, llamada "thnot", que cuando se aplica a una expresión devuelve el valor verdadero si (y solo si) la evaluación de la expresión falla. Normalmente, existe un operador equivalente en las implementaciones modernas de Prolog . Por lo general, se escribe como o , donde hay algún objetivo (propuesta) que el programa debe probar. Este operador difiere de la negación en la lógica de primer orden: una negación como falla cuando la variable se ha vinculado al átomo , pero tiene éxito en todos los demás casos, incluido cuando no está vinculado. Esto hace que el razonamiento de Prolog no sea monótono : siempre falla, mientras que puede tener éxito, vincularse a , dependiendo de si estaba vinculado inicialmente (tenga en cuenta que Prolog estándar ejecuta los objetivos en orden de izquierda a derecha). not(Goal)\+ GoalGoal\+ X == 1X1XX = 1, \+ X == 1\+ X == 1, X = 1X1X

El estado lógico de la negación como fracaso no se resolvió hasta que Keith Clark [1978] mostró que, bajo ciertas condiciones naturales, es una implementación correcta (ya veces completa) de la negación clásica con respecto a la finalización del programa. La finalización equivale aproximadamente a considerar el conjunto de todas las cláusulas del programa con el mismo predicado en el lado izquierdo, digamos

H :- Body1.
H :- Bodyk.

como una definición del predicado

H iff (Body1 or … or Bodyk)

donde "iff" significa "si y solo si". Escribir la terminación también requiere el uso explícito del predicado de igualdad y la inclusión de un conjunto de axiomas apropiados para la igualdad. Sin embargo, la implementación de la negación como fracaso solo necesita las mitades si de las definiciones sin los axiomas de igualdad.

Por ejemplo, la finalización del programa anterior es:

canfly(X) iff bird(X), not abnormal(X).
abnormal(X) iff wounded(X).
bird(X) iff X = john or X = mary.
X = X.
not john = mary.
not mary = john.

La noción de finalización está estrechamente relacionada con la semántica de circunscripción de McCarthy para el razonamiento predeterminado y con la suposición del mundo cerrado .

Como alternativa a la semántica de compleción, la negación como falla también se puede interpretar epistémicamente, como en la semántica del modelo estable de la programación de conjuntos de respuestas . En esta interpretación, no (B i ) significa literalmente que B i no se conoce o no se cree. La interpretación epistémica tiene la ventaja de que se puede combinar muy simplemente con la negación clásica, como en la "programación lógica extendida", para formalizar frases como "no se puede mostrar lo contrario", donde "lo contrario" es la negación clásica y "no se puede mostrar". ser mostrado "es la interpretación epistémica de la negación como fracaso.

Representación del conocimiento

El hecho de que se pueda dar una interpretación procedimental a las cláusulas de Horn y, viceversa, que los procedimientos de reducción de objetivos puedan entenderse como cláusulas de Horn + razonamiento hacia atrás significa que los programas lógicos combinan representaciones declarativas y procedimentales del conocimiento . La inclusión de la negación como falla significa que la programación lógica es una especie de lógica no monótona .

A pesar de su simplicidad en comparación con la lógica clásica, esta combinación de cláusulas de Horn y negación como fracaso ha demostrado ser sorprendentemente expresiva. Por ejemplo, se proporciona una representación natural de las leyes de sentido común de causa y efecto, formalizado por tanto el cálculo de situaciones y cálculo evento . También se ha demostrado que se corresponde con bastante naturalidad con el lenguaje semiformal de la legislación. En particular, Prakken y Sartor atribuyen la representación de la Ley de Nacionalidad Británica como un programa lógico por ser "enormemente influyente para el desarrollo de representaciones computacionales de la legislación, mostrando cómo la programación lógica permite representaciones intuitivamente atractivas que se pueden implementar directamente para generar inferencias automáticas". .

Variantes y ampliaciones

Prólogo

El lenguaje de programación Prolog fue desarrollado en 1972 por Alain Colmerauer . Surgió de una colaboración entre Colmerauer en Marsella y Robert Kowalski en Edimburgo. Colmerauer estaba trabajando en la comprensión del lenguaje natural , usando la lógica para representar la semántica y usando la resolución para responder preguntas. Durante el verano de 1971, Colmerauer y Kowalski descubrieron que la forma clausal de la lógica podría usarse para representar gramáticas formales y que los probadores de teoremas de resolución podrían usarse para analizar. Observaron que algunos probadores de teoremas, como la hiperresolución, se comportan como analizadores sintácticos ascendentes y otros, como la resolución SL (1971), se comportan como analizadores sintácticos descendentes.

Fue en el verano siguiente de 1972 cuando Kowalski, de nuevo trabajando con Colmerauer, desarrolló la interpretación procedimental de las implicaciones. Esta interpretación dual declarativa / procesal más tarde se formalizó en la notación Prolog

H :- B1, …, Bn.

que se puede leer (y utilizar) tanto de forma declarativa como procedimental. También quedó claro que estas cláusulas podrían restringirse a cláusulas positivas o cláusulas de Horn , donde H, , ..., son todas las fórmulas de la lógica de predicados atómicos, y que SL-resolución podrían ser restringidos (y generalizada) a LUSH o SLD-resolución . La interpretación procesal de Kowalski y LUSH se describieron en un memorando de 1973, publicado en 1974. B1Bn

Colmerauer, con Philippe Roussel, utilizó esta interpretación dual de las cláusulas como base de Prolog, que se implementó en el verano y otoño de 1972. El primer programa Prolog, también escrito en 1972 e implementado en Marsella, fue un sistema francés de preguntas y respuestas. . El uso de Prolog como un lenguaje de programación práctico recibió un gran impulso con el desarrollo de un compilador por David Warren en Edimburgo en 1977. Los experimentos demostraron que Edinburgh Prolog podía competir con la velocidad de procesamiento de otros lenguajes de programación simbólicos como Lisp . Edinburgh Prolog se convirtió en el estándar de facto e influyó fuertemente en la definición del estándar ISO Prolog.

Programación lógica abductiva

La programación lógica abductiva es una extensión de la programación lógica normal que permite que algunos predicados, declarados como predicados abducibles, sean "abiertos" o indefinidos. Una cláusula en un programa de lógica abductiva tiene la forma:

H :- B1, …, Bn, A1, …, An.

donde Hes una fórmula atómica que no es abducible, todos son literales cuyos predicados no son abducibles, y son fórmulas atómicas cuyos predicados son abducibles. Los predicados abducibles pueden estar restringidos por restricciones de integridad, que pueden tener la forma: BiAi

false :- L1, …, Ln.

donde son literales arbitrarios (definidos o abducibles, y atómicos o negados). Por ejemplo: Li

canfly(X) :- bird(X), normal(X).
false :- normal(X), wounded(X).
bird(john).
bird(mary).
wounded(john).

donde el predicado normales abducible.

La resolución de problemas se logra derivando hipótesis expresadas en términos de predicados abducibles como soluciones de problemas a resolver. Estos problemas pueden ser observaciones que deben explicarse (como en el razonamiento abductivo clásico ) o metas que deben resolverse (como en la programación lógica normal). Por ejemplo, la hipótesis normal(mary)explica la observación canfly(mary). Además, la misma hipótesis implica la única solución X = marydel objetivo de encontrar algo que pueda volar:

:- canfly(X).

La programación de lógica abductiva se ha utilizado para el diagnóstico de fallas, la planificación, el procesamiento del lenguaje natural y el aprendizaje automático. También se ha utilizado para interpretar la negación como fracaso como una forma de razonamiento abductivo.

Programación metalógica

Debido a que la lógica matemática tiene una larga tradición de distinguir entre el lenguaje de objetos y el metalenguaje, la programación lógica también permite la programación de metanivel . El programa metalogico más simple es el llamado meta-intérprete " vainilla ":

    solve(true).
    solve((A,B)):- solve(A),solve(B).
    solve(A):- clause(A,B),solve(B).

donde verdadero representa una conjunción vacía, y cláusula (A, B) significa que hay una cláusula a nivel de objeto de la forma A: - B.

La programación metalogica permite combinar representaciones a nivel de objeto y metanivel, como en el lenguaje natural. También se puede utilizar para implementar cualquier lógica que se especifique como reglas de inferencia . La metalogic se utiliza en la programación lógica para implementar metaprogramas, que manipulan otros programas, bases de datos, bases de conocimiento o teorías axiomáticas como datos.

Programación lógica de restricciones

La programación lógica de restricciones combina la programación lógica de la cláusula Horn con la resolución de restricciones . Extiende las cláusulas de Horn al permitir que algunos predicados, declarados como predicados de restricción, ocurran como literales en el cuerpo de las cláusulas. Un programa de lógica de restricción es un conjunto de cláusulas de la forma:

H :- C1, …, Cn ◊ B1, …, Bn.

donde Hy todas las fórmulas son atómicas y las restricciones son. Declarativamente, tales cláusulas se leen como implicaciones lógicas ordinarias: BiCi

H if C1 and … and Cn and B1 and … and Bn.

Sin embargo, mientras que los predicados en los encabezados de las cláusulas están definidos por el programa de lógica de restricciones, los predicados en las restricciones están predefinidos por alguna estructura o teoría de la teoría de modelos específica del dominio.

De manera procedimental, los subobjetivos cuyos predicados están definidos por el programa se resuelven mediante la reducción de objetivos, como en la programación lógica ordinaria, pero un solucionador de restricciones específico del dominio verifica si las restricciones son satisfactorias, que implementa la semántica de los predicados de restricciones. Un problema inicial se resuelve reduciéndolo a una conjunción satisfactoria de restricciones.

El siguiente programa de lógica de restricciones representa una base de datos temporal de juguete de la john'shistoria como profesor:

teaches(john, hardware, T) :- 1990  T, T < 1999.
teaches(john, software, T) :- 1999  T, T < 2005.
teaches(john, logic, T) :- 2005  T, T  2012.
rank(john, instructor, T) :- 1990  T, T < 2010.
rank(john, professor, T) :- 2010  T, T < 2014.

Aquí y <están los predicados de restricción, con su semántica prevista habitual. La siguiente cláusula de objetivo consulta la base de datos para averiguar cuándo se johnenseñó logicy fue professor:

:- teaches(john, logic, T), rank(john, professor, T).

La solución es 2010 ≤ T, T ≤ 2012.

La programación de lógica de restricción se ha utilizado para resolver problemas en campos como la ingeniería civil , la ingeniería mecánica , la verificación de circuitos digitales , la programación automatizada de horarios , el control del tráfico aéreo y las finanzas. Está estrechamente relacionado con la programación lógica abductiva .

Programación lógica concurrente

La programación lógica concurrente integra conceptos de programación lógica con programación concurrente . Su desarrollo recibió un gran impulso en la década de 1980 por su elección del lenguaje de programación de sistemas del Proyecto Japonés de Quinta Generación (FGCS) .

Un programa de lógica concurrente es un conjunto de cláusulas Horn protegidas de la forma:

H :- G1, …, Gn | B1, …, Bn.

La conjunción se denomina guardia de la cláusula y es el operador de compromiso. Declarativamente, las cláusulas de Horn protegidas se leen como implicaciones lógicas ordinarias: G1, ... , Gn |

H if G1 and … and Gn and B1 and … and Bn.

Sin embargo, procedimentalmente, cuando hay varias cláusulas cuyas cabezas H coinciden con un objetivo dado, entonces todas las cláusulas se ejecutan en paralelo, verificando si sus guardias se mantienen. Si las protecciones de más de una cláusula se mantienen, entonces se realiza una elección comprometida con una de las cláusulas y la ejecución procede con los subobjetivos de la cláusula elegida. Estos subobjetivos también se pueden ejecutar en paralelo. Por lo tanto, la programación lógica concurrente implementa una forma de "no me importa el no determinismo", en lugar de "no conozco el no determinismo". G1, ... , Gn B1, ..., Bn

Por ejemplo, el siguiente programa de lógica concurrente define un predicado shuffle(Left, Right, Merge) , que se puede usar para mezclar dos listas Lefty Rightcombinarlas en una sola lista Mergeque conserva el orden de las dos listas Lefty Right:

shuffle([], [], []).
shuffle(Left, Right, Merge) :-
    Left = [First | Rest] |
    Merge = [First | ShortMerge],
    shuffle(Rest, Right, ShortMerge).
shuffle(Left, Right, Merge) :-
    Right = [First | Rest] |
    Merge = [First | ShortMerge],
    shuffle(Left, Rest, ShortMerge).

Aquí, []representa la lista vacía y [Head | Tail]representa una lista con el primer elemento Headseguido de list Tail, como en Prolog. (Tenga en cuenta que la primera aparición de | en la segunda y tercera cláusulas es el constructor de listas, mientras que la segunda aparición de | es el operador de compromiso). El programa se puede usar, por ejemplo, para mezclar las listas [ace, queen, king]e [1, 4, 2]invocando la cláusula goal:

shuffle([ace, queen, king], [1, 4, 2], Merge).

El programa generará de forma no determinista una única solución, por ejemplo Merge = [ace, queen, 1, king, 4, 2].

Podría decirse que la programación lógica concurrente se basa en el paso de mensajes, por lo que está sujeta a la misma indeterminación que otros sistemas de paso de mensajes concurrentes, como Actors (consulte Indeterminación en el cálculo concurrente ). Carl Hewitt ha argumentado que la programación lógica concurrente no se basa en la lógica en el sentido de que los pasos computacionales no pueden deducirse lógicamente. Sin embargo, en la programación lógica concurrente, cualquier resultado de un cálculo final es una consecuencia lógica del programa, y ​​cualquier resultado parcial de un cálculo parcial es una consecuencia lógica del programa y del objetivo residual (red de proceso). Por tanto, la indeterminación de los cálculos implica que no se pueden deducir todas las consecuencias lógicas del programa.

Programación de lógica de restricción concurrente

La programación de lógica de restricción concurrente combina la programación de lógica concurrente y la programación de lógica de restricción , utilizando restricciones para controlar la concurrencia. Una cláusula puede contener una protección, que es un conjunto de restricciones que pueden bloquear la aplicabilidad de la cláusula. Cuando se cumplen las garantías de varias cláusulas, la programación lógica de restricción concurrente hace una elección comprometida para usar solo una.

Programación lógica inductiva

La programación lógica inductiva se ocupa de generalizar ejemplos positivos y negativos en el contexto del conocimiento previo : aprendizaje automático de programas lógicos. El trabajo reciente en esta área, combinando programación lógica, aprendizaje y probabilidad, ha dado lugar al nuevo campo del aprendizaje relacional estadístico y la programación lógica inductiva probabilística .

Programación lógica de orden superior

Varios investigadores han ampliado la programación lógica con características de programación de orden superior derivadas de la lógica de orden superior , como las variables de predicado. Dichos lenguajes incluyen las extensiones Prolog HiLog y λProlog .

Programación lógica lineal

Basar la programación lógica dentro de la lógica lineal ha dado como resultado el diseño de lenguajes de programación lógica que son considerablemente más expresivos que los basados ​​en la lógica clásica. Los programas de cláusulas Horn solo pueden representar cambios de estado mediante el cambio de argumentos a predicados. En la programación de lógica lineal, se puede utilizar la lógica lineal ambiental para admitir el cambio de estado. Algunos de los primeros diseños de lenguajes de programación lógica basados ​​en la lógica lineal incluyen LO [Andreoli & Pareschi, 1991], Lolli, ACL y Forum [Miller, 1996]. Forum proporciona una interpretación dirigida a objetivos de toda la lógica lineal.

Programación lógica orientada a objetos

La lógica F amplía la programación lógica con objetos y la sintaxis del marco.

Logtalk amplía el lenguaje de programación Prolog con soporte para objetos, protocolos y otros conceptos de programación orientada a objetos. Es compatible con la mayoría de los sistemas Prolog que cumplen con los estándares como compiladores de backend.

Programación lógica de transacciones

La lógica de transacciones es una extensión de la programación lógica con una teoría lógica de actualizaciones que modifican el estado. Tiene tanto una semántica de teoría de modelos como una de procedimiento. Una implementación de un subconjunto de la lógica de transacción está disponible en el sistema Flora-2 . También hay otros prototipos disponibles .

Ver también

Citas

Fuentes

Introducciones generales

Otras fuentes

Otras lecturas

enlaces externos