Martin DAVIS
Courant Institute of Mathematical Sciences
New York University
______________________________________________________________________
El siguiente texto es una traducción parcial de la conferencia que David ofreció con el
título “Influences of Mathematical Logic on Computer Science” en ocasión de los 50
años del célebre artículo de Alan Turing sobre teoría de la computabilidad, “On
Computable Numbers, with an Application to the Entscheidungssproblem”, en 1987.
La traducción castellana es de Facundo García Valverde
______________________________________________________________________
Cuando yo era estudiante, hasta los topólogos consideraban que los lógicos
matemáticos vivían en el espacio exterior. Hoy en día, las conexiones entre la lógica y
la computación son un asunto de práctica ingenieril en cada nivel de la organización
computacional: abundan compañías con nombres como Logical Devices o Logicsoft;
uno puede ingresar en un negocio y pedir “una prueba lógica”. De ninguna manera esto
es sólo una cuestión de términos. Los temas y conceptos que surgieron por primera vez
en las investigaciones técnicas llevadas a cabo por los lógicos están estrechamente
vinculados con muchos aspectos de la Ciencia de la Computación.
¿Hasta qué punto el trabajo previo de los lógicos influyó en los científicos e
ingenieros en computación? ¿Usaron lo ya hecho o simplemente “inventaron la
pólvora” como algo necesario? Lamentablemente, es mucho más sencillo señalar las
confluencias de ideas que trazar rigurosamente un camino desde el trabajo original hasta
sus aplicaciones. Cuando las ideas en cuestión son verdaderamente fundamentales y,
por lo tanto, finalmente simples (del mismo modo en que tantos conceptos
fundamentales resultan serlo) la gente olvida fácilmente lo sorprendente que fueron esas
ideas cuando se enunciaron por primera vez. Tales ideas pueden transformarse de algo
absurdo a una trivialidad en pocos años. En Davis (1987) se discuten extensamente
algunos de estos temas y se relacionan con el rol que jugó el descubrimiento de la
máquina universal de calcular, realizado por Alan Türing, en el desarrollo actual de las
modernas computadoras electrónicas. En este ensayo, seguiremos el camino de un
conjunto de conceptos que surgieron en el trabajo de los lógicos y que encontraron su
lugar en la teoría y práctica computacional.
Sintaxis formal
Una de las primeras cosas que un usuario principiante debe aprender es que la
computadores tienden a ser totalmente implacables con errores “menores” en la
notación. ¿Quién no se ha sentido frustrado al verse obligado a reingresar una larga
línea de texto únicamente porque una coma debía ser un punto? Podríamos afirmar que
los lenguajes de computadoras (lenguajes de programación, sistemas operativos,
sistemas para bases de datos, etc.) tienen una sintaxis formal totalmente prescripta. La
noción de que un lenguaje creado artificialmente podría ser útil para extender el ámbito
2
de lo que podía ser logrado por el cálculo se retrotrae a Leibniz1. Sin embargo, el primer
ejemplo efectivo de un lenguaje formal fue presentado por Gottlob Frege, en su
Begriffsschrift.2
Frege puede ser considerado el fundador del movimiento logicista en la
justificación teórica de la matemática. El logicismo es la tesis según la cual la
matemática y la lógica son literalmente el mismo asunto: todas las entidades que
aparecen en matemática pueden ser tomadas legítimamente como construcciones
puramente lógicas y la prueba matemática es simplemente una deducción lógica. De tal
modo, un logicismo minucioso debería estar preparado para brindar una rigurosa
formulación de la lógica deductiva. Frege contó con los descubrimientos previos de
George Boole acerca de la posibilidad de tratar la deducción lógica como una rama de
las matemáticas. Pero, ¿no es esto caer en un círculo vicioso? Si la lógica es
desarrollada usando la matemática, ¿cómo puede ser ella, a su vez, el fundamento
subyacente para todas las matemáticas?. La solución de Frege a este problema fue la
sintaxis formal. Creó un lenguaje artificial, su Begriffsschrift –literalmente “escritura de
conceptos” o “conceptografía”–, caracterizado como un Formelsparache des reinen
Denken, un “lenguaje formal del puro pensamiento”. En este lenguaje, la deducción es
reemplazada por la derivación formal, la cual depende exclusivamente de la
manipulación simbólica. De tal forma, la circularidad es evitada. El sistema fregeano
terminó siendo formalmente inconsistente –de lo cual el propio Frege se dio cuenta al
recibir la famosa carta de Bertrand Russell que contenía las “paradojas de Russell”– y,
por consiguiente, su programa no fue, ciertamente, un éxito. No obstante, sus logros
fueron muy importantes. Su Begriffsschrift contuvo, por primera vez, una formulación
de lo que luego se denominó lógica de primer orden (LPO). Pero lo que resultó más
importante para las Ciencias de la Computación fue la clara demostración fregeana de
cómo construir y tratar rigurosamente con un lenguaje formal.
Cuán importante fue el trabajo de Frege resulta evidente cuando se lo compara
con el de sus sucesores. Si bien E. Schröder, G. Peano y Bertrand Russel realizaron
importantes contribuciones, sus trabajos, en gran parte realizados durante las primeras
décadas del siglo veinte, carecían del nivel de rigor de Frege. Así, uno puede encontrar
en Bertrand Russell3 una lista de “axiomas” –llamados por él “proposiciones
primitivas”– con expresiones meramente simbólicas como
q→pvq
Frege nunca habría permitido tal confusión entre el lenguaje formal en el que
trabajaba y las afirmaciones en el lenguaje natural acerca de ese lenguaje formal. Esta
misma formulación aparece en Principia Mathematica, el edificio de tres volúmenes
construido por A. Whitehead y Russell como una encarnación de su visión logicista.
La disertación de Emil Post5 marcó una vuelta a los estándares de rigor de Frege.
Sin embargo, el énfasis de Post era bastante diferente. A diferencia de lógicos como
1
ver, p.e. Davis (1987)
2
Frege, 1879
3
Russel, 1908
4
Una proposición implicada por una premisa verdadera es verdadera
5
Post, 1921
3
Desde esta perspectiva, lo interesante del programa logicista es que suponía que el
éxito en el hallazgo de tales algoritmos podría conducir a la mecanización de extensas
partes de la matemática. Post resolvió sólo la primera parte del problema: encontró
algoritmos para la parte de Principia Mathematica que llamamos ahora cálculo
proposicional. Sus esfuerzos para extender esos resultados lo llevaron a considerar
operaciones formales en un contexto más general, a las cuales denominó producciones.
Como sabemos ahora y como el mismo Post se dio cuenta rápidamente, el problema, en
su totalidad, no tiene solución: el problema de hallar un algoritmo de decisión para el
sistema completo de Principa Mathematica es, como diríamos hoy, indecidible6.
Las producciones de Post son ubicuas en las ciencias de la computación. Su
primera aplicación fue la que llevó a cabo Noam Chomsky, quien encontró en ellas
exactamente lo que necesitaba para su revolucionaria teoría de las gramáticas de los
lenguajes naturales. Esto condujo a Chomsky a su ahora famosa clasificación o
jerarquía de lenguajes basada en la clase específica de producciones que Post permitía
en su gramática de definición. La conexión con las Ciencias de la Computación se hizo
manifiesta cuando resultó que una de las clases de Chomsky consistía en la misma clase
de lenguajes que podían ser reconocidos por un autómata finito y que otra –los llamados
lenguajes independientes del contexto– consistía en lenguajes reconocibles por un
autómata finito equipado con una pila auxiliar (finite automata equipped with an
auxiliary pushdown stack). De forma aparentemente independiente del trabajo
chomskiano, John Backus utilizó las producciones de Post para proveer una sintaxis
apropiada para el desarrollo del lenguaje de programación ALGOL 58; allí resultó que
los lenguajes que podían ser describirse en términos de la sintaxis de Backus eran
exactamente los lenguajes independientes del contexto de Chomsky!.
Estuve particularmente interesado en leer la explicación de Backus respecto a
cómo se le había ocurrido su sintaxis porque, para mi sorpresa, mencionaba mi nombre:
“En cuanto al origen de esta idea, surgió en una clase de Martin Davis que
pude presenciar. Él estaba dictándola en la Universidad de Atlanta State, hablando
acerca de Emil Post y de su noción de producción. Cuando trató de describir el
ALGOL 58 me di cuenta de que existía un problema en la descripción de la
sintaxis. Era obvio que las producciones de Post eran precisamente lo que
necesitaba y me apresuré a adaptarlas a ese uso…7”
descubrimos que no existía esa institución. Pero pronto fui capaz de resolver el misterio.
Había brindado un curso de conferencias para IBM durante el año académico 1960-61
con John Backus entre el público. Las conferencias fueron brindadas en el “The Lamb
State” en el condado de Westchester, estado de Nueva York, donde muchos de los
investigadores de IBM trabajaban en ese momento. Contento con mi explicación,
publiqué lo que pensé era una pequeña pero ingeniosa nota explicando el error en los
“Annals of the History of Computing”8. Poco tiempo después me topé con otro texto de
Backus9 en donde una vez más me daba créditos por ser el canal transmisor por el cual
se había enterado del trabajo de Post. Fue entonces que al examinar la lista de
referencias en su texto, me di cuenta, con cierta desazón, de que Backus ya había dado
una charla sobre su “forma normal” durante el verano de 1959, ¡mucho antes de que él
escuchara mis conferencias! Las discusiones con Backus en los últimos años no han
logrado echar luz sobre este tema.
Esta anécdota personal puede servir para subrayar la dificultad en el trazado del
camino por el cual una idea se transfiere de la teoría a la práctica. Tengo pocas dudas de
que el recuerdo de Backus acerca de las influencias de Post sea correcto. Pero él no era
un lógico. ¿Cómo hizo para enterarse del trabajo de Post? Mi libro (Davis, 1958) fue
una fuente posible, así como los primeros trabajos de Chomsky. Otra posibilidad son los
lógicos que trabajaban con Backus en IBM en el proyecto FORTRAN.
Por supuesto, lo importante e interesante es la transmisión de ideas. Tratar de
establecer el camino “real” sólo es interesante en cuanto ayuda a establecer si la
transmisión ocurrió realmente. Sin embargo, este ejemplo, en el cual todos los
involucrados están vivos y donde no existen asperezas –condiciones que no son, de
ninguna manera, típicas–, demuestran cuán difícil puede ser esta empresa.
Lógica Booleana
8
Davis, 1982a
9
Backus, 1980
10
Shannon, 1938
5
Lenguajes de programación
Los lenguajes de programación son simplemente el vehículo por medio del cual
los usuarios pueden establecer exactamente qué pasos computacionales desean que se
lleven a cabo. Al utilizar las primeras máquinas con programas de almacenamiento
(stored-programs) de los años 50, el único lenguaje de programación disponible para el
usuario de una computadora determinada era el propio de esa máquina, el “lenguaje de
la máquina”. Las “instrucciones” que conformaban un programa consistían,
comúnmente, en “órdenes” de traer desde la memoria cadenas binarias que
representaban números hacia una unidad “aritmética”, donde ellas podían ser operadas
mediante estrategias aritméticas ordinarias y luego devueltas a la memoria. El
programa, en sí, era almacenado en la misma memoria, codificado en forma binaria, y
las instrucciones eran puestas consecutivamente en movimiento en la unidad aritmética.
La secuencia de operaciones aritméticas podía ser interrumpida por un “test”, en general
consistente en determinar si alguna cantidad específica en la unidad aritmética era
positiva o negativa; tal test podía resultar en un “salto” hacia la próxima instrucción
fuera de la secuencia.
Aunque actualmente día los lenguajes de las máquinas no son tan diferentes de los
descriptos, los programadores rara vez trabajan de una manera tan rígida. En el peor de
los casos, trabajan en un lenguaje “ensamblador” (assembly language) en el cual las
señas mnemotécnicas y simbólicas proveen, por lo menos, una interfaz mínimamente
orientada hacia lo humano. Pero más comúnmente, los programadores trabajan en un
lenguaje de “nivel superior” que debe ser “recopilado” – es decir, traducido de una vez
para siempre en el lenguaje de la máquina – o “interpretado” –esto es, operado paso por
paso por un programa especial que realiza cada paso a medida que lo encuentra. Cabe
11
Goldstine, 1972
12
Quine, 1952
13
Ver, p.e., Dietmeyer, 1971
6
señalar que el desarrollo de estos lenguajes ha introducido cada vez más estructuras
lógicas. FORTRAN fue, quizás, el primer lenguaje serio de programación y usado
masivamente con fines múltiples14. […] Su deuda con los lenguajes formales
desarrollados por lógicos puede observarse en este fragmento del manual original de
FORTRAN:
“Si E y F son expresiones de la misma forma y si el primer símbolo de F no
es + o ¬, entonces
E+F
E–F
E≠F
E/F
PASCAL es, hoy en día, el lenguaje de programación con el cual se inician los
estudiantes universitarios de Ciencias de la Computación. PASCAL presenta la clase
“booleana” como una de las más fundamentales: esta clase consiste en dos valores
(“verdadero” y “falso”). Los valores booleanos pueden combinarse utilizando las
operaciones “y”, “o”, y “no”. Las condiciones booleanas pueden utilizarse no sólo para
controlar “saltos” por medio de construcciones del estilo “si… entonces” y “si…
entonces… de lo contrario” (if-then-else), sino también para determinar el punto final de
complejos y reiterados “bucles” (loops) utilizando construcciones del tipo “mientras…
hacer…” y “repetir… hasta…”. Facilidades de este tipo existen en la mayoría de los
lenguajes de programación utilizados actualmente. Por ejemplo, el BASIC que provee
IBM conjuntamente con su línea de computadoras personales tiene, esencialmente, estas
mismas facilidades.
El primer lenguaje de programación con medios lógicos extensivos fue,
probablemente, el LISP desarrollado por John McCarthy a fines de los 50 y que se
continúa usando15. La característica especial del LISP es que los objetos básicos de
información con los que trata no son tanto números sino listas asociativas. Las
facilidades booleanas están disponibles aquí bajo la forma de lo que McCarthy
denomina “expresiones condicionales”, el descendiente directo de las estructuras “si…
entonces… en otro caso” mencionadas anteriormente. A decir verdad, el propio
McCarthy formó parte del grupo que desarrolló ALGOL 60, en el cual se incluyó la
estructura “si… entonces… de lo contrario”, fue esta influencia del ALGOL la que
probablemente motivó la inclusión de tal estructura en todos los lenguajes de
programación serios. […]
Programación lógica
14
Para una discusión detallada de la historia pre-Fortran de los lenguajes de programación, ver
el comprometido ensayo Knuth y Pardo, 1981
15
ver McCarthy, 1981 para un interesante relato de la primera historia de Lisp
7
esperada. El motor lógico puede ser un programa para realizar deducciones en LPO (la
lógica introducida por Frege que se obtiene de añadir los cuantificadores “todo” y
“algún” al cálculo proposicional). Tales programas, llamados comúnmente
“demostradores de teoremas” (theorem-provers), han sido largamente estudiados16. En
Kowalski 1980, se argumenta apasionademente que la programación lógica es la clave
del desarrollo futuro de software.
Los principales sistemas de programación disponibles son los varios dialectos del
lenguaje de programación PROLOG, del cual Colmerauer ha sido su principal artífice.
La conocida ineficiencia de los “testeadores de teoremas” –no totalmente desligada de
la indecibilidad de la lógica de primer orden– es tratada en PROLOG mediante el uso de
una forma brutalmente minimalista de LPO, la autodenominada cláusula lógica “horn”.
Una cláusula “horn” (horn clause) es un enunciado de la forma
p1 ^ p2 ^… ^ pn→ q
Aquí, p1, p2, … pn, q pueden contener variables, pero ellas deben ser atómicas, en el
sentido de no contener en sí mismas otras operaciones lógicas (en particular ésta es una
lógica sin negación). Un programa en PROLOG es, esencialmente, una lista de
cláusulas “horn”. El intérprete de PROLOG es, entonces, básicamente un demostrador
de teoremas de cláusulas horn. Un gran interés ha suscitado tanto PROLOG como la
programación lógica; de hecho, actualmente existe una revista especializada
exclusivamente en estos temas. Los intérpretes y recopiladores de PROLOG son
asequibles para muchos sistemas computacionales, incluyendo el ubicuo IBM-PC/DOS.
Aunque PROLOG ha sido utilizado con bastante efectividad, todavía no ha
llegado a cumplir con todas las expectativas. La estrategia utilizada por el demostrador
de teoremas de la cláusula horn es tan drástica que los resultados dependen críticamente
del orden en el cual se han dado las cláusulas. Aun así, algunas “impurezas” deben ser
añadidas a su lógica para disponer de un sistema operable, particularmente la operación
de corte por medio de la cual el programador impide que el demostrador de teoremas
siga líneas de deducción poco promisorias. A pesar de todo, PROLOG representa un
ejemplo importante y palpable de la asociación entre la lógica y la computación.
Conclusiones
16
ver Davis, 1983 y Loveland, 1984, para la historia.
8
BIBLIOGRAFÍA