LOGICA COMPUTACIONAL TEMA Introducción Lógica de

Anuncio
LOGICA COMPUTACIONAL
TEMA
Introducción
Lógica de Proposiciones
Fundamentos
de Prueba de Teoremas
GSAT
Satisfactibilidad y complejidad
Lógica de Predicados
Formas Prenexas
y Algoritmo Clausular
Sustitución y Unificación
Resolución y Completez
Resolución
Regla de una Literal
de Davis y Putnam
Regla de una Literal Estructurada
con Regla de Partición
Especificación Formal
Lógicas de Hoare
INTRODUCCIÓN
La Lógica Formal proporciona un medio para representar argumentos de una manera formal y
rigurosa, estudia los fundamentos relacionados con su validez y los métodos para inferir
proposiciones a partir de otras consideradas válidas.
Por su parte, la Lógica Computacional es una disciplina que estudia la aplicación de la Lógica Formal
para la representación computacional de argumentos, las técnicas de deducción automática o
asistida por computadora, los fundamentos relacionados con validez y completez (completeness) de
sistemas de proposiciones y, las aplicaciones de esas técnicas a las diferentes áreas de las Ciencias
Computacionales en todas las etapas del desarrollo del software, es decir, especificación, diseño,
construcción y verificación formal de programas.
La Lógica Computacional, sin embargo, no actúa de manera aislada. Para el establecimiento de
fundamentos de las ciencias computacionales concurren conjuntamente con la Lógica
Computacional, disciplinas como Teoría de la Computación y Análisis de Algoritmos; para el
desarrollo de sistemas, la Lógica Computacional participa con la Ingeniería de Software para el
establecimiento de Métodos Formales de Especificación y Verificación de Programas, los cuales
pueden ser usados para el desarrollo de sistemas críticos y/o concurrentes. Por otra parte la Lógica
Computacional en conjunción con otras disciplinas permite la resolución eficiente de problemas
complejos, así por ejemplo Métodos de Optimización Combinatoria y de Lógica Computacional
mezclados adecuadamente con métodos heurísticos de la Inteligencia Artificial ofrecen alternativas
de solución a problemas computacionales muy dificiles que se les ha denominado NP completos.
La Lógica Computacional es muy amplia, por lo que no se puede cubrir plenamente en un solo
semestre. Por esa razón, para este curso se ha hecho una selección de temas representativos de
esta disciplina. Se presentan las técnicas y principios básicos y sus áreas de aplicación. El curso hace
énfasis en la Lógica Proposicional y en la Lógica de Predicados, debido a que de esa manera es mas
fácil presentar ejemplos y aplicaciones sobre ésas lógicas, lo cual no quita ni generalidad a los
conceptos ni valor a las aplicaciones; por otro lado, el aprendizaje de esas Lógicas es necesario
para el entendimiento posterior de Lógicas No-Clásicas; sin embargo se hace una presentación de la
Lógica Modal y Temporal, con información suficiente como para que el alumno empiece a realizar
aplicaciones donde el factor tiempo sea crucial. Se hace un análisis de la Lógica de Hoare y se
explican sus axiomas a la luz del Cálculo de Secuentes de Gentzen. Esto nos permitirá explicar
métodos de especificación y verificación formal. Se discuten la importancia de la Lógica de Hoare en
sistemas distribuídos y concurrentes.
Debido a la amplitud de los temas, consideramos que es mas importante que el alumno aprenda a
realizar investigación y a trabajar en equipo sobre aspectos de la Lógica Computacional y, a
apreciar la importancia de la Lógica y de la Lógica Computacional, ya que de esa manera se habrá
sembrado la semilla de aprender continuamente sobre está disciplina. Por otra parte el trabajo en
equipo, no sólo facilita el aprendizaje, sino que además entrena al alumno a resolver los problemas
como deben ser resueltos en esta sociedad: colaborativamente.
LÓGICA PROPOSICIONAL
En la Lógica Formal se estudian los principios y métodos a través de los cuales podemos determinar
la validez de argumentos, desde el punto de vista solamente de su estructura, sin tomar en cuenta
el contenido semántico de las expresiones de los argumentos. De esta manera si se argumenta que:
Todos los majadistanenses son de Majadistán
Rudistein es Majadistanense
En consecuencia,Rudistein es de Majadistan.
En este argumento, no tomamos en cuenta si los majadistanenses son humanos, perros, pericos o
un concepto abstracto de cualquier área.
Tampoco nos importa si Rudinstein es un ciudadado de alguna ciudad del mundo o si es el nombre
de un perro.
De esta manera desde el punto de vista de su estructura este argumento es válido.
Se hace incapié que la Lógica no se hace responsable de su aplicación a nivel semántico.
Se puede decir que la Lógica es una herramienta para el análisis de la veracidad de argumentos en
base sólo a la estructura de éstos, donde el significado de los elementos que intervienen no es
tomado en cuenta.
El argumento anterior tiene dos partes principales:
A) Las premisas:
Todos los majadistanenses son de Majadistán
Rudistein es Majadistanense
B) La conclusión:
Rudistein es de Majadistán
De esta manera el argumento es válido, ya que de las premisas sigue la conclusión, lo cual hasta
cierto punto nos parece totalmente natural. Consideremos el siguiente argumento:
Argentina está en Africa o Argentina está en Asia.
Argentina no está en Asia
En consecuencia, Argentina está en Africa.
Nuevamente este argumento es válido desde el punto de vista lógico, aún cuando sabemos que la
conclusión es falsa.
¿Cómo puede ser ésto? ¿A partir de la Lógica se pueden obtener conclusiones equivocadas?
La respuesta es afirmativa, ya que la lógica no verifica el significado de las premisas.
Debido a lo anterior es necesario distinguir entre proposiciones verdaderas y proposiciones
lógicamente verdaderas.
Las primeras son verdaderas independientemente de su estructura, mientras que las segundos no lo
son. De esta manera, las proposiciones:
Argentina está en Africa o Argentina está en Asia
Argentina está en Africa
Son verdaderas lógicamente debido a que la primera es una premisa y a que la segunda ha sido
derivada lógicamente de sus premisas.
Las proposiciones son expresiones que pueden ser evaluadas como verdaderas o falsas.
En los lenguajes naturales (Español, Inglés, etc), las proposiciones sólo pueden ser expresiones
declarativas y nunca interrogativas o imperativas.
De esta manera las siguientes son proposiciones:
Los cantantes no duermen.
Comer mucho, engorda
Las montañas cantan bonito
Los mosquitos viven menos de un año
El hombre desciende del elefante
Sin embargo, las siguientes no son proposiciones por no poder ser evaluadas como verdaderas ni
falsas:
¡Levántate temprano!
¿Has entendido lo que es una proposición?
¡Estudia esta lección!
¿Cuál es la dirección de la página de Lógica Computacional?
En este módulo estudiamos la lógica proposicional, es decir, se estudian los principios para
determinar la validez de argumentos conformados con proposiciones. Esto involucra los siguientes
tipos de proposiciones:
* Proposiciones simples o átomos
* Proposiciones compuestas
Los átomos o proposiciones simples son tales que no es posible encontrar en ellas otras
proposiciones, mientras que las proposiciones compuestas están conformadas de varias
proposicones simples a través de lo que se denomina conectores lógicos, entre los cuales se
encuentran: y, o, implica.
Ejemplo de proposiciones compuestas son:
Las montañas cantan bonito o Los mosquitos viven menos de un año.
El hombre desciende del elefante y Comer mucho, engorda.
CONECTIVAS LOGICAS
Las conectivas lógicas también se llaman a veces operadores, y son de dos tipos:
Operadores unarios:
NEGACION: not, ¬
Operadores binarios:
CONJUNCION: and, &, y
DISYUNCION: or
CONDICIONAL: implies, ==>, implica
BICONDICIONAL: <==>
FORMULAS BIEN FORMADAS
El Cálculo Proposicional estudia fórmulas proposicionales simples o compuestas.
Las proposiciones simples o átomos son representadas por símbolos, generalmente las letras del
alfabeto A,B,C,....
Para obtener proposiciones compuestas se utilizan, como se dijo antes, conectores lógicos. Así la
proposición compuesta A or B puede corresponder por ejemplo a:
El coronel no tienen quien le escriba
or
La jubilación del Coronel Buendía es insuficiente para su familia
Una fórmula bien formada (fbf) es una expresión que representa una proposición simple o
compuesta, la cual esta bien escrita de acuerdo con determinada sintaxis.
Ahora bien, una fbf del Cálculo Proposicional, es una fórmula que está bien escrita de acuerdo con
la sintaxis del Cálculo Proposicional.
Las reglas de la sintaxis del Cálculo Proposicional definen de esta manera la forma de escribir o
reconocer susu fbf's. Estas reglas son:
a) Un átomo es una fórmula bien formada.
b) Si G es una fórmula bien formada entonces ¬G también lo es.
c) Si G y H son fórmulas bien formadas, entonces también lo son:
G&H
G or H
G ==> H
G <==> H
d) Todas las fbf's se obtienen aplicando a, b y c.
Es necesario puntualizar en la regla c anterior, que es posible utilizar otras conectivas, pero sin
embargo son reducibles a las que aqui presentamos.
De esta manera, fijaremos nuestra atención solo a las fbf's que aquí describimos.
Ejemplos de fórmulas bien formadas son:
P&Q
P ==> Q
Ejemplos de fórmulas que no son bien formadas son: P &, ==>Q.
DEMOSTRACIÓN Y REGLAS DE INFERENCIA
RESUMEN
En el Cálculo Proposicional, existen dos métodos comunes de realizar una demostración: Directo e
Indirecto.
Ambos métodos realizan una demostración obteniendo una sucesión de fórmulas
F1,F2,...,Fn
Donde cada una de estas fórmulas se obtiene a través de reglas de inferencia o es un axioma. Aquí
se discuten lo dos métodos de demostración directo e indirecto y las principales reglas de inferencia
utilizadas en dichos métodos.
PALABRAS CLAVE: LÓGICA PROPOSICIONAL, DEMOSTRACIÓN, DEDUCCION, I NFERENCIA
INTRODUCCIÓN
Una fórmula G es una consecuencia lógica (CL) de un conjunto de fórmulas F1,F2,...,Fn, si cuando
F1,F2,...,Fn son verdaderas, G también lo es. A partir de esta definición se han establecido dos
teoremas:
TEOREMA 1: G es una CL de F1,F2,..,Fn si y solo si F1Ù F2Ù ..Ù Fn Þ G es válida.
TEOREMA 2: G es una CL de F1,F2,..,Fn si y solo si F1Ù F2Ù ..Ù FnÙ (~ G) es inconsistente.
Para determinar sí una fórmula G sigue de un conjunto de fórmulas F1,F2..,Fn, se pueden utilizar
tablas de verdad. Esto será verdad F1Ù F2Ù ..Ù Fn Þ G es válida
o F1Ù F2Ù ..Ù FnÙ (~ G) es inconsistente.
Otra alternativa es utilizar el enfoque deductivo, el cual considera las fórmulas involucradas (G y
F1,..,Fn) dentro de una teoría formal, de modo que G pueda ser obtenida a partir de las fórmulas F’s
(de ahí que se diga que G siga de las F’s).
En el marco del enfoque deductivo, se dice que una Teoría Formal (TF) consiste de los siguientes
elementos [DOWSING et al] [MENDELSON]:
1) Las reglas de sintaxis que definen las fórmulas que pueden ser tratadas en la TF.
2) Un conjunto de fórmulas llamadas axiomas las cuales se suponen verdaderas en la TF.
3) Un conjunto de Reglas de Inferencia que establece bajo que circunstancias una fórmula se puede
obtener (derivar) a partir de otras existentes. La fórmula derivada será una CL de las formulas que
le dieron origen.
Dentro de cualquier rama de la Ciencia se pueden establecer teorías formales (o TF’s), cada una de
los cuales tendrá sus propios axiomas.
Por ejemplo el siguiente es un axioma de la física newtoniana: La aceleración de un cuerpo es
proporcional al producto de su masa por la fuerza ejercida sobre él. Este axioma se describe por la
fórmula:
F=ma
(1)
Este es un axioma puesto que lo tomamos como verdadero en el contexto de la mecánica
newtoniana.
Es de observar que (1) fué establecido como verdadero partiendo a su vez de otros enunciados
supuestos también verdaderos, lo cual nos remontaría a axiomas como los de la geometría de
Euclides y así sucesivamente hasta llegar a axiomas relacionados con la existencia misma del ser y
la verdad.
Esto, si nos se tiene cuidado, podría llevarnos por caminos absurdos ó no, del dogmatismo.
Podríamos pensar entonces que la ciencia es dogmática, sin embargo, la diferencia entre el
dogmatismo y la ciencia estriba en que la ciencia constante investiga la veracidad de los axiomas y,
en cuanto se descubre que uno de ellos es falso, se realizan un cambio de paradigma, es decir, un
cambio en el conjunto de axiomas y de sus reglas de inferencia.
El problema de la deducción está inmerso en todas las ramas de las Ciencias por lo que es necesario
conocer no solo lo que significa sino también los mecanismos de inferencia que se pueden aplicar en
ellas.
DEMOSTRACIÓN
Una demostración de una fórmula A es una sucesión de fórmulas P1,P2,..,Pn, tales que:
a) Cada Pi es:
* Un axioma o,
* Una fórmula obtenida a partir de las anteriores.
b) El último elemento Pn, es A, la fórmula que se desea demostrar.
En la definición anterior las fórmulas que se mencionan en el inciso b) son obtenidas a partir de
reglas de inferencia.
Como se mencionó en la introducción, las reglas de inferencia nos dicen cuales son las condiciones
para poder obtener por CL otra fórmula a partir de las que previamente han sido probadas; de esta
manera, las fórmulas que obtenemos usando reglas de inferencia son consideradas válidas,
Entre las Reglas de Inferencia más comunes se encuentran Modus Ponens la cual establece que:
||= A, ||= AÞ B
_________________
(2)
||= B
donde el símbolo ||= establece que la fórmula que sigue es verdadera.
La fórmula (2) tiene una estructura conocida como "secuente". Los secuentes fueron establecidos
por Gentzen en lo que se conoce como Cálculo de secuentes, lo que permitió un gran avance en las
técnicas de deducción.
La regla de Modus Ponens comúnmente esta regla se establece como sigue:
"Sí dos proposiciones X, X Þ Y son verdaderas, podemos inferir que Y es verdadera"
REGLAS DE INFERENCIA GENERALES:
Para la realización de cualquier demostración:
P1,P2,...,Pn
Cada Pi se puede obtener por una de las tres reglas de inferencia generales
[TREMBLAY&MANOHAR]:
1) REGLAS P: Una fórmula Pi puede ser introducida en cualquier punto de la demostración.
2) REGLA T: Una fórmula S puede ser introducida en una demostración si S es CL de las fórmulas
precedentes.
3) REGLA CP: Sí podemos derivar S a partir de R y un conjunto de premisas, entonces podemos
derivar RÞ S a partir solamente del conjunto de premisas.
REFERENCIAS
[DOWSING] R.D. Dowsing, V.J. Rayward- Smith. C.D. Walter, " A first course in Formal Logic and its
applications in Computer Science", Blackwell Scientific Publication, 1986, pp 26.
[MENDELSON] Elliot Mendelson, "Introduction to Mathematical Logic",Third Edition,Wadsworth Inc.
Wadsworth & Brookscole Advanced Books & Software Division, 1987.
[TREMBLAY & MANOHAR] J.P. Tremblay, R. Manohar" Discrete Mathematical Structures with
Applications to Computer Science", McGraw Hill International Editions, 1987.
GSAT
INTRODUCCION
G es la abreviatura para Greedy y SAT es la abreviatura satisfactibilidad, refiriéndose al problema de
la lógica proposicional que así se llama y que consiste en determinar los valores de verdad de las
literales Xj de una forma norma conjuntiva F= F1 & F2 & ...& Fn, donde cada Fi se denomina una
cláusula y es una disyunción de literales Xj. Cada literal Xj es tambien conocida como una
proposición y la forma en que se encuentra F se dice que es una Forma Normal Conjuntiva o FNC.
Dado que se pudiera plantear un problema similar en Logica de Predicados ó en otra lógica, el
problema anterior se llama Problema de Satisfactibilidad de Lógica Proposicional, sin embargo, a
menos que se especifique otra cosa, cuando se dice SAT se entiende que se trata del problema SAT
de lógica proposicicional y no de otro.
Para GSAT el problema de SAT es visto como sigue: Dada una fórmula F del Cálculo Proposicional
con clausulas conformadas por literales propositivas (consideradas verdaderas), determinar una
interpretación de las variables (símbolos de proposiciones) que hagan que F sea satisfactible
(verdadera para ésa interpretación). Sí se encuentra dicha interpretación, mostrar cuáles
proposiciones deben ser verdaderas para que la fórmula F sea verdadera en ésa interpretación.
GSAT se ha probado particularmente para la instancia de SAT donde solo se permiten tres literales
propositivas por claúsula; ésa instancia es conocida como 3 SAT y representa al problema de
encontrar una asignación de valores de verdad satisfactoria para una oración en un formato especial
denominado 3 FNC la cual es una forma normal conjuntiva donde solo se permiten tres literales por
claúsula.
Las literales Xj aparecen con signos negativos o sin ellos. Se dice que una literal Xj tiene signo
propositivo si ella conjuntamente con su signo es considerada verdadera. Una proposición
propositiva es aquélla que tiene un signo propositivo. Existen varias convenciones, pero una posible
es aquélla en la cual la primera vez que aparece una literal ésta es considerada propositivamente.
EJEMPLO1 : En la siguiente formula:
(~P v R v ~T) & (P v ~R v S)
Las siguientes son proposiciones propositivas: ~P, R, T, S.
El valor de verdad para las proposiciones propositivas anteriores es V. De esta forma los valores de
verdad para P, R, S, T son respectivamente: F, V, V, V.
Las clausulas Fi pueden tener diferente número de literales dependiendo del problema SAT de que
se trate. Para distinguir entre el número de literales en la instancia del problema de que se trate, se
usa a veces la siguiente denominación:
2 Clausula: Clausula con dos literales
3 Clausula: Cláusula con tres literales
k Clausula: Cláusula con k literales
De esta forma se tienen instancias de problemas SAT denominados como sigue:
2 SAT: Solo se permiten clausulas con dos literales
3 SAT: Solo se permiten clausulas con tres literales
...
k SAT: Solo se permiten clausulas con k literales
3 SAT es la instancia del problema SAT el cual es NP Completo.
Durante mucho tiempo, SAT fue abordado con un enfoque de demostración de teoremas con
algoritmos tipo Resolución. Dentro de estos enfoques sobresale el método de Davis & Putnam
[Davis60] quienes establecieron varias reglas útiles en la demostración automática de Teoremas,
mismas que son estudiadas por la Lógica Computacional. Dentro de las reglas de Davis & Putnam,
hay dos que lllaman la atención: 1) La regla de una literal (R1L) y 2) La regla de Partición (RP). Los
problemas de SAT fueron abordados primero con R1L y luego por RP. Existen además versiones
modernas de las reglas de Davis & Putnam para cómputo paralelo y distribuido [Fang92] las cuales
han sido poco exploradas para el problema de SAT.
Desde la decada de los 1990's, el interes por el problema SAT se vió acrecentado, dadas las
implicaciones en Teoria de la Complejidad y las multiples aplicaciones que SAT tiene en una inmensa
cantidad de problemas, del área de planeación, scheduling, diseño de circuitos, etc. Las técnicas de
solución que han aparecido desde la decada de los 1990´s se han enfocado a métodos de
optimización combinatoria. Uno de los primeros en utilizar ese enfoque fue Selman en su famoso
algoritmo de GSAT [Selman 92]al emplear un algoritmo de optimización tipo GREEDY, es decir
glotón, para tratar de resolver el problema SAT. Algunos investigadors, entre ellos Selman
[Selman93], consideran que algoritmos tipo GSAT resuleven problemas mas dificiles que los
métodos de Davis & Putnam, cuestión que no ha sido absolutamente probada. No obstante el
algorimo de GSAT es importante porque ha dado pie a una gran cantidad de algoritmos y, por que
sirve de medida de comparación en el desarrollo de nuevos algoritmos que abordan SAT. Aqui
presentamos una breve descripción de GSAT.
PROBLEMA SAT VISTO POR GSAT
El problema SAT es vsito por GSAT de la siguiente manera:
Sea una fórmula F que se encuentra en su FNC conformada por claúsulas Fi de forma que:
a) Una literal Xj es un símbolo de proposición con un signo propositivo o su negación.
b) Una cláusula es una disyunción de literales; una cláusula 3 es la disyunción de exactamente tres
literales.
c) Una oración (fórmula) en FNC es un conjunto de cláusulas, una oración 3 FNC es el conjunto de
tres cláusulas.
Ejemplo 2.
Para la siguiente formula normal conjuntiva:
(P or Q or S)(P or Q or -R)(-P or -R or -S)(P or -S or T)
O bien: (P or Q or S) & (P or Q or -R) & (-P or -R or -S) & (P or -S or T)
Es una oración 3FNC con cuatro cláusulas y cinco proposiciones propositivas: P, Q, S, -R, T.
EL AGORITMO DE GSAT
Tal como es planeado por el propio Selman [Selman92], GSAT es un algoritmo no-determinístico de
búsqueda local. Los algoritmos No-determinínisticos son aquéllos que emplean técnicas estocásticas
de búsqueda. En el caso de GSAT, emplea una de tipo Montecarlo. GSAT es un algoritmo glotón o
Hill Climbing de reincio aleatorio. Parte de un estado inicial el cual consiste en asignar valores de
verdad a las variables proposicionales propositivas.
EJEMPLO 3.
Determinar el estado inicial al problema SAT del ejemplo 2.
Solución
Una alternativa es la siguiente. Asignar V(verdadero, ó 1) a las variables propositivas. De esta forma
se tiene:
T(P, Q, S, -R, T. )= (1,1,1,1,1)
Por lo tanto los valores de verdad para P, Q, S, R, T son: (1,1,1,0,1)
FUNCION DE EVALUACION
Los algoritmos de optimización utilizan una función de evaluación para medir la efectividad de cada
una de las soluciones. Dicha medida se conoce con diferentes nombres: Función objetivo, función de
aptitud, función de aceptación y en el caso de GSAT, función de evaluación. Cualquiera que sea el
nombre, el propósito es el mismo. Para SAT (y para la mayoría de los problemas de optimización),
no existe una función de evaluación única. La utiliación de una función de evaluación adecuada
impacta no solo en mejores soluciones sino, en muchos casos, en el tiempo de ejecución de los
algoritmos para llegar a la solución bsucada. La determinación de funciones de evaluación
adecuadas es una linea de investigación abierta.
GSAT usa como función de evaluación la cantidad de cláusulas satisfechas (verdaderas).
EJEMPLO 4
Cuál es el resultado de la función de evaluación de GSAT para el estado inicial del problema SAT del
ejemplo 3.
SOLUCION.
Los valores de verdad del estado inicial son:
para P, Q, S, R, T son: (1,1,1,0,1)
Veamos el resultado de aplicar estos valores de verdad a cada una de las clausulas del problema:
T(P or Q or S)
T(P or Q or -R)
T(-P or -R or -S)
T(P or -S or T)
=1
=1
=1
=1
Por lo tanto, en el caso mencionado el estado incial se evalúa como cuatro.
PRESENTANDO EL ALGORITMO DE GSAT
La función de evaluación mide la cantidad de cláusulas satisfechas (verdaderas). En el caso
mencionado el estado incial se evalúa como tres. Si existen n signos propositivos, habrá n
operadores, donde cada operador tiene que modificar el valor de verdad de uno de los signos.
Puesto que se trata de una búsqueda avara, se utiliza siempre el operador que produce la mejor
evaluación (escogiendo uno al azar en caso de haber varios igualmente buenos). A menos que
encontremos una solución después de emprender un cierto número de ascensos (pruebas)
tendremos que desistir y empezar de nuevo desde una nueva asignación inicial (de ahí lo de que
éste sea un método multi-inicio). He aquí
El algoritmo:
function GSAT (oración, max_reinicios,max_ascensos) returns una asignación de verdad o falla
for i= 1 a max_reinicios hacer
A= Asignación de verdad generada aleatoriamente
for j= 1 para max_ascensos hacer
si A satisface la oración, entonces responder con A
else A= la mejor alternativa de los vecinos de A
end for j
end for i
return falla
EJERCICIO
a) ¿Es confiable el algoritmo GSAT (sound)?
b) ¿Es completo?
c) Implante GSAT y utilícelo para resolver los problemas que se añaden enseguida.
d) Utilice GSAT para resolver problemas 3SAT generados al azar, de diversas extensiones. Hay dos
parámetros clave: N, la cantidad de signos propositivos y C, la cantidad de cláusulas.
Investigaremos los efectos de la relación C/N en el tiempo de ejecución de GSAT. Fije el valor de N
en 20, haga una gráfica de la mediana del tiempo de ejecución en relación con C/N, considerando cd
C/N va de 1 a 10. N simboliza el valor de max_reinicios y 5N es el valor de max_ascensos.
e) Repita el procedimiento para tantos valores de N como su tiempo se lo permita.
f) ¿Qué podría concluir acerca de la dificultad de los problemas 3SAT para distintos valores de N y la
relación C/N?
Existe mucha información sobre SAT por ejemplo, el artículo de Selman et al. (1992) "A new method
for solving hard satisfiability problems", en donde verá más sobre GSAT.
Problemas de prueba.
1.Humo --> Humo
2.Humo --> Fuego
3.(Humo --> Fuego)--> (-Humo --> -Fuego)
4.Humo o Fuego o -Fuego
5.(Humo y calor)--> (Fuego) <--> ((Humo--> Fuego) o (calor --> Fuego))
6.(Humo--> Fuego)-->((humo y calor) --> Fuego)
7.(Grande o callado o (grande --> Callado))
8.(Grande y callado) o -Callado
Nota:
--> Significa implicación,
<--> Significa bicondicional
- Para indicar negación
REFERENCIAS
[Davis60] M. Davis and H. Putnam, "A computing procedure for quantification theory", Journal of
ACM, Vo., 7, No. 3, pp. 201-215, 1960.
[Fang92] Ming-Yi Fang, Wen-Tsuen Chen, "Vectorization of Generalized Procedure for Theorem
Proving in Propositional Logic on Vector Computer", IEEE Transactions on Knowledge and Data
Engineering, Vol. 4, No 5.
[Selman92] Bart Selman, Hector Levesque, David Mitchell, "A New Method for Solving Hard
Satisfiability Problems", Proceedings of the Tenth National Conference on Artificial Intelligence
(AAAI-92), San Jose, CA, July 1992, 440-446.
[Selman93] Bart Selman, Henry A. Kautz, "An empirical Study of Greedy Local Search for
Satisfiability Testing", Proceedings of the eleventh National Conference on Artificial Intelligence
(AAAI-93), Washington ,D.C., 1993.
COMPLEJIDAD COMPUTACIONAL
INTRODUCCIÓN
Prácticamente todas las áreas de las Ciencias Computacionales tratan, en mayor o menor grado con
complejidad computacional. El tema es muy común entre expertos del área, sobre todo entre
aquéllos relacionados con NP-completez y entre quienes buscan algoritmos eficientes para diversos
problemas de aplicación. La importancia de la complejidad computacional estriba en que se ha
convertido en una forma de clasificar buenos y malos algoritmos y de clasificar problemas
computacionales como fáciles y dificiles. Aquí presentaremos una introducción a este tema.
2. Algoritmos y Complejidad: Una Descripción General
Cada vez nos sorprendemos más de la velocidad de las computadoras de sus logros. Han permitido
la solución de problemas muy complejos que serían ciencia ficción hace apenos unos cuantos años:
Realidad virtual,simulación de procesos gigantescos, etc.
Pese a lo que pueda pensarse, las computadoras no realizan ninguna actividad que pudiera
calificarse como de una gran inteligencia. Las computadoras pueden únicamente llevar a cabo
algoritmos; esto es, secuencias de instrucciones precisas y universalmente entendibles que
solucionen cualquier instancia de problemas computacionales rigurosamente definidos.
A pesar de que se ha llegado a logros sorprendentes como derrotar a un campeón de ajedrez Gary
Kasparov en 1997 por una computadora Deep Blue de IBM, es dificil atribuirle características de
inteligencia, cuando se tuvieron miles de horas hombre programando estrategias que derrotaran a
Kasparov. Nótese que la inteligencia de Kasparonv requirió de cientos de cerebros pensando como
derrotarlo. ¿Cuantas horas-hombre hubiera requerido cada uno de los que programaron a Deep
Blue? ¿Cuál sería entonces la inteligencia relativa de estos hombres compardos con Kasparov?
Quienes programaron a Deep Blue pusieron una serie de pasos a realizar para cada posible ataque
de Kasparov. Es decir en Deep Blue pusieron algoritmos.
¿Pero qué son los algoritmos?
El concepto intuitivo de algoritmo, lo tenemos prácticamente todos:
Un algoritmo es una serie finita de pasos para resolver un problema.
Hay que hacer enfásis en dos aspectos para que un algoritmos exista:
1) El número de pasos debe ser finito. De esta manera el algoritmo debe terminar en un tiempo
finito con la solución del problema,
2) El algoritmo debe ser capaz de determinar la solución del problema.
Alan Turing, en 1936 desarrolló su Máquina de Turing (la cual se cubre en los cursos denominados
Teoría de la Computación o Teoría de Automátas), estableciendo que cualquier algoritmo puede ser
representado por ella.
Turing mostró también que existen problemas matemáticos bien definidos para los cuales no hay un
algoritmo. Hay muchos ejemplos de problemas para los cuales no existe un algoritmo. Un problema
de este tipo es el llamado problema de paro (halting problem):
Dado un programa de computadora con sus entradas, ¿parará este alguna vez?
Turing probó que no hay un algoritmo que pueda resolver correctamente todas las instancias de este
problema.
Alguien podría pensar en encontrar algunos métodos para detectar patrones que permitan examinar
el programa para cualquier entrada. Sin embargo, siempre habrá sutilezas que escapen al análisis
correspondiente.
Alguna persona más suspicaz, podría proponer simplemente correr el programa y reportar éxito si se
alcanza una declaración de fin. Desgraciadamente, este esquema no garantiza por sí mismo un paro
y en consecuencia el problema no puede ser resuelto con los pasos propuestos. Como consecuencia
de acuerdo con la definición anterior, ese último procedimiento no es un algoritmo, pues no se llega
a una solución.
Muchas veces aunque exista un algoritmo que pueda solucionar correctamente cualquier instancia
de un problema dado, no siempre dicho algoritmo es satisfactorio porque puede requerir de tiempos
exageradamente excesivos para llegar a la solución.
Por ejemplo, considere el problema del agente viajero, el cual se establece como sigue:
PROBLEMA DEL AGENTE VIAJERO:
Dado un grafo de N nodos y A arcos, determinar la ruta más corta que parta de un
nodo predeterminado Ni y visite todos los nodos solamente una vez y regrese al nodo de partida.
O su versión como un problema de decisión: Existe un recorrido más corto que un
valor K que parta de un nodo inicial Ni , recorra visite todos los otros N-1 nodos una sola vez y
regrese al nodo inicial Ni.
Este problema parece ser muy simple y puede ser que lo sea para ciertos tamaños de N y A.
Sin embargo existen instancias de este problema, con valores ni siquiera demasiado grandes de N y
A, para los cuales encontrar la solución es terriblemente ardúo. Tan solo basta pensar en una red de
computadoras de unos 500 nodos con cierta topología para que sea muy difícil determinar la ruta
más corta de un mensaje enviado desde un nodo i determinado y que debe visitar todos los nodos
solamente una vez, trayendo de regreso el mensaje enviado y la traza de los nodos visitados.
Para cualquier instancia del problema del agente viajero uno podría pensar en seleccionar todos y
cada uno de los diferentes recorridos posibles y luego compararlos para encontrar el de menor
longitud. Sin embargo, la ejecución de este algoritmo en una computadora requerirá de
aproximadamente n! pasos, lo que para instancias relativamente pequeñas lo vuelve inútil.
Para propósitos de comparación del rendimiento de diferentes algoritmos, se requiere de una
medida de rendimiento de algoritmos; la medida más ampliamente aceptada es el tiempo que el
algoritmo en cuestión consume antes de producir la solución final. Esta cantidad de tiempo puede
variar de una computadora a otra, debido a diferencias en su velocidad de procesamiento y en la
forma como el programa es traducido en instrucciones de máquina. En el análisis de algoritmos, el
tiempo siempre es expresado en términos del número de pasos elementales (operaciones
aritméticas, comparaciones, lecturas, escrituras, etc.) requeridos para la ejecución del algoritmo
sobre una computadora hipotética. Dichos pasos elementales tienen una duración unitaria de
tiempo. De esta forma, el tiempo requerido para la ejecución de un algoritmo es establecido como el
número de pasos elementales o instrucciones que efectúa antes de producir la solución final.
El número de pasos requeridos por un algoritmo no es siempre el mismo para todas las entradas y
frecuentemente es difícil obtener una fórmula precisa que establezca la función de tiempo. Es por
ello que se consideran tres medidas del tiempo de ejecución del algoritmo, las cuales dependen del
tamaño de la entrada n:
a. El mínimo tiempo necesario(mejor caso),
b. El máximo tiempo necesario (peor caso) y,
c. El tiempo promedio necesario (caso promedio).
De esta forma la complejidad de un algoritmo es función del tamaño de la entrada (por ejemplo
10n3, 2n, n log n).
El interés principal en el comportamiento de un algoritmo es para entradas grandes, pues estas
establecerán los límites de aplicabilidad de este. Por lo tanto, generalmente se tiene poco interés en
el valor exacto del tiempo requerido para la ejecución de un algoritmo. Siendo el interés principal la
razón de crecimiento del mejor caso
Por ejemplo, supóngase que el tiempo del peor caso de un algoritmo es:
t(n) = 60n2 + 5n + 1
para entradas de tamaño n.
Para n grandes, el término 60n2 es aproximadamente igual a t(n) (ver tabla 1). En este sentido, t(n)
crece como 60n2.
n
t(n) = 60n2 + 5n +
1
60n2
10
100
1,000
10,000
6,051
600,501
60,005,001
6,000,050,001
6,000
600,000
60,000,000
6,000,000,000
Tabla1: Razón de crecimiento del tiempo del peor caso de un algoritmo
Si la medida del tiempo de la tabla 1, está en segundos, se podría dividir entre 60 para obtener una
medida del tiempo del peor caso para entradas de tamaño n en minutos. Este cambio de unidades
no afecta la forma como crece la función f(n) que representa la medida del tiempo del peor caso. De
esta manera, se puede eliminar los coeficientes constantes. Con estas suposiciones t(n) crece como
n2 cuando se incrementa n.
La formalización de la eficiencia de los algoritmos para el peor caso, caso optimista y caso promedio,
se hace a continuación, mediante la definición de las siguientes funciones:
Sea f(n), g(n) dos funciones que van de los enteros positivos a los reales positivos.
a. f(n) es cuando mucho del orden de g(n) , escribiéndose f(n) (< =) O(g(n)),
si existe una constante c > 0 tal que, para una n suficientemente grande,
se cumple que f(n) (<, =) c g(n) .
b. f(n) es del orden de al menos g(n), escribiéndose f(n) (>, =) W (g(n))
si existe una constante c > 0 tal que, para una n suficientemente grande,
f(n) (> =) c g(n).
c. f(n) es del orden de g(n), escribiéndose f(n) = Q (g(n)), si existen dos constantes c,
c’ > 0 tales que, para una n suficientemente grande, c g(n) < f(n) < c’ g(n) .
De acuerdo a las definiciones anteriores:
* si f(n) < = O(g(n)), se puede concluir que f(n) está acotada por arriba por g(n).
Así es que g(n) crece al menos tan rápido como f(n).
* si f(n) > = W (g(n)), entonces, f(n) está acotada por abajo por g(n).
Así es que g(n) crece cuando mucho tan rápido como f(n).
* Si f(n) = Q (g(n)), podemos concluir que f(n) está acotada por arriba y por abajo por g(n).
Así es que f(n) y g(n) crecen a la misma razón.
Usando esta notación la razón de crecimiento de la complejidad de un algoritmo puede ser acotada
mediante frases como "toma un tiempo O(n3)".
Para leer un problema en una computadora, la entrada primero debe ser codificada como una
secuencia de símbolos sobre un alfabeto determinado, generalmente en una secuencia de bits. De
esta forma, el tamaño de la entrada es definido como la longitud de la secuencia o cadena de
símbolos, esto es el número de símbolos en ella.
La derivación de un límite superior riguroso para los requerimientos de tiempo de un algoritmo no es
siempre una tarea sencilla; este puede requerir de tanto ingenio y trucos como el diseño de un
algoritmo.
En la actualidad hay un acuerdo general entre los investigadores de que un algoritmo es de utilidad
práctica cuando su complejidad computacional crece polinomialmente con respecto del tamaño de la
entrada, por ejemplo, algoritmos de complejidad O(n) o O(n3). Naturalmente, algoritmos para los
cuales la complejidad asintótica no es un polinomio en sí pero puede ser acotada por un polinomio
n log n)
también están incluidos (n2.5,
Se le da el nombre de algoritmo exponencial a todo aquel que viola todo acotamiento polinomial
para instancias suficientemente grandes. Se les da este nombre porque 2n es una razón de
crecimiento no polinomial. Otros ejemplos de razones exponenciales de crecimiento son kn (para
cualquier constante k > 1), n!, nn y nlog n. Es obvio que, cuando el tamaño de la entrada crece,
cualquier algoritmo polinomial eventualmente llegará a ser más eficiente que cualquier algoritmo
exponencial (ver tabla 2).
Función
Valores Aproximados
n
10
100
n log n
33
n3
1,000
1,000,000
109
106 n8
1,014
1022
1030
2n
1,024
1.27 x 1030
nlog n
2,099
1.93 x 1013
7.89 x
1029
n!
3,628,800
10158
4x
102,567
664
1,000
9,966
1.05 x
10301
Tabla 2: Crecimiento de funciones polinomiales y exponenciales
Otra característica positiva de los algoritmos polinomiales es que toman más ventaja de los avances
de la tecnología. Por ejemplo, cada vez que una mejora tecnológica incrementa la velocidad de las
computadoras 10 veces, el tamaño de la instancia más grande que puede ser solucionada por un
algoritmo polinomial en una hora, por ejemplo, será multiplicado por una constante entre 1 y 10. En
contraste, un algoritmo exponencial experimentará únicamente un incremento pequeño que se
sumará al tamaño de la instancia que este puede resolver (ver tabla 3).
Función
Tamaño de la Instancia
Solucionada en un Día
Tamaño de la
Instancia
Solucionada en
un Día
en una
Computadora
10 Veces Más
Rápida
1012
1013
n log n
0.948 x 1011
0.87 x 1012
n2
106
3.16 x 106
n3
104
2.15 x 104
108 n4
10
18
2n
n
40
43
n
12
13
log n
79
95
14
15
10
n
n!
Tabla 3: Algoritmos de tiempo polinomial toman más ventaja de los avances de la tecnología.
Finalmente se puede decir que los algoritmos polinomiales tienen la propiedad de cerradura:
pueden ser combinados para resolver casos especiales del mismo problema; un algoritmo polinomial
puede llamar otro algoritmo polinomial como una subrutina y el algoritmo resultante continuará
siendo polinomial.
Hay que tener cuidado cuando la complejidad de un algoritmo se expresa en términos de la entrada
numérica de la instancia y no en función del tamaño de la entrada. Puede darse el caso que al
codificar la entrada numérica de la instancia la longitud de la cadena se vuelva exponencial y por
ende la razón de crecimiento de la entrada sea exponencial. A los algoritmos que poseen este tipo
de acotamiento en tiempo se les da el nombre de pseudo-polinomiales.
Probablemente la tesis de que un algoritmo acotado en tiempo polinomial es bueno pareciera caerse
cuando uno se va a los extremos, por ejemplo, un algoritmo de complejidad n80 tomará para
resolver instancias de tamaño 3 tiempos astronómicos, mientras que un algoritmo exponencial
correrá más rápidamente para toda instancia razonable. Sin embargo, la experiencia ha demostrado
que para la mayoría de los problemas una vez que un algoritmo acotado en tiempo polinomial es
descubierto, el grado del polinomio rápidamente sufre una serie de decrementos tan pronto como
varios investigadores mejoran la idea. Generalmente, la razón final de crecimiento es O(n3) o mejor.
En contraste, los algoritmos exponenciales normalmente consumen tanto tiempo en la práctica como
en la teoría, y ellos son rápidamente abandonados una vez que un algoritmo polinomial para el
mismo problema es descubierto. No obstante esto no es una verdad absoluta, ya que en contra
parte se tienen algoritmos exponenciales como el método simplex, el cual resuelve muchas
instancias prácticas.
2.2. REGLAS PRACTICAS PARA los Conjuntos O(f)
No existe una regla general para calcular la complejidad de todos los algoritmos. Sin embargo, es
posible tratar sistematicamente una gran cantidad de ellos, si se siguen algunas reglas simples para
instrucciones como las siguientes:
1.
2.
3.
4.
5.
Sentencias sencillas
secuencia (;)
decisión (IF ... THEN ... ELSE ...)
bucles (WHILE, REPEAT, FOR)
llamadas a procedimientos
SENTENCIAS SENCILLAS
Son sentencias de asignación, entrada/salida, etc, siempre y cuando no trabajen sobre variables
cuyo tamaño esté relacionado con el tamaño N del problema.
Complejidad: O(1).
Secuencia (;)
La complejidad: Suma de las complejidades individuales.
Decisión (IF ... THEN ... ELSE ... END)
La condición suele ser de O(1), complejidad a sumar con la peor posible, bien en la rama THEN, o
bien en la rama ELSE. En decisiones multiples (ELSIF, CASE), se tomara la peorde las ramas.
Bucles (WHILE, REPEAT, FOR)
En los bucles con contador explícito, podemos distinguir dos casos, que el tamaño N forme parte de
los límites o que no. Si el bucle se realiza un número fijo de veces, independiente de N, entonces la
repetición sólo introduce una constante multiplicativa que puede absorberse.
Ej.- FOR i:= 1 TO K DO algo_de_O(1) END; => K*O(1) = O(1)
Si el tamaño N aparece como límite de iteraciones ...
Ej.- FOR i:= 1 TO N DO algo_de_O(1) END; => N * O(1) = O(n)
Ej.- FOR i:= 1 TO N DO
FOR j:= 1 TO N DO
algo_de_O(1)
tendremos N * N * O(1) = O(n2)
Ej.- FOR i:= 1 TO N DO
FOR j:= 1 TO i DO
algo_de_O(1)
el bucle exterior se realiza N veces, mientras que el interior se realiza 1, 2, 3, ... N veces
respectivamente. En
total,
1 + 2 + 3 + ... + N = N*(1+N)/2 -> O(n2)
A veces aparecen bucles multiplicativos, donde la evolución de la variable de control no es lineal
(como en los casos anteriores)
Ej.- c:= 1;
WHILE c <N DO algo_de_O(1) c:= 2*c;
El valor incial de "c" es 1, siendo "2k" al cabo de "k" iteraciones. El número de iteraciones es tal
que
2k >= N => k= eis (log2 (N)) [el entero inmediato superior]
y, por tanto, la complejidad del bucle es O(log n).
Ej.- c:= N;
WHILE c > 1 DO
algo_de_O(1)
c:= c / 2;
Un razonamiento análogo nos lleva a log2(N) iteraciones y, por tanto, a un orden O(log n) de
complejidad.
Ej.- FOR i:= 1 TO N DO
c:= i;
WHILE c > 0 DO
algo_de_O(1)
c:= c/2;
tenemos un bucle interno de orden O(log n) que se ejecuta N veces, luego el conjunto es de
orden O(n log n)
Llamadas a procedimientos
La complejidad de llamar a un procedimiento viene dada por la complejidad del contenido del
procedimiento en sí. El coste de llamar no es sino una constante que podemos obviar
inmediatamente dentro de nuestros análisis asintóticos. El cálculo de la complejidad asociada a un
procedimiento puede complicarse notáblemente si se trata de procedimientos recursivos. Es fácil que
tengamos que aplicar técnicas propias de la matemática discreta, tema que queda fuera de los
límites de esta nota técnica.
Ejemplo: evaluación de un polinomio
Vamos a aplicar lo explicado hasta ahora a un problema de fácil especificación: diseñar un programa
para evaluar un polinomio P(x) de grado N;
CONST N= ...;
TYPE TPolinomio= array [0..N] of real;
FUNCTION EvaluaPolinomio (C: TPolinomio; X: REAL): REAL;
VAR i, j: INTEGER;
XN, S: REAL;
BEGIN
S:= C[0];
FOR i:= 0 TO N DO BEGIN
1
XN:= 1.0;
1
FOR j:= 1 TO i DO
2
XN:= XN * X;
2
S:= S + C[i]*XN;
1
END;
1
EvaluaPolinomio:= S;
END {EvaluaPolinomio};
Como medida del tamaño tomaremos para N el grado del polinomio, que es el número de
coeficientes en C. Así pues, el bucle más exterior (1) se ejecuta N veces. El bucle interior (2) se
ejecuta, respectivamente
1 + 2 + 3 + ... + N veces = N*(1+N)/2 => O(n2)
Intuitivamente, sin embargo, este problema debería ser menos complejo, pues repugna al sentido
común que sea de una complejidad tan elevada. Se puede ser más inteligente a la hora de evaluar
la potencia xn:
FUNCTION Potencia (X: REAL; j: INTEGER): REAL;
VAR t: REAL;
BEGIN
IF j = 0 THEN Potencia:= 1.0
ELSE IF (j mod 2) = 1 THEN Potencia:= X * Potencia (X, j-1)
ELSE BEGIN
t:= Potencia (X, j DIV 2);
Potencia:= t*t;
END;
END {Potencia};
FUNCTION EvaluaPolinomio (C: TPolinomio; X: REAL): REAL;
VAR i: INTEGER;
S: REAL;
BEGIN
S:= C[0];
FOR i:= 0 TO N DO
S:= S + C[i] * Potencia (X, i);
EvaluaPolinomio:= S;
END {EvaluaPolinomio};
El análisis de la función Potencia es delicado, pues si el exponente es par, el problema tiene una
evolución logarítmica; mientras que si es impar, su evolución es lineal. No obstante, como si "j" es
impar entonces "j-1" es par, el caso peor es que en la mitad de los casos tengamos "j" impar y en la
otra mitad sea par. El caso mejor, por contra, es que siempre sea "j" par. Un ejemplo de caso peor
seria x31, que implica la siguiente serie para j:
31 30 15 14 7 6 3 2 1
cuyo número de terminos podemos acotar superiormente por
2 * eis (log2(j)),
donde
eis(r) = entero inmediatamente superior
Este cálculo responde al razonamiento de que en el caso mejor visitaremos eis(log2(j)) valores
pares de "j"; y en el caso peor podemos encontrarnos con otros tantos números impares
entremezclados.
Por tanto, la complejidad de Potencia es de orden O(log n). Insertada la función Potencia en la
función EvaluaPolinomio, la complejidad compuesta es del orden O(n log n), al multiplicarse por N
un subalgoritmo de O(log n). Así y todo, esto sigue resultando estravagante y excesivamente
costoso. En efecto, basta reconsiderar el algoritmo almacenando las potencias de "X" ya calculadas
para mejorarlo sensiblemente:
FUNCTION EvaluaPolinomio (C: TPolinomio; X: REAL): REAL;
VAR i: INTEGER;
XN, S: REAL;
BEGIN
XN:= 1.0;
S:= C[0];
FOR i:= 0 TO N DO BEGIN
1
XN:= XN*X;
1
S:= S + C[i]*XN;
1
END;
1
EvaluaPolinomio:= S;
END {EvaluaPolinomio};
que queda en un algoritmo de O(n). Habiendo N coeficientes C distintos, es imposible encontrar
ningun algoritmo de un orden inferior de complejidad. En cambio, si es posible encontrar otros
algoritmos de idéntica complejidad:
FUNCTION EvaluaPolinomio (C: TPolinomio; X: REAL): REAL;
VAR i: INTEGER;
S: REAL;
BEGIN
S:= 0.0;
FOR i:= N DOWNTO 0 DO
1
S:= S*X + C[i];
1
EvaluaPolinomio:= S;
END {EvaluaPolinomio};
No obstante que ambos algoritmos son del mismo orden de complejidad, cabe resaltar que sus
tiempos de ejecución serán notablemente distintos. En efecto, mientras el último algoritmo ejecuta
N multiplicaciones y N sumas, el penúltimo requiere 2N multiplicaciones y N sumas. Si, como es
frecuente, el tiempo de ejecución es notablemente superior para realizar una multiplicación, cabe
razonar que el último algoritmo ejecutará en la mitad de tiempo que el anterior.
2. Problemas NP completos
En la sección anterior, la tabla 2 muestra que los algoritmos cuya complejidad es descrita por una
función polinomial pueden ser ejecutados para entradas grandes en una cantidad de tiempo
razonable, mientras que los algoritmos exponenciales son de poca utilidad excepto para entradas
pequeñas. En esta sección se tratarán los problemas cuya complejidad es descrita por funciones
exponenciales, problemas para los cuales el mejor algoritmo conocido requeriría de muchos años o
centurias de tiempo de cálculo para entradas moderadamente grandes. De esta forma se
presentarán definiciones que pretenden distinguir entre los problemas tratables (aquellos que no son
tan duros) y los problemas intratables (duros o que consumen mucho tiempo). La mayoría de estos
problemas ocurren como problemas de optimización combinatoria.
Problemas Intratables
Garey & Johnson, plantean una situación de intratabilidad interesante que describimos a través del
siguiente caso:
Si trabajas para una compañía que está pensando entrar a una nueva era globalizadora gavernicola
y tu jefe te propone que obtnegas un método para determinar si o no cualquier conjunto dado de
especificaciones para un nuevo componente gavernicola pueden ser satisfechas de alguna manera y,
si es así, se deberá construir el diseño que satisfaga dichas expecificaciones. La realidad es que
despues de un tiempo comprobaras que no hay manera de obtener tal método. De modo que
tendrás dos alternativas: 1) Renunciar para evitar la pena de que te corran por inepto y 2) Esperar a
que te corran por inepto. Sería muy penoso, pero tendrías que confesar que no pudiste resolver el
problema por falta de capacidad.
Para evitar la situación anterior tu podrías tratar de tomar una actitud de una persona más valiente
y demostrar que enb realidad dicho método no se puede obtener. Si eso fuera así entonces tu
podrías ir con tu jefe y aclararle que el problema no lo resolviste porque no se puede resolver: Es
intratable. Sin embargo, es muy probable que a tu jefe esta característica del problema le tenga sin
cuidado y, de todas maneras, te corran o tengas que renunciar. Es decir regresarás a las
alternativas 1) y 2) antes citadas.
Una situación mas prometedora, es tratar de probar que el problema no solo es tan dificil que nose
puede resolver, sinoque ademas pertenece a una clase de problemas tales que cientos y miles de
personas famosas e inteligentes, tampoco pudieron resolver.Aún así, no estamos muy seguros aun
de tu permanencia en la compañia!, En realidad el conocimiento de que un problema es intratable es
de gran utilidad en problemasde tipo computacional. Dado que el problema completo es intratable,
tu podrías resolver el problema para ciertas instancias del mismo, o bien, reslver un problemamenos
ambicioso, Por ejemplo, podra conformarte con obtener un método para las especificaciones de solo
cieto tipo de componentes para determinadosconjuntos de entrada y no para "cualquier conjunto
dado de especificaciones". Esto seguramente te llevará a tener mejor relaciones con tu compañía.
En general, nos interesa encontrar el algoritmo más eficiente para resolver un problema
determinado. Desde ese punto de vista tendríamos que considerar todos los recursos utilizados de
manera que el algoritmo más eficiente sería aquél que consumiera menos recursos. ¿Cuáles
recursos?. Si pensamos nuevamente que tu jefe te encarga que obtnegas el algoritmo más eficiente,
es decir el que consume menos recursos so pena de que si no lo obtienes seas eliminado de la
nominade la compañía, estoy seguro, en que pensarias en todos los recursos posibles (horashombre para construir el algoritmo, tiempo de sintonización, tiempo requerido para obtner una
solución, número de procesadores empleados, cantidad de memoria requerida, etc.). Para simplificar
un poco la tarea, consideraremos que tu jefe te permite que la eficiencia la midas sobre un solo
recurso: El tiempo de ejecución. Pensemos por un momento que solo se tiene una sla máquina de
modo que el número de procesadores no requiere de un análisis. ¿Qué le pasó a tu jefe? ¿De pronto
se volvió comprensivo contigo? En realidad los otros parámetros los ha tomado en cuenta como
costo directo del programa en cuestión. Esto es en realidad lo que se hace en teoría de complejidad.
Para el análisis de complejidad, se considera por lo general la eficiencia sobre el tiempo, para un
solo procesador en cómputo secuencial; para cómputo paralelo se considera también el número de
procesadores.
Los algorimos han sido divididos como buenos o malos algoritmos. La comunidad computacional
acepta que un buen algoritmo es aquél para el cual existe un algoritmo polinomial deterministico
que lo resuelva. Tambien se acepta que un mal algoritmo es aquel para el cual dicho algoritmo
simplemente no exisste. Un problema se dice intratable, si es muy dificil que un algoritmode tiempo
no polinomial lo resuelva. No obstante,esta clasificación de algoritmos en buenos y malos puede
resultar a veces engañosa, ya que se podría pensar que los algoritmos exponenciales no son de
utilidad práctica y que habrá que utilizar solamente algoritmos polinomiales. Sin embargo se tiene el
caso de los métodos simplex y Branch & Bound, los cuales son muy eficientes para muchos
problemas prácticos. Desafortunadamente ejemplos como estos dos son raros, de modo que es
preferible seguir empleando como regla de clasificación en buenos y malos algoritmos, la que lo
hace dependiendo de si son o no polinomiales; todo esto con la prudencia necesaria.
La teoría de la NP-Completés fué presentada inicialmente por Cook desde 1971. Cook provó que un
problema particular que se estudia en Lógica (no necesitamos ahora estudiarlo) y que se llama "El
Problema de Satisfactibilidad", tenía la propiedad de que cualquier problema que perteneciera a la
clase NP, podía ser reducido a él a través de una transformación de tipo polinomial. Estosignificaba
que si el problema de satisfactibilidad podia ser resuelto en tiempo polinomial, todos los problemas
No Polinomiales también podrían resolverse en tiempo polinomial, lo que significaría que la clase NP
dejaría de existir!!. De esta forma, si cualquier problema en NP es intratable, entonces
satisfactibilidad es un problema intratable.Cook también sugirió que el problema de satisfactibilidad
y otros problemas NP tenían la característica de ser los problemas mas duros. Estos problemas
tienen dos versiones: de decisión y deopitmización. El conjunto de estos problemas de optimización
se denominan NP Completos,mientras que a sus correspondientes problemas de optimización,
reciben el nombre de NP Hard.
Problemas de Decisión
Aquí hemos hablado de problemas de optimización como aquél donde buscamos el máximo ó el
mínimo de una funicón donde existen ó no un conjunto de restricciones. Sin embargo un problema
de optimización combinatoria puede también ser formulado de manera más relajada como sigue:
Dado un problema de optimización, podemos encontrar el costo de la solución óptima
Se sabe que dado un problema de optimización, se puede definir un problema de decisión asociado
a él, esto es, una pregunta que puede ser contestada por si o no. Por otro lado, varios problemas
computacionales bien conocidos son problemas de decisión. Entre los problemas de decisión se
pueden mencionar por ejemplo:
El problema de paro: dado un algoritmo y su entrada, ¿Parará éste alguna vez?
El problema de satisfacibilidad: dada una fórmula booleana, ¿Es ésta satisfacible?
El problema del circuito Hamiltoniano: dado un grafo G, ¿Hay un circuito en G que visite todos los
nodos exactamente una vez?.
La definición de problema de decisión a partir del problema de optimización permite estudiar ambos
tipos de problemas de una manera uniforme. Además, como se ha puntualizado que un problema de
decisión no es más difícil que el problema de optimización original, cualquier resultado negativo
probado sobre la complejidad del problema de decisión será aplicable al problema de optimización
también.
Se está interesado en clasificar los problemas de decisión de acuerdo a su complejidad. Se denota
por P a la clase de problemas de decisión que son polinomialmente acotados, esto es, la clase de
problemas de decisión que pueden ser solucionados en tiempo polinomial. La clase P puede ser
definida muy precisamente en términos de cualquier formalismo matemático para algoritmos, como
por ejemplo la Máquina de Turing.
Se puede decir que P es la clase de problemas de decisión relativamente fáciles, para los cuales
existe un algoritmo que los soluciona eficientemente.
Para una entrada dada, una "solución" es un objeto (por ejemplo un grafo coloreado) que satisface
el criterio en el problema y justifica una respuesta afirmativa de si. Una "solución propuesta" es
simplemente un objeto del tipo apropiado, este puede o no satisfacer el criterio. Informalmente se
puede decir que NP es la clase de problemas de decisión para los cuales una solución propuesta
dada para una entrada dada, puede ser checada rápidamente (en tiempo polinomial) para ver si
ésta es realmente una solución, es decir, si ésta satisface todos los requerimientos del problema.
Una solución propuesta puede ser descrita por una cadena de símbolos a partir de algún conjunto
finito. Simplemente se necesita alguna convención para describir grafos, conjuntos, funciones, etc.
usando estos símbolos. El tamaño de la cadena es el número de símbolos en ella. Checar una
solución propuesta incluye checar que la cadena tenga sentido (esto es, que tenga una sintaxis
correcta) como una descripción del tipo de objeto requerido, también como checar que ésta
satisface el criterio del problema.
ALGORITMOS NO DETERMINÍSTICOS
Un algoritmo no determinístico tiene dos faces:
1a. Fase no Determinística: alguna cadena de caracteres, s, completamente arbitraria es escrita
a partir
de algún lugar de memoria designado. Cada vez que el algoritmo corre, la cadena escrita
puede diferir
(Esta cadena puede ser vista como una adivinación de la solución para el problema, por lo
que a esta
fase se le da el nombre de fase de adivinación, pero s también podría ser ininteligible o
sin sentido).
2a. Fase Determinística: Un algoritmo determinístico ( es decir ordinario) siendo ejecutado.
Además de la
entrada del problema de decisión, el algoritmo puede leer s, o puede ignorarla.
Eventualmente éste
para con una salida de si o no, o puede entrar en un loop infinito y nunca parar (véase
ésta como la
fase de checar, el algoritmo determinístico verifica s para ver si ésta es una solución para
la entrada del
problema de decisión).
El número de pasos llevados a cabo durante la ejecución de un algoritmo no determinístico es
definido como la suma de los pasos en ambas fases; esto es, el número de pasos tomados para
escribir s (simplemente el número de caracteres en s) más el número de pasos ejecutados por la
segunda fase determinística.
Normalmente cada vez que se corre un algoritmo con la misma entrada se obtiene la misma salida.
Esto no ocurre con algoritmos no determinísticos; para una entrada particular x, la salida a partir de
una corrida puede diferir de la salida de otra debido a que ésta depende de s. aunque los algoritmos
no determinísticos no son realistas (algoritmos útiles en la práctica), ellos son útiles para clasificar
problemas.
Se dice que un algoritmo no determinístico es polinomialmente acotado si hay un polinomio p tal
que para cada entrada de tamaño n para la cual la respuesta es si, hay alguna ejecución del
algoritmo que produce una salida si en cuando mucho p(n) pasos.
De esta forma se puede decir que: NP es la clase de problemas de decisión para los cuales hay un
algoritmo no determinístico acotado polinomialmente (el nombre de NP viene de no determinístico
polinomialmente acotado).
Un algoritmo ordinario (determinístico) para un problema de decisión es un caso especial de un
algoritmo no determinístico. En otras palabras, si A es un algoritmo determinístico para un problema
de decisión, entonces A es la segunda fase de un algoritmo no determinístico. A simplemente ignora
lo que fue escrito por la primera fase y procede con su cálculo usual. Un algoritmo no determinístico
puede hacer cero pasos en la primera fase (escribiendo la cadena nula), Así si A corre en tiempo
polinomial, el algoritmo no determinístico con a como su segunda fase corre también en tiempo
polinomial. De lo mencionado se deduce que P es un subconjunto propio de NP.
La gran pregunta es ¿ P = NP o es P un subconjunto propio de NP? Se cree que NP es un conjunto
mucho mayor que P, pero no hay un solo problema en NP para el cual éste haya sido probado que el
problema no está en P. No hay un algoritmo polinomialmente acotado conocido para muchos
problemas en NP, pero ningún límite inferior mayor que un polinomio ha sido probado para estos
problemas.
NP-completo es el término usado para describir los problemas de decisión que son los más difíciles
en NP en el sentido que, si hubiera un algoritmo polinomialmente acotado para un problema NPcompleto, entonces habría un algoritmo polinomialmente acotado para cada problema en NP.
Definición Formal de la Clase NP
La definición formal de NP-completo usa reducciones, o transformaciones, de un problema a otro.
Suponga que se quiere resolver un problema P 1 y que se tiene ya un algoritmo para otro problema
P 2. Suponga también que tiene una función T que toma la entrada x para P 1 y produce T(x), una
entrada para P 2 tal que la solución correcta de P 1 en x es afirmativa (si) si y solo si la respuesta
correcta para P 2 en T(x) es un si. Entonces, haciendo una composición de T y el algoritmo para P 2,
se obtiene un algoritmo para P 1.
Sea T una función que va del conjunto de entradas para el problema de decisión P 1 al conjunto de
entradas para el problema de decisión P 2. T es una reducción polinomial (también llamada
transformación polinomial) de P 1 a P 2 si
T puede ser calculada en un tiempo acotado polinomialmente
Para cada entrada x de P 1, la respuesta correcta para P 2 en T(x) es la misma que la respuesta
correcta para P 1 en x.
P 1 es polinomialmente reducible (también llamada polinomialmente transformable) a P 2 si existe
una transformación polinomial de P 1 a P 2. La notación P 1 µ P 2 es usada para indicar que P 1 es
reducible a P 2.
El punto fundamental de la reducibilidad es que P 2 es al menos tan duro o difícil de resolver como P
Esto puede precisarse a través del siguiente teorema.
1.
Si P
1
µP
2
yP
2
está en P, entonces P
1
está en P.
Ahora se puede dar una definición formal de NP-completo:
Un problema P es NP-completo si éste está en NP y para cada otro problema P ’ en NP,
Del teorema anterior y la definición de NP completo se deduce el siguiente teorema:
Si cualquier problema NP-completo esta en P, entonces P=NP
P’µP
Este teorema indica, por un lado, que tan valioso sería encontrar un algoritmo polinomialmente
acotado para cualquier problema NP-completo y, por otro, que tan improbable es que tal algoritmo
exista pues hay muchos problemas en NP para los cuales han sido buscados algoritmos
polinomialmente acotados sin ningún éxito.
Como se señaló antes, el primer problema de decisión que se propuso como un problema NPcompleto es el satisfacibilidad de la lógica proposicional. Todos los problemas NP para los cuales se
puede comprobar que pueden ser reducibles al problema de satisfctibilidad, son NP-completos. Así
tenemos que los siguientes problemas son NP-completos: rutas y circuitos de Hamilton, asignación
de trabajos con penalizaciones, el agente viajero, el problema de la mochila.
Actualmente para probar que un problema es NP-completo, es suficiente con probar que algún otro
problema NP-completo es polinomialmente reducible a éste debido a que la relación de reducibilidad
es transitiva. La lógica de lo dicho es la siguiente:
Si P ’ es NP-completo, entonces todos los problemas en NP µ P ’
Si se demuestra que P ’ µ P
Entonces todos los problemas en NP µ P
Por lo tanto, P es NP-completo
Supóngase un problema P , P * es el complemento del problema P si el conjunto de símbolos en la
cadena s de la fase de adivinación del algoritmo no determinístico que codifican las instancias si de P
* son exactamente aquellas que no están codificando las instancias si de P . Por ejemplo, el
problema del circuito Hamiltoniano es: dado un grafo G=(V, E), es G Hamiltoniano. Y el
complemento del problema del circuito Hamiltoniano es: dado un grafo G=(V, E), es G no
Hamiltoniano.
Supóngase un problema P en P, entonces hay un algoritmo acotado polinomialmente que resuelve P
. Un algoritmo acotado polinomialmente que solucione el complemento de P es exactamente el
mismo algoritmo, únicamente con la sustitución de no por si cuando se obtiene una solución
afirmativa y viceversa. El siguiente teorema expresa lo mencionado
Si P es un problema en P, entonces el complemento P * de P está también en P.
Los mismos argumentos no pueden ser aplicados para demostrar que un problema en NP está
también en NP. Esto motiva la siguiente definición:
La clase co.NP es la clase de todos los problemas que son complemento de problemas en NP
Decir que el complemento de todos los problemas en NP está también en NP es equivalente a decir
que NP = co-NP. Sin embargo, hay razones para creer que NP ¹ co-NP. La evidencia es tan
circunstancial como la que se estableció para la conjetura de que P ¹ NP: Muchos investigadores han
tratado por largo tiempo, sin éxito, de construir pruebas sucintas para el complemento del problema
del circuito Hamiltoniano, así como para muchos otros problemas, Sin embargo, puede ser mostrado
(como con P ¹ NP) que si la conjetura es verdadera, está en los problemas NP-completo testificar su
validez.
Si el complemento de un problema NP-completo está en NP, entonces NP = co-NP
Así de todos los problemas en NP, Los problemas NP-completo son aquellos con complementos de
estar en NP. Contrariamente, Si el complemento de un problema en NP está también en NP, esto es
evidencia de que el problema no está en NP.
Cuando todos los problemas en NP se transforman polinomialmente al problema P , pero no es
posible demostrar P Î NP, se dice que P es tan difícil como cualquier problema en NP y por lo tanto
NP-hard.
NP-hard es usado también en la literatura para referirse a los problemas de optimización de los
cuales su problema de decisión asociado es NP-completo
Problemas que pueden ser solucionados por algoritmos cuyas operaciones pueden ser confinadas
dentro de una cantidad de espacio que está acotado por un polinomio del tamaño de la entrada,
pertenecen a la clase PSPACE. P, NP y co-NP son subconjuntos de PSPACE.
Se dice que un problema es PSPACE-completo si éste está en PSPACE y todos los otros problemas
en PSPACE son polinomialmente reducibles a él.
Un esquema de las clases de problemas desde el punto de vista de la teoría de la complejidad.
FÓRMULAS PRENEXAS
Y ALGORITMO CLAUSULAR
FÓRMULAS PRENEXAS :
Las fórmulas prenexas, son aquellas donde todos los cuantificadores, Q1,Q2,..Qn, que pueda tener
una fórmula del cálculo de predicados, están colocados a la izquierda de la fórmula, de manera que
a la izquierda de ella queda una fórmula M sin cuantificadores. Es decir:
F = (Q1 x1) ...(Qn xn) (M)
donde las Qi son cuantificadores universales o existenciales y M es una fórmula sin cuantificadores,
cuyos elementos son uno
o más símbolos de predicados separados por conectores lógicos. A la forma anterior se le conoce
como la Forma Normal Prenexa y es posible llegar a ella mediante un procedimiento simple:
PASO
PASO
PASO
PASO
1.
2.
3.
4.
Eliminar símbolos de implicación y doble implicación.
Pasar negaciones hacia adelante.
Renombrar variables ligadas.
Mover los cuantificadores hacia la izquierda.
ALGORITMO CLAUSULAR :
1)
2)
3)
4)
5)
6)
7)
8)
Eliminar => y <=>
Pasar ~ hacia adelante
Estandarizar variables
Eliminar E's
Convertir a la forma prenexa
Escribir la matriz en forma conjuntiva
Eliminar A's
Eliminar ^ 's
SUSTITUCIÓN Y UNIFICACIÓN
EL PROBLEMA DE LA UNIFICACIÓN Y EL UNIFICADOR MÁS GENERAL
En el caso de la lógica proposicional, es relativamente sencillo realizar apareamientos de claúsulas
para obtener resolventes. Para ejemplificar apareamientos de cláusulas en Cálculo Proposicional,
consideraremos un ejemplo.
EJEMPLO 1.
Si tenemos las siguientes cláusulas
[1] P v Q
[2] ¬ P v R
el resolvente de [1] y [2] es:
{1,2} [3] Q v R
donde {1,2} [3] significa que se utilizan las cláusulas [1] y [2] en la obtención una nueva cláusula
y [3] es el nombre de dicha claúsula. A [3] también se le llama resolvente de [1] y [2]. Obsérvese
que las cláusulas [1] y [2] se pueden aparear debido a que ambas contienen un átomo que es
diferente solamente en el signo (es decir P en [1] y ¬P en [2]). De esta manera se dice que P y ¬P
son átomos complementarios o bien que forman un par complementario.
DEFINICIÓN. Dos átomos son complementarios si difieren solamente en el signo. Cuando dos
átomos L y ¬L son complementarios, se dice que forman un par complementarios.
En el caso del cálculo de predicados, la situación es diferente, ya que las cláusulas tienen símbolos
de predicados, los cuales tienen términos como argumentos. Por ejemplo, supongamos que
deseamos encontrar el resolventes de las cláusulas:
[1] P(x) v Q(x)
[2] ¬ P(f(x)) v R(x)
Las cláusulas [1] y [2] tienen átomos, con símbolos de predicado del mismo nombre (la literal P)
que son diferentes en signo, de modo que estas dos cláusulas son candidatas a aparearse, para así
obtener el resolvente correspondiente. No obstante, dicho apareamiento no podrá realizarse, a
menos que exista una sustitución que logre que los argumentos de los símbolos de los predicados P
y ¬P sean iguales, de modo que las literales P y ¬P sean complementarias. Al problema de
encontrar una sustitución que logre que el conjunto de argumentos de dos símbolos de predicados
sean iguales, se le llama el problema de unificación.
Así tenemos que el problema de unificación es el siguiente:
DEFINICIÓN. Dados dos términos (construidos a partir de símbolos de funciones, constantes y
variables), el problema de unificación consiste en encontrar una sustitución, que logre que los dos
términos sean idénticos.
Regresemos al problema de encontrar un resolvente de las cláusulas [1] y [2]. Las cláusulas [1] y
[2] no tienen ningún símbolo de predicado (al que nos referiremos como literal) que sea
complementario, ya que en [1] existen diferencias adicionales al signo que impiden que P y ¬ P sean
iguales. Sin embargo, podemos obtener nuevas instancias de [1] y [2] como se ilustra en el ejemplo
siguiente.
EJEMPLO 2.
Considerar las cláusulas [1] y [2] que se repiten aquí:
[1] P(x) v Q(x)
[2] ¬ P(f(x)) v R(x)
encontrar instancias de [1] y [2] que logre que en [1] y [2] se tenga un par complementario:
SOLUCIÓN.
Solo podemos formar un par complementario entre las literlas P y ¬P de las cláususlas [1] y [2]
respectivamente. Encontramos instancias de estas cláusulas como sigue:
a) de [1], cambiando x por f(a), se obtiene:
[1']
P(f(a)) v Q(f(a))
b) de [2], cambiando x por a:
[2']
¬ P(f(a)) v R(a)
En [1'] y [2'] hemos obtenido instancias aterrizadas de [1] y [2], ya que hemos cambiado el valor
de la variable por una constante. De esta forma se ha logrado que estas dos cláusulas
tengan una literal complementaria, es decir P(f(a)) con ¬ P(f(a)). Como consecuencia se puede
obtener el resolvente de [1] y [2] para obtener la cláusula:
[3'] Q(f(a)) v R(a)
EJEMPLO 3:
Consideremos nuevamente el conjunto del ejemplo 1, que reproducimos nuevamente aquí:
[1] P(x) v Q(x)
[2] ¬ P(f(x)) v R(x)
encontrar una sustitución de [1] y [2], en base solo a las diferencias en los términos de P y ¬P que
permita obtener un par complementario.
SOLUCIÓN
Los términos de P y ¬P son respectivamente x y f(x), es decir forman el conjunto D:
D = {x, f(x)}
De esta manera las diferencias de los términos de P y ¬P son justamente los elementos del conjuto
D. Si sustituimos f(x) por x en [1] para obtener el siguiente conjunto de cláusulas:
{1, f(x)/x}
[1a] P(f(x)) v Q(f(x))
[2] ¬P(f(x)) v R(x)
Donde {1, f(x)/x} [1a] significa que tomamos la cláusula 1, y realizamos la sustitución f(x) en lugar
de x, para obtener la cláusula [1a]. Aquí empleamos la notación f(x)/x para denotar que sustituimos
x en lugar de x. Efectuando el apareamiento
de [1a] por [2] se obtiene:
[3]
Q(f(x)) V R(x)
Nótese que el resolvente [3'] es una instancia del resolvente [3] que acabamos de obtener, ya que
si en este último sustituimos x por a, obtenemos [3']. En realidad lo que pasa es que [3] es la
cláusula mas general que podemos obtener, de modo que para cualquier par de instancias de [1] y
[2] para las cuales obtengamos un resolvente [3x] cualquiera, siempre habrá un sustitución de las
variables de [3], mediante la cual se obtendrá como aterrizamiento la cláusula [3x].
En el ejemplo 3, la sustitución que realizamos de cambiar f(x) en lugar de x se puede representar
por el conjunto:
Ø = {f(x) / x}
De esta manera podemos decir que una sustitución es un conjunto donde se reemplazan términos
por variables, como se define a continuación. Aquí el término sustitución se define como sigue:
DEFINICIÓN: Una sustitución es un conjunto finito de la forma:
{t1/v1, ....tn/vn}
donde ti y vi son términos y variables respectivamente que cumplen las siguientes condiciones:
A) Cada término ti es un término diferente a vi. Es decir el numerador y el denominador son
diferentes. Ésto se debe a que, en caso contrario, no habría en realidad sustitución alguna.
B) No existen dos elementos del conjunto que tengan la misma variable.
EJEMPLO 4.
El conjunto:
{ f(z)/ x, (a/z) }
satisface la definicición de sustitución, ya que ninguna variable vi (los denominadores de cada
elemento del conjunto) es igual a otra sus numeradores y denominadores son diferentes.
EJEMPLO 5.
El conjunto:
{3/x, 4/x}
no satisface la definición de sustitución, ya que no satisface la condición B, pues los dos elementos
elementos de este conjunto tienen la misma variable. Nótese que no se permite cambiar 3 y 4 al
mismo tiempo por la variable x.
TÉCNICAS DE RESOLUCIÓN
En esta sección describiremos las reglas de inferencia del Cálculo Proposicional usadas en el método
de resolución, la forma clausular utilizada en resolución y las técnicas de resolución más comunes.
REGLAS DE INFERENCIA
Resolución Proposicional utiliza solamente una regla de inferencia, que se puede expresar en
cualquiera de la siguientes tres formas, todas ellas equivalentes entre sí:
FORMA I :
1) P => Q
2) Q => R
---------3) P => R
FORMA II :
!- P => Q;
!- Q => R
------------------------!- P => R
FORMA III :
1) - P v Q
2) -Q v R
-------------3) -P v R
La primera forma, también se conoce como regla de inferencia de encadenamiento, e indica que si p
implica q (proposición 1), y q a su vez implica r (proposión 2), entonces se puede inferir que p
implica r (proposición 3). El uso de la regla de inferencia de encadenamiento es muy utilizada en
sistemas expertos y en aplicaciones tipo Prolog, donde los lados izquierdos de las implicaciones se
conocen como premisas.
La segunda forma, es la misma regla de inferencia pero escrita en la notación del Cálculo de
Secuentes. Un secuente tiene dos partes principales, separadas por una linea horizontal como sigue:
PREMISA1, PREMISA 2, ... , PREMISA N
------------------------------------------------------CONCLUSIÓN A
Que se lee: "dadas las premisas 1, premisa2, ... , premisan, se deduce la CONCLUSIÓN A". De esta
manera la FORMA 2 de la regla de encadenamiento, se lee: "dado que es válido P => Q, que es
válido
Q => R, se puede deducir que es válido P => R".
La tercera forma, es la regla de inferencia de eliminación, la cual puede deducirse de la propia regla
de encadenamiento, de acuerdo con las siguientes tautologías:
P => Q
Q => R
P => R
= ~P v Q
= ~Q v R
= ~P v R
La forma III se puede también escribir (tomamos ahora símbolos de proposiciones, a las literalesA,
B y C)
FORMA III:
(1) A v B
(2) ~A v C
------------------{1,2}(3) B v C
En la forma III, se indica que, dadas las cláusulas (1) y (2), se puede deducir (3), es decir, (3) es
una consecuencia lógica de (1) y (2). De esta manera, la válidez de la forma III se puede
comprobar, (de acuerdo con la definición de consecuencia lógica) verificando que la implicación de
(1) y (2) es una fórmula válida.
Es bastante conocido que para el Cálculo Proposicional, usando solamente la Forma III cómo la
única regla de inferencia (sin ningún esquema axiomático u otras reglas de inferencia), es posible
construir un demostrador de teoremas que sea consistente y completo para todos las lógicas
conocidas del Cálculo Proposicional.
FORMA CLAUSULAR EN RESOLUCIÓN
El método de resolución se usa con el conjunto de fórmulas escritas en la forma normal conjuntiva,
es decir, cada una de las fórmulas participantes (premisas y fórmula objetivo) se transforman en
uno ó más cláusulas de la forma:
fi1 v fi2 v ... v fik
Una simple literal, representando a un símbolo de proposiciones, o simplemente, una literal,
digamos P o su negación ~P son cláusulas y, por tanto, no requieren transformación. Se dice
entonces que una literal puede ser una sentencia atómica P o bien su negación ~P. De esta forma se
define cláusula como sigue:
DEFINICION: Una cláusula es una literal o una disyunción de literales. De esta forma se puede
también definir cláusula como sigue:
P
~P
PvQ
Las cláusulas también se escriben como conjuntos de literales, es decir:
{P}
{~P}
{P,Q}
A veces se utiliza el término Base de Datos de Cláusulas o simplemente Base de Datos, para
referirse a un conjunto de cláusulas. De esta manera, la siguiente base de datos:
{{-P,Q},{R,-Q}}
representa al conjunto de clausulas:
-P V Q
R V -Q
CLÁUSULA VACÍA
La cláusula vacía, denotada por NIL, es por definición falsa de modo que es insatisfactible. Esto se
debe a que NIL es equivalente a una disyunción vacía (sin literales), de modo que no se satisface
para ninguna interpretación. Sin embargo la base de datos vacía {} es satisfactible, ya que es
equivalente a una conjunción vacía de cláusulas para la cual no se puede deducir NIL. Sin embargo,
la base de datos conteniendo sólo de la cláusula vacía (es decir NIL), es no satisfactible, ya que NIL
es siempre falsa.
CONVERSIÓN A LA FORMA CLAUSULAR:
Se hace en cuatro pasos:
PASO 1) Eliminar implicaciones:
P1 => P2
--->
P1 <= P2
--->
P1 <=> P2 --->
~P1 v P2
P1 v ~P2
(~P1 v P2) & (P1 v ~P2)
paso 2) Pasar las negaciones hacia adelante:
~~P
---> P
~(P1 & P2) ---> ~P1 v ~P2
~(P1 v P2) ---> ~P1 & ~P2
Paso 3) Usar leyes distributivas:
(Pasar disyunciones hacia adentro)
P1 V (P2 & P3) ---> (P1 V P2) & (P1 V P3)
Paso 4) Pasar operadores hacia afuera:
4A) DISYUNCIONES P1 v P2, SE ESCRIBEN COMO UNA SIMPLE CLÁUSULA
{P1,P2}
4B) CONJUNCIONES SE ELIMINAN PARA FORMAR CLÁUSULAS
P1 & P2 & ...Pm se escriben como m cláusulas:
{P1},{P2},..,{Pm} donde las Pi son disyunciones.
Ejemplo.
Convertir a su forma clausular:
(G & (R => F))
SOLUCIÓN
Paso 1:
(G & (~R v F))
Paso 2:
no es necesario
Paso 3:
no es necesario
Paso 4:
1) {G}
2) {~R,F}
Ejemplo.
Convertir a su forma clausular:
~(G & (R => F))
SOLUCIÓN
Paso 1:
Eliminar implicaciones.
~(G & (~R v F))
Paso 2:
Pasar negaciones hacia adelante.
(~G v ~(~R v F)) = (~G v (~~R& ~F))
(~G v (R & ~F))
Paso 3:
no es necesario
Paso 4
A) Pasar disyunciones hacia adelante
(~G v R) & (~G v ~F)
Paso 4
B) Eliminar &'s
Cláusula 1:
Cláusula 2:
La cláusula ~G v R se escribe:
{~G, R}
La Cláusula ~G v ~F se escribe:
{~G, ~F}
TÉCNICAS DE RESOLUCIÓN COMUNES
Existen diversas técnicas de resolución, las más comunes son las siguientes:
1)
2)
3)
4)
5)
6)
Nivel de saturación
Resolución unitaria
Resolución ordenada
Conjunto de Soporte
Resolución Semántica
Regla de una literal
LA REGLA DE UNA LITERAL
Y EL MÉTODO DE RESOLUCIÓN
1. INTRODUCCIÓN
Para verificar si un conjunto de cláusulas S es insatisfactible usando el principio de resolución, la
idea esencial es verificar si S contiene (o de él puede derivarse), la cláusula vacía, en cuyo caso S es
insatisfactible. Este principio tiene sus bases en la Regla de una Literal del método de Davis y
Putnam, la cual se explica en este ensayo. Se presentan ejercicios tomados del libro de Chang &
Lee, pero resueltos todos aplicando la regla de una literal. Se espera que con los ejemplos
proporcionados, los alumnos podrán por sí mismos reconocer un algoritmo que aplique dicha regla.
Los ejemplos son solamente del cálculo de proposiciones pero ilustran correctamente el empleo de la
regla de una literal.
2. Lemas para la Regla de una Literal
2.1 LEMA 1
"Sea un conjunto de cláusulas S0 : {L V A1, L V A2, L}, donde L no pertenece a Ai
pertenece a NIL; entonces S0 es satisfactible".
y L no
DEMOSTRACIÓN :
Considérese la Base de Datos, conformada únicamente por tres cláusulas:
S0 = {L v A1, L v A2, L}
Denotemos por S1 al siguiente conjunto, conformado solo por solamente dos cláusulas de S0:
S1= {
(a)
(b)
L V A1
L V A2
}
Como S0 y S1 difieren solamente en la cláusula unitaria L, y esta es satisfactible, hay sólo dos
condiciones sobre S1 que permiten que S0 sea satisfactible:
A) El resolvente de (a) y (b) no sea ~L
B) El resolvente de (a) y (b) no sea la cláusula vacía.
Se pueden tener los siguientes casos sobre el conjunto S1, para los cuales examinamos el
resolvente de las cláusulas (a) y (b).
CASO 1. A1 y A2 son cláusulas unitarias simples y forman un par complementario.
{a,b} (c) L
por lo tanto S1 es satisfactible y S0 también.
CASO 2. A1 y A2 son cláusulas unitarias simples pero no complementarias.
Entonces no se puede determinar ningún resolvente para las cláusulas (a) y (b), de modo que el
conjunto S1 es satisfactible. Como S0 y S1 difieren solamente en L, entonces S0 es satisfactible.
CASO 3. A1 y A2 son disyunciones.
Sean las disyunciones de A1 y A2 las siguientes:
A1= a11 v ....a1n
A2= a21 v ....a2m
de forma que las cláusulas de S1 se escriben:
(a') a11 v....v a1n v L
(b') a21 v ...v a2m v L
Dado que L no pertenece ni a A1 ni a A2, no existe ningun par complementario entre las literales aij
y L. Esto significa que a partir de (a) y (b) no es posible eliminar L. Por lo tanto S1 es satisfactible.
Por lo tanto S0 es satisfactible.
LEMA 1.1 Sean las cláusulas: A1, A2, ...An, L, tales que en Ai no existe L. Entonces, cualquier
conjunto de la forma:
S0={L V A1, L v A2, L v A3, ..., L v An, L}
es satisfactible.
DEMOSTRACIÓN.
Sea el conjunto:
S1={ L v A1,L v A2, L v A3,..., L v An}
puesto que todas las Ai son diferentes de L, no existe ningun resolvente que sea igual a ~L.Puesto
que S1 y S0 difieren solamente en L, no es posible obtener un par complementario {L, ~L}, En
consecuencia S0 es satisfactible.
LEMA 1.2 Sea el conjunto
S0 = {S1, L}
donde S1 es un conjunto de cláusulas, entonces S0 es satisfactible si todas las cláusulas del
conjunto S1 contienen la literal L.
DEMOSTRACIÓN
Del lema 1 anterior, si S1 contiene la literal L, entonces S0 es satisfactible.
COROLARIO :
Dado un conjunto S0 de cláusulas, con una cláusula unitaria L, si se eliminan todas las cláusulas en
S0 conteniendo L para obtener un conjunto S1, S0 es satisfactible si S1 es vacío.
2.2 LEMA 2 :
Dado los conjuntos de cláusulas S0, S1 y S2:
S0 = {L v X1, L v X2, ...., L v Xn, ~L v B1, B2, L}
S1= {~Lv B1, B2}
S2= {B1, B2}
donde S1, se ha obtenido eliminando de S0 todas las cláusulas que tengan L.
Entonces S0 es insatisfactible.
DEMOSTRACIÓN
Eliminando de S0 todas las cláusulas que tengan L, se obtiene el conjunto:
S1= {~L v B1, B2}
Debido al corolario del lema 1, no podemos concluir que S0 es satisfactible, dado que S1 no es
vacío. Obsérvese que al eliminar todas las cláusulas que tienen L, no se afecta la satisfactibilidad de
S0. De esta manera, S0 es insatisfatible sólo si en S1 se produce la cláusula ~L, ya que al
eliminarse todas las literales con la literal L solo queda en S0:
a) Una cláusula unitaria L y
b) Dos cláusulas: -L V B1, B2
1) De las cláusulas b:
S1 = [-L V B1, B2]
2) Quitando -L de las cláusulas de S1 (i.e. solamente la primera de ellas):
S2 = {B1, B2}
Entonces si S2 es insatisfactible, S0 lo es.
NOTA: Otra forma de ver este lema es el siguiente:
Si S2 es insatisfactible, el resolvente de las cláusulas de S1 es -L.
Como S1 (donde se infiere -L) existe en S0 (donde existe L), entonces se concluye:
de S0 se deduce NIL.
Entonces S0 es insatisfactible
COROLARIO :
Dado un conjunto S0 con una cláusula unitaria L, obtener el conjunto S1 eliminando todas las
cláusulas que contengan L. Si S1 no es vacío, eliminar de S1 la literal -L para formar el conjunto
S2. S2 es insatisfactible si y solo si S0 lo es.
Note que si -L es una cláusula unitaria, entonces la cláusula se vuelve vacía cuando -L es
eliminada.
2.3 Enunciado de la Regla de una Literal
Del análisis anterior hemos obtenido las siguientes conclusiones para un conjunto S0 de cláusulas,
con una cláusula unitaria L :
1) Si se eliminan todas las cláusulas en S0 conteniendo L para obtener un conjunto S1, entonces S0
es satisfactible si S1 es vacío.
2) Si al eliminar de S0 todas las cláusulas que contengan L, el conjunto S1 no es vacío, eliminar
de S1 la literal -L para formar el conjunto S2. S2 es insatisfactible si y solo si S0 lo es.
Note que si -L es una cláusula aterrizada, entonces la cláusula se vuelve vacía cuando -L es
eliminada.
De esta forma la regla de una literal establece que
"Si hay una cláusula aterrizada L en S0, obtener S1 a partir de S0, eliminando las cláusulas que
contengan L :
a) Si S1 es vacío, entonces S0 es satisfactible.
b) Si S1 no es vacío, obtener S2 eliminando de S1 a la literal -L. S2 es insatisfactible si S0 lo
es.
Note que si -L es una cláusula unitaria, esta eliminación indica de inmediato NIL y que S0 es
insatisfactible".
3. Ejemplos
EJEMPLO 1. Demostrar que el siguiente conjunto es insatisfactible.
(1)
(2)
(3)
(4)
(5)
P V Q V -R
P V -Q
-P
R
U
ITERACIÓN 1 :
S0
(1)
(2)
(3)
(4)
(5)
P V Q V -R
P V -Q
-P
R
U
S1/-P
(1) P V Q V -R
(2) P V -Q
(3)
(4) R
(5) U
S2/P
(1) Q V -R
(2) -Q
(3)
(4) R
(5) U
ITERACIÓN 2 : (EL ÚLTIMO CONJUNTO SE LLAMA AHORA S0)
S0
(1)
(2)
(3)
(4)
(5)
Q V -R
-Q
R
U
S1/-Q
(1) Q V -R
(2)
(3)
(4) R
(5) U
S2/Q
(1) -R
(2)
(3)
(4) R
(5) U
ITERACIÓN 3 :
Ahora S0 (que es el conjunto anterior) contiene un par complementario sobre la literal R. De este
modo se determina NIL, ya que de acuerdo con la regla de una literal, si en el primer paso se
elimina R para S, en el segundo paso al determinar S2 y encontrarse que -L (es decir -R) es
unitaria, se determina la cláusula vacía.
EJEMPLO 2. Determinar si el siguiente conjunto es satisfactible.
(1) P V Q
(2) -Q
(3) -P V Q V -R
ITERACIÓN 1 :
S0
(1) P V Q
(2) -Q
(3) -P V Q V -R
S1/-Q
(1) P V Q
(2)
(3) -P V Q V -R
S2/Q
(1) P
(2)
(3) -P V -R
ITERACIÓN 2 :
S0
S1/P
S2/-P
(1) P
(2)
(3) -P V -R
(1)
(2)
(3) -P V -R
(1)
(2)
(3) -R
ITERACIÓN 3 :
S0
S1/-R
(1)
(2)
(3) -R
(1)
(2)
(3)
Puesto que S1 es vacío (es decir, no tiene cláusulas), el conjunto S inicial es satisfactible.
EJEMPLO 3.
S0
(1)
(2)
(3)
(4)
P V -Q
-P V Q
Q V -R
-Q V -R
INICIALIZACIÓN : OBTENER CLÁUSULAS UNITARIAS POR SATURACIÓN
(Nivel 1)
[1,2]
[1,3]
[2,4]
[3,4]
(Nivel 2)
TAUTOLOGÍA
(5) P V -R
(6) -P V -R
(7) -R
[1,6] ---- (existente)
[..]
---- no hay cláusulas unitarias
SE AGREGA LA CLÁUSULA UNITARIA AL CONJUNTO INICIAL PARA FORMAR S0 :
S0
(1')
(2')
(3')
(4')
(5')
P V -Q
-P V Q
Q V -R
-Q V -R
-R
S1/-R
(1')
(2')
(3')
(4')
(5')
P V -Q
-P V Q
Q
-Q
Puesto que S1 no es vacío, no podemos determinar que S0 es satisfactible, eso no implica que S0 no
lo sea. Debido a ello, debemos recurrir a otra técnica. Una posibilidad es generar las cláusulas
unitarias por el método de nivel de saturación; en ese caso en particular, la única cláusula unitaria
que será generada es -R; como consecuencia, el resultado obtenido será que el conjunto es
satisfactible.
CONCLUSIONES :
La regla de una literal permite obtener un tratamiento eficiente al demostrar teoremas mediante
resolución. Sin embargo, existen situaciones donde se necesita de técnicas alternativas, ya que
requiere que se tengan cláusulas unitarias.
REGLA DE UNA LITERAL ESTRUCTURADA
CON REGLA DE PARTICIÓN
INTRODUCCIÓN
En el módulo anterior vimos la regla de una literal de Davis y Putnam (a la que nos referiremos
como la regla R1L de Davis) aplicada a un conjunto S0 de cláusulas, para el cual deseamos saber si
es satisfactible o no. Para la aplicación de dicha regla, se requiere que S0 cuente entre sus
elementos con una cláusula unitaria que denominamos L. En el primer paso de esta regla se
eliminan todas las cláusulas que tengan la cláusula unitaria L, para así obtener un nuevo conjunto
S1. Una condición que determina que S0 es satisfactible ocurre cuando S1 es un conjunto vacío de
cláusulas. Si esa condición no se presenta, entonces se procede al segundo paso de la regla, que
consiste en eliminar de cada cláusula de S1 la literal ~L, obteniendo de este modo un nuevo
conjunto S2. Durante este segundo paso, se proporciona una condición para la insatisfactibilidad de
S0 cuando S2 lo es.
Nótese que la regla R1L de Davis no contempla la eliminación distribuida y que pierde de vista las
cláusulas descendientes de la fórmula objetivo. Hay que notar también que esta regla sólo se aplica
si existe al menos una cláusula unitaria en el conjunto S0 antes de interés.
Por otro lado Davis y Putnam obtuvieron otras reglas útiles para la demostración de teoremas, entre
las que destaca la Regla de Partición, misma que permite la demostración de teoremas en forma
distribuida.
De esta manera, nos proponemos mostrar una Regla de una Literal Estructurada en base a la
identificación de la cláusula objetivo negada y de sus descendientes, para su utilización en forma
distribuida en la demostración de teoremas. A esta regla la denominaremos regla R1L estructurada.
DEFINICIONES PRELIMINARES
Consideraremos la siguiente convención:
S0 = conjunto de cláusulas para el cual se desea saber si éste es o no satisfactible.
Sa es una secuencia de cláusulas cualesquiera de orden mayor o igual a 1.
A1, A2,… , An son cláusulas de orden mayor o igual a 1.
L es una cláusula unitaria tal que ni ella ni su complemento, ~L, existen en ninguna Ai
L o ~L, pero no las dos, pueden existir en cada cláusula de Sa
S1 es el conjunto obtenido de S0, eliminando las cláusulas que tengan la literal L.
NIL= La cláusula vacía.
Conjunto = Conjunto de cláusulas.
DEFINICIÓN: Una cláusula es una disyunción de literales.
Ejemplo. Las siguientes son cláusulas:
i) A v B v C
ii) A
iii) NIL
La primera es una disyunción de 3 literales, la segunda de 1 y la tercera de 0 (la cláusula vacía).
DEFINICIÓN. El orden de una cláusula es el número de literales en ella.
De este modo, el orden de las cláusulas del ejemplo anterior es 3, 1 y cero, respectivamente.
DEFINICIÓN. Una literal L en un conjunto S0 es pura, si ~L no existe en So.
EJEMPLO: A es pura para el conjunto:
S0 = { A v B, A v ~B}
Mientras que B y ~B no lo son..
DEFINICIÓN: Un conjunto no unitario es un conjunto de cláusulas en el cual no existe ninguna
cláusula de orden menor o igual que la unidad.
EJEMPLO:
Los siguientes son conjuntos no unitarios:
{ A v B, A v ~B, R v Q, R v ~Q}
{A v B, A v ~C}
REGLA DE UNA LITERAL DE DAVIS
Para un conjunto S0 de cláusulas donde existe una cláusula unitaria L, proceder como sigue:
PASO 1: Formar un conjunto S1, eliminando de S0, todas las cláusulas que tengan L. S0 es
satisfactible si S1 es vacío.. Si S1 no es vacío, pasar al paso 2.
PASO 2. Formar el conjunto S2, eliminando de cada cláusula i de S1 la literal ~L (esto equivale a
obtener el resolvente de cada cláusula i con la cláusula L). So es insatisfactible si S2 lo es.
JUSTIFICACIÓN DE R1L DE DAVIS
La estableceremos mediante varios teoremas que postularemos a continuación.
TEOREMA 1:
Todo conjunto no-unitario, con una literal pura L, de la forma:
Ç= { A1 v L, A2 v L, ... , A n v L}
(6)
es satisfactible.
DEMOSTRACIÓN
Procederemos por demostración al absurdo.
Supongamos que Ç es insatisfactible. Entonces ~ L existe en al menos una de las cláusulas de Ç.
La existencia de ~ L en Ç, contradice su definición. En consecuencia el conjunto Ç es satisfactible. []
TEOREMA 2:
Todo conjunto de cláusulas con una literal pura de la forma:
Ç= { A1 v L, A2 v L, ... , A n v L, L}
(7)
es satisfactible.
DEMOSTRACION
Supongamos que Ç es insatisfactible. Entonces NIL se puede obtener de los conjuntos:
a) L
b) A1 v L, A2 v L, ... , A n v L
En a) no existe NIL, puesto que L es diferente de ella. Las cláusulas de b) se pueden conformar en
un conjunto no unitario y, por el teorema 1, éste es satisfactible. Por lo tanto NIL no existe en b).
Entonces NIL se debe poder obtener como un resolvente entre L y las cláusulas en b). Como
consecuencia, en b) se puede obtener ~ L como resolvente. Por lo tanto, ~ L existe en alguna
cláusula del conjunto b, lo cual es imposible. En consecuencia el conjunto Ç es satisfactible. []
El conjunto (7) contiene una literal pura en todas sus cláusulas. Conjuntos como éste se
denominarán puros, como se establece en la siguiente definición.
DEFINICIÓN. Un conjunto puro contiene una literal pura en todas sus cláusulas.
COROLARIO: Todo conjunto puro es satisfactible.
Un procedimiento que determine que un conjunto es puro, indicará también que es satisfactible.
Para ello usamos la siguiente nomenclatura:
sign (Li) es el signo de una literal Li en S0
Sum (Li) es la suma acumulada de sign(Li) para Li en cada cláusula
Max (S) el máximo valor entre todos los Sum (Li).
N el número de cláusulas en S0.
El algoritmo simple siguiente detecta si un conjunto S0 es puro y por tanto satisfactible.
Si
Max(S0) = N
Entonces
S0 es puro y satisfactible.
EJEMPLO:
Determinar si el siguiente conjunto es satisfactible:
S0 = {P v ~Q v R, P v Q, P}
SOLUCIÓN
N = 3 cláusulas
sign(P) = {1, 1, 1} ; SUM (P) = 3
sign(Q) = {-1, 1, 0} ; Sum (Q) = 0
sign(R) = {1, 0, 0} ; Sum(R) = 1
de modo que Max (S0) = 3.
por lo tanto S0 es satisfactible.
EJEMPLO:
Determinar sI los siguientes conjuntos son satisfactibles.
ii) {P v B v R, P v ~B}
iii) {Pv Q}
iv) P
SOLUCIÓN
Los tres casos conforman conjuntos puros. Por lo tanto, esos conjuntos son satisfactibles.
TEOREMA 3
Sea un conjunto:
S0 = {A1 v L, A2 v L, ..., An v L, L, Sa}
(8)
tal que S1 es vacío, entonces S0 es satisfactible.
DEMOSTRACIÓN
Puesto que S1 es vacío y, al obtenerlo, se eliminaron de S0 todas las cláusulas con la literal L,
entonces todas las cláusulas en Sa contienen la literal L y por lo tanto ~L no existe en S0.
En consecuencia el conjunto S0 contiene una literal pura. Es decir es de la forma:
S0 = {C1 v L, C2 v L, ... , Cm v L, L}
Esto es, S0 es puro. Del teorema 2, S0 es satisfactible. []
En consecuencia S0 es satisfactible si al eliminar las cláusulas conteniendo L, el conjunto S1
resultante es vacío. Esto significa que este teorema justifica el paso 1 de la regla R1L de Davis.
TEOREMA 4
Sea un conjunto de cláusulas
S0 = {A1 v L, A2 v L, ..., An v L, L, Sa}
Tal que S1 no es vacío y se forma un conjunto S2, quitando de S1 la literal ~L,
Entonces S0 es insatisfactible si S2 es insatisfactible.
DEMOSTRACIÓN
Como S1 no es vacío, no se puede concluir que S0 es satisfactible, pero tampoco que no lo es.
Observe que S0 es insatisfactible si el resolvente de Sa y L es NIL; entonces se requiere que Sa
tenga en alguna cláusula, la literal ~L. Como al momento de formar S1, se eliminaron de Sa las
cláusulas con la literal L, entonces en Sa hay dos posibles tipos de cláusulas:
a) Las que no contienen ~L
b) Las que contienen ~L.
Ahora bien, todos los resolventes de la cláusula L con las cláusulas tipo b de Sa se encuentran
forzosamente en S2. De manera que si S2 es insatisfactible, S0 lo es. En consecuencia, este
teorema justifica el paso 2 de la regla R1l de Davis.
A partir de este teorema se desprende la regla de una literal pura de Davis la cual establece que
para el conjunto S0 anterior, si Sa es insatisfactible, entonces, S0 es insatisfactible. Esto se justifica
fácilmente, ya que para S0 sus cláusulas están en la fórmula normal conjuntiva. Es decir que S0 se
puede representar por la secuencia:
S0 = (A1 v L) & (A2 v L) &, ..., & (An v L) & , L, & Sa
de tal manera que si Sa es insatisfactible, S0 forzosamente lo es. La regla de una literal pura de
Davis & Putnam (no confundir con la regla de una literal, descrita aquí como R1L), se enuncia
entonces como sigue:
REGLA DE UNA LITERAL PURA:
Sea un conjunto S0 de cláusulas del Cálculo Proposicional (o del Cálculo de Predicados, si las
cláusulas están aterrizadas), de modo que en S0 se tenga una literal pura L. Se forma el conjunto
S1 eliminando de S0, todas las cláusulas que contengan L. S0 es insatisfactible si S1 lo es.
Si ocurre que S1 es vacío, S0 es satisfactible.
EJEMPLO:
Determinar si el siguiente conjunto de cláusulas es insatisfactible:
S0 = { (A v B), (A v ~B), (C v B), (C v ~B)}
SOLUCIÓN
So tiene dos literales puras, que son A y C, pero S0 no es puro. Aplicando La regla de una literal
pura sobre A, se tiene:
S1/A = {(C v B), (C v ~B)}
Hacemos
S0 = {(C v B), (C v ~B)}
Aplicamos ahora la regla de una literal pura sobre C para obtener:
S' = {}
==> So es satisfactible.
EXTENSIONES DE LA REGLA DE UNA LITERAL
Es posible establecer extensiones de R1L para considerar aplicaciones distribuidas de la misma. Para
ello se exponen aquí dos versiones:
a) R1L ESTRUCTURADA CON CONJUNTO DE SOPORTE
b) REGLA R1L ESTRUCTURADA PARA N LITERALES
Para lo anterior recordemos que deseamos saber si una fórmula objetivo G, es una consecuencia
lógica de un conjunto de fórmulas,
Ø= {F1, F2, ..., Fn}
(1)
el cual es un conjunto de axiomas consistente, es decir, en Ø no existe ninguna cláusula
contradictoria.
Es decir, se desea saber si se cumple que:
Ø |- G
(2)
Como hemos visto, se puede proceder negando la fórmula objetivo para determinar si la conjunción
siguiente es inconsistente:
F1 & F2 & ...& Fn & ~ G
(3)
o bien
F1 & F2 & ...& Fn & G'
(3a)
donde G' = ~G
Pasando ~G a su forma normal conjuntiva, obtenemos un conjunto S0 de cláusulas
S0 = {F1, F2, ...Fn, g1, g2, ... , gr}
(3b)
donde g1, g2, … son cláusulas de la fórmula objetivo negada. Es decir las g's son de la forma:
gi = gi1 v gi2 v, …, v gil
(4)
Consideraremos a S0 como una base de datos, de manera que cada posición de S0 es un campo.
Obtendremos una regla de una literal, de manera que las cláusulas de los pasos 1 y 2 de R1L de
Davis, se obtengan en los mismos campos de S0. Buscamos extender la regla R1l de Davis, de
modo que se aproveche la información de la fórmula objetivo negada y que los resolventes
obtenidos en cada uno de los pasos se almacenen en los mismos lugares del conjunto S0 original.
Estos procedimientos de resolución se conocen como Procedimientos de Conjunto de Soporte y la
práctica ha demostrado que son eficientes. Para obtener la regla que buscamos, primero
enunciaremos la regla R1l de Davis en forma compacta.
R1L DE DAVIS EN FORMA COMPACTA
Sea So = { Ø, G'} un conjunto de cláusulas conteniendo un conjunto de axiomas Ø y una fórmula
objetivo negada G'. Entonces se puede determinar la satisfactibilidad de So de la siguiente manera:
PRIMER PASO: Obtener un conjunto S1 ={Ø, G'} a partir de S0, eliminando aquellas cláusulas que
contengan una literal Li, las cláusulas restantes se acomodan en la Base de datos S1, en los lugares
Ø o G' según corresponda a los axiomas ó a la formula objetivo, respectivamente. Si S1 es vacío,
entonces S0 es satisfactible. Si S1 no es vacío, continuar con el paso 2.
SEGUNDO PASO: Obtener el conjunto S2, al eliminar ~Li de S1. S0 es insatisfactible, si S2 lo es.
Durante el primer paso de esta regla, si el conjunto S1 es vacío, esto significa que Ø y también G' es
vacío. En este caso S0 es satisfactible. Pero G = ~G’. En consecuencia G no es un teorema.
La regla que acabamos de enunciar como R1L de Davis en forma compacta, es en realidad la regla
R1L de Davis, solamente que hemos identificado al conjunto de axiomas y a la fórmula objetivo.
Ahora podremos enunciarla aprovechando el hecho de que cualquier contradicción sólo se puede
presentar con la participación de las cláusulas de la G’ ó descendientes de ella.
R1L ESTRUCTURADA CON CONJUNTO DE SOPORTE
Sea So = {Ø, G'} un conjunto de cláusulas conteniendo un conjunto de axiomas Ø y una fórmula
objetivo negada G' = ~G. Suponga que existe una literal L en Ø; entonces, para determinar la
satisfactibilidad de S0 (y si G es una consecuencia lógica de Ø), se realizan los siguientes pasos:
PASO 1: Formar S1, eliminando de S0 las cláusulas que tengan L, de modo que las cláusulas
resultantes se acomodan en Ø y G' según provengan. Entonces si G' es vacío, S0 es satisfactible, de
modo que G no es una consecuencia lógica de Ø. Si G' no es vacío, seguir con el paso 2.
PASO 2. Eliminar la literal ~L de S1 para formar el conjunto S2, acomodando las cláusulas
resultantes en Ø o G' según corresponda. Entonces si S2 es insatisfactible, S0 también lo es y G no
sigue de los axiomas originales Ø.
EJEMPLO
Determinar si G es una consecuencia lógica de Ø:
Ø = {A, B, ~C, D v R, ~D v A}
G = {~A, ~ B, ~ C}
SOLUCIÓN
G' = ~G = A v B v C
Registramos la información de S0, S1, S2, en la siguiente base de datos:
S0
S1/A
Ø
G'
______________
A, B, ~C
AvBvC
DvR
~D v A
_______________
B, ~C
vacío
DvR
~D
_______________
S1 es vacío, lo que significa que:
G no es una consecuencia lógica de Ø
Este resultado se puede comprobar usando R1L de Davis:
S0 = {A, B,~C, D v R, ~D v A, A v B v C}
S1/A = { B, ~C, D v R} = S2/~A = So
S1/B = {~C, D v R} = S2/~B = So
S1/~C = {D v R} = S2/C
S0 = {D v R}
Como S0 es un conjunto puro de cláusulas, S0 es satisfactible. En consecuencia, G no es una
consecuencia lógica de Ø. Nótese la conveniencia de contar con un procedimiento que detecte
conjuntos de cláusulas puros. Obsérvese también que R1L estructurada se aplica cuando Ø cuenta
con cláusulas unitarias y, que en el momento que S0 (incluyendo desde el principio), no cuente con
cláusulas unitarias, habrá que utilizar otro método.
EJEMPLO
So = { A v L, ~B v D, A v B, B}
G=DvA
SOLUCIÓN
G'= ~G = {~D, ~A}
Registramos la información de S0, S1, S2, en la siguiente base de datos:
Ø
G'
______________
S0 A v L,
~D, ~A
~B v D,
A v B,
B
_______________
AvL
~D, ~A
S1/B
~B v D
S2/~B
_______________
AvL
~D, ~A
D
________________
Aplicando resolución unitaria, encontramos que S2 es insatisfactible, debido a la presencia de las
cláusulas unitarias D y ~D. Esto significa que:
G es una consecuencia lógica de Ø
Este resultado se puede comprobar usando el método de conjunto de soporte con resolución unitaria
y eliminando cláusulas repetidas:
(1) A v L
(2) ~B v D
(3) A v B
(4) B
(5) ~ D
(6) ~A
{6,1} (7) L
{6,3} repetida
{5,2}(8) ~B
{4,8}(9) nil
Es posible extender la Regla R1L de Davis, para eliminar a la vez varias cláusulas unitarias. Para ello
exponemos primero algunos teoremas relacionados.
TEOREMA 5
Sea Aij cláusulas de 1 ó mas literales y L1, L2, ...,Lm son cláusulas unitarias tal que ni Li ni su
complemento existen en ninguna Aij. Entonces todo conjunto de cláusulas
S0 ={ A11 v L1, A12 v L1, ... , A1n v L1, L1,
A21 v L2, A22 v L1,... A2n v L2, L2,
................................................................
................................................................
Am1 v L1, Am2 v L2, ... , Amn v Lm, Lm }
es satisfactible.
DEMOSTRACIÓN
S0 está formado por conjuntos de cláusulas de la forma:
Ai1 v Li, Ai2 v Li, ..., Ain v Li, Li; i =1, .., m
En el primer paso de R1L de Davis, eliminamos L1 para obtener S1 igual a S2 excepto que no
contiene el primer renglón. Es decir:
S1: {A21 v L2, A22 v L2,..., A2n v L2, L2,
.............................................................
..............................................................
Am1 v L1, Am2 v L2, ... , Amn v Lm }
Aplicamos ahora el segundo paso de R1L. Puesto que no existe ~L2 en S1, se obtiene S2 igual al
conjunto S1 anterior. Se hace ahora S0 igual al último S2. Repitiendo este proceso para todas las
Li’s, obtenemos finalmente un conjunto S1 vacío. Por lo tanto S0 es satisfactible. []
COROLARIO
Para el paso 1 de R1l, si se eliminan todas las cláusulas que contengan literales Li que sean
cláusulas unitarias en Ø, Si el conjunto S1 resultante es vacío, S0 es satisfactible.
Cuando se conforme el conjunto S1 de la manera descrita en este corolario, se dirá que éste se
obtiene de manera distribuida. De otra manera se dirá que S1 se obtiene de manera simple.
Para el siguiente teorema (teorema 6), consideraremos que S1 se ha formado de manera distribuida
y fué diferente de vacío. En consecuencia, no se pudo concluir que S0 sea insatisfactible.
Supondremos como antes que Sa es cualquier conjunto de cláusulas.
Como S1 resultó diferente de vacío, se procede a construir conjuntos S2 como sigue. Para la literal
L1, se buscan todas las cláusulas en S1 que contengan la literal ~L1, se les quita dicha literal y se
agrupan en el conjunto S21. Se procede de manera similar para L2, ... , Lm, formando los conjuntos
S22, ...S2m. Como veremos en el teorema 6, S0 es insatisfactible si existe algún subconjunto S2i
que sea insatisfactible.
TEOREMA 6
Sea Aij cláusulas de 1 ó mas literales y sean L1, L2, ... ,Lm cláusulas unitarias tales que ninguna de
ellas ni su complemento existen en ninguna Aij. Sea el conjunto de cláusulas:
S0 ={ A11 v L1, A12 v L1, ... , A1n v L1, L1,
A21 v L2, A22 v L2,... A2n v L2, L2,
................................................................
Ak1 v Li, Ak2 v Li, ... , Akr v Li, Li
................................................................
Am1 v Lm, Am2 v Lm, ... , Amn v Lm, Lm, Sa }
Considere que se forma el conjunto S1 en forma distribuida, y resulta que este no es vacío y, se
toman de S1 las cláusulas que contengan las literales ~L1, ~L2, ... , ~Lm, para obtener
respectivamente los subconjuntos S21, S22, ...S2m a partir de ésas cláusulas pero sin la literal ~Li
correspondiente.
Si existe uno o mas subconjuntos S21, S22, ... , S2m que sea insatisfactible, S0 es insatisfactible.
DEMOSTRACIÓN
El conjunto Sa debe, forzosamente, contener una literal complementaria ~Li, ya que de otra manera
los conjuntos S2i no se pueden formar. Aplicamos el primer paso de la regla R1l de Davis eliminado
el renglón Li de S0, para obtener el conjunto S1 y todas las cláusulas en Sa que contengan Li:
S1 ={ A11 v L1, A12 v L1, ... , A1n v L1, L1,
A21 v L2, A22 v L2,... A2n v L2, L2,
................................................................
................................................................
Am1 v Lm, Am2 v Lm, ... , Amn v Lm, Lm, Sai }
Donde Sai, es el conjunto Sa pero sin las cláusulas que tengan Li.
Puesto que S1 no es vacío, aplicamos el segundo paso de R1l de Davis, para formar el conjunto S2.
En ese conjunto las cláusulas sin ~Li, las colocamos en el subconjunto S2i. Se repite este
procedimiento para todas las cláusulas unitarias Li.
S2 es entonces la conjunción de todas las cláusulas de los subconjuntos S2i. Entonces, resulta que
si S2i es insatisfactible, S2 lo es y, por la regla R1L de Davis, S0 también lo es. []
TEOREMA 7
Sea el conjunto
S0 ={ A11 v L1, A12 v L1, ... , A1n v L1, L1,
A21 v L2, A22 v L2,... A2n v L2, L2,
................................................................
................................................................
Am1 v Lm, Am2 v Lm, ... , Amn v Lm, Lm, Sa }
Si Sa no contiene ninguna literal complementaria ~Li, S0 es satisfactible si Sa también lo es.
DEMOSTRACIÓN
Note que no podemos aplicar el teorema 6 ya que no podemos formar los subconjutnos S2i. En este
caso todas las Li son literales puras de modo que al aplicar sucesivamente la regla RIL de Davis, se
encuentra que
S1 = Sa
en consecuencia si Sa es insatisfactible, S1 también lo es. Aplicando la regla de una literal pura, se
obtiene entonces que si Sa es insatisfactible, So también lo es. []
Con estos elementos podemos enunciar una primera regla R1l estructurada.
REGLA R1L ESTRUCTURADA PARA N LITERALES
Sea un conjunto S0 = { Ø, G’} de cláusulas con n literales L1, L2, ..., Ln en Ø. Entonces se puede
determinar la satisfactibilidad de S0 en dos pasos:
PASO 1: Formar el conjunto S1 en forma distribuida, eliminando de S0, todas las cláusulas que
contengan alguna literal Li. S0 es satisfactible si S1 lo es. Si S1 no es vacío pasar al paso 2.
PASO 2: Si S1 construido en forma distribuida y no es vacío se procede como sigue. Se toman de
S1 las cláusulas que contengan las literales ~L1, ~L2, ... , ~Lm, para obtener respectivamente los
subconjuntos S21, S22, ...S2m, conformados con esas cláusulas, pero sin la literal ~Li
correspondiente. Si existe uno o mas subconjuntos S21, S22, ... S2m que sean insatisfactible, S0 es
insatisfactible.
REGLA DE PARTICIÓN
En ocasiones no se puede aplicar la Regla de una literal (en ninguna de sus versiones) debido a que
el conjunto S0 no contiene cláusulas unitarias. Por otro lado puede resultar que el conjunto S0 sea
demasiado grande y por lo tanto, es conveniente encontrar un proceso distribuido que permita
buscar la satisfactibilidad de S0 en varios conjuntos de cláusulas, simultáneamente. Para estos caso
la Regla de Partición de Davis & Putnam es ideal. Esta regla se enuncia a continuación.
REGLA DE PARTICION DE DAVIS & PUTNAM:
Sea el conjunto:
S0 = { A1 v L, A2 v L, ... , An v L,
B1 v ~L, B2 v L, ..., Bm v ~ L, Ra}
Donde Ra son cláusulas que no tienen L ni ~L.
Se forman lo conjuntos S(L) "sin L" y S(~L) sin ~L:
S(L) = {A1, A2, ..., An, Ra}
S(~L)={B1, B2, ...., Bm, Ra}
Entonces S0 es insatisfactible si S(L) y S(~L) son ambos insatisfactibles.
La regla de partición se puede combinar con la Regla de una literal (en cualquiera de sus versiones)
para producir un algoritmo eficiente.
ESPECIFICACIÓN FORMAL
INTRODUCCION
Los métodos formales para el desarrollo de software (sw) o, simplemente métodos formales, son
métodos que se utilizan para todas las etapas del ciclo de desarrollo de software y que tienen la
característica que usan formalismos matemáticos para la representación o derivación de los
elementos involucrados en cada etapa.
El punto de arranque en la mayoria de los proyectos de sw es un Documento de Requerimientos del
Sistema (DRS), en el cual se plazman lo que el usuario desea que haga el sw que desea adquirir.
Este documento se escribe por lo general en lenguaje natural (español, inglés, frances, etc.) y, si es
necesario, se utilizan también gráficas, tablas y figuras que ayuden a describir con mayor precisión
lo que el usuario desea. De esta manera, el lenguaje empleado para escribir un DRS es un lenguaje
informal, pero amigable. Los lenguajes informales (como el español), son de naturaleza ambigua, es
decir, una misma expresión puede tener más de un significado. El lenguaje informal en que se
describe un DRS es mas cercano al usuario y, se describe más en términos de su entorno de
aplicación que en términos computacionales. De esta manera empleará expresiones como la
siguiente:
"El sistema deberá calcular la caida de presión de agua de cada tubería del sistema"
"el sistema de control de alarmas para cada centro de control de energía deberá desplegar
informes resumidos en forma ejecutiva cada día, según el anexo de este documento"
De esta manera, términos computacionales ajenos al lenguaje del usuario, son por lo general
evitados en un DRS. De esta forma se evitan términos como "tipo entero", "modulo", etc.
El DRS, por lo general se elabora con la (evidente) participación del usuario. A menudo, el usuario
es asistido para la escritura del DRS por uno ó más miembros del grupo de desarrollo del sistema.
En el DRS, se describen los requerimientos funcionales y no funcionales del sistema de sw que se
desea. Los requerimientos funcionales describen al sistema en términos de entrada-salida, mientras
que los no-funcionales, en téminos de cualidades deseables del sistema. Por ejemplo, los siguientes
son requerimientos funcionales:
"Cuando el operador central teclee el comando DOWN, todos los mensajes de alarma
almacenados en la pantalla desaparecerán del monitor principal, apareciendo en su lugar el
diagrama unifilar de la subestación eléctrica correspondiente"
"Cuando se selecciona la opción RESUMEN en el munú 1825, se desplegarán los promedios de
energía generada por cada planta generadora perteneciente al centro del control correspondiente".
Son ejemplos de requerimientos no funcionales, los siguientes:
"El sistema de manejo de eventos no deberá tardar mas de 10 segundos en proporcionar
resumenes de información ejecutiva"
"El sistema será desarrollado en java e integrado en un estación de trabajo en tiempo real IDM
tipo 6890-56".
A menudo los DRS se escriben sin la participacion diseñadores de sistemas de cómputo, de modo
que no presentan directivas que conlleven a un diseño eficiente. Por otro lado contienen
imprecisiones, de manera que se requiere una tarea de analisis que especifique, claramente y sin
ambiguedades, el sistema a realizar. El DRS está dirigido para una relación entre el lider y analistas
del proyecto de sw y el usuario, mientras la especificación es un documento de trabajo de uso casi
exclusivo para el grupo de desarrollo de sw. Esta situación desde luego que debe cambiar ya que la
participación del usuario en todas las etapas de desarrollo del sistema.
Los métodos formales se pueden utilizar tanto para la especificación como para la verificación formal
de programas y, en principio, para la construcción (de código) formal de programas; esta última da
lugar a programación automática y derivación formal de programas; sin embargo, en sistemas
reales, es mucho más frecuente encontrar aplicaciones de métodos formales para la etapa de
especificación que para la verificación formal y, prácticamente nula para el caso de construcción
formal de programas. En esta sección trataremos sobre los métodos de especificación formal.
LÓGICA DE HOARE
INTRODUCCIÓN
En 1969, C.A.R Hoare presentó un artículo [HOARE69] que iniciaba textualmente así:
"Programación es una ciencia exacta en la que todas las propiedades de un programa y todas las
consecuencias de ejecutarlo en un ambiente dado, pueden ser determinadas, en principio, a partir
del texto mismo del programa a través de razonamiento inductivo puro"
Hoare presentó, en ese entonces, un sistema axiomático para los constructores (o instrucciones)
principales de un programa. Desde entonces ha sido desarrollada una gran cantidad de
investigaciones, aplicaciones y extensiones, por muchos investigadores (incluyendo las realizadas
por el propio Hoare), a tal grado que, en la Enciclopedia de la Computación, a ese artículo, se le
considera el más referenciado en las Ciencias Computacionales. Entre las áreas de aplicación más
importantes se encuentran, especificación y verificación de sistemas distribuidos y en tiempo real y
entre las principales líneas de investigación se encuentran lo que se denomina como Lógica de
Hoare, la cual es objeto de esta sección. La Lógica de Hoare ha dado origen a diversos lenguajes de
especificación, entre los que destaca CSP (Communicating Secuencial Process), un lenguaje
orientado a procesos que desarrolló Hoare, el cual se usa hasta el momento para la especificación de
sistemas concurrentes. CSP ha servido de base para otros lenguajes de especificación formal
orientados a procesos como LOTOS (un lenguaje de la ISO para especificar sistemas concurrentes).
Por otro lado la Lógica de Hoare se puede utilizar para especificación y verificación de programas
secuenciales, distribuidos o concurrentes. De esta forma el conocimiento de la lógica de Hoare es
importante no sólo por las aplicaciones que se derivan directamente de ella, sino también para
comprender y posteriormente aplicar diversos formalismos que de ella se derivan.
LA LOGICA DE HOARE
La lógica de Hoare, emplea:
a) la tripleta {P} S {Q} denominada aserción inductiva, donde
{P} se denomina la precondición
S es un programa o fragmento de programa
{Q} se denomina la poscondición
b) Un sistema axiomático
La tripleta {P} S {Q} de la lógica de Hoare se debe a Floyd quien la utilizó para la verificación
formal de diagramas de flujo [FLOYD67]. La idea sustentada por Hoare es que todo programa
debería estar documentado con estas tripletas a lo largo de todo el programa y en diferentes puntos
estratégicos. De esta manera cada sección S de programa debe estar acompañada por su
documentación conformada por su precondición {P} y su postcondición {Q}. La idea de documentar
programas no es nueva, no obstante, Hoare exige que tanto {P} como {Q}, estén escritos en lógica
de primer orden.
La notación {P} S {Q} es tal que:
1) Representa la especificación funcional del programa, donde:
{P} representa el estado de las variables antes de que S se ejecute
{Q} representa el estado de las variables después de que S se ha ejecutado.
Si el programa no se ha escrito, S es el nombre del programa. De otra manera, S está
documentado formalmente con su especificación formal.
2) Representa la correctividad parcial del programa S. Esto significa que el programa S satisface su
especificación (la cual es precisamente {P} S {Q}
Para propositos de verificación, un programa S constituido por fragmentos S1,S2,..,Sn, se
documenta formalmente con aserciones A1, A2,...,An como se ilustra a continuación.
{A1}
S1
{A2}
S2
{A3}
........
......
{ An}
Cada fragmento {Ai} Si {Aj}, es tal que Ai es la precondición de Si y, Aj su postcondición, de
manera que Aj es a la vez la precondición del siguiente fragmento Si+1. Cada Ai se denomina una
aserción.
SISTEMA AXIOMÁTICO DE HOARE
LA INSTRUCCIÓN DE ASIGNACIÓN
La principal diferencia entre las Matemáticas Computacionales y el resto de las matemáticas radica
en la instrucción de asignación. En el caso de computación la asignación se refiere a localidades de
memoria, de manera que cuando se escribe por ajemplo x = x +1, significa que en la localidad de
memoria se incrementará en una unidad, mientras que en Algebra, representa a la indetidad 0 = 1.
Para efectuar una distinción el signo igual de la expresión anterior se escribe x:= x +1.
Cuando se tiene una instrucción de asignación está podrá ser documentada con sus dos aserciones,
su precondición y su postcondición:
P(x)
x := E(x,y)
Q(x)
Donde
E(x,y) = Expresión tal que y representa todos los términos diferentes de x (es decir no contienen
a x).
Para propósitos de verificación es posible:
* Obtener una precondicón derivada (Pder) de la postcondición y de la instrucción de asignación
efectuando una sustitución hacia atrás. Es decir,
* Pder se obtiene reemplazando en Q todas las ocurrencias de x por E.
Por otra parte, la precondición P(x) representa la precondición proporcionada por el usuario. En esta
sección a una precondición porporcionada por el usuario se le representara por Pdada.
EJEMPLO 1.
Determinar la precondición derivada para el siguiente fragmento de código:
{P}
x:= 2*y + 1
{x < 11}
SOLUCIÓN
Sustituyendo hacia atrás:
Pder == {x <11} [x = 2*y + 1]
=={ 2*y + 1 < 11}
=={y <5}
REGLA DE PRUEBA EN REVERSA (backward testing)
La regla de prueba en reversa (RPR) se fundamenta en el siguiente teorema:
TEOREMA
Todo fragmento de código {P} S {Q}, se puede verificar de la siguiente manera. Dado que {P}
representa la precondición dada por el usuario Pdada, S es correcto si dada una precondición
derivada Pder, a partir de {S,Q}, se cumple que:
Pdada => Pder
es válida.
La regla de prueba en reversa, establece que para determinar que un programa S es válido se
efectuan los siguientes pasos:
PASO 1. Identificar la Precondición dada por el usuario Pdada.
PASO 2: Obtener la precondición derivada Pder.
PASO 3: Determinar si Pdada => Pder es una fórmula válida, en cuyo caso el programa S es
correcto.
REGLA DE PRUEBA DE IF THEN
Sea una instrucción IF-THEN:
{P}
IF B THEN S
{Q}
Es decir la Instrucción IF-THEN tiene dos partes, para las cuales se debe realizar lo que a
continuación se indica:
a) El lado Then: Que ocurre cuando B se cumple y, se ejecuta la instrucción S terminando el
estado de las variables de acuerdo con Q. Esta parte tiene como precondición dada {P & B} la cual
representa el estado de las variables antes de que S se ejecute. Una vez que S se ejecuta, se tiene
como postcondición a {Q}, es decir la postcondición de toda la instrucción IF-THEN. Esto significa
que una condición necesaria (pero no suficiente) para que sea correcta la instrucción {P} IF THEN S
{Q} es que la instrucción {P & B} S {Q} sea correcta. Esto puede verificarse, siguiendo los tres
pasos de la Regla de Prueba en Reversa (RPR). El primer paso de RPR es simple, ya que Pdada es
simplemente {P&B}. La obtención de la precondición derivada Pder para el lado del Then, se obtiene
entonces a partir del conjunto {S,Q}. La verificación de Pdada => Pder se puede realizar entonces
usando una tabla de verdad o, por resolución.
b) El lado Falso: Que ocurre cuando B no se cumple. Esta parte los programadores, por lo
general, no la consideran como parte del Then, no obstante que formalmente está presente. Puesto
que el lado falso de la instrucción IF-THEN, no contiene ninguna instrucción, no tenemos fragmento
de código a verificar. Sin embargo se debe cumplir la fórmula P & ~B =>Q. Esto se debe a que para
que el control de ejecución tome el camino de lado falso se debe haber cumplido la fórmula P y
luego la fórmula ~B; de esta forma durante el camino del lado falso se debe cumplir P & ~B. Una
vez que se llega al final del Then se debe cumplir la postcondición Q, de modo que la implicación
de P &~B => debe ser una fórmula válida.
En resumen, de acuerdo con lo anterior un IF-THEN se verifica de la siguiente manera
PASO1: VERIFICACION DEL LADO DEL THEN.
1-A: IDENTIFICACION Pdada:
Pdada == { P & B}
1-B: DETERMINACION DE Pder.
Pder se obtiene con Q y el fragmento de código S del lado del then. Esto se expresa en la
forma:
{Q, S} |- Pder
que significa que a partir de la postcondición Q y el fragmento de código S del lado del
Then se deduce (o debe deducirse) la precondición derivada Pder del lado del Then (el símbolo |- se
lee se "se deduce").
1-C: VERIFICAR SI ES VALIDO:
Pdado |- Pder
PASO 2: VERIFICACION DEL LADO ELSE.
Cuando la condición B no se cumple, no se entra al lado then, de modo que se debe verificar si es
válido:
(P & ~B) -> Q
EJEMPLO
Verificar si el siguiente fragmento de código es correcto:
P = = { X = X'}
IF X < 0 then X = -X
Q= = { (X' < 0 => X = - X') & (X' >= 0 => X = X') }
SOLUCION
PASO 1:PRUEBA P1(VERIFICACION DEL LADO DEL THEN)
1-A
Pdada = = {P & B}
== { (X = X' & X <0}
1-B:
Pder = = { (X' < 0 => X = - X') & (X' >= 0 => X = X') } [X := -X]
= = { (X' < 0 => -X = - X') & (X' > =0 => -X = X') }
1-C Verificar Pdada -> Pder
Construimos una tabla de verdad con 1-A y con una 1-B:
(X = X' & X <0) => (X' < 0 =>-X = - X') & (X' >= 0 => -X = X')
V
V
V
V
V
F
V
V
V
V
V
PASO 2: VERIFICAR P & ~B => Q
X = X' & ~( X <0) => (X' < 0 => X = - X') & (X' >= 0 => X = X')
V
V
F
V
F
V
V
V
V
V
V
V
V
V
En consecuencia, este programa es correcto.
REGLA DE PRUEBA DE IF THEN ELSE
Dada una instrucción if-then-else, de la forma:
{P}
IF B THEN
S1
ELSE
S2
{Q}
Para verificar esta instrucción se deben realizar dos pruebas:
PASO1: VERIFICAR
{P & B } S1 {Q}
PASO 2: VERIFICAR
{P & ~B} S2 {Q}
EJEMPLO
{TRUE}
IF X>= Y THEN MAX := X ELSE MAX:= Y
{X >=Y & MAX = X) OR (X<Y & MAX = Y)
SOLUCION
PRUEBA 1:
Se debe probar si el siguiente programa es correcto:
{TRUE & X>= Y } MAX := X {X >= Y & MAX = X) OR (X<Y & MAX = Y)
donde:
Pdada =={ X>=Y}
y Pder se obtiene reemplazando X en lugar de MAX en la postcondición, es decir:
Pder = = {{X >= Y & X= X) OR (X<Y & X = Y)}
Ahora verificamos si Pdada => Pder es una fórmula válida. Para ello usamos la tabla de verdad:
[X>= Y ] => {X >= Y & X= X) OR (X<Y & X = Y}
V
V
V
F
V
V
F
V
V
V
En consecuencia el programa es correcto.
DETERMINACION DE UNA PRECONDICION DE UN IF-THEN-ELSE
Dada una instrucción IF-THEN-ELSE para la cual no contamos con su precondición:
{?} IF B THEN S1 ELSE S2 {Q}
La precondición se obtiene como sigue:
P= {(P1 & B) OR (P2 & ~B)}
Donde:
P1= precondición derivada del lado del then.
P2= precondición derivada del lado del else.
EJEMPLO:
{?} If x <0 then y := x else y := x-2 {-1 < = y < = 4}
Solución:
La precondición derivada del lado se obtiene reemplazando en la postcondición x por y para obtener
P1 del lado del then, mientras que se reemplaza y por x-2 para obtener P2 del lado del else. Es
decir:
P1 == {-1 < = y < = 4} [y:=x]
=={-1 < = x < = 4}
P2 =={-1 < = y < = 4} [y:=x-2]
== {-1 < = x-2 < = 4}
== {1 < = x < = 6}
De esta forma la precondición buscada es:
P =={-1 < = x < = 4} or {1 < = x < = 6}
EJERCICIO:
Verificar si es correcto el siguiente fragmento de programa:
{ 3 < = |X| < = 4}
IF X <0 THEN Y := -X ELSE Y:= X
{2 < = Y < = 4}
REFERENCIAS
[FLOYD67} Floyd R. W. Assignment Meaning to programs?, Proc. American Mathematical Society
Sym. on Applied Mathematics, Vol. 19.
[HOARE69] Hoare C.A.R., An Axiomatic basis for computer programming?, Commm. ACM, 12 (10),
pp. 576-580
[FRAUSTO] Frausto Solís J, Sánchez Ante G., "Fundamentos de Lógica Computacional", Editorial
Trillas, Enero 2000. ISBN 968-24-6100-6
Descargar