You are on page 1of 34

Introducción

Se ha dicho que el papel de la lógica en las ciencias de la computación


es análogo al del cálculo en la física y en la ingeniería. Sin embargo, esta
tesis no se refleja adecuadamente en el contenido de muchos planes de
estudio en el área. El objetivo de la materia de Análisis lógico es subsanar
esta deficiencia.
El cálculo de proposiciones es la base de la lógica, pero el cálculo de
predicados constituye el núcleo de una buena parte de las aplicaciones en
ciencias de la computación: la especificación y la verificación de programas,
la axiomatización de álgebras abstractas (subyacentes a los distintos tipos
de datos de los lenguajes de programación), la programación lógica, las
bases de datos relacionales, etc. Por esta razón, el estudio del cálculo de
predicados es el tema principal del curso.
Sin embargo, otras ramas de la lógica también tienen su lugar. Por una
parte, el cálculo de predicados de primer orden es insuficiente para forma-
lizar todos los objetos que aparecen en la ciencia de la computación. Por la
otra, el uso de las lógicas no clásicas se extiende cada vez más en la forma-
lización de sistemas concurrentes o en la elaboración de sistemas expertos,
por citar sólo dos ejemplos. El curso concluye con una breve introducción
a estas lógicas.

Qué es la lógica
Uno de los objetivos centrales de la lógica es la teoría de la demostra-
ción, que intuitivamente se puede ver como el estudio de los argumentos
correctos. Sin embargo, la corrección de un argumento (al menos para la
lógica) no depende del contenido de éste, sino de su forma. Consideremos
el ejemplo clásico de argumento correcto:

5
6 ÍNDICE GENERAL

Todos los hombres son mortales.

Sócrates es un hombre.
En consecuencia

Sócrates es mortal.

En el cual en realidad no nos importan el significado de las palabras


“hombre”, “mortal” o “Sócrates”, sino la forma de los enunciados que las
contienen: el también clásico “silogismo” Darii. Aquí tenemos otro ejemplo
del mismo silogismo:

Todos los borogovos son frumosos.

El Jabberwock es un borogovo.
En consecuencia

El Jabberwock es frumoso.

Que también es correcto, a pesar de que no tenemos ni la más remota


idea de qué son las palabras “borogovo”, “frumoso” y “Jabberwock” (aun-
que Lewis Carroll las “define” en La caza del snark).
Un lenguaje lógico consta normalmente de los tres elementos siguien-
tes:

Una sintaxis formal, es decir, con reglas precisas que permiten deter-
minar sin ambigüedad qué cadenas de símbolos de un alfabeto dado
pertenecen al lenguaje.

Una semántica matemática: el significado de los enunciados del len-


guaje se define por medio de interpretaciones, las cuales son funciones
que relacionan los símbolos del lenguaje con elementos de un domi-
nio matemático.

Reglas de inferencia (o derivación) que permiten obtener enunciados


verdaderos a partir de enunciados verdaderos llamados teoremas.

Los matemáticos (y mucha gente de computación) están especialme-


ne interesados en el último elemento. En particular se preocupan por los
sistemas de demostración que contienen una o más reglas de inferencia y
ÍNDICE GENERAL 7

que permiten demostrar teoremas de un lenguaje lógico particular (por


ejemplo, una formalización de la aritmética de los números naturales). Los
sistemas de demostración tienen un poder variable que depende en parte
de decisiones de diseño y en parte de limitaciones absolutas. En general se
busca que posean las siguientes propiedades:
Consistencia: no es posible que un enunciado y su negación sean teo-
remas del sistema al mismo tiempo.
Corrección (soundness): los teoremas del sistema son enunciados váli-
dos (es decir, verdaderos en cualquier interpretación).
Completitud: se puede dar en dos versiones: (a) como una propiedad
recíproca de la corrección, a saber: todos los enunciados válidos son
teoremas; (b) como la propiedad de que dado un enunciado sin varia-
bles libres, o bien éste es un teorema del sistema o bien su negación
lo es.
Decidibilidad: existe un método efectivo (es decir, que siempre termi-
na) para determinar si un enunciado es o no es un teorema.
Sin embargo, la norma es que no se cuente con todas las anteriores.
Las dos primeras deben estar presentes en todo sistema que se respete,
pero la completitud (b) es inalcanzable para todo lenguaje de complejidad
suficiente como para expresar las verdades de la aritmética de números
naturales. La decidibilidad está ausente incluso en el cálculo de predicados
sin axiomas especiales.

Lógica y computación
Sin embargo, hasta el momento no se ha explicado de manera más pre-
cisa cuál es la relación entre la lógica y la computación. Esta relación la
podemos ver en tres niveles al menos:
1. Ambas tratan de lenguajes formales.
2. Como ya se dijo, la lógica se aplica en áreas específicas de la com-
putación: especificación, verificación y transformación de programas;
programación lógica y bases de datos; sistemas expertos e inteligencia
artificial, etc.
8 ÍNDICE GENERAL

3. En un sentido teórico (y técnico) son equivalentes: los enunciados


demostrables en el cálculo de predicados son equivalentes a las fun-
ciones computables por una máquina de Turing o por los formalismos
equivalentes a éstas. En pocas palabras, su poder “computacional” es
el mismo.

Durante el curso se dará más sustancia a las afirmaciones anteriores. Por


lo pronto conviene ya entrar en materia y se comenzará con los conceptos
de inducción y recursión.
Capítulo 1

Inducción y recursión

En este capítulo se estudiarán los conjuntos inductivos y las funciones


recursivas definidas en éstos. Dichos conjuntos y funciones serán los ele-
mentos básicos de todos los lenguajes que se verán en el resto del curso.

1.1. Relaciones e inducción bien fundadas


Si dos elementos a, b de un conjunto están en una relación R se escribirá
(a, b) 2 R, a R b o R(a, b).
Definición 1.1.1 Sea U un conjunto y sea R  A  A. Se dice que R es:

1. Reflexiva sii 8a 2 A . R(a, a).

2. Simétrica sii 8a, b 2 A . R(a, b) ) R(b, a).

3. Antisimétrica sii 8a, b 2 A . R(a, b) ^ R(b, a) ) a = b.

4. Transitiva sii 8a, b, c 2 A . R(a, b) ^ R(b, c) ) R(a, c).

5. Total sii 8a, b 2 A . a 6= b ) R(a, b) _ R(b, a).

Dada una relación R en A  A se puede construir sus cerraduras transi-


tiva y reflexiva y transitiva, denotadas por R+ y R , respectivamente:

R0 = f(a, a) j a 2 ag
R1 = R

9
10 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

R+ =
[
Rn+1 = Rn [ f(a, c) j 9b . (a, b) 2 Rn ^ (b, c) 2 Rn g
Rn+1

R =
n[2N R n

n 2N
En matemáticas hay un tipo de relaciones muy comunes llamadas órde-
nes. Sin embargo, los órdenes vienen en distintos sabores.

Definición 1.1.2 Una relación R es un pre-orden (o cuasi orden) sii es refle-


xiva y transitiva.
Un orden parcial (o poset, por el inglés partially ordered set) es una rela-
ción reflexiva, transitiva y antisimétrica.
Un orden total o lineal es simplemente una relación total. Obsérvese cómo
no se supone que tenga ninguna otra propiedad.

El orden parcial más conocido es  en N . En el mismo conjunto, < es


un orden total. Un ejemplo de pre-orden en P(N ) es la siguiente relación
A vL B 8a 2 A . 9b 2 B . a  b,
sii
llamada el preorden inferior o de Hoare. Se tiene que f0, 1, 2g vL f1, 2g y
f1, 2g vL f0, 1, 2g pero f0, 1, 2g 6= f1, 2g.
Se usarán con frecuencia los símbolos  y  para denotar relaciones de
orden arbitrarias.
Una relación de orden en un conjunto A se puede extender a An al
menos de dos formas:

1. Orden lexicográfico. Sea  A  A un orden. La relación lex  ( A 


A)  ( A  A) se define así:
(a, b) lex (a0 , b0) sii a  a0 o
a = a0 y b  b0 .
La definición anterior se extiende a An de la misma forma en que se
extiende el concepto de par ordenado a n-adas arbitrarias.
2. Orden por coordenadas. coor es la siguiente relación:
(a, b) coor (a0 , b0) sii a  a0 y b  b0 ,
que se extiende del mismo modo a n-adas arbitrarias.
1.1. RELACIONES E INDUCCIÓN BIEN FUNDADAS 11

Conviene dar nombre a algunos elementos especiales de un conjunto


ordenado:

Definición 1.1.3 Sea  una relación en A  A y sea X  A. Se dice que x 2 X


es un:

1. mínimo sii 8 y 2 X . x 6= y ) x  y.

2. máximo sii 8 y 2 X . x 6= y ) y  x.

3. minimal sii :9 y 2 X . x 6= y ^ y  x.

4. maximal sii :9 y 2 X . x 6= y ^ x  y.

Ejemplos. Sea A = f0, 1, 2g. Si se ordena P( A) con la relación  entonces


; y A son el mínimo y el máximo de . En cambio, P( A) f;g no tiene
mínimo, pero si tres minimales: f0g, f1g y f2g. Por su parte, P( A) f Ag
no tiene máximo, pero sí tres maximales: f0, 1g, f0, 2g y f1, 2g.
En un orden parcial, un mínimo es un minimal, pero esto no es necesa-
riamente el caso en un preorden. Más adelante se verán otros órdenes en
los que los mínimos son siempre minimales.

Definición 1.1.4 Sea  un orden en U  U y sea C  U. Decimos que C es una


cadena sii 8 x, y 2 C es el caso que x  y o y  x. Una cadena descendente
infinita es una cadena C tal que 8 x 2 C, 9 y 2 C tal que y  x. De manera
dual, una cadena infinita ascendente C tiene la propiedad de que 8 x 2 C,
9 y 2 C tal que x  y.
Obsérvese cómo una cadena C  X es un subconjunto de X que visto
de manera aislada forma un orden total. Las cadenas descendentes nos
permiten caracterizar los órdenes bien fundados.

Definición 1.1.5 Sea  U  U una relación. Decimos que  es un bien


fundada sii no existen cadenas infinitas descendentes en U.

El ejemplo clásico de una relación bien fundada es < en N . Si denotamos


por suc la relación inducida por suc : N ! N ( la función sucesor)

x suc y sii y = suc( x),


12 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

esta relación también es bien fundada. Por cierto, a diferencia de <, no es


transitiva.
Un ejemplo de importancia en lenguajes formales es la relación basada
en el concepto de prefijo. Un alfabeto es un conjunto no vacío finito .
Una cadena es un sucesión finita (posiblemente vacía) de símbolos de
. La cadena vacía se representa con el símbolo . El conjunto de cadenas
es  y el de cadenas no vacías es + . Hay una operación binaria en  :
la concatenación, y no se usará ningún signo especial para marcarla. La
relación  pre está determinada por la regla:

 pre sii 9 . = ^ 6= .
Puede verificarse fácilmente que  pre es un orden bien fundado y que su
mínimo en  es , mientras que en + no tiene mínimo sino varios mini-
males, a saber, los elementos de .

Teorema 1.1.6 Sea  una relación bien fundada. Entonces: (a)  no es refle-
xiva ni simétrica; (b) su cerradura transitiva es bien fundada; (c) los órdenes
lexicográfico y por coordenadas basados en  son bien fundados; (d)  es un
orden parcial.

Demostración: (a) Si  fuera reflexiva, entonces es muy fácil formar una


cadena infinita descendente a partir de un solo elemento:

    a  a.
Del mismo modo, si  fuera simétrica, basta con tomar dos elementos a y
b tales que a  b:
    b  a  b,
para tener otra cadena infinita.
(b) Supongamos que la relación  es bien fundada. Si tenemos una
cadena
   + ai +    + a0,
y suponemos que es descendente infinita, entonces para todo i existen ai0 =
ai , . . . , aim = ai+1 tales que

aim      ai
1.1. RELACIONES E INDUCCIÓN BIEN FUNDADAS 13

es decir, la misma cadena de + se puede transformar en una cadena de ,


por lo que tenemos una cadena infinita descendente en , lo cual es una
contradicción.
(c) Sea C una cadena en A  A con el orden coor :

   coor (a1 , b1) coor (a0, b0).


Si esta cadena fuera infinita, sería posible construir dos cadenas infinitas
en 
    b1  b0 y     a1  a0,
por lo que C no puede ser infinita descendente. En cuanto a lex , considé-
rese la siguiente cadena descendente infinita:

   lex (a1 , b1) lex (a0, b0).


En consecuencia, es posible construir una cadena en  usando el siguiente
método: el primer elemento es a0 , el segundo es el primer ai tal que a0 6= ai .
Si no existe tal elemento, entonces, por la definición de lex tenemos una
cadena descendente infinita en 

    b1  b0 ,
lo cual no es posible. Por otro lado, suponer que podemos encontrar un
número infinito de diferentes ai nos lleva a otra cadena infinita

    a1  a0 ,
lo que tampoco es posible. Por lo tanto, lex tampoco contiene cadenas
infinitas descendentes.
(d) Es claro que la cerradura transitiva y reflexiva tiene dos de las pro-
piedades de un orden parcial. La antisimetría viene del hecho de que si
tenemos que a  b y b  a y no fuera el caso que a = b, se podría formar
una cadena descendente infinita en  siguiendo el método de (a).

El teorema 1.1.7 nos da una caracterización alternativa de las relaciones


bien fundadas.

Teorema 1.1.7 Una relación  es bien fundada en A  A sii todo X  A


(X 6= ;) tiene un minimal.
14 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

Demostración. a) Supongamos que  es bien fundada y que ; = 6 X  A.


Ahora bien, si X no tiene un elemento minimal, entonces 8m 2 X . 9b 2
X . b  m. Iterando este razonamiento, podemos construir una cadena
descendente infinita de elementos en X, lo cual es una contradicción.
Si ahora suponemos que todo subconjunto no vacío de A tiene un mini-
mal y además tenemos una cadena descendente

    ai      a0 ,
basta con que tomemos el conjunto de elementos en la cadena que por
hipótesis debe de tener un elemento minimal y, en consecuencia, la cadena
no puede descender infinitamente.

Sea P una propiedad de elementos de A y sea  A  A. La siguiente


afirmación se conoce como el principio de inducción:

(8a 2 A . P(a)) , (8a 2 A .((8b 2 A . b  a ) P(b)) ) P(a))).


Este principio se aplica en conjuntos donde  es un orden bien fundado:

Teorema 1.1.8 Sea  A  A una relación bien fundada y sea P : A !


fV, Fg un predicado. Entonces el principio de inducción vale.
Demostración. La implicación ) es inmediata, así que procederemos con
la inversa. Supongamos, por reducción al absurdo, que 9a 2 A.: P( A). Sea
Q = fa 2 A j : P( A)g y, dado que  es bien fundada, entonces existe un
elemento minimal m de Q. Aquí hay dos opciones:

(i) 9b 2 A . b  m;
(ii) :9b 2 A . b  m.
En el primer caso, por hipótesis b  m ) P(b) y, dada la hipótesis prin-
cipal, P(m), lo que contradice la suposición. En el segundo, el enunciado

((8b 2 A . b  a ) P(b))
sería verdadero por vacuidad, y como P(m) es falso, entonces todo el enun-
ciado sería falso. Pero en ese caso, sabemos que no existiría a 2 A tal que
P( A) y, en consecuencia,
(8a 2 A . P(a))
1.2. CONJUNTOS DEFINIDOS INDUCTIVAMENTE 15

sería falso también, con lo que tendríamos la otra implicación.

El principio de inducción nos da una estrategia para demostrar una pro-


piedad P en un conjunto A con una relación bien fundada ;

1. Se demuestra que todos los elementos minimales cumplen P.

2. Se asume como hipótesis inductiva 8b 2 A . b  a ) P(b).

3. Se demuestra que entonces P(a).

Más adelante habrá oportunidad de usar esta estrategia.

1.2. Conjuntos definidos inductivamente


En matemáticas es muy común definir un conjunto de manera “circu-
lar”. Por ejemplo, las fórmulas del cálculo de proposiciones:
“Si  y son proposiciones, entonces : y  _ son proposiciones”.
Por supuesto, si la definición anterior fuera realmente circular, sería in-
correcta. En realidad, lo que se hace en los textos de lógica es definir el
conjunto anterior de manera inductiva, lo que evita la circularidad aparen-
te.1 Una definición inductiva parte de un conjunto básico y de un conjunto
de funciones que generan nuevos elementos a partir del conjunto básico,
como se verá en las siguientes definiciones.

Definición 1.2.1 Sea A  U un conjunto y sea F = f fin : U n ! U g un


conjunto de funciones. Decimos que A es cerrado bajo F sii 8 fkn 2 F y 8a1 ,
. . . an 2 A resulta que fkn ( x1 , : : : , yn ) 2 A.
Sea X  U. Entonces, un conjunto Y  U es inductivo en X bajo F sii
X  Y y Y es cerrado bajo F.

De todos los conjuntos inductivos en X nos interesa uno en particular al


que llamaremos la cerradura inductiva. Existen dos métodos para definirla:
1
En algunos textos se llama recursivas a las definiciones como la anterior. Sin embargo,
esto es un error terminológico (¡pero un error muy común!). La confusión surge de que en
los conjuntos inductivos se pueden definir funciones recursivas de manera muy natural,
como se verá más adelante.
16 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

Definición 1.2.2 Sea X  U y sea F = f fin : U n ! U g un conjunto de fun-


ciones. La cerradura inductiva de X bajo F, construida de abajo hacia arriba,
se define de este modo:

X0 = X

X+ =
[
Xi+1 = Xi [ f fkn ( x1 , : : : , xn ) j fkn
Xi .
2 F ^ x 1 , : : : , x n 2 Xi g
i2N
Definición 1.2.3 Sea X  U y sea F = f fin : U n ! U g un conjunto de
funciones y sea X la familia de conjuntos inductivos en X bajo F. La cerradura

\ Y.
inductiva de X bajo F, construida de arriba hacia abajo es el conjunto

X+ =
Y 2X
Los dos métodos se usan con frecuencia. El teorema 1.2.4 nos dice que
son equivalentes.

Teorema 1.2.4 Ambas definiciones son equivalentes, es decir X+ = X + .

Demostración. Es claro que X+ es inductivo en X y, dado que X + es la in-


tersección de los conjuntos inductivos en X, se tiene que X +  X+ . La otra
contención se demostrará por inducción matemática:
Caso base. X0 = X  X + .
Hipótesis inductiva. Xi  X + . Por demostrar que Xi+1  X + . Pero esto
último se sigue del hecho de que X + es cerrado. Por inducción, 8n 2 N . Xn 
X + . Entonces X+  X + .

El ejemplo del cálculo de proposiciones se puede ahora plantear de la


siguiente forma. Sea  = f p, q, r, p1 , : : :g [ f(, )g [ f_, :g un alfabeto y sea
:S :  !  y _S :    !  las funciones definidas de la siguiente
forma:

:S ( ) = :
_S ( , ) = ( _ ).
Sea Pa = f p, q, r, p1 , : : :g el conjunto básico. Entonces el conjunto fórmulas
del cálculo de proposiciones, P, se puede definir usando los dos métodos:

P0 = Pa
1.2. CONJUNTOS DEFINIDOS INDUCTIVAMENTE 17

P+ =
\
P = P+ = P+
Y,
Y 2P

donde P es la familia de conjuntos inductivos en Pa .


Los conjuntos definidos por medio de la notación Backus-Naur (BNF en
adelante) se pueden transformar fácilmente en conjuntos inductivos. Por
ejemplo, las expresiones aritméticas del conjunto EA se definen así:

A ::= N j X j A + A j A  A j A A

donde A 2 EA y N es un entero (Z) y X una variable (Var). Estos dos con-


juntos se pueden considerar como conjuntos ya dados o se pueden definir
de manera similar:
N ::= 0 j suc( N ) j pred( N ),
con suc y pred las funciones de sucesor y predecesor, respectivamente. Las
variables se definirán así:

X ::= x j y j z j xN j yN j zN
con N 2 Z. Este último conjunto no es inductivo en realidad (su construc-
ción se realiza en un solo paso), pero Z y EA sí lo son. Veamos el caso de
EA. Nuevamente, se comienza con un conjunto básico: EA0 = Z [ Var y un
conjunto de funciones que nos dan nuevas expresiones a partir de otras ya
existentes:

+ S ( , ) = +
 S ( , ) = 
S ( , ) = .
y se obtienen así las expresiones aritméticas EA = EA+ = EA+ .
En algunos casos, el conjunto inductivo se genera a partir de un con-
junto básico y otro conjunto ajeno. Un ejemplo es el conjunto de listas de
naturales L(N ). En este caso partimos de un conjunto básico con un solo
elemento, la lista vacía: [ ℄ y las funciones de agregación de elementos y
concatenación de listas:

n :: [n1 : : : nn ℄ = [n n1 : : : nn ℄
[ ℄ ++ l = l ++ [ ℄ = l
18 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

(n :: l) ++ l0 + l0 )
= n :: (l +

donde ::: N  L(N ) ! N y + +: L(N )  L(N ) ! L(N ). Obsérvese cómo la


operación de agregación de elementos tiene dos argumentos, el primero
de los cuales no es una lista. Hay dos formas de ajustar las listas a las
definiciones 1.2.2 y 1.2.3:

1. N es un conjunto ajeno a las listas de naturales (pues un número natu-


ral no es una lista). En ese sentido, al tomar naturales para construir
listas no cambiamos la esencia de una definición inductiva, a saber, la
generación de nuevos elementos a partir del conjunto básico (en este
caso, a partir de las lista vacía), pues N ya está dado y no se genera
ni por la operación de agregación ni por la de concatenación.

2. Se puede suponer que no existe una sola función de agregación, sino


una por cada natural. Por ejemplo,

::1 ([2 3℄) = [1 2 3℄ y ::0 ([2 3℄) = [0 2 3℄

y el conjunto L(N ) es generado por todas estas funciones, con lo que


no habría diferencia con respecto a las expresiones aritméticas o al
cálculo de proposiciones.

En cualquiera de los dos casos, L(N ) = f[ ℄g+ = f[ ℄g+ .

1.3. Funciones recursivas y conjuntos inducti-


vos
Una forma muy común de definir funciones en conjuntos es por enu-
meración. Por ejemplo, la función identidad en el conjunto f1, 2g se puede
expresar como un conjunto de pares ordenados: f(1, 1), (2, 2)g. No obstan-
te, con conjuntos de gran tamaño (y no se diga con los infinitos) esto es
poco práctico. Cuando contamos con una regla que nos permite calcular el
valor de una función en un elemento dado es mejor usar una ecuación:

f ( x) = x2
o varias ecuaciones
!0 = 1
1.3. FUNCIONES RECURSIVAS Y CONJUNTOS INDUCTIVOS 19

!(n + 1) = !n  (n + 1)

El último ejemplo ilustra además una posibilidad más: las definiciones pue-
den ser recursivas, es decir, la función definida puede aparecer no sólo del
lado izquierdo, sino también del lado derecho de la ecuación que la define.
Sin embargo, es muy fácil cometer “errores” en las definiciones recursivas:

g( x) = g( x + 1)

es una “función” que nunca nos da un resultado. Aunque este ejemplo es


muy obvio, en general no es posible decir si una función recursiva con
dominio y contradominio en los naturales da un resultado o no (la pregunta
es equivalente al famoso problema de la detención en máquinas de Turing).
Un problema adicional es cuando se puede obtener más de un resultado,
dependiendo del orden en que se apliquen las ecuaciones que definen la
función. Supóngase que se desea evaluar las expresiones aritméticas EA
tal y como se definieron en la sección anterior. Para esto, se partirá de una
asignación de valores a las variables por medio de una función e : Var ! Z,
es decir, se supondrá que para toda x 2 Var, e( x) ya está dado. También se
tendrá que e(n) = n, para todo n 2 Z. Ahora hay que extender e al conjunto
de elementos de EA:

e( x) = m ya está dado 8 x 2 Var


e(n) = n 8n 2 Z
e( + ) = e( ) +Z e( )
e(  ) = e( ) Z e( )
e( ) = e( ) Z e( )

donde +Z, Z y Z son las operaciones de suma, multiplicación y resta en


los enteros y no los símbolos sintácticos respectivos. Con estas ecuaciones,
queremos evaluar la expresión 2+3  2. Como las ecuaciones no establecen
ningún orden especial para la evaluación de las expresiones, existen dos
posibilidades:

e(2 + 3  2) = e(2) +Z e(3  2) = 2 +Z (e(3) Z e(2)) = 2 +Z (3 Z 2)


= 2 +Z 6 = 8

y también

e(2 + 3  2) = e(2 + 3) Z e(2) = (e(2) +Z e(3)) Z 2 = (2 +Z 3) Z 2


20 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

= 5 Z 2 = 10
Aunque no hay condiciones necesarias para saber si una función recursiva
está bien definida, la definición 1.3.1 y el teorema 1.3.2 nos dan condi-
ciones suficientes. El concepto clave es la generación libre de un conjunto
inductivo:
Definición 1.3.1 Sean A un conjunto, X  A y F = f fin : An ! Ag un
conjunto de funciones. Se dice que X+ (o X + ) es generado libremente por X y
F sii se cumplen las siguientes condiciones:
(i) La restricción de toda f n 2 F a X+n es inyectiva.
(ii) Para todas fkm y fin 2 F, si fkm = 6 fin entonces fkm( X+ ) \ fin ( X+) = ;.
(iii) Los elementos de X son realmente básicos, es decir, para toda fin 2 F y
para todas x1 , . . . , xn 2 X+ , se tiene que fin ( x1 , : : : , xn ) 62 X.
En el caso de EA, el conjunto no se generó libremente, pues no se cum-
ple con la condición (ii). Por ejemplo, la expresión 2 + 3  2 se puede
generar de dos maneras, a saber, +S (2, 3  2) y S (2 + 3, 2), por lo que
las imágenes de +S y S no son ajenas. Este problema es muy común cuan-
do se trata de evaluar operaciones con más de un argumento. La solución
más general consiste en encerrar entre paréntesis las expresiones genera-
das por las funciones de tal forma que se impone un orden de evaluación.
De esta manera, se redefinen las funciones para expresiones aritméticas:
+ S ( , ) = ( + )
S ( , ) = (  )
S ( , ) = ( )
y la ambigüedad desaparece. Se deja como ejercicio para el lector que la
nueva definición cumple con las condiciones (i)–(iii) de la definición 1.3.1.
En cuanto a las listas, la definición que se dio no cumple ni con (i) ni
con (ii):
+[
l+ ℄ = [ ℄ ++ l = l
0 :: [ ℄ = [ ℄ ++ [0℄
Aquí el problema es la función + +. Una nueva definición de listas en la que
la única función constructora es :: resuelve el problema (y el lector puede
verificarlo en un ejercicio fácil).
1.3. FUNCIONES RECURSIVAS Y CONJUNTOS INDUCTIVOS 21

La definición de funciones recursivas en conjuntos generados libre e


inductivamente se puede realizar sin problemas gracias al siguiente hecho:

Teorema 1.3.2 Sea X+ (o X + ) un conjunto generado libremente por X y el


conjunto de funciones F y sea B un conjunto cualquiera distinto de ;, acom-
pañado por un conjunto de funciones G = f gni : Bn ! Bg. Sea Æ : F ! G una
i implica que n = m. Finalmente, sea h : X ! B
función tal que Æ ( fin ) = gm
una función. Entonces, existe una única ĥ : X+ ! B tal que:

(i) Para todo x 2 X . ĥ( x) = h( x)

(ii) Para toda fkn 2 F y para todas x1, : : : , xn 2 X+ se tiene que


ĥ( fin ( x1 , : : : , xn)) = gm
k (ĥ( x1 ), : : : , ĥ( xn )),

donde Æ ( fin ) = gm
k.

En álgebra, una función como ĥ se conoce como un homomorfismo. Los


homomorfismos se pueden explicar por medio de diagramas conmutativos.
Sea  : X ! X+ la función inclusión (i.e., 8 x 2 X . ( x) = x). Entonces, la
cláusula (i) de la definición dice lo siguiente:


X X+


h

Que quiere decir que para llegar al vértice marcado con B partiendo del
vértice X se puede ir directamente a través de h o indirectamente a través
de i, primero, y ĥ, después, y el resultado será el mismo. La cláusula (ii)
del teorema dice, a su vez:
22 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

fin
X+n X+

ĥn ĥ

Bn X+
Æ ( fin )

Antes de demostrar el teorema anterior, veamos el siguiente lema.

Lema 1.3.3 Sea X+ un conjunto generado libre e inductivamente por X y F.


Para toda fkn 2 F, si x1 , . . . , xn 2 Xi , entonces fkn ( x1 , : : : , xn ) 62 Xi .

Demostración. Se aplicará inducción sobre i.


Caso base: i = 0. Por la condición (iii) de la definición, es verdad que
8 fkn 2 F y x1, . . . , xn 2 X0 se tiene que fkn( x1, : : : , xn) 2= X0.
Hipótesis inductiva: 8 fkn 2 F, x1 , : : : , xn 2 Xi . fkn ( x1 , : : : , xn) 2
= Xi . Se
debe demostrar que lo mismo vale en Xi+1 . Para esto, hay que considerar
una función fkn y elementos x1 , . . . , xn 2 Xi+1 Xi (pues si los elementos
estuvieran también en Xi , quedarían cubiertos por la hipótesis inductiva).
Supóngase que fkn ( x1 , : : : , xn ) = x y que x 2 Xi+1 . Entonces, por defi-
nición de Xi+1 , hay dos opciones (a) x 2 Xi ; (b) existen gm q 2 F y y1 , . . . ,
ym 2 Xi tales que x = gq ( y1 , : : : , ym ). La opción (a) es imposible, pues
m

contradiría la hipótesis inductiva. Pero (b) contradiría la condición (i) de


la definición si fkn = gm q o la condición (ii) si fk 6= gq . En cualquiera de los
n m

casos, no es posible que x 2 Xi+1 y, por inducción matemática, esto vale


para toda Xn .

Con el lema 1.3.3 ya se puede demostrar el teorema 1.3.2:

Demostración de 1.3.2. Considérese la siguiente sucesión de funciones:

h0 = h

ĥ = hi
[
hi+1 = hi [ f( fin ( x1 , : : : , xn), gnk (hi ( x1 ), : : : , hi ( xn ))) j x1 , : : : , xn 2 dom(hi)g
2N
i
1.3. FUNCIONES RECURSIVAS Y CONJUNTOS INDUCTIVOS 23

Obsérvese primero que, dado que X+ es generado libremente, dom(hi ) 


Xi . Por otro lado, queremos demostrar que ĥ es en realidad una función, es
decir, si ( x, y) 2 ĥ y ( x, z) 2 ĥ, entonces y = z. Lo haremos por inducción.
Caso base: x 2 X. En este caso, como X+ es generado libremente, no
existen fqm 2 F ni x1 , : : : , xm 2 X+ tales que x = fqm ( x1 , : : : , xn ). Como
h0 ( x) = h( x) y no asignamos ningún nuevo valor a x en las futuras hi
(i  1), entonces ĥ( x) tiene una asignación única.
Hipótesis inductiva: 8m  i + 1 tenemos que si x 2 Xm y ( x, y) 2 ĥ
y ( x, z) 2 ĥ, entonces y = z. Sea ahora x 2 Xi+1 Xi . Es decir, por las
condiciones (i) y (ii) de 1.3.1, existen x1 , : : : , xn 2 Xi y fqn 2 F únicos tales
que fqn ( x1 , : : : , xn ) = x. El lema 1.3.3 nos dice que fqn ( x1 , : : : , xn ) 62 Xi y
por esta razón, hi no está definida en x. Entonces, tenemos que aplicar la
definición de ĥ,

ĥ( x) = y = gnk (hi ( x1 ), : : : , hi( xn ))


ĥ( x) = z = gnk (hi ( x1 ), : : : , hi ( xn ))

Pero por hipótesis inductiva, ĥ es una función en x1 , . . . , xn y, por tanto,


y = z. Es decir, ĥ también es una función en x 2 Xi+1 y, por inducción, lo
es en todo X+ .
Finalmente, se verá la unicidad de ĥ. Supóngase que ĥ0 : X+ ! B cum-
ple con las condiciones (i) y (ii) del teorema. Demostraremos por inducción
en X+ que ĥ y ĥ0 son iguales.
Caso base: sea x 2 X0 . Por la condición (i), ĥ( x) = h( x) = ĥ0 ( x).
Hipótesis inductiva: 8m  i+1, tenemos que si x 2 Xm , entonces ĥ( x) =
ĥ ( x). Sea x 2 Xi+1 Xi , es decir, existen x1 , . . . , xn 2 Xi y fqn 2 F únicos
0
tales que fqn ( x1 , : : : , xn) = x. Sea Æ ( fqn ) = gnk . Por la condición (ii):

ĥ( x) = = ĥ( fqn ( x1 , : : : , xn )) = gnk (ĥ( x1 ), : : : , ĥ( xn ))


ĥ0 ( x) = = ĥ0 ( fqn ( x1 , : : : , xn)) = gnk (ĥ( x1 ), : : : , ĥ( xn ))

y, por hipótesis inductiva, ĥ( x1 ) = ĥ0 ( x1 ), . . . , ĥ( xn ) = ĥ0 ( xn ). En conse-


cuencia, ĥ( x) = ĥ0 ( x) y, por inducción, ĥ = ĥ0 .

Como se recordará, la función de evaluación de expresiones aritméticas


e : EA ! Z no funcionó con la definición original de EA. Sin embargo,
este último conjunto se redefinió de forma que era generado libremente
24 CAPÍTULO 1. INDUCCIÓN Y RECURSIÓN

por Z [ Var y las nuevas funciones +S , S y S , por lo que el teorema 1.3.2


permite asegurar que la función de evaluación siguiente está bien definida:
ê(n) = n 8n 2 Z
ê( x) = e( x) 8 x 2 Var
ê(( + )) = ê( ) +Z ê( )
ê((  )) = ê( ) Z ê( )
ê(( )) = ê( ) Z ê( )
En cuanto a las listas de enteros generadas libremente por ::, también
se pueden definir funciones recursivas de manera natural. Por ejemplo, se
tiene la función long : L(N ) ! N :
long([ ℄) = 0
long(n :: l) = 1 + long(l)
La generación libre también nos da un orden natural para estos conjun-
tos, como se muestra en la siguiente definición.

Definición 1.3.4 Sea X+ un conjunto generado libre e inductivamente por el


conjunto básico X y las funciones F y sean , 2 X+ . Entonces
S sii 9 fin 2 F ^ x1, : : : , xn 1 2 X+ . = fin ( x1, : : : , , xn 1).
S se conoce como el orden sintáctico o estructural y es claramente una
relación bien fundada. Por esta razón, se puede usar como base de un mé-
todo de demostración llamado inducción estructural. Veamos un ejemplo.
Considérese nuevamente EA, con la nueva definición. A simple vista
parece que toda expresión de EA tiene paréntesis balanceados, es decir,
a un paréntesis que se abre corresponde siempre uno que se cierra. Esta
conjetura se demostrará por inducción estructural. Sea 2 EA
Caso base: 2 Z o 2 Var. Entonces, como las variables y los enteros
no incluyen paréntesis, la proposición es trivialmente cierta.
Hipótesis inductiva: y tienen paréntesis balanceados. Se debe de-
mostrar ahora que ( + ), (  ) y ( ) también tienen paréntesis
balanceados, pues

, S ( + ), (  ), ( ).
Supóngase que ( + ) tiene más paréntesis que se abren de los que se cie-
rran. Dado que el primer paréntesis y el último de la expresión se cancelan
1.3. FUNCIONES RECURSIVAS Y CONJUNTOS INDUCTIVOS 25

mutuamente, entonces el problema debe estar en o en , lo que contra-


dice la hipótesis inductiva. Entonces, ( + ) tiene paréntesis balanceados.
Con un razonamiento análogo se demuestran los casos de (  ) y ( ).
Capítulo 2

Lenguajes de programación

Con el fin de ilustrar algunas aplicaciones de la lógica a la computa-


ción, presentaremos tres tipos de lenguajes. El primer tipo consiste en dos
lenguajes imperativos: IMP y el lenguaje de comandos custodiados de Dijks-
tra. En estas notas se sigue la notación que aparece en [10], pero ambos
lenguajes aparecieron antes ([6] y [4]).

El segundo comprende dos lenguajes funcionales. La sintaxis de los dos


es igual y se distinguen únicamente por su semántica. La notación presen-
tada está tomada también de [10].

El tercero no es exactamente un lenguaje de programación, sino de des-


cripción de procesos concurrentes (es decir, procesos que actúan de manera
simultánea e intercambian información entre sí): CCS (calculus of concu-
rrent systems). Este lenguaje es el tema de [9].

La notación de Backus-Naur (BNF) es ya un estándar para la presen-


tación de la sintaxis de lenguajes de programación. Sin embargo, en el
terreno de la semántica siguen predominando las explicaciones informales.
Aquí, en cambio, se usará una notación formal de aceptación creciente: la
semántica operacional estructural. Aunque no es el único formalismo para
describir los lenguajes de programación (por ejemplo, la semántica denota-
cional es una opción matemáticamente más elegante) sí es el más cercano
a las intuiciones del programador típico.

27
28 CAPÍTULO 2. LENGUAJES DE PROGRAMACIÓN

2.1. Programación imperativa


La sintaxis del lenguaje IMP se describe a continuación en la notación
de Backus-Naur. Empezaremos con las expresiones aritméticas (que ya se
presentaron antes):

a ::= n j x j (a + a0 ) j (a a0 ) j (a  a0 )

donde n 2 Z, x 2 Var y a, a0 2 EA.


Tenemos ahora las expresiones booleanas EB:

b ::= V j F j a0 = a1 j a0  a1 j :b j (b ^ b0) j (b _ b0)


donde a0 , a1 2 EA y b, b0 2 EB. Finalmente, los comandos del lenguaje se
definen así:

c ::= skip j x := a j (c ; c0 ) j (if b then c else c0 ) j (while b do c)

2.1.1. Semántica operacional estructural


La forma más común de definir el significado de las construcciones de
un lenguaje es por medio de explicaciones en una lengua natural (inglés,
generalmente). Sin embargo, el lenguaje natural se presta a las ambigüe-
dades y éstas, a su vez, a los errores o a las divergencias entre las diferentes
implementaciones de un mismo lenguaje. Para evitar estos problemas, aquí
se usarán reglas de semántica operacional estructural o SOE, para abreviar.
Una regla de inferencia tiene la forma siguiente:
p1 , : : : , pn
q
donde p1 , . . . , pn son las premisas y q es la conclusión. Las reglas de SOE
son un tipo particular de reglas de inferencia en las que las premisas y la
conclusión son transiciones. Una transición tiene la forma

!
La forma concreta de las expresiones y , así como las transiciones acep-
tables, se definirán más adelante.
IMP es un lenguaje imperativo típico: el comando básico es la asignación
de valor a las variables de la memoria de la computadora. Para definir
2.1. PROGRAMACIÓN IMPERATIVA 29

el significado de una asignación se puede partir de la existencia de una


máquina virtual que posee una memoria con localidades con nombre: x, y,
etc. Para simplificar, se puede pensar que el conjunto de localidades de la
memoria coincide con el conjunto Var y que estas localidades pueden tomar
valores de Z.
Un estado de la memoria es una función  : Var ! Z. La expresión
 ( x) nos dice que valor contiene la localidad x en el estado  . La alteración
del valor de una sola localidad de la memoria cuando ésta se encuentra
en el estado  se representa por medio de la función = x℄ , donde x es la
localidad cuyo valor se modifica y m es el nuevo valor. Más formalmente,
se tiene que: n
=x℄ ( y) =  ( y) si x 6= y
m en caso contrario.
El conjunto de estados es .
En el caso de las expresiones aritméticas, las transiciones ! tiene
la forma
ha, i ! n
donde a 2 EA,  2  y n 2 Z. En este caso diremos que “evaluar operacio-
nalmente la expresión a en el estado  da como resultado el valor n”. Dicha
evaluación se realiza de acuerdo con las siguientes reglas:

hn, i ! n h x, i ! ( X )
ha0, i ! n0 ha1, i ! n1 n0 op n1 = n
ha0 op a1, i ! n
En esta regla op puede ser +, o  y op, +Z, Z o Z (por conveniencia,
ambos operadores deben coincidir).
En las expresiones booleanas, una transición es hb,  i ! T, con b 2 EB,
 2  y T 2 fV, Fg. Las reglas operacionales son:
hV, i ! V hF, i ! F
ha0, i ! n ha1, i ! m
ha0 = a1, i ! V sii n y m son iguales

ha0, i ! n ha1, i ! m
ha0 = a1, i ! F sii n y m no son iguales
30 CAPÍTULO 2. LENGUAJES DE PROGRAMACIÓN

ha0, i ! n ha1, i ! m
ha0  a1, i ! V sii n es menor o igual a m

ha0, i ! n ha1, i ! m
ha0  a1, i ! F sii n no es menor o igual a m

hb, i ! V hb, i ! F
h:b, i ! F h:b, i ! V
hb0, i ! T0 hb1, i ! T1 con T = V si T0 , T1 = V y T = F
hb0 ^ b1, i ! T en caso contrario

hb0, i ! T0 hb1, i ! T1 con T = V si T0 = V o T1 = V y


hb0 ^ b1, i ! T T = F en caso contrario
Las reglas de transición de los comandos son así:
hc, i ! 0,
donde c 2 IMP y , 0 2 . El valor de 0 se infiere de este modo:
Comandos atómicos

hskip, i !  ha, i ! m
h X := a, i !  m= X
[ ℄

Composición secuencial
hc0, i ! 00 hc1, 00i ! 0
hc0 ; c1, i ! 0
Condicionales
hb, i ! V hc0, i ! 0 hb, i ! F hc1, i ! 0
hif b then c0 else c1 , i ! 0 hif b then c0 else c1 , i ! 0
Ciclos
hb, i ! F
hwhile b do c, i ! 
hb, i ! V hc, i ! 00 hwhile b do c, 00i ! 0
hwhile b do c, i ! 0
2.1. PROGRAMACIÓN IMPERATIVA 31

Dadas las reglas anteriores, no es difícil ver que el programa de IMP


siguiente calcula el factorial del número n (si n  0) y lo guarda en la
localidad y:
x := 1;
y := 1;
while x  n do
( x := x + 1;
y := y  x)

2.1.2. No determinismo
Como primera aproximación a la computación, IMP es bastante bueno.
No obstante, hay una serie de “fenómenos” computacionales que no pue-
den modelarse con IMP. Uno de estos es el no determinismo, es decir, la
posibilidad de que la ejecución de un programa (o un conjunto de ellos) dé
resultados distintos en distintas ocasiones a pesar de que recibe los mismos
datos de entrada siempre.
El no determinismo puede surgir en diversas situaciones. La más común
es la concurrencia de procesos (como se verá más adelante), pero también
puede presentarse por una decisión en el diseño mismo de los lenguajes
de programación. En este caso, el lector que se enfrenta por primera vez
al no determinismo podrá pensar que se trata de una maniobra artificial
sin justificación. Pero sí hay un motivo para introducir voluntariamente
no determinismo en un lenguaje: al presentarlo al margen de sus causas
(como la concurrencia) es mucho más fácil entender su naturaleza pues no
aparece entremezclada con características propias de otras situaciones (de
nuevo, como en la concurrencia).
Así que ahora se presentará un lenguaje imperativo con no determinis-
mo explícito. Para esto necesitaremos una categoría especial de comandos
llamados comandos resguardados (guarded commands). La sintaxis es

g ::= b ! c j g g0

donde g y g0 son comandos resguardados y b 2 EB.


Como los comandos resguardados son básicos en nuestro lenguaje, lo
llamaremos GCL: guarded command language. He aquí la sintaxis de GCL:

c ::= skip j abort j x := a j (c ; c0 ) j if g fi j do g od


32 CAPÍTULO 2. LENGUAJES DE PROGRAMACIÓN

donde abort es un nuevo programa primitivo, g es un comando resguarda-


do y c, c0 2 GCL.
Nuevamente, la mejor forma de explicar el significado de los coman-
dos de GCL es por medio de reglas operacionales. Comencemos con las de
comandos resguardados:
hb, i ! V hb, i ! F
hb ! c, i ! hc, i hb ! c, i ! fail
hg0, i ! hc, 0i hg1, i ! hc, 0i
hg0 g1, i ! hc, 0i hg0 g1, i ! hc, 0i
hg0, i ! fail hg1, i ! fail
hg0 g1 , i ! fail
Ahora seguimos con las reglas para comandos generales:

hskip, i !  ha, i ! m
h X := a, i !  m= X
[ ℄

hc0, i ! 00 hc1, 00i ! 0 hc0, i ! hc00, 0i


hc0 ; c1, i ! 0 hc0 ; c1, i ! hc00 ; c1 , 0i
hg, i ! hc, 0i
hif g fi, i ! hc, 0i
hg, i ! fail hg, i ! hc, 0i
hdo g od, i !  hdo g od, i ! hc ; do g od, 0i
El lector puede verificar, haciendo uso de las reglas anteriores y de su
conocimiento del viejo algoritmo de Euclides, que el siguiente programa
calcula el máximo común divisor de los enteros positivos n y m y lo guarda
en las localidades x y y.
x := n;
y := m;
do
x > y ! x := x y

y > x ! y := y x
od
2.2. UN LENGUAJE FUNCIONAL 33

Nota: x > y es una abreviatura, obviamente, de y  x ^ :( x = y).

2.2. Un lenguaje funcional


Un estilo de programación radicalmente distinto al imperativo es el fun-
cional. A riesgo de simplificar, la idea básica es que en lugar de programas
con instrucciones detalladas a la computadora, se deben usar definiciones
de funciones y aplicaciones de éstas a argumentos dados. Para evitar con-
fusiones, es mejor entrar en materia y presentar la sintaxis de un lenguaje
funcional simple:
t ::= n j x j t + t0 j t t0 j t  t0 j if t then t0 else t00 j fi(t1, : : : , tn)
t, t0 y t0 designan términos de nuestro lenguaje funcional. Obsérvese co-
mo en el condicional no se usan expresiones booleanas sino términos como
condición. Como se verá más adelante en la presentación formal de la se-
mántica, el valor 0 tendrá el papel de verdadero y cualquier otro valor se
considerará falso.
El estilo funcional de programación permite prescindir de la referencia
a una máquina virtual y su memoria. En su lugar, las funciones tomarán su
significado a partir de declaraciones. Una declaración es un conjunto finito
de ecuaciones donde, del lado izquierdo, aparace una función con varia-
bles como argumentos y, del lado derecho, aparecen términos del lenguaje
funcional.
f1 ( x1 , : : : , xn1 ) = d1
..
.
fk ( x1 , : : : , xnk ) = dk

donde d1 , . . . , dk son términos del lenguaje funcional. No se permite más de


una ecuación por cada función, pero sí se acepta la recursividad, es decir,
que una función aparezca del lado derecho de la ecuación que la define.
Las transiciones ahora son de la forma
t !ds t0
donde t y t0 son términos del lenguaje, d es una declaración (y, por tanto,
las transiciones dependen de declaraciones específicas) y s puede tomar el
34 CAPÍTULO 2. LENGUAJES DE PROGRAMACIÓN

valor v (llamada por valor) o n (llamada por nombre), que designan a dos
estilos semánticos posibles. En el estilo de llamada por valor, los argumen-
tos de las funciones son evaluados antes de evaluar la función misma. En
el estilo de llamado por nombre, la evaluación se pospone hasta que se
evalúa el cuerpo mismo de la función. La diferencia entre los dos estilos
se manifiestan sólo en una regla de evaluación de términos y, por este mo-
tivo, es mejor pasar directamente a las reglas antes de profundizar en las
diferencias semánticas:

Reglas con llamada por valor

Números
n !dv n

Operadores
t0 !dv n0 t1 !dv n1
t0 op t1 !dv n0 op n1

Condicional verdadero
t0 !dv 0 t1 !dv n1
if t0 then t1 else t2 !dv n1

Condicional falso
t0 !dv n0 t2 !dv n2 n0 6= 0
if t0 then t1 else t2 !dv n2

Funciones
t1 !dv n1    tmi !dv nm i
di [n1 = x1 ,:::,nmi = xmi ℄ !dv n
fi (t1 , : : : , tmi ) !dv n

Conviene prestar atención a la última regla, pues es la que varía con res-
pecto a la llamada por nombre.
2.2. UN LENGUAJE FUNCIONAL 35

Reglas con llamada por nombre

Números
n !dn n

Operadores
t0 !dn n0 t1 !dn n1
t0 op t1 !dn n0 op n1

Condicional verdadero
t0 !dn 0 t1 !dn n1
if t0 then t1 else t2 !dn n1

Condicional falso
t0 !dn n0 t2 !dn n2 n0 6= 0
if t0 then t1 else t2 !dn n2

Funciones
!dn n
di [t1 = x1 ,:::,tmi = xmi ℄
fi (t1 , : : : , tm ) !dn n
i

Es momento de presentar un ejemplo de programa. Supóngase que se


tiene la siguiente declaración:
f1 ( x) = if x then 1 else f1 ( x 1)  x
f2 ( x, y) = x
f3 ( x) = f3 ( x + 1)
Entonces el programa f1 (n) calcula el factorial de n, en cualquiera de los
dos estilos de programación. En cambio, considérese el programa
f2 (2, f3 (1)).
De acuerdo con las reglas de llamado por nombre, para realizar la evalua-
ción del programa debemos evaluar la expresión
x[ x=2, y= f3 (1)℄ = 2
36 CAPÍTULO 2. LENGUAJES DE PROGRAMACIÓN

que, de acuerdo con la regla para números, nos da 2. En cambio, las reglas
de llamada por valor nos piden que primero evaluemos los términos

2 y f3 (1)

el segundo de los cuales nunca nos da un resultado, como puede deducirse


de la tercera ecuación de la declaración.
Nota: si se adopta el estilo de llamada por valor, el lenguaje funcional
se asemeja a un subconjunto de ML. Si se adopta llamada por nombre, será
parecido a Haskell.

2.3. Procesos concurrentes


La idea de que un sistema de cómputo se basa en la ejecución secuencial
de una serie de instrucciones por parte de un ente aislado hace mucho que
es obsoleta.
La mayoría de los sistemas actuales contiene, en mayor o menor medi-
da, subsistemas que actúan de manera simultánea (real o simuladamente)
y que intercambian información entre sí. Estos sistemas se llaman concu-
rrentes.
Hay varios modelos de cómo se realiza el intercambio de información
entre subsistemas, pero dos son los fundamentales: (a) memoria comparti-
da; (b) envío de mensajes. En el primero, se supone que hay un área de la
memoria (variables, buffers, etc.) a la que varios sistemas concurrentes tie-
nen acceso para guardar o leer datos. Por su parte, el envío de mensajes se
realiza por un medio abierto (difusión) o por medio de canales específicos.
En los 80, Robin Milner propuso un lenguaje de especificación para pro-
cesos concurrentes: CCS (Communicating Concurrent Systems). Dicho len-
guaje consta de:

Un conjunto de valores (enteros, por ejemplo) que se envían o reciben


a través de canales , , etc.

Operadores para la composición secuencial o paralela de procesos.

Un operador de “elección”

Operaciones para reetiquetar canales y restringir el acceso a éstos.


2.3. PROCESOS CONCURRENTES 37

Para comenzar, tenemos las acciones de comunicación entre procesos


básicas:
 ::=  j !m j ?m
 es la acción nula, !m es el envío de m por el puerto de salida del canal
y ?m es la recepción de m por el puerto de entrada del mismo canal.
Recurriendo de nuevo a la notación BNF, los procesos de CCS se definen
así: X
p ::= nil j  . p j pi j p k p0 j pn L j p[ f ℄ j P
2
i I

En términos informales, la sintaxis contienen los siguientes elementos:

nil es un proceso que no realiza ninguna acción y se considera primi-


tivo;

 es una acción;
P es la elección arbitraria de un proceso tomado del conjunto de
procesos indexado por I;

k es la composición paralela de procesos (intuitivamente, ambos pro-


cesos pueden realizarse simultáneamente);

L es un conjunto de canales (cuyo acceso se restringirá a otros proce-


sos, como se verá más adelante en las reglas);

P designa a un proceso definido por medio de una expresión del tipo

P def p

que puede tener carácter recursivo.

Las ideas anteriores se pueden expresar con más claridad por medio de
reglas SOE:

Procesos resguardados

. p !p


Sumas
38 CAPÍTULO 2. LENGUAJES DE PROGRAMACIÓN

P 2 p!!q q

j2I
pj

i I i

Composición

p0 ! p00

p1 ! p01

p0 ! p00 p1 !
 ¯
p01
p0 k p1 ! p00 k p01

p0 k p1 ! p00 k p1

p0 k p1 ! p0 k p01


Restricción
! q  62 L [ L̄
p


pn L ! qn L


Reetiquetamiento

p !q 

p[ f ℄ ! q[ f ℄
f ( )

Identificadores
p !q

donde P def p.
P !q


You might also like