Prolog es un lenguaje de programación lógica que tiene sus orígenes en la inteligencia artificial , la demostración automatizada de teoremas y la lingüística computacional . [1] [2] [3]
Prolog tiene sus raíces en la lógica de primer orden , una lógica formal , y a diferencia de muchos otros lenguajes de programación , Prolog está pensado principalmente como un lenguaje de programación declarativo : el programa es un conjunto de hechos y reglas , que definen relaciones . Un cálculo se inicia ejecutando una consulta sobre el programa. [4]
Prolog fue uno de los primeros lenguajes de programación lógica [5] y sigue siendo el más popular en la actualidad, con varias implementaciones gratuitas y comerciales disponibles. El lenguaje se ha utilizado para demostrar teoremas , [6] sistemas expertos , [7] reescritura de términos , [8] sistemas de tipos , [9] y planificación automatizada , [10] así como su campo de uso original previsto, el procesamiento del lenguaje natural . [11] [12]
Prolog es un lenguaje de programación de propósito general, Turing-completo, muy adecuado para aplicaciones de procesamiento de conocimiento inteligente.
En Prolog, la lógica del programa se expresa en términos de relaciones, y un cálculo se inicia ejecutando una consulta sobre estas relaciones. Las relaciones y las consultas se construyen utilizando el tipo de datos único de Prolog, el término . [4] Las relaciones se definen mediante cláusulas . Dada una consulta, el motor Prolog intenta encontrar una refutación de resolución de la consulta negada. Si la consulta negada puede refutarse, es decir, se encuentra una instanciación para todas las variables libres que hace que la unión de cláusulas y el conjunto singleton que consiste en la consulta negada sea falsa, se deduce que la consulta original, con la instanciación encontrada aplicada, es una consecuencia lógica del programa. Esto hace que Prolog (y otros lenguajes de programación lógica) sea particularmente útil para aplicaciones de bases de datos, matemáticas simbólicas y análisis de lenguaje. Debido a que Prolog permite predicados impuros , verificar el valor de verdad de ciertos predicados especiales puede tener algún efecto secundario deliberado , como imprimir un valor en la pantalla. Por este motivo, al programador se le permite utilizar cierta cantidad de programación imperativa convencional cuando el paradigma lógico no le resulta conveniente. Tiene un subconjunto puramente lógico, llamado "Prolog puro", así como una serie de características extralógicas.
El único tipo de datos de Prolog es el término . Los términos pueden ser átomos , números , variables o términos compuestos . [nota 1]
x
, red
, 'Taco'
, 'some atom'
y 'p(a)'
.person_friends(zelda,[tom,jim])
.Casos especiales de términos compuestos:
[]
. Por ejemplo, [1,2,3,4]
o [red,green,blue]
.double_quotes
. Por ejemplo, "to be, or not to be"
. [13]Los programas Prolog describen relaciones, definidas por medio de cláusulas. Prolog puro está restringido a cláusulas Horn . Se utilizan dos tipos de cláusulas Horn para definir programas Prolog: reglas y hechos. Una regla tiene la forma
Cabeza :- Cuerpo .
y se lee como "Head es verdadero si Body es verdadero". El cuerpo de una regla consta de llamadas a predicados, que se denominan objetivos de la regla. El operador lógico integrado (es decir, un operador,/2
de aridad 2 con nombre ) denota conjunción de objetivos y denota disyunción . Las conjunciones y disyunciones solo pueden aparecer en el cuerpo, no en el encabezado de una regla.,
;/2
Las cláusulas con cuerpos vacíos se denominan hechos . Un ejemplo de un hecho es:
humano ( sócrates ).
lo que equivale a la regla:
humano ( sócrates ) :- verdadero .
El predicado incorporado true/0
siempre es verdadero.
Dado el hecho anterior, uno puede preguntarse:
¿Es Sócrates un humano?
?- humano ( sócrates ). Sí
¿Que cosas son los humanos?
?- humano ( X ). X = sócrates
Las cláusulas con cuerpo se denominan reglas . Un ejemplo de regla es:
mortal ( X ) :- humano ( X ).
Si añadimos esa regla y preguntamos ¿qué cosas son mortales?
?- mortal ( X ). X = sócrates
Un predicado (o definición de procedimiento ) es una colección de cláusulas cuyos núcleos tienen el mismo nombre y aridad. Usamos la notación nombre/aridad para referirnos a los predicados. Un programa lógico es un conjunto de predicados. Por ejemplo, el siguiente programa Prolog, que define algunas relaciones de familia, tiene cuatro predicados:
madre_hijo ( trude , sally ).padre_hijo ( tom , sally ). padre_hijo ( tom , erica ). padre_hijo ( mike , tom ).hermano ( X , Y ) :- padre_hijo ( Z , X ), padre_hijo ( Z , Y ).padre_hijo ( X , Y ) :- padre_hijo ( X , Y ). padre_hijo ( X , Y ) :- madre_hija ( X , Y ).
El predicado father_child/2
tiene tres cláusulas, todas las cuales son hechos, y el predicado parent_child/2
tiene dos cláusulas, ambas son reglas.
Debido a la naturaleza relacional de muchos predicados integrados, estos pueden usarse típicamente en varias direcciones. Por ejemplo, length/2
puede usarse para determinar la longitud de una lista ( length(List, L)
, dada una lista List
), y para generar un esqueleto de lista de una longitud dada ( length(X, 5)
), y para generar ambos esqueletos de lista y sus longitudes juntos ( length(X, L)
). De manera similar, append/3
puede usarse tanto para anexar dos listas ( append(ListA, ListB, X)
dadas las listas ListA
y ListB
), como para dividir una lista dada en partes ( append(X, Y, List)
, dada una lista List
). Por esta razón, un conjunto comparativamente pequeño de predicados de biblioteca es suficiente para muchos programas Prolog.
Como lenguaje de propósito general, Prolog también proporciona varios predicados integrados para realizar actividades rutinarias como entrada/salida , uso de gráficos y otras formas de comunicación con el sistema operativo. Estos predicados no tienen un significado relacional y solo son útiles para los efectos secundarios que presentan en el sistema. Por ejemplo, el predicado write/1
muestra un término en la pantalla.
Los algoritmos iterativos se pueden implementar mediante predicados recursivos. [14]
Considere el parent_child/2
predicado definido en el programa de relación familiar anterior. El siguiente programa Prolog define la relación de antecesor :
ancestro ( X , Y ) :- padre_hijo ( X , Y ). ancestro ( X , Y ) :- padre_hijo ( X , Z ), ancestro ( Z , Y ).
Expresa que X es un ancestro de Y si X es padre de Y o X es padre de un ancestro de Y. Es recursivo porque se define en términos de sí mismo (hay una llamada al predicado ancestor/2
en el cuerpo de la segunda cláusula).
La ejecución de un programa Prolog se inicia cuando el usuario envía un único objetivo, denominado consulta. Lógicamente, el motor Prolog intenta encontrar una refutación de la resolución de la consulta negada. El método de resolución utilizado por Prolog se denomina resolución SLD . Si la consulta negada se puede refutar, se deduce que la consulta, con las vinculaciones de variables adecuadas en su lugar, es una consecuencia lógica del programa. En ese caso, se informan al usuario todas las vinculaciones de variables generadas y se dice que la consulta ha tenido éxito. Operativamente, la estrategia de ejecución de Prolog puede considerarse como una generalización de las llamadas de función en otros lenguajes, con la diferencia de que varias cabezas de cláusula pueden coincidir con una llamada dada. En ese caso, el sistema crea un punto de elección, unifica el objetivo con la cabeza de cláusula de la primera alternativa y continúa con los objetivos de esa primera alternativa. Si algún objetivo falla durante la ejecución del programa, se deshacen todas las vinculaciones de variables que se realizaron desde que se creó el punto de elección más reciente y la ejecución continúa con la siguiente alternativa de ese punto de elección. Esta estrategia de ejecución se denomina retroceso cronológico . Por ejemplo, dado el programa de relación familiar definido anteriormente, la siguiente consulta se evaluará como verdadera:
?- Hermanos ( Sally , Erica ). Sí
Esto se obtiene de la siguiente manera: Inicialmente, el único encabezado de cláusula coincidente para la consulta sibling(sally, erica)
es el primero, por lo que probar la consulta es equivalente a probar el cuerpo de esa cláusula con los enlaces de variables apropiados en su lugar, es decir, la conjunción (parent_child(Z,sally), parent_child(Z,erica))
. El siguiente objetivo a probar es el más a la izquierda de esta conjunción, es decir, parent_child(Z, sally)
. Dos encabezados de cláusula coinciden con este objetivo. El sistema crea un punto de elección y prueba la primera alternativa, cuyo cuerpo es father_child(Z, sally)
. Este objetivo se puede probar utilizando el hecho father_child(tom, sally)
, por lo que Z = tom
se genera el enlace y el siguiente objetivo a probar es la segunda parte de la conjunción anterior: parent_child(tom, erica)
. Nuevamente, esto se puede probar con el hecho correspondiente. Dado que todos los objetivos se pueden probar, la consulta tiene éxito. Dado que la consulta no contenía variables, no se informan enlaces al usuario. Una consulta con variables, como:
?- padre_hijo ( Padre , Hijo ).
enumera todas las respuestas válidas al retroceder.
Tenga en cuenta que con el código indicado anteriormente, la consulta ?- sibling(sally, sally).
también se realiza correctamente. Si lo desea, puede insertar objetivos adicionales para describir las restricciones relevantes.
El predicado Prolog incorporado \+/1
proporciona negación como falla , lo que permite un razonamiento no monótono . El objetivo \+ illegal(X)
en la regla
legal ( X ) :- \+ ilegal ( X ).
se evalúa de la siguiente manera: Prolog intenta probar illegal(X)
. Si se puede encontrar una prueba para ese objetivo, el objetivo original (es decir, \+ illegal(X)
) falla. Si no se puede encontrar ninguna prueba, el objetivo original tiene éxito. Por lo tanto, el \+/1
operador de prefijo se llama operador "no demostrable", ya que la consulta ?- \+ Goal.
tiene éxito si el objetivo no es demostrable. Este tipo de negación es sólida si su argumento es "fundamento" (es decir, no contiene variables). La solidez se pierde si el argumento contiene variables y el procedimiento de prueba está completo. En particular, la consulta ?- legal(X).
ahora no se puede utilizar para enumerar todas las cosas que son legales.
En Prolog, cargar código se denomina consultar . Prolog se puede utilizar de forma interactiva introduciendo consultas en el indicador de Prolog ?-
. Si no hay una solución, Prolog escribe no
. Si existe una solución, se imprime. Si hay varias soluciones para la consulta, se pueden solicitar introduciendo un punto y coma ;
. Existen directrices sobre buenas prácticas de programación para mejorar la eficiencia, la legibilidad y la capacidad de mantenimiento del código. [15]
A continuación se muestran algunos programas de ejemplo escritos en Prolog.
Ejemplo de una consulta básica en un par de dialectos populares de Prolog:
Esta comparación muestra que el mensaje ("?-" vs "| ?-") y el estado de resolución ("verdadero" vs "sí", "falso" vs "no") pueden diferir de una implementación de Prolog a otra.
Cualquier cálculo puede expresarse de forma declarativa como una secuencia de transiciones de estado. Por ejemplo, un compilador optimizador con tres pasos de optimización podría implementarse como una relación entre un programa inicial y su forma optimizada:
programa_optimizado ( Prog0 , Prog ) :- optimización_pass_1 ( Prog0 , Prog1 ), optimización_pass_2 ( Prog1 , Prog2 ), optimización_pass_3 ( Prog2 , Prog ).
o equivalentemente utilizando la notación DCG :
programa_optimizado --> paso_optimización_1 , paso_optimización_2 , paso_optimización_3 .
El algoritmo de ordenamiento quicksort , que relaciona una lista con su versión ordenada:
partición ([], _ , [], []). partición ([ X | Xs ], Pivote , Pequeños , Grandes ) :- ( X @< Pivote -> Pequeños = [ X | Resto ], partición ( Xs , Pivote , Resto , Grandes ) ; Grandes = [ X | Resto ], partición ( Xs , Pivote , Pequeños , Resto ) ).ordenación rápida ([]) --> []. ordenación rápida ([ X | Xs ]) --> { partición ( Xs , X , Menor , Mayor ) }, ordenación rápida ( Menor ), [ X ], ordenación rápida ( Mayor ).
Un patrón de diseño es una solución general reutilizable para un problema que ocurre con frecuencia en el diseño de software . Algunos patrones de diseño en Prolog son esqueletos, técnicas, [16] [17] clichés, [18] esquemas de programas, [19] esquemas de descripción lógica, [20] y programación de orden superior . [21]
Un predicado de orden superior es un predicado que toma uno o más predicados como argumentos. Aunque el soporte para programación de orden superior lleva a Prolog fuera del dominio de la lógica de primer orden, que no permite la cuantificación sobre predicados, [22] ISO Prolog ahora tiene algunos predicados de orden superior integrados como call/1
, call/2
, call/3
, findall/3
, setof/3
, y bagof/3
. [23] Además, dado que se pueden construir y evaluar objetivos arbitrarios de Prolog en tiempo de ejecución, es fácil escribir predicados de orden superior como maplist/2
, que aplica un predicado arbitrario a cada miembro de una lista dada, y sublist/3
, que filtra elementos que satisfacen un predicado dado, lo que también permite currar . [21]
Para convertir soluciones de representación temporal (sustituciones de respuestas al volver atrás) a representación espacial (términos), Prolog tiene varios predicados de todas las soluciones que recopilan todas las sustituciones de respuestas de una consulta dada en una lista. Esto se puede utilizar para la comprensión de listas . Por ejemplo, los números perfectos son iguales a la suma de sus divisores propios:
perfecto ( N ) :- entre ( 1 , inf , N ), U es N // 2 , findall ( D , ( entre ( 1 , U , D ), N mod D =:= 0 ), Ds ), listasum ( Ds , N ).
Esto se puede utilizar para enumerar números perfectos y para comprobar si un número es perfecto.
Como otro ejemplo, el predicado maplist
aplica un predicado P
a todas las posiciones correspondientes en un par de listas:
maplist ( _ , [], []). maplist ( P , [ X | Xs ], [ Y | Ys ]) :- llamar ( P , X , Y ), maplist ( P , Xs , Ys ).
Cuando P
es un predicado que para todos X
, P(X,Y)
se unifica Y
con un único valor único, maplist(P, Xs, Ys)
es equivalente a aplicar la función map en programación funcional como Ys = map(Function, Xs)
.
El estilo de programación de orden superior en Prolog fue iniciado en HiLog y λProlog .
Para la programación en grandes sistemas , Prolog proporciona un sistema de módulos , que se encuentra en el estándar ISO. [24] Sin embargo, mientras que la mayoría de los sistemas Prolog admiten la estructuración del código en módulos, prácticamente ninguna implementación se adhiere a la parte de módulos del estándar ISO. En cambio, la mayoría de los sistemas Prolog han decidido admitir como estándar de módulos de facto el sistema de módulos Quintus / SICStus . Sin embargo, algunas implementaciones proporcionan predicados de conveniencia adicionales relacionados con los módulos y, a menudo, tienen diferencias sutiles en su semántica. [25]
Algunos sistemas optan por implementar conceptos de módulos como compilación de fuente a fuente en el Prolog ISO base, como es el caso de Logtalk . [26] GNU Prolog inicialmente se desvió de los módulos ISO, optando en su lugar por la Programación Lógica Contextual, en la que la carga y descarga de unidades (módulos) se puede hacer dinámicamente. [27] Ciao diseñó un sistema de módulos estricto que, si bien es básicamente compatible con el estándar de facto utilizado por otros sistemas Prolog, es susceptible de análisis estático preciso, admite el ocultamiento de términos y facilita la programación a gran escala. [28] XSB adopta un enfoque diferente y ofrece un sistema de módulos basado en átomos . [29] Los dos últimos sistemas Prolog permiten controlar la visibilidad de los términos además de la de los predicados. [25]
Existe una notación especial llamada gramática de cláusulas definidas (DCG, por sus siglas en inglés). Una regla definida mediante -->/2
en lugar de :-/2
se expande por el preprocesador ( expand_term/2
, una función análoga a las macros en otros lenguajes) de acuerdo con unas pocas reglas de reescritura sencillas, lo que da como resultado cláusulas Prolog comunes. En particular, la reescritura equipa al predicado con dos argumentos adicionales, que se pueden usar para enhebrar implícitamente el estado, [ aclaración necesaria ] de manera análoga a las mónadas en otros lenguajes. Las DCG se usan a menudo para escribir analizadores sintácticos o generadores de listas, ya que también proporcionan una interfaz conveniente para las listas de diferencias.
Prolog es un lenguaje homoicónico y ofrece muchas facilidades para la programación reflexiva (reflexión). Su estrategia de ejecución implícita permite escribir un evaluador metacircular conciso (también llamado metaintérprete ) para código Prolog puro:
resolver ( verdadero ). resolver (( Subobjetivo1 , Subobjetivo2 )) :- resolver ( Subobjetivo1 ), resolver ( Subobjetivo2 ). resolver ( Cabeza ) :- cláusula ( Cabeza , Cuerpo ), resolver ( Cuerpo ).
donde true
representa una conjunción vacía y clause(Head, Body)
se unifica con cláusulas en la base de datos de la forma Head :- Body
.
Dado que los programas Prolog son en sí mismos secuencias de términos Prolog ( es un operador:-/2
infijo ) que se leen e inspeccionan fácilmente mediante mecanismos integrados (como ), es posible escribir intérpretes personalizados que aumenten Prolog con características específicas del dominio. Por ejemplo, Sterling y Shapiro presentan un metaintérprete que realiza razonamiento con incertidumbre, reproducido aquí con ligeras modificaciones: [30] : 330 read/1
solve ( true , 1 ) :- !. solve (( Subobjetivo1 , Subobjetivo2 ), Certidumbre ) :- !, solve ( Subobjetivo1 , Certidumbre1 ), solve ( Subobjetivo2 , Certidumbre2 ), Certidumbre es min ( Certidumbre1 , Certidumbre2 ). solve ( Objetivo , 1 ) :- builtin ( Objetivo ), !, Objetivo . solve ( Cabeza , Certidumbre ) :- cláusula_cf ( Cabeza , Cuerpo , Certidumbre1 ), solve ( Cuerpo , Certidumbre2 ), Certidumbre es Certidumbre1 * Certidumbre2 .
Este intérprete utiliza una tabla de predicados Prolog integrados con la forma [30] : 327
incorporado ( A es B ). incorporado ( leer ( X )). % etc.
y cláusulas representadas como clause_cf(Head, Body, Certainty)
. Dados estos, se puede llamar solve(Goal, Certainty)
a ejecutar Goal
y obtener una medida de certeza sobre el resultado.
Prolog puro se basa en un subconjunto de la lógica de predicados de primer orden , las cláusulas de Horn , que es Turing-completa . La completitud de Turing de Prolog se puede demostrar utilizándolo para simular una máquina de Turing:
turing ( Tape0 , Tape ) :- ejecutar ( q0 , [], Ls , Tape0 , Rs ), revertir ( Ls , Ls1 ), agregar ( Ls1 , Rs , Tape ).realizar ( qf , Ls , Ls , Rs , Rs ) :- !. realizar ( Q0 , Ls0 , Ls , Rs0 , Rs ) :- símbolo ( Rs0 , Sym , RsRest ), una vez ( regla ( Q0 , Sym , Q1 , NewSym , Acción )), acción ( Acción , Ls0 , Ls1 , [ NewSym | RsRest ], Rs1 ), realizar ( Q1 , Ls1 , Ls , Rs1 , Rs ).símbolo ([], b , []). símbolo ([ Sym | Rs ], Sym , Rs ).acción ( izquierda , Ls0 , Ls , Rs0 , Rs ) :- izquierda ( Ls0 , Ls , Rs0 , Rs ). acción ( quedarse quieto , Ls , Ls , Rs , Rs ). acción ( derecha , Ls0 , [ Sym | Ls0 ], [ Sym | Rs ], Rs ).izquierda ([], [], Rs0 , [ b | Rs0 ]). izquierda ([ L | Ls ], Ls , Rs , [ L | Rs ]).
Un ejemplo sencillo de máquina de Turing se concreta en los hechos:
regla ( q0 , 1 , q0 , 1 , derecha ). regla ( q0 , b , qf , 1 , quedarse ).
Esta máquina realiza un incremento de uno en uno de un número en codificación unaria: recorre cualquier cantidad de celdas "1" y agrega un "1" adicional al final. Ejemplo de consulta y resultado:
? -turing ([ 1 , 1 , 1 ], Ts ). Ts = [ 1 , 1 , 1 , 1 ] ;
Esto ilustra cómo cualquier cálculo puede expresarse declarativamente como una secuencia de transiciones de estados, implementada en Prolog como una relación entre estados sucesivos de interés.
La norma técnica Prolog de la Organización Internacional de Normalización (ISO) consta de dos partes. La ISO/IEC 13211-1, [23] [31] publicada en 1995, tiene como objetivo estandarizar las prácticas existentes de las numerosas implementaciones de los elementos centrales de Prolog. Ha aclarado aspectos del lenguaje que antes eran ambiguos y conduce a programas portables. Hay tres correcciones: Cor.1:2007, [32] Cor.2:2012, [33] y Cor.3:2017. [34] La ISO/IEC 13211-2, [23] publicada en 2000, añade soporte para módulos a la norma. La norma es mantenida por el grupo de trabajo ISO/IEC JTC1 / SC22 /WG17 [35] . ANSI X3J17 es el grupo asesor técnico de EE. UU. para la norma. [36]
Para lograr una mayor eficiencia, el código Prolog se compila normalmente en código de máquina abstracto, a menudo influenciado por el conjunto de instrucciones de la máquina abstracta de Warren (WAM) basada en registros. [37] Algunas implementaciones emplean una interpretación abstracta para derivar información de tipo y modo de predicados en tiempo de compilación, o compilan en código de máquina real para un alto rendimiento. [38] El diseño de métodos de implementación eficientes para el código Prolog es un campo de investigación activa en la comunidad de programación lógica, y en algunas implementaciones se emplean varios otros métodos de ejecución. Estos incluyen la binarización de cláusulas y las máquinas virtuales basadas en pilas . [ cita requerida ]
Los sistemas Prolog suelen implementar un método de optimización conocido llamado optimización de llamadas de cola (TCO) para predicados deterministas que presentan recursión de cola o, de manera más general, llamadas de cola: el marco de pila de una cláusula se descarta antes de realizar una llamada en una posición de cola. Por lo tanto, los predicados deterministas con recursión de cola se ejecutan con un espacio de pila constante, como los bucles en otros lenguajes.
La búsqueda de cláusulas que se puedan unificar con un término en una consulta es lineal en cuanto al número de cláusulas. La indexación de términos utiliza una estructura de datos que permite búsquedas en tiempo sublineal . [39] La indexación solo afecta el rendimiento del programa, no afecta la semántica. La mayoría de Prologs solo utilizan la indexación en el primer término, ya que la indexación en todos los términos es costosa, pero las técnicas basadas en palabras codificadas en campos o palabras de código superpuestas proporcionan una indexación rápida en toda la consulta y el encabezado. [40] [41]
Algunos sistemas Prolog, como WIN-PROLOG y SWI-Prolog, ahora implementan algoritmos hash para ayudar a manejar conjuntos de datos grandes de manera más eficiente. Esto tiende a producir grandes mejoras de rendimiento cuando se trabaja con corpus grandes como WordNet .
Algunos sistemas Prolog ( B-Prolog , XSB , SWI-Prolog , YAP y Ciao ) implementan un método de memorización llamado tabulación , que libera al usuario de tener que almacenar manualmente los resultados intermedios. La tabulación es una compensación de espacio-tiempo ; el tiempo de ejecución se puede reducir utilizando más memoria para almacenar los resultados intermedios: [42] [43]
Los subobjetivos encontrados en la evaluación de una consulta se mantienen en una tabla, junto con las respuestas a estos subobjetivos. Si se vuelve a encontrar un subobjetivo, la evaluación reutiliza la información de la tabla en lugar de volver a realizar la resolución en relación con las cláusulas del programa. [44]
La tabulación se puede ampliar en varias direcciones. Puede admitir predicados recursivos a través de la resolución SLG o la tabulación lineal. En un sistema Prolog multiproceso, los resultados de la tabulación se pueden mantener privados para un subproceso o compartir entre todos los subprocesos. Y en la tabulación incremental, la tabulación puede reaccionar a los cambios.
Durante el proyecto de Sistemas Informáticos de Quinta Generación , hubo intentos de implementar Prolog en hardware con el objetivo de lograr una ejecución más rápida con arquitecturas dedicadas. [45] [46] [47] Además, Prolog tiene una serie de propiedades que pueden permitir la aceleración a través de la ejecución paralela. [48] Un enfoque más reciente ha sido compilar programas Prolog restringidos en una matriz de puertas programables en campo . [49] Sin embargo, el rápido progreso en hardware de propósito general ha superado constantemente a arquitecturas más especializadas.
Sega implementó Prolog para su uso con Sega AI Computer, lanzado para el mercado japonés en 1986. Prolog se utilizó para leer entradas de lenguaje natural , en el idioma japonés , a través de un panel táctil . [50]
Aunque Prolog se utiliza ampliamente en investigación y educación, [51] Prolog y otros lenguajes de programación lógica no han tenido un impacto significativo en la industria informática en general. [52] La mayoría de las aplicaciones son pequeñas según los estándares industriales, y pocas superan las 100 000 líneas de código. [52] [53] La programación a gran escala se considera compleja porque no todos los compiladores Prolog admiten módulos y existen problemas de compatibilidad entre los sistemas de módulos de los principales compiladores Prolog. [26] La portabilidad del código Prolog entre implementaciones también ha sido un problema, pero los avances desde 2007 han significado que: "la portabilidad dentro de la familia de implementaciones Prolog derivadas de Edinburgh/Quintus es lo suficientemente buena como para permitir el mantenimiento de aplicaciones portátiles en el mundo real". [54]
El software desarrollado en Prolog ha sido criticado por tener una gran pérdida de rendimiento en comparación con los lenguajes de programación convencionales. En particular, la estrategia de evaluación no determinista de Prolog puede ser problemática cuando se programan cálculos deterministas, o incluso cuando se utiliza el "no determinismo sin importancia" (donde se realiza una única elección en lugar de retroceder sobre todas las posibilidades). Es posible que se deban utilizar cortes y otras construcciones del lenguaje para lograr el rendimiento deseado, destruyendo uno de los principales atractivos de Prolog, la capacidad de ejecutar programas "hacia atrás y hacia adelante". [55]
Prolog no es puramente declarativo: debido a construcciones como el operador de corte , se necesita una lectura procedimental de un programa Prolog para comprenderlo. [56] El orden de las cláusulas en un programa Prolog es significativo, ya que la estrategia de ejecución del lenguaje depende de él. [57] Otros lenguajes de programación lógica, como Datalog , son verdaderamente declarativos pero restringen el lenguaje. Como resultado, muchos programas prácticos Prolog se escriben para ajustarse al orden de búsqueda en profundidad de Prolog , en lugar de ser programas lógicos puramente declarativos. [55]
Se han desarrollado varias implementaciones a partir de Prolog para ampliar las capacidades de programación lógica en muchas direcciones. Estas incluyen tipos , modos, programación lógica de restricciones (CLP), programación lógica orientada a objetos (OOLP), concurrencia, lógica lineal (LLP), capacidades de programación lógica funcional y de orden superior , además de interoperabilidad con bases de conocimiento :
Prolog es un lenguaje sin tipos. Los intentos de introducir y ampliar Prolog con tipos comenzaron en la década de 1980, [58] [59] y continúan hasta 2008. [actualizar][ 60] La información de tipos es útil no solo para la seguridad de tipos sino también para razonar sobre los programas Prolog. [61]
La sintaxis de Prolog no especifica qué argumentos de un predicado son entradas y cuáles son salidas. [62] Sin embargo, esta información es importante y se recomienda que se incluya en los comentarios. [63] Los modos proporcionan información valiosa al razonar sobre programas Prolog [61] y también se pueden utilizar para acelerar la ejecución. [64]
La programación lógica de restricciones extiende Prolog para incluir conceptos de satisfacción de restricciones . [65] [66] Un programa de lógica de restricciones permite restricciones en el cuerpo de cláusulas, como: A(X,Y) :- X+Y>0.
Es adecuado para problemas de optimización combinatoria a gran escala [67] y, por lo tanto, es útil para aplicaciones en entornos industriales, como la elaboración de horarios automatizados y la programación de la producción . La mayoría de los sistemas Prolog se entregan con al menos un solucionador de restricciones para dominios finitos y, a menudo, también con solucionadores para otros dominios como los números racionales .
Flora-2 es un sistema de razonamiento y representación de conocimiento orientado a objetos basado en F-logic e incorpora HiLog , lógica de transacciones y razonamiento derrotable .
Logtalk es un lenguaje de programación lógica orientado a objetos que puede utilizar la mayoría de las implementaciones de Prolog como compilador de back-end. Como lenguaje multiparadigma, incluye soporte tanto para prototipos como para clases.
Oblog es una extensión pequeña, portátil y orientada a objetos de Prolog creada por Margaret McDougall de EdCAAD, Universidad de Edimburgo.
Objlog era un lenguaje basado en marcos que combinaba objetos y Prolog II del CNRS, Marsella, Francia.
Prolog++ fue desarrollado por Logic Programming Associates y lanzado por primera vez en 1989 para PC con MS-DOS. Se agregó compatibilidad con otras plataformas y se lanzó una segunda versión en 1995. Addison-Wesley publicó un libro sobre Prolog++ escrito por Chris Moss en 1994.
Visual Prolog es un lenguaje multiparadigma con interfaces, clases, implementaciones y expresiones de objetos.
Los sistemas Prolog que proporcionan una biblioteca de gráficos son SWI-Prolog , [68] Visual Prolog , WIN-PROLOG y B-Prolog .
Prolog-MPI es una extensión SWI-Prolog de código abierto para computación distribuida sobre la interfaz de paso de mensajes . [69] También existen varios lenguajes de programación Prolog concurrentes. [70]
Algunas implementaciones de Prolog, en particular Visual Prolog , SWI-Prolog y Ciao , admiten programación web del lado del servidor con soporte para protocolos web, HTML y XML . [71] También hay extensiones para admitir formatos web semánticos como Resource Description Framework (RDF) y Web Ontology Language (OWL). [72] [73] Prolog también se ha sugerido como un lenguaje del lado del cliente . [74] Además, Visual Prolog admite JSON-RPC y Websockets .
Cedar es un intérprete Prolog básico y gratuito. A partir de la versión 4, Cedar tiene compatibilidad con FCA (Flash Cedar App). Esto proporciona una nueva plataforma para programar en Prolog a través de ActionScript .
Existen marcos que pueden servir de puente entre Prolog y otros lenguajes:
El nombre Prolog fue elegido por Philippe Roussel, por sugerencia de su esposa, como abreviatura de programmation en logique ( en francés, programación en lógica ). [76] Fue creado alrededor de 1972 por Alain Colmerauer con Philippe Roussel, basándose en la interpretación procedimental de las cláusulas de Horn de Robert Kowalski . Fue motivado en parte por el deseo de reconciliar el uso de la lógica como lenguaje de representación de conocimiento declarativo con la representación procedimental del conocimiento que era popular en América del Norte a fines de la década de 1960 y principios de la de 1970. Según Robert Kowalski , el primer sistema Prolog fue desarrollado en 1972 por Colmerauer y Phillipe Roussel. [77] [78] [79] La primera implementación de Prolog fue un intérprete escrito en Fortran por Gerard Battani y Henri Meloni. David HD Warren llevó este intérprete a la Universidad de Edimburgo , donde implementó un front-end alternativo que llegó a definir la sintaxis de "Edinburgh Prolog" utilizada por la mayoría de las implementaciones modernas. Warren también implementó el primer compilador para Prolog, creando el influyente DEC-10 Prolog en colaboración con Fernando Pereira. Warren luego generalizó las ideas detrás de DEC-10 Prolog para crear la Warren Abstract Machine .
Los investigadores europeos de IA favorecieron Prolog mientras que los estadounidenses favorecieron Lisp , lo que al parecer causó muchos debates nacionalistas sobre los méritos de los lenguajes. [80] Gran parte del desarrollo moderno de Prolog provino del impulso del proyecto Fifth Generation Computer Systems (FGCS), que desarrolló una variante de Prolog llamada Kernel Language para su primer sistema operativo .
Originalmente, Prolog puro estaba restringido al uso de un demostrador de teoremas de resolución con cláusulas de Horn de la forma:
B :- B 1 , ..., B n .
La aplicación del demostrador de teoremas trata dichas cláusulas como procedimientos:
para mostrar/resolver H, mostrar/resolver B 1 y ... y B n .
Sin embargo, el Prolog puro pronto se amplió para incluir la negación como fracaso , en el que las condiciones negativas de la forma not(B i ) se muestran al intentar y fallar en la resolución de las condiciones positivas correspondientes B i .
Las extensiones posteriores de Prolog realizadas por el equipo original introdujeron capacidades de programación de lógica de restricciones en las implementaciones.
Prolog se ha utilizado en Watson . Watson utiliza el software DeepQA de IBM y el marco Apache UIMA (Unstructured Information Management Architecture). El sistema fue escrito en varios lenguajes, incluyendo Java, C++ y Prolog, y se ejecuta en el sistema operativo SUSE Linux Enterprise Server 11 utilizando el marco Apache Hadoop para proporcionar computación distribuida. Prolog se utiliza para la coincidencia de patrones sobre árboles de análisis de lenguaje natural. Los desarrolladores han declarado: "Necesitábamos un lenguaje en el que pudiéramos expresar convenientemente reglas de coincidencia de patrones sobre los árboles de análisis y otras anotaciones (como los resultados de reconocimiento de entidades nombradas), y una tecnología que pudiera ejecutar estas reglas de manera muy eficiente. Descubrimos que Prolog era la opción ideal para el lenguaje debido a su simplicidad y expresividad ". [12] Prolog se está utilizando en la plataforma de desarrollo de bajo código GeneXus , que se centra en la IA. [ cita requerida ] La base de datos de gráficos de código abierto TerminusDB se implementa en Prolog. [81] TerminusDB está diseñado para construir y curar de forma colaborativa gráficos de conocimiento .