anexos -...
Post on 07-May-2018
241 Views
Preview:
TRANSCRIPT
1
ANEXOS
ANEXO 1. Formulas lógicas proposicionales para SAT-FNC ............................................................................. 3
ANEXO 2. Conjuntos, Relaciones y Funciones .................................................................................................10
ANEXO 3. Programación Lógica: algoritmo en lenguaje C ...............................................................................27
ANEXO 4. Problemas Satisfactibilidad ...............................................................................................36
ANEXO 5. Problemas -completos .................................................................................................................38
ANEXO 6. Problemas y ............................................................................................................................41
ANEXO 7. Proposiciones y variables lógicas .....................................................................................................49
ANEXO 8. El poder de los lenguajes de programación ......................................................................................60
ANEXO 9. Lenguajes recursivamente numerables y recursivos .........................................................................77
ANEXO 10. Ordenamiento y búsqueda ............................................................................................................97
ANEXO 11. Sistemas Secuenciales Biestables ...............................................................................................108
TEOREMAS .........................................................................................................................................................132
Teorema 1. Dos conjuntos son iguales si, y solo si, cada uno es subconjunto del otro ..........................................132
Teorema 2. El conjunto vacío es subconjunto de cualquier conjunto. ..................................................................132
Teorema 3. Dado un conjunto y subconjuntos del mismo ........................................................................132
Teorema 4. Sea un conjunto y subconjuntos arbitrarios de el. ..............................................................132
Teorema 5. La relación inversa de una equivalencia es ella misma. ......................................................................133
Teorema 6. Sea una equivalencia definida en un conjunto entonces cada elemento del conjunto está en la
clase que representa. ...............................................................................................................................................133
Teorema 7. Si es una equivalencia en el conjunto , sus clases de equivalencia constituyen una partición de .
................................................................................................................................................................................133
Teorema 8. Dada una partición de un conjunto, existe una equivalencia definida en dicho conjunto cuyas clases de
equivalencia son los subconjuntos que constituyen la partición. ...........................................................................134
Teorema 9. La relación inversa de un orden es también un orden, denominado orden inverso. ............................134
Teorema 10. Todo elemento máximo es maximal y, si existe, el máximo es único. .............................................134
Teorema 11. Un subconjunto acotado superiormente tiene máximo si, y solo si, tiene supremo y este pertenece a
dicho subconjunto. ..................................................................................................................................................134
Teorema 12. En un orden total todo maximal es máximo y, por tanto, único y todo minimal es mínimo y, por
tanto, único. ............................................................................................................................................................134
Teorema 13. En un conjunto con más de un elemento, si un orden total es lineal, entonces no verifica las
propiedades del inmediato sucesor ni del inmediato antecesor. .............................................................................135
Teorema 14. Un orden total verifica la propiedad del supremo si, y solo si, verifica la propiedad del ínfimo. .....135
Teorema 15. Ordenación por comparación ............................................................................................................135
Teorema 16. no es un lenguaje recursivamente enumerable. ...........................................................................135
2
Teorema 17. Si es un lenguaje recursivo, entonces también lo es. ..................................................................135
Teorema 18. Si existe una reducción de a ...................................................................................................136
Teorema 19. Las implicaciones directa y contrapositiva son equivalentes, y las implicaciones inversa y reciproca
son equivalentes. .....................................................................................................................................................136
Teorema 20. La doble implicación es equivalente a la conjunción de las implicaciones directa e inversa............137
Teorema 21. La implicación de dos proposiciones es equivalente a la disyunción de la negación de la primera con
la segunda. ..............................................................................................................................................................137
Teorema 22. La negación de la negación es equivalente a la proposición original. ...............................................137
Teorema 23. Conjunción de proposiciones satisface las propiedades de idempotencia, asociatividad,
conmutatividad, existencia de un elemento neutro y de un elemento dominante ...................................................138
Teorema 24. La disyunción de proposiciones satisface las propiedades de idempotencia, asociatividad,
conmutatividad, existencia de un elemento neutro y de un elemento dominante. ..................................................138
Teorema 25. Las siguientes relaciones son validas para cualesquiera proposiciones ..................................139
Teorema 26. Si es un enunciado abierto, con una variable, entonces se cumplen las equivalencias .........140
Teorema 27. Si es un enunciado abierto que depende de dos variables, se cumplen las siguientes
equivalencias entre proposiciones. .........................................................................................................................140
Teorema 28. Para proposiciones cualesquiera los siguientes son razonamientos lógicos ........................140
GLOSARIO...........................................................................................................................................................142
11
p1
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┬ ┬ ┬
┬ ┴ ┴
┴ ┬ ┴
p1
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
1 1 1
1 0 0
0 1 0
p1
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
r 1 r 2
r 3 r 4
c11
c12
c13
c21
c22
c23
c31
c32
c33
1 1 0 0 0 0 0 0
1 1
1 1
1 1
1
0 0 0
0 0 0 0 0 0
0 0 0
0 0 0 0 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 00 0 0
1
10
1
1 10
0 1
0
p1
11
12
13
21
22
23
31
32
33
c11 c12 c13
c21
c32
r 1r 2
r 3
r 4
12
p2
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┬ ┴ ┴
┬ ┬ ┬
┴ ┬ ┴
p2
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
1 0 0
1 1 1
0 1 0
p2
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
r 1
r 2 r 3
r 4
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 0
1 10 0 0 0 0 0
1
10
p2
1 1 1
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 00 0 0
11
12
13
21
22
23
31
32
33
c11
c21c22 c23
c32
r 1
r 2
r 3
r 4
14
p3
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┴ ┬ ┴
┬ ┴ ┴
┬ ┬ ┬
p3
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
0 1 0
1 0 0
1 1 1
p3
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
r 1
r 2
r 3
r 4
c11
c12
c13
c21
c22
c23
c31
c32
c33
p3
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 10 0 0 0 0 010
0 1 1 0 0 0 0 0 01
1 1 10 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
11
12
13
21
22
23
31
32
33
c21
c12
c31 c32 c33
15
p4
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┬ ┬ ┴
┬ ┬ ┴
┴ ┬ ┬
p4
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
1 1 0
1 1 0
0 1 1
p4
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
r 1
r 2
r 3
r 4
r 5
r 6
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 1 10 0 0 00 0 0
p4
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 10 0 0 0 0 010
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
11
12
13
21
22
23
31
32
33
c11 c12
c21 c22
c32 c33
r 1
r 2
r 3
r 4
r 5
r 6
17
p5
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┴ ┬ ┴
┬ ┬ ┬
┬ ┬ ┴
p5
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
0 1 0
1 1 1
1 1 0
p5
M
c11 c12 c13
c21 c22 c23
c31 c32 c33r 1
r 2
r 3
r 4
r 5
r 6
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 1 10 0 0 00 0 0
0 0 0 0 0 00 0 0
p5
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 10 0 0 0 0 010
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0
12
21
22
23
31
32
12
13
23
c12
c21 c22 c23
c31 c32
r 1
r 6
r 2
r 3
r 4
r 5
19
p6
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┬ ┴ ┴
┬ ┬ ┴
┬ ┬ ┬
p6
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
1 0 0
1 1 0
1 1 1
p6
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
r 1
r 2
r 3
r 4
r 5
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 1 10 0 0 00 0 0
0 0 0 0 0 0 00 0 0
p6
0 1 1 0 0 0 0 0 01
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
11
12
13
21
22
23
31
32
33
c11
c21 c22
c31 c32 c33
r 1
r 2
r 3
r 4
r 5
21
p7
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┴ ┬ ┬
┴ ┬ ┴
┬ ┬ ┴
p7
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
0 1 1
0 1 0
1 1 0
p7
M
c11 c12 c13
c21 c22 c23
c31 c32 c33r 1
r 2
r 3
r 4
r 5
r 6
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 1 10 0 0 00 0 0
0 0 0 0 0 0 00 0 0
1 10 0 0 0 0 010
1 10 0 0 0 0 010
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
p7
11
12
13
21
22
23
31
32
33
c31 c32
c22
c12
c13
r 1
r 2
r 3
r 6
r 5
r 4
23
p8
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┴ ┬ ┴
┴ ┬ ┴
┬ ┬ ┬
p8
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
0 1 0
0 1 0
1 1 1
p8
M
c11 c12 c13
c21 c22 c23
c31 c32 c33r 1
r 2
r 3 r 4
r 5
r 6
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 1 10 0 0 00 0 0
0 0 0 0 0 0 00 0 0
p8
1 10 0 0 0 0 010
1 10 0 0 0 0 010
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
0 0 0 0 0 0 00 0 0
11
12
13
21
22
23
31
32
33
c12
c22
c32c31
c33
r 1
r 2
r 3
r 4
r 5
r 6
24
p9
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┴ ┴ ┬
┬ ┬ ┬
┴ ┬ ┬
p9
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
0 0 1
1 1 1
0 1 1
p9
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
r 5
r 1
r 2
r 3 r 4
r 6
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 1 10 0 0 00 0 0
0 0 0 0 0 0 00 0 0
p9
1 10 0 0 0 0 010
0 0 0 0 0
0 0 0
0 0
0 0 0 0 0
0 0 0
0 0
0 0
0 0 0
1 1 10 0 00 0 0 000 0 0
10 0 0 0 0 0 00 0 0 0 0 0
0 0 0 0 0 0 00 0 0 0 0 0 0 0
0 0 0 0 0 0 00 0 0 0 0 0 0 0
0
1
11
12
13
21
22
23
31
32
33
c13
c23
c33
c22
c32
c21
r 1
r 2
r 3
r 4
r 5
r 6
26
p10
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
┴ ┬ 1
┴ ┬ ┬
┬ ┬ ┬
p10
M
c11 c12 c13
c21 c22 c23
c31 c32 c33
0 1 1
0 1 1
1 1 1
p10
M
c11 c12 c13
c21 c22 c23
c31 c32 c33r 1
r 2
r 3
r 4
r 5
r 6
r 7
r 8
p10
c11
c12
c13
c21
c22
c23
c31
c32
c33
0 1 1 0 0 0 0 0 01
1 10 0 0 0 0 010
1 1 10 0 0 00 0 0
0 0 0 0 0 0 00 0 0
1 10 0 0 0 0 010
0 0 0
0
0 0
0 0 0
0
0 0
0 0
0
1 1 10 0 00 0 000 0 0
1 10 0 0 0 0 010 00 0
1 1 10 0 0 00 0 0 0 0 0
0 0 0 0 0 0 00 0 0 0 0 0
1
1
12
13
21
22
23
31
32
33
c31c32
c22
c12 c13
c23
c33
r 1
r 2
r 3
r 4
r 5
r 6
r 8
r 7
27
ANEXO 3. Programación Lógica: algoritmo en lenguaje C
/* * File: main.c * Author: mrincon * * Created on June 15, 2016, 2:55 PM */ #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <math.h> #include <errno.h> #include <time.h> #define L 15 //Recurso Labor(ManoObra) #define E 15 //Recurso Equip(Maquina) #define C 8 //Dimension MUX81 #define M 15 //Recurso Inv(Materiales) #define T 200 //Tiempo 480 min/dia #define D 2 //Tiempo dias #define P 10 //Cant Prod #define W 8 //Cant WC #define X 1050 //Dimension Filas Tabla Verdad #define Y 11 //Dimension Columna Tabla Verdad. # Variables max int MUX81(int MUXi[], int z); void main(){ int xx,c1,c2,c3,SelP,SelW,t1,t2,t3,z1,z2,sumP[P],sumWP[W][P],mat[M],equ[E],lab[L],In[M],Eq[E],La[L]; int s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12,s13; int SOc[P],SOi[P],SOt[P],SOe[P],WCrPc[W][P],WCiPi[W][P],WCtPt[W][P],WCePe[W][P],WCe[W],WCt[W],WCr[W],WCb[W]; int p0,p1,p2,p3,p4,p5,p6; int *ip; double random(); FILE *infile; //p1=1;p2=1;p3=1;p4=1; printf("\n\tPRODUCTION SCHEDULE\n"); /* printf("Print SOi [0,1] "); scanf("%d",&p0); printf("Print SOt [0,1] "); scanf("%d",&p1); printf("Print SOe [0,1] "); scanf("%d",&p2); */ p1=p2=p3=0; printf("Print WCi [0,1] "); scanf("%d",&p3); printf("Print WCt [0,1] "); scanf("%d",&p4); printf("Print WCe [0,1] "); scanf("%d",&p5); if((infile=fopen("C:/temp/inv.txt","rt"))==NULL) exit(0); for(c1=1;c1<=M;c1++) fscanf(infile,"%d",&In[c1]); //Inventario Disponibilidad (t) fclose(infile); if((infile=fopen("C:/temp/equ.txt","rt"))==NULL) exit(0); for(c1=1;c1<=E;c1++) fscanf(infile,"%d",&Eq[c1]); //CRP Disponibilidad (t) seg/dia fclose(infile);
28
if((infile=fopen("C:/temp/lab.txt","rt"))==NULL) exit(0); for(c1=1;c1<=L;c1++) fscanf(infile,"%d",&La[c1]); //CRP Disponibilidad (t) seg/dia fclose(infile); /* Sistema Logico Combinacional por c/u WC */ t1=1; do{ if((infile=fopen("C:/temp/SOc.txt","rt"))==NULL) exit(0); c1=0; while(!feof(infile)){ fscanf(infile,"%d",&SOc[c1]); //Cant.(OS/WO) Setup MPS if(SOc[c1]>0) SOt[c1]=SOi[c1]=1; else SOt[c1]=SOi[c1]=0; //printf("\nSOi=%d\t\tSOt[%d]=%d",SOi[c1],c1,SOt[c1]); sumP[c1]=0; //printf(" %d",SOc[c1]); c1++; } fclose(infile); z1=c1-1; //printf("\n%d",z1); if((infile=fopen("C:/temp/WCr.txt","rt"))==NULL) exit(0); c2=0; while(!feof(infile)){ fscanf(infile,"%d",&WCr[c2]); //Cant.(OS/WO) Setup MPS //printf("\ntWCr[%d]=%d",c2,WCr[c2]); c2++; } fclose(infile); z2=c2-1; //printf("\n%d",z2); if((infile=fopen("C:/temp/WCiPi.txt","rt"))==NULL) exit(0); while(!feof(infile)){ for(c2=0;c2<=z2;c2++){ //Cant.WCi2 for(c1=0;c1<=z1;c1++){ //Cant.Pi fscanf(infile,"%d",&WCiPi[c2][c1]); //Relacion.(WCi/Pi) Setup CRP. !!MRP?!! WCtPt[c2][c1]=WCiPi[c2][c1]; WCrPc[c2][c1]=WCr[c2]*SOc[c1]*WCiPi[c2][c1]; WCePe[c2][c1]=sumWP[c2][c1]=0; //printf("[%d][%d] %d\n",c2,c1,WCtPt[c2][c1]); //printf("%d\t",WCrPc[c2][c1]); } WCe[c2]=0; //printf("%d %d %d| ",z2,c2,WCe[c2]); //printf("\n"); } } fclose(infile); t3=0; for(t2=1;t2<=T;t2++){ for(c1=1;c1<M;c1++){ mat[c1]=1;//random();
29
equ[c1]=1;//random(); lab[c1]=1;//random(); } //Centro de trabajo C11 s0=(mat[1]&&mat[2]); s1=(mat[3]&&mat[4]); s2=(mat[5]&&mat[6]); s3=(s0&&s1); s4=(s3&&s2); s5=(mat[5]&&mat[6]&&equ[1]&&lab[1]); s6=(equ[2]||equ[3]); s9=(lab[1]||lab[2]); s7=(s0&&s1&&s5&&s6&&s9); s10=(s9||lab[3]); s8=(s2&&s3&&s7&&equ[3]&&s10); WCb[0]=(s4&&s8&&s10); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[0],s4,s8,s10); //Centro de trabajo C21 s0=(mat[1]&&mat[2]); s1=(mat[3]&&mat[4]); s2=(mat[5]&&mat[6]); s3=(mat[7]&&mat[8]); s4=(s0&&s1); s5=(s2&&s3); s6=(s4&&s5); s7=(mat[5]&&mat[6]&&equ[1]&&lab[1]); s8=(mat[7]&&mat[8]&&equ[3]&&lab[2]); s11=(lab[1]||lab[2]); s12=(s11||lab[3]); s9=(equ[2]&&s0&&s1&&s7&&s8&&s11); s10=(equ[4]&&s4&&s5&&s9&&s12); WCb[1]=(s6&&s10&&s12); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[1],s6,s10,s12); //Centro de trabajo C31 s0=(mat[1]&&mat[2]); s1=(mat[3]&&mat[4]); s2=(s0&&s1); s3=(s2&&mat[5]); s7=(lab[1]||lab[3]); s8=(s7||lab[2]); s9=(s8||lab[3]); s4=(mat[1]&&mat[2]&&s1&&equ[1]&&s7); s5=(equ[2]&&s0&&s1&&s4); s6=(equ[3]&&s2&&s5&&s9); WCb[2]=(s3&&s6&&s9); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[2],s3,s6,s9); //Centro de trabajo C12 s0=(mat[1]&&mat[2]&&mat[3]); s1=(mat[4]&&mat[5]&&mat[6]); s2=(s0&&s1); s6=(lab[1]||lab[2]); s7=(s6||lab[3]); s3=(lab[1]&&s1&&equ[1]); s4=(equ[2]&&s0&&s3&&s6); s5=(equ[3]&&s2&&s4&&s7); WCb[3]=(s2&&s5&&s7); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[3],s2,s5,s7); //Centro de trabajo C22 s0=(mat[1]&&mat[2]); s1=(mat[5]&&mat[6]); s2=(s0&&s1&&mat[3]&&mat[4]); s6=(lab[1]||lab[2]); s7=(lab[3]||lab[4]); s8=(s6||s7);
30
s3=(equ[1]&&mat[5]&&mat[6]&&s1&&s6); s4=(equ[2]&&s0&&s3&&s7); s5=(equ[3]&&s2&&s4&&s8); WCb[4]=(s3&&s6&&s9); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[4],s3,s6,s9); //Centro de trabajo C32 s0=(mat[1]&&mat[2]&&mat[3]&&mat[4]&&mat[5]); s4=(lab[1]||lab[2]||lab[3]); s1=(equ[1]&&s0&&s4); s2=(equ[2]&&s0&&s4); s3=(s1&&s2); WCb[5]=(s3&&s6&&s9); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[5],s3,s6,s9); //Centro de trabajo C13 s0=(mat[1]&&mat[2]); s1=(mat[4]&&mat[5]&&mat[6]); s2=(s0&&s1); s3=(s2&&s1); s8=(lab[2]||lab[3]); s9=(s8||lab[3]); s4=(equ[1]&&lab[2]&&s1); s5=(equ[3]&&lab[1]&&s0); s6=(equ[2]&&s2&&s4&&s5&&s8); s7=(equ[4]&&s3&&s6&&s9); WCb[6]=(s3&&s7&&s9); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[6],s3,s7,s9); //Centro de trabajo C23 s0=(mat[1]&&mat[2]); s1=(mat[3]&&mat[4]); s2=(mat[5]&&mat[6]); s3=(mat[7]&&mat[8]); s4=(s0&&s1); s5=(s2&&s3); s6=(s4&&s5); s10=(lab[1]||lab[3]); s11=(lab[2]||s10); s12=(lab[3]||s11); s7=(equ[1]&&mat[7]&&mat[8]&&s10); s8=(equ[2]&&s1&&s7&&s11); s9=(equ[3]&&s4&&s5&&s8&&s12); WCb[7]=(s6&&s9&&s12); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[7],s6,s9,s12); //Centro de trabajo C33 s0=(mat[1]&&mat[2]); s1=(mat[4]&&mat[5]&&mat[6]); s2=(s0&&s1); s3=(s2&&s1); s8=(lab[2]||lab[3]); s9=(s8||lab[3]); s4=(equ[1]&&lab[2]&&s1); s5=(equ[3]&&lab[1]&&s0); s6=(equ[2]&&s2&&s4&&s5&&s8); s7=(equ[4]&&s3&&s6&&s9); WCb[8]=(s3&&s7&&s9); //printf("\n<%d> WC.Bool \t%d\t%d\t%d\t%d",WCt[7],s3,s7,s9); c1=0; do{ SelP=MUX81(SOt,z1); //Select Product de SOt en MUX81. MT Nivel I c2=0; do{ for(c3=0;c3<=z2;c3++){ WCt[c3]=WCtPt[c3][c1]; //printf("%d\t",WCtPt[c3][SelP]);
31
} //printf("\n"); SelW=MUX81(WCt,z2); //Select Centro Trabajo de WCi en MUX81. MT Nivel II if(((WCtPt[c2][c1]==1)&&(c2==SelW))){ if(!(WCePe[c2][c1]^WCe[c2])){ WCe[c2]=WCePe[c2][c1]=1; sumWP[c2][c1]+=WCePe[c2][c1]; if(sumWP[c2][c1]>WCrPc[c2][c1]){ WCe[c2]=WCtPt[c2][c1]=WCePe[c2][c1]=0; sumWP[c2][c1]--; //WCrPc[c2][c1]-=sumWP[c2][c1]; } } } else{ WCePe[c2][c1]=0; } c2++; }while(c2<=z2); //WCe[c2]=(WCe[c2]||WCtPt[c2][c1]); /* for(c2=0;c2<=z2;c2++){ for(c1=0;c1<=z1;c1++){ WCe[c2]=(WCe[c2]||WCtPt[c2][c1]); //printf("%d\t",WCtPt[c2][c1]); } } */ //if((SOi[c1]||SOt[c1])==1){ /* if(SOt[c1]==1){ SOe[c1]=1; //SOi[c1]=0; sumP[c1]+=SOe[c1]; if(sumP[c1]>SOc[c1]){ // SOt[c1]=SOe[c1]=0; sumP[c1]--; //SOc[c1]-=sumP[c1]; } } else SOe[c1]=0; */ c1++; }while(c1<=z1); printf("\n<%d> %d\t",t1,t2); /* printf("\t"); for(c1=0;c1<=z1;c1++) printf("%d ",SOc[c1]); */ if(p0==1){ printf("\t"); for(c1=0;c1<=z1;c1++){ if(SOi[c1]==1) printf("%d ",SOi[c1]); else printf("%d ",SOi[c1]); } } if(p1==1){ printf("\t");
32
for(c1=0;c1<=z1;c1++){ if(SOt[c1]==1) printf("%d ",SOt[c1]); else printf("%d ",SOt[c1]); } } if(p2==1){ printf("\t"); for(c1=0;c1<=z1;c1++){ if(SOe[c1]==1) printf("%d ",SOe[c1]); else printf("%d ",SOe[c1]); } } /* printf("\t"); for(c1=0;c1<=z1;c1++) printf("%d ",sumP[c1]); printf("\t"); for(c2=0;c2<=z2;c2++) printf("%d\t",WCr[c1]); */ if(p3==1){ printf("\n"); for(c1=0;c1<=z1;c1++){ printf("\t"); for(c2=0;c2<=z2;c2++){ if(WCiPi[c2][c1]==1) printf("%d",WCiPi[c2][c1]); else printf("%d",WCiPi[c2][c1]); } } } if(p3==1){ printf("\n"); for(c1=0;c1<=z1;c1++){ printf("\t"); for(c2=0;c2<=z2;c2++){ if(WCtPt[c2][c1]==1) printf("%d",WCtPt[c2][c1]); else printf(" "); } } } if(p4==1){ //printf("\n"); for(c1=0;c1<=z1;c1++){ printf("\t"); for(c2=0;c2<=z2;c2++){ if(WCePe[c2][c1]==1) printf("%d ",WCePe[c2][c1]); else printf(" "); } } } if(p5==1){ //printf("\n"); //for(c1=0;c1<=z1;c1++){ printf("\t");
33
for(c2=0;c2<=z2;c2++){ if(WCe[c2]==1) printf("%d ",c2); else printf(" "); } //} } /* printf("\t"); for(c2=0;c2<=z2;c2++) printf("%d\t",sumW[c2]); */ //getch(); } //getch(); t1++; }while(t1<D); } int _seed1=1000,_seed2=12000,_seed3=28000; double random() { double r; int s; _seed1=(_seed1%177)*171-(_seed1/177)*2; if(_seed1<0)_seed1+=30269; _seed2=(_seed2%176)*172-(_seed2/176)*35; if(_seed2<0)_seed2+=30307; _seed3=(_seed3%178)*170-(_seed3/178)*63; if(_seed3<0)_seed3+=30323; r=_seed1/30269.0+_seed2/30307.0+_seed3/30323.0; while(r>1.0) r-=1.0; if(r<=0.5) s=0; else s=1; return s; } double bool(p) double p; { /* Random Booleano Generador de Numeros Pseudoaleatorios de 0 y 1 */ int c,i0,i1,j0,j1,k0,k1,v0,bool[X][Y]; FILE *fp; i1=p; //Cant.Variables j1=pow(2.0,p); //Cant.Combinaciones k1=(j1/2); //Frecuencia por Variable - Tabla de Verdad c=(i1*j1)/2; //Cant.(c/u) - Ceros y Unos /* printf("\nCant.Combinaciones\t%d\nFrec.Variable (2n/2)\t%d\nCant.Binaria\t%d\n",j1,k1,c); getch(); */ for(i0=1;i0<=i1;i0++){ //printf("\nVar %d",i0); k1=(pow(2.0,i0)/2); k0=1; for(j0=1;j0<=j1;j0++){ //printf("\n<%d>",j0); if(k0<=k1){ v0=0;
34
k0++; } else{ if((k0>k1)&&(k0<=(2*k1))){ v0=1; k0++; } } if(k0>(2*k1)) k0=1; bool[j0][i0]=v0; //printf("\tj%d i%d\t%d",j0,i0,bool[j0][i0]); //getch(); } } fp = fopen("C:/temp/test.txt","w+"); for(j0=1;j0<=j1;j0++){ //fprintf(fp,"<%d>",j0); for(i0=1;i0<=i1;i0++){ fprintf(fp,"%d\t",bool[j0][i0]); } fprintf(fp,"\n"); } fclose(fp); } int MUX81(int MUXi[C], int z){ int i,j,x,e,m1,m2,MUXs[C][3],iMUX[C]; int I,F,s0,s1,s2,i0,i1,i2,i3,i4,i5,i6,i7; double q; FILE *fw; q=3; //q Cant bits bool(q); //Llama a la funcion bool() if((fw=fopen("C:/temp/test.txt","rt"))==NULL) //Tabla de verdad - Selecccionador s0,s1,s2 MUX41 exit(0); for(i=0;i<C;i++){ for(j=0;j<3;j++){ fscanf(fw,"%d",&MUXs[i][j]); } } fclose(fw); /* for(m1=0;m1<=z;m1++) printf("\n<%d>MUX wo.wc\t%d",m1,MUXi[m1]); //Valores SOt / WOt printf("\nInhibir? 0/1 "); scanf("%d",&e); */ e=0; x=0; for(i=0;i<C;i++){ I=!e; s0=MUXs[i][0]; s1=MUXs[i][1]; s2=MUXs[i][2]; //printf("\n<%d> %d\t\t%d\t%d\t%d\t\t",i,I,s0,s1,s2); //Out s0,s1,s2 Select iMUX[0]=(MUXi[0]&&I&&(!s0)&&(!s1)&&(!s2)); iMUX[1]=(MUXi[1]&&I&&s0&&(!s1)&&(!s2)); iMUX[2]=(MUXi[2]&&I&&(!s0)&&s1&&(!s2)); iMUX[3]=(MUXi[3]&&I&&s0&&s1&&(!s2)); iMUX[4]=(MUXi[4]&&I&&(!s0)&&(!s1)&&s2); iMUX[5]=(MUXi[5]&&I&&s0&&(!s1)&&s2); iMUX[6]=(MUXi[6]&&I&&(!s0)&&s1&&s2);
35
iMUX[7]=(MUXi[7]&&I&&s0&&s1&&s2); F=0; for(j=0;j<C;j++){ F=F||iMUX[j]; //printf("\t%d",iMUX[j]); } //printf("\t\tMUX.wo %d",F); //Out F del MUX81 if(iMUX[i]==1){ //iMUX[i]=0; x=i; //i=C; break; } //getch(); } return x; }
36
ANEXO 4. Problemas Satisfactibilidad
Definición. 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 los literales de una forma normal conjuntiva , donde
se denomina una clausula y es una disyunción de literales . Cada literal es también conocido como una proposición y
la forma en que se encuentra se dice que es una forma normal conjuntiva o . Dado que se pudiera plantear un
problema similar en lógica de predicados o 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 se entiende que se trata del
problema de lógica proposicional y no de otro. [1]
El problema se trata de un problema donde se pretende determinar si existe una interpretación que satisface una
expresión booleana o proposicional con variables y sin cuantificadores. En otras palabras, se establece si las variables de una
formula booleana dada pueden ser asignadas de una manera tal como para hacer que la formula se evalúa como verdaderas
. Si no existen tales asignaciones, la función expresada por la formula es idéntica a falsa para todas las posibles
asignaciones de variables. En este último caso, se denomina insatisfacible, de lo contrario satisfacible.
Una instancia de sería el saber si existen valores para tales que la expresión:
es cierta.
Por el contrario, el problema de si la expresión en cuestión adquiere valor falso para todas las combinaciones de sus variables,
se denomina
Mientras que la pertenencia del problema o de satisfacibilidad booleana a la clase de los -completos fue demostrada
utilizando mecanismos particulares, las pertenencias de los 21 problemas siguientes fueron demostradas mediante
reducciones polinomiales. Así, el problema se redujo polinomialmente a los problemas 0-1 INTEGER
PROGRAMMING, CLIQUE y 3- , y estos a su vez se redujeron a otros varios. La lista completa es la que se muestra
en el anexo 1. Las sangrías denotan el hecho que la -completitud del problema fue demostrada por reducción polinomial
del problema en el nivel directamente superior. Note que los nombres de los problemas están escritos con letras mayúsculas y
corresponden a abreviaciones del nombre en inglés, como es lo usual; junto a ellos, entre paréntesis, se escribe la traducción
del nombre en español.
El problema parece ser más difícil satisfactibilidad ( -completo) si permitimos que los cuantificadores "para todos
" y "existencial ", que enlace las variables booleanas. Si se utiliza sólo cuantificadores, este sigue siendo el problema SAT.
Si permitimos que sólo los cuantificadores se convierte en el problema de la tautología: -completo. Si dejamos que
ellos, el problema se llama el problema de la fórmula booleana cuantificados (QBF), que puede se ha demostrado
completa. Se cree ampliamente que los problemas son PSPACE completa-es son más difíciles que cualquier problema en NP,
aunque esto aún no ha sido demostrada. . El problema de la máxima satisfactibilidad, una generalización de , para pedir
el número máximo de cláusulas que pueden ser satisfechas por ninguna asignación. Este problema tiene aproximación de con
algoritmos eficientes, sino que es -difícil de resolver con precisión. Peor aún, el problema es -completo, lo que
significa que no hay ningún sistema de aproximación polinomial de tiempo a este problema a menos que .
37
(Problema de satisfacibilidad booleana, para fórmulas en forma normal conjuntiva)
INTEGER PROGRAMMING (Problema de la programación lineal entera)
CLIQUE (Problema del clique, véase también Problema del conjunto independiente)
SET PACKING (Problema del empaquetamiento de conjuntos)
VERTEX COVER (Problema de la cobertura de vértices)
SET COVERING (Problema del conjunto de cobertura)
FEEDBACK NODE SET
FEEDBACK ARC SET
DIRECTED HAMILTONIAN CIRCUIT (Problema del sistema hamiltoniano dirigido)
o UNDIRECTED HAMILTONIAN CIRCUIT (Problema del sistema hamiltoniano no dirigido)
3- (Problema de satisfacibilidad booleana de 3 variables por cláusula)
CHROMATIC NUMBER (Problema de la coloración de grafos)
CLIQUE COVER (Problema de la cobertura de cliques)
EXACT COVER (Problema de la cobertura exacta)
HITTING SET
STEINER TREE
3-DIMENSIONAL MATCHING (Problema del matching tridimensional)
KNAPSACK (Problema de la mochila)
JOB SEQUENCING (Problema de las secuencias de trabajo en programación de
operaciones)
PARTITION (Problema de la partición)
o MAX-CUT (Problema del corte máximo)
38
ANEXO 5. Problemas -completos
Usamos el término -completo para describir los problemas de decisión más difíciles en en el sentido de que, si
existiera un algoritmo polinómicamente acotado para un problema -completo, existiría un algoritmo polinómicamente
acotado para todos los problemas en .
Algunos de los problemas que se describen, podrían parecer más fáciles que otros y, de hecho, las complejidades de peor
caso de los algoritmos que se han ideado para resolverlos sí difieren (son funciones de crecimiento rápido como
etc.) pero, lo cual es sorprendente, todos son equivalentes en el sentido de que, si cualquiera está en
, todos lo están. Todos son -completos.
Reducciones polinómicas. La definición formal de “ -completo” emplea reducciones, o transformaciones, de un
problema a otro. Supóngase que nos interesa resolver un problema y ya tenemos un algoritmo para otro problema .
Supóngase que también tenemos una función que toma una entrada para y produce una entrada para tal que
la respuesta correcta para con x es sí si y sólo si la respuesta correcta para con es sí. Entonces, componiendo y
el algoritmo para resolver , tendremos un algoritmo para resolver .
Reducción polinómica y reducibilidad. Sea una función que establece una correspondencia entre el conjunto de
entrada de un problema de decisión y el conjunto de entrada de un problema de decisión es una reducción
polinómica (también llamada transformación polinómica) de a si se cumplen todas las condiciones siguientes:
1. se puede calcular en tiempo polinómicamente acotado.
2. Para toda cadena , si es una entrada de sí para es una entrada de sí para .
3. Para toda cadena , si es una entrada de no para es una entrada de no para .
Por lo regular es más fácil demostrar la contrapositiva.
3’. Para toda , si es una entrada de sí para es una entrada de sí para .
El problema es polinómicamente reducible (o polinómicamente transformable) a si existe una transformación
polinómica de a . (En este apartado por lo regular diremos sólo que se puede reducir a ; la cota polinómica se
sobreentiende.) Usamos la notación
para indicar que se puede reducir a .
Cabe señalar que las partes de la definición de reducción se combinan para decir que tiene la misma
respuesta para el problema que tiene para , para toda
El meollo de la reducibilidad de a es que es por lo menos tan “difícil” de resolver como . El teorema que sigue
plantea esto con mayor precisión.
Si está en , entonces está en . Sea una cota polinómica para el cálculo de , y sea una cota
polinómica para un algoritmo que resuelve . Sea una entrada de tamaño para . Entonces el tamaño de no es
mayor que (puesto que, en el peor de los casos, un programa para efectuar escribe un símbolo en cada paso). Si se
proporciona al algoritmo para resolver , dicho algoritmo ejecuta cuando más pasos. Así pues, la cantidad
39
total de trabajo efectuada para transformar en y luego usar el algoritmo que resuelve para obtener la respuesta
correcta de con es , un polinomio en
Ya podemos dar la definición formal de completo.
-difícil y -completo. Un problema es -difícil si todo problema en se puede reducir a ; es decir,
. Un problema es -completo si está en y es -difícil. Es importante darse cuenta de que “ -difícil”
no significa “en y difícil”; significa “al menos tan difícil como cualquier problema en ”. Así, un problema puede ser
-difícil y no estar en .
Ser -difícil constituye una cota inferior para el problema. Estar en constituye una cota superior. Así pues, la clase
de los problemas -completos está acotada tanto por abajo como por arriba, aunque el estado actual del conocimiento
humano no permite definir de forma nítida ninguna de esas fronteras. El teorema que sigue es consecuencia directa de la
definición y del teorema.
Si cualquier problema -completo está en , entonces Este teorema indica, por una parte, lo valioso que sería
hallar un algoritmo polinómicamente acotado para cualquier problema -completo y, por la otra, lo poco probable que
es la existencia de tal algoritmo, en vista de la gran cantidad de problemas en para los que se han buscado
infructuosamente algoritmos polinómicamente acotados.
Aunque hemos visto que muchos problemas están en , no es de ninguna manera evidente que cualquiera de ellos sea
-completo. Después de todo, para demostrar que algún problema es -difícil, lo cual es la segunda mitad del
requisito para ser -completo, es necesario demostrar que todos los problemas en , incluso los que no conocemos, se
pueden reducir al problema específico . ¿Cómo podríamos siquiera comenzar a atacar tal labor?. La primera
demostración de que cierto problema efectivamente es -completo es uno de los mayores logros de la teoría de la
computación y de las matemáticas.
El problema de la satisfactibilidad booleana es -completo1. La demostración de este teorema, y de otros que
presentamos aquí sin demostrarlos, se puede hallar en las fuentes que se dan en Notas y referencias al final del capítulo.
Aquí sólo bosquejaremos la idea. La demostración debe mostrar que cualquier problema en se puede reducir a la
satisfactibilidad. La demostración de Steven Cook da un algoritmo para construir una fórmula para una entrada de
tal que la fórmula, en términos informales, describe el cálculo efectuado por un algoritmo no determinista para resolver
al actuar sobre . La fórmula , que es muy larga pero se construye en tiempo acotado por una función polinómica
de la longitud de , se podrá satisfacer si y sólo si el cálculo produce la respuesta sí con algún certificado.
La reducción polinómica es una relación transitiva. Por tanto, si la satisfactibilidad se puede reducir a algún problema
también es -difícil. Si también está en (lo cual por lo regular se puede demostrar fácilmente), entonces es
1 Teorema de Cook - El problema de SAT pertenece a NP dado que puede ser resuelto con una máquina de Turing no determinista que genera todas las
posibles combinaciones de valores para las variables de la expresión y, en forma no determinista intenta verificar si alguna de ellas hace que la expresión se
evalúe en verdadero, en cuyo caso acepta la entrada.
40
-completo. Así, la reducción sirve para demostrar que otros problemas son -completos sin tener que repetir todo el
trabajo del Teorema de Cook. La satisfactibilidad se puede reducir a 3-satisfactibilidad.
La satisfactibilidad (y la 3-satisfactibilidad) son problemas lógicos, y no tienen una relación obvia con los demás
problemas, ni con los muchos otros problemas de optimización que no parecen tener una solución eficiente, algunos en el
campo de los grafos y otros en el de los compiladores y los sistemas operativos. Si los únicos problemas -completos
fueran parecidos al de la satisfactibilidad, la calidad de ser -completo no habríapasado de ser una curiosidad
interesante.
El segundo trabajo crucial en el campo fue el escrito por Richard Karp , quien demostró que los planteamientos como
problemas de decisión de un gran número de problemas de optimización, incluidos varios de los problemas muestra que
describimos antes, también son -completos.
Se requirieron reducciones muy ingeniosas para demostrar que los problemas se podrían reducir a otros al parecer muy
distintos. Karp mostró que la 3-satisfactibilidad se podía reducir (mediante una cadena de reducciones, en algunos casos)
a problemas de grafos que al parecer no tenían ninguna relación, como el del ciclo hamiltoniano y el de coloreado de
grafos.
Esto fue el inicio de una avalancha. Pronto se demostró que muchos problemas para los cuales se estaban buscando
infructuosamente algoritmos polinómicamente acotados eran -completos. De hecho, la lista de problemas -
completos llegó a los centenares en los años setenta.
Como ya dijimos, para demostrar que un problema es -completo basta con demostrar que algún otro
problema -completo se puede reducir polinómicamente a , pues la relación de reducibilidad es transitiva. Por ello, las
diversas partes del teorema se demuestran estableciendo cadenas de transformaciones que parten del problema de la
satisfactibilidad. Presentaremos unas cuantas como modelos.
Muchos se confunden en cuanto a la dirección de la reducción que se requiere para demostrar que un problema es -
completo, por lo que cabe hacer hincapié en que, para demostrar que un problema es -completo, se escoge algún
problema -completo conocido y se reduce a , no al revés. La lógica es la siguiente:
1. Puesto que es -completo, todos los problemas se pueden reducir a P; es decir,
2. Demostrar que .
3. Entonces todos los problemas satisfacen , por la transitividad de las reducciones.
4. Por tanto, es -completo.
El problema de la sumatoria de subconjunto se puede reducir al problema de calendarización de trabajos.
41
ANEXO 6. Problemas y
Algunos de los algoritmos son directos, mientras que otros son complicados y sutiles, pero prácticamente todos
ellos tienen complejidad en donde es el tamaño de las entradas debidamente definido. Desde el punto de
vista adoptado, consideraremos que todos los algoritmos que hemos examinado hasta ahora requieren un tiempo
relativamente corto. Examinemos otra vez la tabla. Ahí vimos que los algoritmos cuya complejidad se describe
con funciones polinómicas simples se pueden ejecutar con entradas relativamente grandes en un tiempo razonable.
La última columna de la tabla muestra que si la complejidad es , el algoritmo de nada sirve a menos que las
entradas sean muy pequeñas. En este apartado nos ocuparemos de problemas cuya complejidad podría describirse
con funciones exponenciales, problemas cuya resolución incluso con los mejores algoritmos conocidos requeriría
muchos años o siglos de tiempo de computadora con entradas moderadamente grandes. Presentaremos
definiciones encaminadas a distinguir entre los problemas dóciles (es decir, “no tan difíciles”) que ya hemos visto
y los renuentes (es decir, “difíciles” o muy tardados). Analizaremos una importante clase de problemas que tienen
una propiedad irritante: ni siquiera sabemos si se pueden resolver de manera eficiente o no.
“ ” es una clase de problemas que se pueden resolver en “tiempo polinómico”. La descripción de “ ” es más
complicada. No se han descubierto algoritmos razonablemente rápidos para estos problemas, pero tampoco se ha
podido demostrar que los problemas requieren mucho tiempo. Dado que muchos de estos problemas son
problemas de optimización que se presentan con frecuencia en aplicaciones, la falta de algoritmos eficientes tiene
importancia real.
6.1 Problemas de decisión
Muchos de los problemas que describiremos en este apartado se dan naturalmente como problemas de
optimización (aunque se les llama problemas de optimización combinatoria), pero también se pueden formular
como problemas de decisión. Las clases , que se definirán, son clases de problemas de decisión.
Básicamente, un problema de decisión es una pregunta que tiene dos posibles respuestas, sí y no. La pregunta se
refiere a alguna entrada. Un ejemplar de problema es la combinación del problema y una entrada específica. Por
lo regular, el planteamiento de un problema de decisión tiene dos partes:
1. La parte de descripción de ejemplar define la información que cabe esperar en la entrada.
2. La parte de pregunta plantea la pregunta tipo “sí o no” en sí; la pregunta contiene variables definidas en
la descripción de ejemplar.
42
La salida de un problema de decisión es sí o bien no según sea la respuesta correcta de la pregunta, aplicada a una
entrada dada. Por ello, podemos ver de manera abstracta un problema de decisión como una correspondencia entre
todas las entradas y el conjunto {sí, no}.
6.1.1 Secuenciación de trabajos con castigos
Supóngase que hay trabajos que deben ejecutarse uno por uno. Se nos dan los tiempos de ejecución
los plazos (medidos a partir de la fecha de inicio del primer trabajo ejecutado) y castigos por
no terminar un trabajo dentro del plazo correspondiente . Supóngase que los tiempos de ejecución,
plazos y castigos son enteros positivos. Un calendario para los trabajos es una permutación de
donde es el trabajo que se efectúa primero, es el que se ejecuta en segundo lugar, y así.
Para un calendario dado, el castigo para el -ésimo trabajo se denota con , y se define como si el
trabajo se termina después de transcurrido el plazo en caso contrario. El castigo total para un
calendario dado es
Problema de optimización: Determinar el castigo más bajo posible (y hallar un calendario óptimo, es decir, uno
que reduzca al mínimo el castigo total).
Problema de decisión: Dado, además de las entradas descritas, un entero no negativo , ¿existe un calendario con
?
La clase . Ninguno de los algoritmos que se conocen para los problemas que acabamos de describir tiene
garantía de ejecutarse en un tiempo razonable. No definiremos “razonable” de forma rigurosa, pero sí definiremos
una clase de problemas que incluye a los que tienen algoritmos razonables.
Decimos que un algoritmo está polinómicamente acotado si su complejidad de peor caso está acotada por una
función polinómica del tamaño de las entradas (es decir, si existe un polinomio tal que, para toda entrada de
tamaño , el algoritmo termine después de cuando más pasos), y si existe un algoritmo polinómicamente
acotado para resolverlo.
43
sólo está definida para problemas de decisión. Podría parecer un tanto extravagante utilizar la existencia de una
cota de tiempo polinómica como criterio para definir la clase de problemas más o menos razonables: los
polinomios pueden ser muy grandes. No obstante, hay varias razones de peso para hacerlo.
En primer lugar, si bien no es verdad que todos los problemas en tengan un algoritmo de eficiencia aceptable, sí
podemos asegurar que, si un problema no está en , será extremadamente costoso y probablemente imposible de
resolver en la práctica. Es probable que ninguno de los problemas que describimos esté en ; no existen
algoritmos para resolverlos que se sepa estén polinómicamente acotados, y la mayoría de los investigadores en el
campo piensan que no existen tales algoritmos. Es factible que la definición del hecho de estar o no en sí es un
criterio útil en el caso de problemas renuentes.
Un segundo motivo para usar una cota polinómica para definir es que los polinomios tienen bonitas propiedades
de “cierre”. Podríamos obtener un algoritmo para un problema complejo combinando varios algoritmos para
problemas más sencillos. Algunos de los algoritmos más simples podrían trabajar con las salidas o los resultados
intermedios de otros. La complejidad del algoritmo compuesto podría estar acotada por la suma, multiplicación y
composición de las complejidades de sus algoritmos componentes. Puesto que los polinomios están cerrados bajo
estas operaciones, cualquier algoritmo que se construya de diversas formas naturales a partir de varios algoritmos
polinómicamente acotados también estará polinómicamente acotado. Ninguna clase más pequeña de funciones
que sean cotas de complejidad útiles tiene estas propiedades de cierre.
Un tercer motivo para emplear una cota polinómica es que hace a independiente del modelo de cómputo formal
específico que se use. Se usan varios modelos formales (definiciones formales de algoritmos) para demostrar
teoremas rigurosos acerca de la complejidad de los algoritmos y problemas. Los modelos difieren en cuanto al
tipo de operaciones permitidas, los recursos de memoria disponibles y los costos asignados a diferentes
operaciones. Un problema que requiere ) pasos con un modelo podría requerir más de pasos con
otro, pero en el caso de prácticamente todos los modelos realistas, si un problema está acotado polinómicamente
con uno, estará acotado polinómicamente con los demás.
La clase . Muchos problemas de decisión (incluidos todos los que hemos puesto de muestra) se plantean como
preguntas de existencia: ¿Existe una asignación de verdad que haga verdadera una fórmula dada? Para una
entrada dada, una “solución” es un objeto (por ejemplo una asignación de verdad) que satisface los criterios del
problema y por tanto justifica una respuesta de sí (por ejemplo, la asignación de verdad hace que la fórmula
sea verdadera). Una “solución propuesta” no es más que un objeto del tipo apropiado: podría satisfacer o no los
criterios.
44
A veces se usa el término certificado para referirse a una solución propuesta. En términos informales, es la
clase de problemas de decisión para los que una solución propuesta dada con una entrada dada se puede verificar
rápidamente (en tiempo polinómico) para determinar si realmente es una solución (es decir, si satisface los
requisitos del problema). Más formalmente, las entradas de un problema y las soluciones propuestas se deberán
describir con cadenas de símbolos de algún conjunto finito, por ejemplo, el conjunto de caracteres del teclado de
una terminal de computadora. Necesitamos algunas convenciones para describir grafos, conjuntos, funciones, etc.,
que usan tales símbolos. El conjunto de convenciones que se adopta para un problema dado es la codificación de
ese problema. El tamaño de una cadena es el número de caracteres que contiene.
Algunas cadenas de símbolos del conjunto escogido no son codificaciones válidas de objetos pertinentes al
problema en cuestión; sólo son basura. En términos formales, una entrada de un problema y una solución
propuesta para ese ejemplar del problema pueden ser cualquier cadena formada a partir del conjunto de caracteres.
La verificación de una solución propuesta incluye verificar que la cadena tenga sentido (es decir, que tenga la
sintaxis correcta) como descripción del tipo de objeto requerido, además de verificar que satisfaga los criterios del
problema. Por tanto, cualquier cadena de caracteres puede verse como un certificado para un ejemplar de un
problema.
Podría haber problemas de decisión para los que no haya una interpretación natural de las “soluciones” o las
“soluciones propuestas”. En lo abstracto, un problema de decisión no es más que una función que relaciona un
conjunto de cadenas de entrada con el conjunto í . Una definición formal de considera todos los
problemas de decisión. La definición emplea algoritmos no deterministas, que definiremos a continuación.
Aunque tales algoritmos no son realistas ni útiles en la práctica, sirven para clasificar los problemas.
Algoritmo no determinista. Un algoritmo no determinista tiene dos fases y un paso de salida:
1. La fase de “conjetura” no determinista. Se escribe alguna cadena totalmente arbitraria de caracteres, ,
principiando en algún lugar designado de la memoria. Cada vez que se ejecuta el algoritmo, la cadena que
se escribe podría ser distinta. (Esta cadena es el certificado; podría considerarse como una conjetura de la
solución del problema, por lo que podríamos llamar a ésta la fase de conjetura, pero s bien podría ser sólo
basura.)
2. La fase de “verificación” determinista. Comienza a ejecutarse una subrutina determinista (o sea,
ordinaria). Además de las entradas del problema de decisión, la subrutina podría usar , o podría hacer
caso omiso de s. Tarde o temprano devolverá un valor de verdadero o falso, o podría entrar en un ciclo
infinito y nunca parar. (Podemos pensar en la fase de verificación como un examen de s encaminado a
determinar si es una solución para las entradas del problema de decisión, es decir, si justifica una
respuesta de sí para las entradas del problema de decisión.)
45
3. El paso de salida. Si la fase de verificación devolvió verdadero, el algoritmo produce sí. De lo contrario,
no se produce ninguna salida.
El número de pasos que se ejecutan durante una ejecución de un algoritmo no determinista se define como la
suma de los pasos de las dos fases; es decir, el número de pasos que se ejecutan para escribir (que es
simplemente el número de caracteres de ) más el número de pasos que ejecuta la segunda fase determinista.
También podemos describir un algoritmo no determinista con una estructura de subrutina explícita.
Supóngase que genCertif genera un certificado arbitrario.
void aNoDet(String entrada)
String s genCertif();
boolean revisOK verifA(entrada, s);
if (revisOK)
Enviar a la salida “sí”.
return;
Normalmente, los algoritmos terminan con todas las entradas y cada vez que ejecutamos un algoritmo con la
misma entrada obtenemos la misma salida. Esto no sucede con los algoritmos no deterministas; con una entrada
específica , la salida (o ausencia de salida) de una ejecución podría diferir de la de otra porque podría depender
de . Entonces, ¿qué “respuesta” calcula un algoritmo no determinista, digamos , para un problema de decisión
dado con la entrada ?. La respuesta de con se define como sí si y sólo si existe alguna ejecución de A que
produzca sí como salida. La respuesta es no si, para toda , no se produce salida. Utilizando nuestro concepto
informal de s como una solución propuesta, la respuesta de con es sí si y sólo si existe alguna solución
propuesta que “funcione”.
es la clase de problemas de decisión para la cual existe un algoritmo no determinista polinómicamente
acotado. (El nombre proviene de “No determinista Polinómicamente acotado”.)
Demostración Un algoritmo ordinario (determinista) para resolver un problema de decisión es, con una
modificación menor, un caso especial de un algoritmo no determinista. Si es un algoritmo determinista para
resolver un problema de decisión, basta con hacer que sea la segunda fase de un algoritmo no determinista, pero
modificándolo de modo que, en todos los casos en que produciría la salida sí, devuelva verdadero, y en todos los
casos en que produciría la salida no, devuelva falso. simplemente hará caso omiso de lo que haya escrito la
primera fase y procederá a efectuar su cálculo acostumbrado. Un algoritmo no determinista puede ejecutar cero
46
pasos en la primera fase (escribiendo la cadena nula) de modo que, si se ejecuta en tiempo polinómico, el
algoritmo no determinista que tiene el A modificado como segunda fase también se ejecutará en
tiempo polinómico. Producirá si lo habría hecho, y no producirá nada en caso contrario.
La pregunta importante es, ¿ o es un subconjunto propio de ? Dicho de otro modo, ¿es el no
determinismo más potente que el determinismo en el sentido de que algunos problemas se pueden resolver en
tiempo polinómico con un “conjeturador” no determinista pero no se pueden resolver en tiempo polinómico con
un algoritmo ordinario? Si un problema está en , con una cota de tiempo polinómico, digamos p, podremos dar
(de forma determinista) la respuesta correcta (sí o no) si verificamos todas las cadenas cuya longitud no sea mayor
que (es decir, ejecutamos la segunda fase del algoritmo no determinista con cada una de las cadenas
posibles, una por una). El número de pasos requeridos para verificar cada cadena es cuando más . El
problema es que hay demasiadas cadenas que verificar. Si nuestro conjunto de caracteres contiene c caracteres,
habrá denas de longitud . El número de cadenas es exponencial, no polinómico, en Claro que hay
otra forma de resolver problemas: usar algunas de las propiedades de los objetos en cuestión y un poco de ingenio
para idear un algoritmo que no tenga que examinar todas las posibles soluciones. Al ordenar, no verificamos cada
una de las permutaciones de las claves dadas para ver cuál coloca las claves en orden. La dificultad, en el
caso de los problemas que tratamos, estriba en que tal enfoque no ha producido algoritmos eficientes; todos los
algoritmos conocidos examinan todas las posibilidades o bien, si se valen de ardides para reducir el trabajo, tales
ardides no son lo bastante buenos como para dar pie a algoritmos polinómicamente acotados.
Se cree que es un conjunto mucho más grande que , pero no existe un solo problema en para el cual se
haya demostrado que el problema no está en . No se conocen algoritmos polinómicamente acotados para muchos
problemas que están en , pero no se han demostrado cotas inferiores mayores que las polinómicas para esos
problemas. Por tanto, la pregunta que hicimos antes, ¿es ? sigue pendiente.
El tamaño de las entradas. Consideremos el problema siguiente problema: Dado un entero positivo , ¿existen
enteros tales que ? (es decir, ¿es no primo?). ¿Este problema está en ? Consideremos el
algoritmo siguiente, que busca un factor de .
factor = 0
for (j 2; j n; j)
if ((n mod j) 0)
factor = j;
break;
47
return factor;
El cuerpo del ciclo se ejecuta menos de veces, y es indudable que se puede evaluar en , así
que el tiempo de ejecución del algoritmo está holgadamente en . Sin embargo, no se sabe que el problema
de determinar si un entero es primo o es factorizable esté en y, de hecho, la dificultad para hallar factores de
enteros grandes es la base de varios algoritmos de cifrado precisamente porque se le considera un problema
difícil. ¿Cómo resolvemos esta aparente paradoja?
La entrada del algoritmo para probar primos es el entero pero, ¿qué tamaño tiene la entrada?
Hasta ahora, hemos utilizado cualquier medida cómoda y razonable del tamaño de las entradas; no era importante
contar caracteres o bits individuales. Si nuestra medida del tamaño de una entrada podría marcar la diferencia
entre si un algoritmo es polinómico o es exponencial, hay que tener más cuidado. El tamaño de una entrada es el
número de caracteres que se requieren para escribirla. Si , escribimos tres dígitos, no 150 dígitos. Así
pues, un entero n escrito en notación decimal tiene un tamaño aproximado de . Si optamos por considerar
la representación interna en una computadora, donde los enteros se representan en binario, el tamaño de n será
aproximadamente . Estas representaciones difieren en un factor constante;
es decir, , así que no es crucial cuál representación usemos. Lo que sí es importante es
que, si el tamaño s de las entradas es y el tiempo de ejecución de un algoritmo es n, el tiempo de ejecución
del algoritmo será una función exponencial del tamaño de las entradas . Por tanto, el algoritmo anterior
para determinar si n es primo no está en . No se conocen aún algoritmos para probar primos en tiempo
polinómico. Sin embargo, la pregunta: “¿El entero n es primo?” está en .
En los problemas que examino, la variable que usábamos para describir el tamaño de las entradas correspondía
(aproximadamente) a la cantidad de datos contenida en ellas. Usamos como tamaño de la entrada al ordenar una
lista de claves. Cada una de las claves se representaría, digamos, en binario, pero dado que hay claves, habrá
por lo menos n símbolos en la entrada. Por tanto, si la complejidad de un algoritmo está acotada por un polinomio
en n, estará acotada por un polinomio en el tamaño exacto de la entrada.
Asimismo, usamos como el tamaño de las entradas de grafos, pero es necesario enumerar explícitamente
todas las aristas, lo cual requiere al menos símbolos en la entrada. Aunque no es necesario enumerar los n
vértices en la entrada, en todos los problemas de interés todo vértice incide en alguna arista, así que es
cuando más tres veces el número de símbolos que hay en la entrada. Una vez más, si la complejidad de un
algoritmo está acotada por un polinomio en estará acotada por un polinomio en el tamaño exacto de la
entrada.
48
Si dos medidas del tamaño de las entradas están acotadas cada una por una función polinómica de la otra,
determinar si el problema está en no dependerá de la medida específica que se use.
En ordenamiento, si una medida es el número de claves , y la otra es (clave máxima), que cuenta bits
individuales, tendremos y ). Por tanto, cada una de las
medidas no está a más de una función polinómica de la otra.
Por ello, normalmente no tenemos que especificar con toda precisión el tamaño de las entradas.
No obstante, debemos tener cuidado en los casos en que el tiempo de ejecución de un algoritmo se expresa como
función polinómica de uno de los valores de entrada, como sucede con el problema de la prueba de primos.
Unos cuantos de los problemas de muestra que describimos antes tienen soluciones de programación dinámica
que a primera vista parecen estar polinómicamente acotados pero, al igual que el programa de prueba de primos,
no lo están. Recordemos el problema de la sumatoria de subconjunto: ¿Existe un subconjunto de los objetos con
tamaños cuya suma sea exactamente ? Si utilizamos las técnicas, podremos resolver este problema
con una tabla de por y sólo requeriremos unas cuantas operaciones para calcular cada elemento de la tabla.
Existen soluciones de programación dinámica similares para diversas versiones del problema de la mochila.
La solución de programación dinámica para el problema de la suma de subconjunto se ejecuta en tiempo
Puesto que hay objetos en la entrada, el término no representa ningún problema, pero el valor del número es
exponencialmente mayor (en general) que la entrada, porque el dato en la entrada se representaría con bits.
Por ello, la solución de programación dinámica no es un algoritmo polinómicamente acotado. Desde luego, si
no es demasiado grande, el algoritmo podría ser útil en la práctica.
49
ANEXO 7. Proposiciones y variables lógicas
La lógica es la herramienta que usan las matemáticas para desarrollarse. El objetivo del mismo es describir en qué
consiste una teoría matemática. Para lograrlo, primero hay que exponer sucintamente las reglas de la lógica de
proposiciones, definir con precisión que es un razonamiento lógico y, por último, explicar en qué consiste su
aplicación en el desarrollo del trabajo de investigación (brevemente, una serie de axiomas, definiciones y
teoremas relacionados entre sí mediante argumentos lógicos usados para sustentar la hipótesis propuesta).
La lógica es un esquema de reglas que permite deducir verdades a partir de otras verdades. El medio que lleva de
las primeras verdades a las otras deducidas se llama razonamiento lógico. La lógica analiza, los razonamientos
lógicos, estableciendo cuando un razonamiento es válido, independientemente del contenido de las verdades que
se enuncien. Solo le interesan las manipulaciones que se hacen con los enunciados, no su contenido.
Todos los resultados mostrados en se prueban rigurosamente. Sin embargo, no se usa para ello el razonamiento
lógico, sino el simple y eficaz camino de las tablas introducidas. Por supuesto, algunos resultados sí se podrían
demostrar a partir de otros anteriores mediante las leyes del algebra de proposiciones, que se exponen. Se prefiere
dejar todo en manos de las tablas, pues en el resto de la investigación son los argumentos lógicos los
protagonistas. Por contra, aunque no se habla de axiomas, definiciones y teoremas en las teorías matemáticas,
desde el principio llamados teoremas a los resultados que se obtuvieren y se podrán visualizar en el anexo
Teoremas.
Proposiciones y variables lógicas. Puesto que la lógica busca deducir verdades a partir de otras verdades, su
materia prima son los enunciados de esas verdades. Eso es lo que se llama proposiciones: un enunciado que se
puede juzgar como verdadero o falso.
Los siguientes enunciados “la máquina está disponible”, “el inventario es suficiente” y “el operario está libre”
son proposiciones, pues se puede juzgar objetivamente que son falsas o verdaderas. Deliberadamente no se escribe
una definición formal del concepto de proposición en nuestra teoría por dos razones. Primero, en muchos casos es
cuestión de opinión si un enunciado se puede juzgar como verdadero o falso, o simplemente, el juicio no será
unánime. La segunda razón es que las proposiciones no son parte de la lógica. Son los ladrillos con los que se
construyen los razonamientos lógicos. La lógica se ocupa de las relaciones entre las proposiciones, no de su
contenido.
Es de interés particular, pues, asignar a cada proposición un valor binario, previa validación de la variable de
estado. Por ello se debe usar símbolos que representen proposiciones cualesquiera y examinar las relaciones entre
estos símbolos independientemente de corroborar su registro particular.
50
Se utilizara letras latinas minúsculas, especialmente . ., para representar proposiciones cualesquiera. La
única característica que nos recuerda que representan proposiciones es que estos símbolos pueden tener dos
valores: verdadero (representado por ) o falso (representado por ). Y como representan proposiciones
cualesquiera, pueden tomar cualquiera de los dos. Estos símbolos no son proposiciones sino variables discretas,
que comúnmente construyen recursivamente las formulas atómicas usadas en la lógica proposicional. Entre estas
variables lógicas discretas para una planta de producción, se definen las materias primas y proceso ( ), equipos
( ), la mano de obra ( ), pertenecientes a cada a centros de trabajo ( ) y productos ( ).
Sin embargo, una vez aclarada la diferencia entre proposiciones y variables lógicas, y puesto que una variable
lógica representa una proposición cualquiera, se empleara los dos términos indistintamente. El análisis utilizando
la lógica va a consistir en analizar variables lógicas y describir las relaciones entre ellas. La relación más sencilla
es la de variables dependientes e independientes. Dos variables lógicas son dependientes si el valor que tome una
condiciona el valor que puede tomar la otra. Son independientes si no son dependientes.
Al representar las variables lógicas por letras como . . Si en una expresión aparecen las variables y
ambas pueden tomar los valores y , y se tiene un total de cuatro combinaciones posibles de los valores de y
. Al tener tres variables, hay ocho posibilidades Una tabla de verdad, o simplemente tabla en este contexto,
es una representación en filas y columnas de los valores de algunas variables lógicas. Cada columna representa
una variable, y cada fila una posible combinación de los valores de las mismas. En la tabla 5 se muestran todas las
posibles combinaciones de los valores y para tres variables.
Una variable lógica puede, en principio, tomar los valores 0 o . Sin embargo, es posible que una variable
dependiente de otras, cuyo valor queda condicionado por estas, tome siempre el valor 1 (verdadero) para cualquier
situación de las variables de las que depende. O bien, otra variable que tome siempre el valor 0 (falso). Las
variables con este comportamiento reciben un nombre. Se llama tautología a la variable lógica, dependiente de
otras, la cual toma el valor 1 independientemente del valor de las variables de las que depende. Análogamente se
llama contradicción a la variable lógica cuyo valor es 0 en cualquier situación.
Tabla 1. Combinaciones de los valores y
p q r
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
51
1 1 0
1 1 1
1.1.1. Conectivos lógicos
Los conectores permiten construir nuevas proposiciones a partir de unas dadas. La nueva proposición es
dependiente de las proposiciones con las que se construye. Un conector monario llamado negación el cual, a partir
de una proposición, construye otra. También varios conectores binarios, que a partir de dos proposiciones dan
otra: conjunción, disyunción, implicación y doble implicación. En los cinco casos se dará una explicación intuitiva
seguida de una descripción formal.
La descripción formal consiste en describir exactamente como depende la nueva proposición de las proposiciones
con que se construye. La descripción se hace mediante tablas en las que aparecen todas las combinaciones
posibles de valores que toman las variables independientes. Inicialmente la negación de una proposición, que es
otra proposición con valor opuesto a la primera. Si la primera es cierta, su negación es falsa y viceversa.
En términos de variables lógicas, la negación de una variable es otra variable dependiente de la primera porque su
valor está determinado por el de ella.
La negación de una proposición , denotada , es la proposición cuyo valor es el opuesto al de . Se puede
definir la negación mediante la tabla 6. En ella se indica, para cada valor de la proposición , el valor que toma la
proposición
Tabla 2. Negación de una proposición
0 1
1 0
La conjunción es un conector binario que funciona como la conjunción copulativa “ ” del español. La conjunción
de dos proposiciones, entonces, es una proposición que es cierta si ambas son ciertas, y es falsa si alguna de ellas
es falsa. La conjunción de dos proposiciones denotada es la proposición que solo es cierta si ambas
son ciertas. En un proceso de producción donde las máquinas están dispuestas en serie se podrá expresar en
términos de la conjunción. La descripción mediante la tabla 7 consiste ahora en ilustrar, para cada valor que
pueden tomar las proposiciones y el valor que resulta en la proposición
Tabla 3. Conjunción de dos proposiciones denotada
52
0 0 0
0 1 0
1 0 0
1 1 1
La disyunción es el conector que opera de forma parecida a la conjunción disyuntiva “ ” del español. La
disyunción de dos proposiciones es otra proposición que es cierta si alguna de las dos originales es cierta. Es
decir, basta que una de ellas sea cierta para que la disyunción lo sea. Sin embargo en lógica se emplea en sentido
inclusivo como se aprecia en la tabla que la define. En un proceso de producción donde las máquinas están
dispuestas en paralelo se podrá expresar en términos de la disyunción. La disyunción de dos proposiciones ,
denotada , es la proposición que solo es falsa si ambas son falsas. En forma de tabla 8.
Tabla 4. disyunción de dos proposiciones , denotada
0 0 0
0 1 1
1 0 1
1 1 1
El siguiente conector que se introduce es la implicación, que tiene gran importancia en la lógica pues es la base
del razonamiento deductivo. Requiere un poco de atención para entender bien su descripción formal que, al
principio, no parece responder a la intuición. Cuando se afirma que una proposición implica otra se quiere
expresar el hecho de que si la primera es cierta, entonces la segunda debe ser cierta también.
En el lenguaje corriente se usa la expresión “Si . . . entonces . . . ”. Las dos proposiciones que aparecen en la
implicación se llaman antecedentes y consecuentes. El antecedente es la condición que, si es cierta, asegura que se
cumple el consecuente. Base del lenguaje PWL, la setencia if... Then.. en cualquier lenguaje de
programación.
Decir qué valor tiene la implicación en cada caso de los posibles valores de antecedente y consecuente. Es claro
que quiero decir que una implicación es cierta si el antecedente es cierto y el consecuente también. Por todo ello
se define la implicación del siguiente modo. La implicación de dos proposiciones denotada es la
proposición que solo es falsa si es verdadera y es falsa. La tabla 9 correspondiente es:
Tabla 5. La implicación de dos proposiciones denotada
53
0 0 1
0 1 1
1 0 0
1 1 1
Es fácil convencerse de que la proposición no es la misma que . Esta observación es suficientemente
importante como para asignar nombres a cada una de estas implicaciones.
Dada una implicación , se otorgan nombres a las siguientes implicaciones:
implicación directa,
implicación inversa,
implicación reciproca,
implicación contrapositiva.
El último conector que se introduce es el de doble implicación o bicondiciónal. Como su nombre indica, si dos
proposiciones están relacionadas con el conector doble implicación, significa que una implica la otra y la otra la
una. Entonces, si una de ellas es cierta, la otra debe serlo también, que es lo mismo que decir que si una es falsa la
otra también. La doble implicación de dos proposiciones denotada es la proposición que solo es
verdadera si ambas coinciden en su valor. De la tabla 10 resulta :
Tabla 6. La doble implicación de dos proposiciones denotada
0 0 1
0 1 0
1 0 0
1 1 1
Una explicación que se enuncia a partir de la doble implicación es la de variables lógicas equivalentes. Dos
variables son equivalentes si son dependientes de modo que siempre toman el mismo valor. Si una es verdadera,
entonces la otra también y viceversa. Es claro que el conector de doble implicación puede ayudar a expresar esta
idea. Una forma de hacerlo es decir que la doble implicación entre dos proposiciones equivalentes es siempre
cierta. Dos variables y son equivalentes, y se denota , si es una tautologıa. (Barnes, 1978)
Es claro que en cualquier expresión puedo sustituir una proposición por otra equivalente, y la nueva expresión que
obtengo es equivalente a la original pues los valores son los mismos. De ahí que el concepto de proposiciones
equivalentes sea importante y muy utilizado en lógica. Ahora se puede enunciar un primer resultado sencillo pero
54
muy útil en la teoría y en la práctica de la lógica. Es la relación entre las implicaciones directa, inversa, reciproca
y contrapositiva. Ver anexo Teorema 19.
Otro teorema relacionado con el concepto de equivalencia es la que dice que el conector doble implicación es
equivalente a la implicación directa junto con la implicación inversa. Es la formulación precisa de lo que el
símbolo ↔ expresa abiertamente. Ver anexo Teorema 20.
En las expresiones que incluyen algunos o todos los operadores , en la ausencia de paréntesis, primero se
evalúa después y luego . Esta convención se conoce como precedencia del operador. En álgebra, la
precedencia del operador indica que se evalúan y antes que y –.
1.1.2. Leyes del algebra proposicional
Los conectores entre proposiciones (negación, conjunción, disyunción, etc.) se pueden ver, desde un punto de
vista algebraico, como operaciones definidas en el conjunto de las proposiciones. Se toma una proposición (en el
caso de la negación) o dos proposiciones (en los otros casos) y se operan, obteniendo como resultado otra
proposición. Resulta imperativo analizar algunas propiedades algebraicas de estas operaciones como son la
aplicación reiterada, asociatividad, conmutatividad, existencia de elemento neutro, etc. (Badesa C, 1998)
Como primer paso se observa que los conectores de implicación y doble implicación se pueden escribir en
términos de la negación, conjunción y disyunción solamente. Entonces bastara con analizar las propiedades
algebraicas de estas tres operaciones. (En realidad, también el conector de disyunción se puede expresar en
función del de conjunción y el de negación, pero estos tres en conjunto tienen más y mejores propiedades
algebraicas. Ver anexo Teorema 21.
Puesto que en el teorema que la doble implicación es equivalente a la implicación directa y la inversa, entonces la
doble implicación también se puede expresar solo con negación, conjunción y disyunción. En definitiva, se darán
uso a las propiedades de la negación, la conjunción y la disyunción.
Propiedades de la negación. Debido a que la negación es una operación monaría, la única propiedad que en este
caso puede analizarse es la aplicación reiterada. El resultado es muy evidente por estar trabajando con
proposiciones que solo pueden tomar dos valores. La negación es cambiar el valor de una proposición, y como
solo hay dos posibilidades, si se cambia dos veces se regresa al valor original. Ver anexo Teorema 22.
55
Propiedades de la conjunción. La conjunción es una operación binaria y en ella sí procede analizar más
propiedades. La idempotencia, da el resultado de operar una proposición consigo misma. La asociatividad nos
indica cómo se puede efectuar la conjunción de tres proposiciones. La conmutatividad muestra que el orden de las
proposiciones en una conjunción es irrelevante. Existe un elemento neutro (la proposición con valor 1, que se
denota simplemente como 1) que al operarlo con cualquier proposición da como resultado la misma proposición.
Existe también un elemento dominante (la proposición con valor 0, que se denota simplemente como 0) que
operado con cualquier proposición arroja el resultado 0. Ver anexo Teorema 23.
La presencia de la propiedad asociativa permite definir el símbolo , sin paréntesis, como o bien
puesto que son iguales. El resultado en ambos casos es que solo es cierto si las tres
proposiciones y son ciertas. Generalizando esta idea se define la conjunción de las variables
denotada como la variable que solo es cierta si todas las variables
son ciertas. Las
propiedades asociativa y conmutativa aseguran que la descripción es coherente con la anterior.
Propiedades de la disyunción. El análisis de la disyunción sigue los mismos pasos que el de la conjunción pues
las propiedades que satisfacen son las mismas. La única diferencia es que los papeles de y , como elementos
neutro y dominante respectivamente, se invierten ahora. Ver anexo Teorema 24.
Las propiedades asociativa y conmutativa aseguran que la explicación es coherente con la descripción de la
disyunción de dos variables.
Propiedades de las operaciones combinadas. Ahora se estudian algunas propiedades que surgen al considerar
expresiones con dos o las tres operaciones combinadas. Ver anexo Teorema 25.
La simplificación de una proposición mediante manipulaciones algebraicas. Cada proposición es equivalente a la
anterior por la ley algebraica que se indica a su lado.
proposición a simplificar
segunda ley de De Morgan
doble negación y conmutatividad
distributividad
complementariedad de la negación
1 neutro de .
Prueba algebraica de la ley de absorción (suponiendo probadas las leyes algebraicas anteriores). Partiendo de la
proposición mediante pasos algebraicos se llega a que es equivalente a la proposición .
56
0 neutro de _
comp. de negación
distributividad
distributividad
idemp. y complemento
distrib., idemp. y dominación
complemento y 1 neutro de ^
0 neutro de .
Cuantificadores. Se introducen los enunciados abiertos y, tras ellos, los cuantificadores. Son elementos muy
habituales en la formulación de definiciones y resultados en matemáticas en expresiones de la forma “para todo
numero entero. . . ” o “existe una función tal que . . . ”.
Se llama abierto a un enunciado que contiene variables que toman valores en un conjunto dado, llamado universo,
de forma que para cada valor que tomen las variables, el enunciado se convierte en una proposición.
Un enunciado abierto no es una proposición por sí mismo, sino que se convierte en una cuando las variables
toman un valor. En el caso anterior, el enunciado puede ser verdadero o falso según los valores que tome la
variable.
Puesto que las proposiciones se representan por letras , los enunciados abiertos se representan por
símbolos como donde son las variables que contiene el enunciado.
Los cuantificadores son unos prefijos que, antepuestos a enunciados abiertos los convierten en proposiciones. Se
utilizan dos: el cuantificador universal y el cuantificador existencial. El primero se simboliza por , y se suele
leer “para todo”. Indica que el enunciado que le sigue debe ser cierto para todos los posibles valores de la
variable. El segundo se simboliza por , y se lee “existe algún”.
Indica que el enunciado que sigue es cierto para, al menos, uno de los valores que puede tomar la variable.
Tomar su propiedad de convertir enunciados abiertos en proposiciones como base para dar una aclaración.
Si es un enunciado abierto que depende de la variable , la cual toma valores en un conjunto universo dado,
definir el símbolo como la proposición que es cierta solo si el enunciado abierto es verdadero para todos
los valores que la variable puede tomar en su universo.
a. Se define el símbolo como la proposición que es cierta si el enunciado abierto es verdadero para
algún valor de los que la variable toma en su universo.
b. La proposición no es en realidad otra cosa que una conjunción, mientras que se trata de
una disyunción como se aprecia a continuación.
57
La necesidad de introducir los cuantificadores aparece cuando los posibles valores de la variable no se pueden
enlistar como en el caso anterior: si ahora toma valores en los numeros reales, no se puede escribir de
otro modo. Para usar cuantificadores basta recordar que un cuantificador junto a un enunciado abierto es una
proposición y, a partir de ahí, se maneja como cualquier otra proposición. Sin embargo hay algunas reglas que
simplifican el uso de proposiciones que contienen cuantificadores. En concreto se analizara dos de ellas: la
negación de proposiciones con cuantificadores y la combinación de cuantificadores. (Enderton, 1972)
Una proposición que comienza con el cuantificador universal necesita que el enunciado abierto sea cierto para
todos los valores de la variable, por tanto basta con que en un valor sea falso para que toda la proposición sea
falsa. Por ello, la negación con un cuantificador universal nos lleva a un cuantificador existencial y viceversa. Al
recordar que es una conjunción y es una disyunción, esto no es otra cosa que las leyes de De
Morgan vistas en el teorema. El resultado preciso se recoge en el siguiente teorema. Ver anexo Teorema 26.
Las primera y segunda reglas nos dicen que combinar cuantificadores universales y combinar cuantificadores
existenciales es conmutativo. Ver anexo Teorema 27.
Gracias a este resultado se puede escribir sin ambigüedad , y o en lugar de , ası como y o
en lugar de , y el orden de las variables e es irrelevante. Sin embargo hay que tener cuidado pues el
orden si es importante cuando se combinan cuantificadores de ambos tipos. (Ershov, 1990)
Para terminar se define el cuantificador de existencia y unicidad, simbolizado . Como su nombre indica este
símbolo contiene dos afirmaciones: primero, la existencia de un elemento que cumple el enunciado; segundo, que
dicho elemento es el único que lo cumple. La forma de enunciar la unicidad es diciendo que si hay dos elementos
que cumplen la propiedad, entonces son iguales. Si es un enunciado abierto, el símbolo es la
proposición definida por
1.1.3. El razonamiento lógico
Finalmente el objetivo de la lógica: obtener proposiciones verdaderas a partir de otras proposiciones verdaderas ya
conocidas. Esta deducción se efectúa mediante lo que se llama un razonamiento lógico. Por ello, se define que es
un razonamiento lógico y cómo construirlo. La finalidad no es desarrollar la capacidad de crear nuevos
razonamiento lógicos, sino poder analizar razonamientos ya hechos y determinar si son correctos.
Lo que se pretende con un razonamiento lógico es deducir una proposición verdadera nueva a partir de otras
proposiciones verdaderas ya conocidas. Al analizar esta idea, empezando por nombrar sus elementos. Las
58
proposiciones que son conocidas se llaman hipótesis o premisas. La proposición que se deduce es la tesis,
resultado o consecuencia. El hecho de que las premisas nos lleven a deducir la consecuencia se puede expresar por
medio de una implicación: si las premisas son ciertas, entonces la consecuencia debe ser cierta.
Si son las premisas y es la consecuencia, quiero expresar la idea de que si todas las premisas son
ciertas, entonces la consecuencia es cierta. Es decir .
Nos interesa el razonamiento lógico independientemente del contenido de las proposiciones. Si es cierto que de
las premisas se sigue necesariamente la consecuencia , entonces la expresion
debe ser siempre verdadera.
Una proposición de la forma es un razonamiento lógico si es una tautología. Entonces el
razonamiento se denota las proposiciones se llaman premisas y la
proposición consecuencia.
Al considerar las proposiciones: “si un numero entero no es cero, entonces su valor absoluto es positivo” y “
no es cero”. Puedo deducir que el valor absoluto de −4 es un número positivo. Pero la deducción no depende de
que estar hablando acerca del valor absoluto de números enteros, sino de su estructura lógica. Las premisas son
(“si un numero entero no es cero, entonces su valor absoluto es positivo”) y (“un numero entero, , no
es cero”), es decir, y la consecuencia es (“su valor absoluto, es positivo”). El razonamiento
ha sido y es valido sean quienes sean y
Por ello tiene nombre propio: modus ponendo ponens (del latın, que se puede traducir como el razonamiento que
afirmando (ponendo) afirma (ponens)).
Con la misma implicación de antes “si un numero entero no es cero, entonces su valor absoluto es positivo” y
además con la proposición “el valor absoluto del numero a no es positivo”, puedo deducir que “el numero a es
cero”. El razonamiento en este caso ha sido y se llama modus tollendo tollens (el
razonamiento que negando (tollendo) niega (tollens).
Este razonamiento, cuya estructura es se llama silogismo.
La pregunta ahora es, dado una expresión de la forma ¿como saber si es un razonamiento
lógico o no? Las dos formas de probar que es un razonamiento lógico son: Primera, demostrar directamente que
dicha proposición es una tautología, mediante una tabla, parte de la investigación es expresar que el problemas
es una tautologia. Es útil para razonamientos sencillos, cuyas tablas no sean grandes. Segunda,
descomponer el razonamiento en razonamientos más simples ya conocidos. Es decir, partiendo de las premisas y
59
aplicando razonamientos simples conocidos ir deduciendo nuevas proposiciones ciertas hasta llegar a la que se
enunciaba como consecuencia. Este segundo es el método habitual de probar la validez de razonamientos lógicos
complejos. (Van Dalen, 1983)
Para poder utilizar cadenas de razonamientos simples en la prueba de un razonamiento complicado se necesita
tener algunos razonamientos ya demostrados de forma directa. Se exponen algunos de estos razonamientos que
son muy habituales y, prácticamente, se podría decir que responden en gran medida al sentido común: se llaman
reglas de inferencia y tienen nombres propios. Ver anexo Teorema 28. (Enderton, 1972)
Aunque tal vez haya un camino más corto para determinar los valores de verdad de una proposición formada al
combinar las proposiciones usando operadores como y , la tabla de verdad siempre proporcionará
todos los valores de verdad posibles de para diferentes valores de las proposiciones que la constituyen .
60
ANEXO 8. El poder de los lenguajes de programación
Como aplicación práctica de la teoría presentada, regresamos a nuestra pregunta con respecto al poder expresivo
de los lenguajes de programación. Lo que nos concierne ahora seria la cuestión de que aspectos deben incluirse en
un lenguaje de programación, para garantizar que una vez diseñado e implementado no descubramos que existen
problemas computables cuyas soluciones no pueden especificarse con dicho lenguaje. Al concebir el lenguaje a
utilizar sea en código binario, y las instrucciones se ejecuten como un sistema lógico computable, con lo cual se
optimizaría en parte la problemática de expresar un algoritmo que sea recursivo o decidible.
La estrategia consistirá en desarrollar un lenguaje de programación esencial, con el cual se pueda expresar un
programa para calcular cualquier función recursiva parcial. Esto asegurara (suponiendo que la tesis de Church-
Turing es verdadera) que, mientras un lenguaje de programación cuente con las características de nuestro lenguaje
esencial, permitirá expresar una solución para cualquier problema que pueda resolverse de manera algorítmica.
8.1 El lenguaje de la lógica proposicional
El alfabeto de la lógica de proposiciones debe proporcionar los símbolos necesarios para representar
proposiciones sobre el mundo. Como el número de proposiciones que pueden manejarse en un mismo
razonamiento no está limitado, debe proveer un número infinito de letras proposicionales.
Alfabeto de la lógica de proposiciones. El alfabeto A de la Lógica de proposiciones consta de los siguientes
elementos: infinitas letras proposicionales: , símbolos lógicos: constantes ( ), conectiva monaria
( ) y conectivas binarias ( ) y dos símbolos auxiliares de puntuación: paréntesis izquierdo’(’ y derecho
’)’. Así,
En las exposiciones teóricas, el número de letras proposicionales que se consideran simultáneamente es pequeño
(por ejemplo, de a ). En estos casos se suelen notar informalmente con las últimas letras del alfabeto latino:
A las expresiones aceptables se las denominará fórmulas o expresiones bien formadas. El
conjunto (infinito) que incluye todas estas fórmulas (y nada más) es el lenguaje de la lógica de proposiciones, que
notaremos como .
El conjunto , que contiene todas las expresiones aceptables en nuestro lenguaje (y sólo éstas), es el menor
de los conjuntos que verifica que todas las fórmulas atómicas pertenecen a ; si la expresión entonces
; y si las expresiones entonces .
Un lenguaje de programación esencial. Dado que nuestro lenguaje de programación esencial se usara para
calcular funciones recursivas parciales, el único tipo de dato que se requiere es el entero no negativo (como ya
61
hemos señalado, en un ordenador digital moderno todo dato se representa como un entero no negativo, aunque los
lenguajes de alto nivel puedan disfrazar esta realidad). Por esta razón, nuestro lenguaje de programación esencial
no necesita enunciados de declaración de tipo, sino que los identificadores se declaran automáticamente como de
tipo entero no negativo con solo aparecer una vez en un programa. Para su representación se ha utilizado el
lenguaje C, como puede ser cualquier lenguaje existente. El lenguaje contendrá los dos enunciados de asignación
siguientes:
incr nombre; y decr nombre;
El primero incrementa en uno el valor asignado al identificador nombre, mientras que el segundo lo decrementa
en uno, a menos que el valor a decrementar sea 0, en cuyo caso permanece con dicho valor. El lenguaje se
completa entonces con una estructura de control formada por los dos siguientes enunciados:
while nombre 6= 0 do
...
end;
Esta estructura indica que es necesario repetir los enunciados que se encuentren entre while y end mientras el
valor asignado al identificador nombre no sea cero. Lenguaje de programación el lenguaje de programación
se denomina (por programming language while, es decir, lenguaje de programación con repeticiones
while). Ver capitulo 7 donde se aplica el concepto. Este es entonces nuestro lenguaje de programación esencial.
Efectivamente, es tan sencillo que nuestro primer objetivo sería el de incorporar algunos enunciados más potentes,
que puedan simularse con secuencias de enunciados esenciales. Una vez hecho esto, podremos utilizar los
enunciados adicionales para escribir programas más claros. Más concretamente, adoptaremos la sintaxis: clear
nombre; como versión abreviada de la secuencia:
while nombre 6 0 do
decr nombre;
end;
cuyo efecto es asignar el valor 0 al identificador nombre. Además, utilizaremos
nombre1 nombre2;
para representar el siguiente segmento de programa:
clear aux;
clear nombre1;
while nombre2 6= 0 do
62
incr aux;
decr nombre2;
end;
while aux 6= 0 do
incr nombre1;
incr nombre2;
decr aux;
end;
el cual asigna el valor de nombre2 al identificador nombre1, asignándolo primero a la variable auxiliar aux, y
Después reasignándolo tanto a nombre1 como a nombre2. Obsérvese que el esfuerzo que implica el uso de aux
permite evitar el efecto colateral de destruir la asignación original de nombre2.
Recursiva parcial implica programable con lo esencial. La siguiente tarea sería la de mostrar que para
cualquier función recursiva parcial existe un algoritmo que calcula dicha función, el cual puede expresarse con
nuestro sencillo lenguaje de programación esencial. Para ello, estableceremos la convención de que para calcular
una función de a escribiremos un programa con los identificadores para contener los valores
de entrada, y con para almacenar los valores de salida. Con nuestro sencillo lenguaje esencial es fácil
expresar los programas que corresponden al cálculo de las funciones iniciales:
La función o función cero está representada por:
clear ;
La función o función sucesor se representa mediante:
;
incr ;
Y las funciones de proyección j pueden calcularse como sigue:
;
Seguidamente al centrar la atención sobre la técnica de construcción de los algoritmos correspondientes a las
funciones recursivas parciales:
Combinación. Si y son dos programas que calculan las funciones parciales y ,
respectivamente, entonces la función se puede calcular concatenando al final del programa ,
modificando y para que asignen sus salidas a los identificadores apropiados ( debe asignar su salida
63
a a la vez que asigna su salida a ) y ajustando para que no destruya los valores de
entrada antes de que pueda utilizarlos.
Por supuesto, tanto aquí como en los casos que se presentan más adelante, suponemos que los programas en
cuestión no tienen nombres de variables auxiliares comunes que pudieran ocasionar efectos colaterales. En este
caso, si los tuvieran, siempre podríamos cambiarlos para obtener espacios de nombres distintos, haciendo que
todos los identificadores del programa estuvieran precedidos por la letra y todos los del programa por la
letra
Composición. Si y son dos programas que calculan las funciones parciales y ,
respectivamente, entonces la función g ∘ f se puede calcular concatenando al final del programa y ajustando
los identificadores de salida de para que vayan de acuerdo con los identificadores de entrada de .
Recursividad primitiva. Ahora supongamos que el programa calcula la función parcial , el
programa calcula y, usando recursividad primitiva, la función se define como:
Entonces se puede calcular con el siguiente programa:
G
aux ;
clear ;
while aux 6= 0 do
...
.
H
incr ;
decr aux;
end;
donde, sin pérdida de generalidad, podemos suponer que y no tienen efectos secundarios indeseables.
Minimalizacion. Si es un programa que calcula la función parcial , entonces podemos producir un
programa que calcule como sigue:
64
clear ;
G
while do
incr ;
G
end;
;
Este programa lleva a cabo dicha tarea calculando hasta que produce una salida
cero para un cierto valor , almacenado realmente en , el cual constituirá el valor final de salida del
programa. Obsérvese que se puede diseñar para que no altere las asignaciones originales de sus variables de
entrada.
Hasta aquí se ha mostrado entonces que cualquier función recursiva parcial puede calcularse por medio de un
programa escrito en nuestro lenguaje de programación esencial. Por tanto, de acuerdo con la tesis de Church-
Turing, sabemos que cualquier lenguaje que proporcione el tipo entero no negativo y la capacidad para
incrementar un valor, decrementarlo y ejecutar un ciclo while, tendría el poder expresivo suficiente para plantear
la solución de cualquier problema que tenga una solución algorítmica. Todas las características adicionales de un
lenguaje representan simplemente conveniencias que facilitan las labores de programación.
Programable con lo esencial implica recursiva parcial. Después de haber descubierto el sorprendente poder de
nuestro sencillo lenguaje, se podría pensar que ofrece un medio para calcular algo más que las funciones
recursivas parciales. Por supuesto, si esta conjetura fuera verdadera, contradirá la tesis de Church-Turing ya que
obtendríamos un método para calcular una clase de funciones mayor que la de las funciones recursivas parciales
(que son las computables por máquinas de Turing). Por tanto, efectivamente, no constituye ninguna sorpresa el
encontrar que cualquier cálculo expresado en nuestro sencillo lenguaje de programación puede modelarse por
medio de una función recursiva parcial. La estrategia para demostrar esta afirmación consiste en aplicar
razonamientos inductivos sobre el posible número de enunciados de un programa.
Si nos centramos en la máquina de Turing, en la que no existen estas limitaciones, podremos entender mejor la
idea básica de que algún dispositivo de computación será capaz de hacerlo, si no hoy día, sí en un futuro. Se
proporcionara una descripción formal de que existe un problema de las máquinas de Turing que ninguna de ellas
puede resolver. Las máquinas de Turing pueden simular computadoras reales, incluso a aquellas que no tienen las
limitaciones que sabemos que actualmente tienen, por lo que dispondremos de un argumento riguroso de que el
siguiente problema: ¿Se acepta esta máquina de Turing a sí misma (su propia codificación) como entrada? no
65
puede ser resuelto por una computadora, independientemente de lo generosamente que se relajen las limitaciones
prácticas. Para el sistema lógico proposicional nuestro codificación es binaria, y por tal motivo la generación de la
cinta con la cadena de unos y ceros tiene un significado, y lo más básico es expresarlos en términos lógicos: si
está o no en operación, está o no está disponible, existe capacidad o no, se cuenta con inventario o no etc. Lo no
expresado de forma binario se codificara con un sistema lógico cambinacional que interpretara la MT. Este
concepto se desarrolla en el procedimiento de diseño de algoritmos combinacionales.
Se divide entonces los problemas que puede resolver una máquina de Turing en dos categorías: aquellos que
tienen un algoritmo (es decir, una máquina de Turing que se detiene en función de si acepta o no su entrada), y
aquéllos que sólo son resueltos por máquinas de Turing que pueden seguir ejecutándose para entradas que no
aceptan. Esta última forma de aceptación es problemática, ya que sea cual sea el tiempo que la esté en
ejecución, no podemos saber si la entrada es aceptada o no. Por tanto, vamos a centrarnos en las técnicas que
demuestran que los problemas son “indecidibles”, es decir, que no tienen ningún algoritmo, independientemente
de si son o no aceptados por una máquina de Turing que no se detiene para algunas entradas. (Carlos Guillén,
2005)
Describiré que el siguiente problema es indecidible: ¿Acepta esta máquina de Turing esta entrada?
A continuación, se aplicara el resultado obtenido acerca de la indecidibilidad a una serie de problemas
indecidibles. Todos los problemas no triviales acerca del lenguaje aceptado por una máquina de Turing son
indecidibles, así como una serie de problemas que no tienen nada que ver con las máquinas de Turing, los
programas o las computadoras. En capitulo 6, se explica detalladamente el funcionamiento de la máquina de
Turing., y por el momento nos interesa determinar que el lenguaje a utilizar lo acepte.
El término “recursivamente enumerable” recuerda la misma familia de conceptos. Una función podría enumerar
todos los elementos de un lenguaje en un cierto orden. Los lenguajes que pueden enumerar sus elementos en
cierto orden son los mismos que los lenguajes aceptados por algunas , aunque dichas pueden no detenerse
nunca para las entradas que no aceptan.
8.2 Lenguajes recursivos
Decimos que un lenguaje es recursivo si para una máquina de Turing tal que:
1. Si pertenece a , entonces acepta (y por tanto se para).
2. Si no pertenece a , entonces termina parándose, aunque nunca llega a un estado de aceptación.
66
Una de este tipo se corresponde con nuestro concepto informal de “algoritmo”, una secuencia bien definida
de pasos que siempre termina y genera una respuesta. Si pensamos en el lenguaje como en un “problema”, lo
que será frecuente, entonces se dice que el problema es decidible si es un lenguaje recursivo, y se dice que es
indecidible si no es un lenguaje recursivo.
La existencia o no existencia de un algoritmo para resolver un problema a menudo tiene más importancia que la
existencia de una que resuelva el problema. Como se ha mencionado anteriormente, las máquinas de Turing
que no garantizan la parada no pueden proporcionarnos la suficiente información como para concluir que una
cadena no pertenece al lenguaje, por lo que en cierto sentido no “resuelven el problema”. Por tanto, dividir los
problemas o los lenguajes entre decidibles (aquellos que se resuelven mediante un algoritmo) e indecidibles, a
menudo es más importante que la división entre lenguajes recursivamente enumerables (aquellos para los que
existen máquinas de Turing de alguna clase) y lenguajes no recursivamente enumerables (aquellos para los que no
existe ninguna ). La figura 18 muestra la relación entre estas tres clases de lenguajes:
1. Los lenguajes recursivos.
2. Los lenguajes que son recursivamente enumerables pero no recursivos.
3. Los lenguajes no recursivamente enumerables
El lenguaje no lo hemos colocado apropiadamente y también el lenguaje o “lenguaje universal”, que
demostraremos en breve que no es recursivo, aunque sí .
Complementarios de los lenguajes recursivos y . Una potente herramienta para comprobar qué lenguajes
están dentro del segundo círculo de la figura 18 (es decir, que son , pero no recursivos) es el complementario
del lenguaje. Demostraremos que los lenguajes recursivos son cerrados para la complementación. Por tanto, si un
lenguaje es , pero , el complementario de , no es , entonces sabemos que no puede ser recursivo. Si
fuera recursivo, entonces también sería recursivo y, por tanto, seguramente . Ahora vamos a demostrar esta
importante propiedad de clausura de los lenguajes recursivos. Ver anexo Teorema 17.
Figura 1. Relación entre los lenguajes RE y no RE
67
Recursivo
RE pero
no recursivo
No RE
. Ld
. Lu
Fuente: Autor
El lenguaje universal. Se explicara informalmente cómo podría emplearse una máquina de Turing para simular
una computadora cargada con un programa arbitrario. Esto quiere decir que una única máquina de Turing se
puede emplear como una “computadora que ejecuta un programa almacenado”, que toma el programa y los datos
de una o más cintas en las que se coloque la entrada. Vamos a repetir esta idea con la formalidad adicional de que
el programa almacenado también es una representación de una máquina de Turing.
Se define , el lenguaje universal, para que sea el conjunto de cadenas binarias que codifican, utilizando la
notación, un par , donde es una con el alfabeto de entrada binario y es una cadena de tal
que pertenece a Es decir, es el conjunto de cadenas que representan a una y una entrada aceptada
por dicha . Se mostrara que existe una , a menudo conocida como máquina de Turing universal, tal
que . Puesto que la entrada a es una cadena binaria, es en realidad una de la lista de máquinas de
Turing con entrada binaria que se ha desarrollado.
Es más fácil describir como una máquina de Turing de varias cintas. La aplicación de una de tres cintas se
da en el nivel II, cuando obtengamos en la salida de la que representa cada centro de trabajo. Las cintas
necesarias serán para cada una de los recursos declarados en cada clausula2 en la formula lógica proposicional que
igualmente son que se ejecutan con un sistema lógico secuencial. En el caso de , las transiciones de se
almacenan inicialmente en la primera cinta, junto con la cadena . Una segunda cinta se utilizará para almacenar
la cinta simulada de , utilizando el mismo formato que para el código de . Es decir, representará el símbolo
de cinta de y los símbolos de cinta se separarán mediante un único 1. La tercera cinta de almacena el
estado de , con el estado representado por ceros.
El funcionamiento de puede resumirse como sigue:
2 Cláusula de Horn. En lógica proposicional, una fórmula lógica es una cláusula de Horn si es una cláusula (disyunción de literales) con, como máximo, un
literal positivo. Se llaman así por el lógico Alfred Horn, el primero en señalar la importancia de estas cláusulas en 1951.
68
1. Al examinar la entrada para asegurar que el código para es un código válido para una . Si no lo es, se
para sin aceptar. Puesto que se supone que los códigos no válidos representan la sin ningún movimiento y
que tal no acepta ninguna entrada, esta acción es correcta.
2. Inicializar la segunda cinta para que contenga la entrada , en su forma codificada. Es decir, para cada 0 de ,
se incluye 10 en la segunda cinta y para cada 1 de , se incluye 100 en la misma. Observe que los espacios en
blanco de la cinta simulada de , que están representados por 1000, no aparecerán en dicha cinta; todas las
casillas situadas más allá de las que utiliza almacenarán los espacios en blanco de . Sin embargo, sabe
que, si busca un símbolo simulado de y encuentra su propio espacio en blanco, tiene que reemplazar dicho
espacio en blanco por la secuencia 1000 para simular el espacio en blanco de .
3. Colocar 0, el estado inicial de , en la tercera cinta y mover la cabeza de la segunda cinta de a la primera
casilla simulada.
4. Para simular un movimiento de , busca en la primera cinta una transición tal que sea el
estado de la cinta 3 y sea el símbolo de cinta de que comienza en la posición de la cinta 2 señalada por la
cabeza de . Esta transición determina la siguiente acción de . tiene que:
a. Cambiar el contenido de la cinta 3 a ; es decir, simular el cambio de estado de Para ello, en
primer lugar, cambia todos los ceros de la cinta 3 por espacios en blanco, y luego copia de la
cinta 1 a la cinta 3.
b. Reemplazar 0j de la cinta 2 por ; es decir, cambiar el símbolo de cinta de . Si se necesita más o
menos espacio (es decir, ), utiliza la cinta auxiliar y la técnica de desplazamiento para gestionar
la utilización del espacio.
c. Mover la cabeza de la cinta 2 a la posición en la que se encuentre el siguiente 1 hacia la izquierda o
hacia la derecha, respectivamente, dependiendo de si (movimiento a la izquierda) o
(movimiento a la derecha). Así, simula los movimientos de hacia la izquierda o hacia la derecha.
5. Si no dispone de ninguna transición que corresponda al estado y símbolo de cinta simulados, entonces en el
paso (4), no se encontrará ninguna transición. Por tanto, se para en la configuración simulada y deberá
hacer lo mismo.
6. Si entra en un estado de aceptación, entonces acepta.
De esta forma, simula sobre . acepta el par codificado si y sólo si acepta .
Indecidibilidad del lenguaje universal. Ahora se aborda un lenguaje que es pero no recursivo: el lenguaje .
Saber que es indecidible (es decir, que no es un lenguaje recursivo) es mucho más valioso que nuestro anterior
descubrimiento de que no es . La razón es que la reducción de a otro problema puede emplearse para
demostrar que no existe ningún algoritmo para resolver , independientemente de si es o no es . Sin
embargo, la reducción de a sólo es posible si no es , por lo que no se puede utilizar para demostrar la
69
indecidibilidad de aquellos problemas que son pero no son recursivos. Por el contrario, si deseamos demostrar
que un problema no es , entonces sólo podemos utilizar , ya que no es útil en este caso puesto que es .
Una universal más eficiente. Una simulación eficiente de por parte de , que no exigiese tener que
desplazar los símbolos de la cinta, pasaría por, en primer lugar, que determinase el número de símbolos de cinta
que utiliza. Si existen entre símbolos, podría utilizar un código binario de bits para
representar de forma unívoca los diferentes símbolos de cinta. Las casillas de la cinta de podrían simularse
mediante casillas de la cinta de . Para hacer las cosas todavía más fáciles, podría reescribir las transiciones
de para utilizar un código binario de longitud fija en lugar del código unario de longitud variable que se ha
utilizado aquí.
El problema de la parada. A menudo se dice que el problema de la parada de las máquinas de Turing es similar
al problema (un problema que es pero no recursivo). De hecho, la máquina de Turing original de A. .
Turing acepta por parada, no por estado final. Se podría definir para la como el conjunto de entradas
tales que se detiene para la entrada dada, independientemente de si acepta o no w. Entonces, el
problema de la parada es el conjunto de pares tales que pertenece a Este problema/lenguaje es
otro caso de un problema que es pero no recursivo.
¿Por qué los problemas y sus complementarios son diferentes?. La intuición nos dice que un problema y su
complementario realmente son el mismo problema. Para resolver uno de ellos, podemos utilizar un algoritmo para
el otro y, en el último paso, complementar la salida: indicar “sí” en lugar de “no”, y viceversa. Esta idea intuitiva
es correcta siempre y cuando el problema y su complementario sean recursivos.
Sin embargo, existen otras dos posibilidades. La primera de ellas es que ni el problema ni su complementario son
. En este caso, ningún tipo de puede resolver ninguno de ellos, por lo que en cierto sentido de nuevo los
dos son similares. Sin embargo, el caso interesante, tipificado por y , es cuando uno es y el otro es
.
Para el lenguaje que es , podemos diseñar una que tome una entrada y busque una razón por la que
pertenezca al lenguaje. Así, para , dada una como entrada, hacemos que nuestra T busque cadenas
que la acepte, y tan pronto como encuentre una, aceptamos . Si es una con un lenguaje vacío,
nunca sabremos con certeza que no pertenece a , pero nunca aceptaremos , y ésta es la repuesta correcta
que proporciona la nueva .
Por otro lado, para el problema complementario , el que es no-RE, no existe ninguna manera de aceptar todas
sus cadenas. Suponga que tenemos una cadena que es una cuyo lenguaje es el lenguaje vacío. Se puede
probar las entradas aplicadas a la , y es posible que ni siquiera encontremos una que acepte, y aún así
70
nunca podremos estar seguros de que no existe alguna entrada que todavía no haya sido comprobada y que sea
aceptada por esta . Por tanto, puede no ser nunca aceptada, incluso aunque tuviera que serlo.
Lenguaje no recursivamente enumerable. Un lenguaje es recursivamente enumerable si ) para
alguna máquina de Turing . Los lenguajes “recursivos” o “decidibles” que no sólo no son recursivamente
enumerables, sino que son aceptados por una que siempre se detiene, independientemente de si acepta o no.
Nuestro objetivo a largo plazo es demostrar la indecibilidad del lenguaje que consta de pares tales que:
1. es una máquina de Turing (codificada adecuadamente en binario) con el alfabeto de entrada
2. es una cadena de ceros y unos, y
3. acepta la entrada .
Si este problema con entradas restringidas al alfabeto binario es indecidible, entonces con toda probabilidad el
problema más general, en el que la puede utilizar cualquier alfabeto, será indecidible.
El primer paso consiste en enunciar este problema como una cuestión acerca de la pertenencia a un determinado
lenguaje. Por tanto, tenemos que determinar una codificación para las máquinas de Turing que sólo utilizan ,
independientemente de cuántos estados tenga la . Una vez que dispongamos de esta codificación, podremos
tratar cualquier cadena binaria como si fuera una máquina de Turing. Si la cadena no es una representación bien
formada de una , podemos interpretarlo como una representación de un sin movimientos. Por tanto,
podemos pensar que cualquier cadena binaria representa una .
Un objetivo intermedio, implica al lenguaje , el “lenguaje de diagonalización”, formado por todas aquellas
cadenas tales que la representada por no acepta la entrada Se demostrara que no es aceptado por
ninguna máquina de (Turing, 1936). Recuerde que demostrando que no existe ninguna máquina de Turing para un
lenguaje, estamos demostrando algo aún más restrictivo que el hecho de que el lenguaje sea indecidible (es decir,
que no existe ningún algoritmo, o ninguna que siempre se pare).
El lenguaje desempeña un papel análogo al programa hipotético , que imprime cuando su salida no imprimía
hola, mundo al proporcionarse él mismo como entrada.
Dicho de forma más precisa, igual que no puede existir porque su respuesta al proporcionarse él mismo como
entrada lleva a una paradoja, no puede ser aceptado por una máquina de Turing, porque si lo fuera, entonces
dicha máquina de Turing tendría que estar en desacuerdo consigo misma cuando se le proporcionara su propio
código como entrada. (Sara Baase, 2002)
Enumeración de cadenas binarias. A continuación, se necesita asignar enteros a todas las cadenas binarias, de
modo que cada cadena se corresponda con un entero y que cada entero se corresponda con una cadena. Si es
71
una cadena binaria, se trata como el entero binario Entonces se considera que es la -ésima cadena. Es
decir, es la primera cadena, 0 es la segunda, 1 la tercera, 00 la cuarta, 01 la quinta, etc. De forma equivalente, las
cadenas se ordenan de acuerdo con la longitud, y las cadenas de la misma longitud se ordenan alfabéticamente.
De aquí en adelante, se denominara a la cadena -ésima.
Códigos para las máquinas de Turing. Nuestro siguiente objetivo es definir un código binario para las máquinas
de Turing de modo que cada con el alfabeto de entrada pueda interpretarse como una cadena binaria.
Puesto que ya ha visto cómo enumerar cadenas binarias, se dispone entonces de un medio de identificación de las
máquinas de Turing mediante enteros, y se podria hablar de “la -ésima máquina de Turing, ”. Para representar
una como una cadena binaria, primero se tiene que asignar números enteros al
estado, los símbolos de cinta y las direcciones y .
Se supone que los estados son para algún . El estado inicial siempre será y será el único estado
de aceptación. Observe que, dado que se puede suponer que la se para cuando entra en un estado de
aceptación, nunca existe la necesidad de que haya más de un estado de aceptación.
Suponer que los símbolos de cinta son para algún . siempre será el símbolo 0, será el 1 y
será , el espacio en blanco. No obstante, pueden asignarse otros símbolos de cinta a los restantes enteros de
forma arbitraria. Al denominar la dirección (izquierda) y a la dirección (derecha) .
Dado que el orden en que se asignan los enteros a los estados y símbolos de cinta de cada puede ser
diferente, existirá más de una codificación para cada Sin embargo, este hecho no es importante, ya que se va a
demostrar que ninguna codificación puede representar una tal que .
Al asignar un entero a cada estado, símbolo y dirección, se puede codificar la función de transición Suponer
que una regla de transición es para los valores enteros y . Codificar esta cadena
mediante la cadena . Observe que, dado que y valen, como mínimo, uno, no existen
subcadenas de dos o más unos consecutivos en el código de una única transición.
Un código para la completa consta de todos los códigos correspondientes a las transiciones, en un cierto
orden, separados por pares de unos:
donde cada una de las corresponde al código de una transición de . En la teoría de autómatas la es una
representación de este mismo, y lo abordare no desde el punto de vista computacional sino como un sistema
lógico secuencial asíncrono y síncrono y defino la función de transición. Ver sección 5.3.
El lenguaje de diagonalización. Se han codificado las máquinas de Turing, por lo que ahora se tiene un concepto
concreto de , la “máquina de Turing -ésima”: es aquella cuyo código es , la cadena binaria -ésima.
72
Muchos enteros no se corresponden con ninguna . Por ejemplo, 11001 no comienza por 0, y
0010111010010100 tiene tres unos consecutivos. Si no es un código válido de , interpretar que es una
con un estado y ninguna transición. Es decir, para dichos valores de , es una máquina de Turing que se
detiene de forma inmediata para cualquier entrada. Por tanto, ) es si no es un código válido de la .
Ahora se esta en condición de establecer una explicación extremadamente importante. El lenguaje , el lenguaje
de diagonalización, es el conjunto de cadenas tal que no pertenece a ). Es decir, consta de todas las
cadenas tales que la , cuyo código es , no acepta cuando se proporciona como entrada.
La razón por la que se denomina lenguaje de “diagonalización” puede verse fijándose en la tabla.
Tabla 7. Tabla que representa la aceptación de cadenas por máquinas de Turing.
1 2 3 4 5 …
1 0 1 1 0 0 0 …
2 1 1 0 0 1 1 …
3 0 0 1 1 0 1 …
4 0 0 0 1 1 0 …
5 1 0 1 0 1 1 …
. . . . . .
Esta tabla indica para todo y , si la acepta o no la cadena de entrada ; 1 signfica que “sí la acepta” y 0
indica que “no la acepta”.1 La fila -ésima puede intrepretarse como el vector característico del lenguaje );
es decir, los unos de esta fila indican las cadenas que pertenecen a este lenguaje.
Los valores de la diagonal indican si acepta . Para construir , se complementa la diagonal de la tabla 4. Si
la tabla 4 fuera la tabla correcta, entonces la diagonal complementada comenzaría por 1,0,0,0, . . . Por tanto,
contendría , no contendría hasta , que son 0, 1 y 00, etc.
El proceso que consiste en complementar la diagonal para construir el vector característico de un lenguaje, que no
puede ser el lenguaje que aparece en ninguna de las filas, se denomina diagonalización. Este proceso funciona
porque el complementario de la diagonal es en sí mismo un vector característico que describe la pertenencia a un
lenguaje, que se denomina . Este vector característico difiere en alguna columna de todas las filas de la tabla
mostrada en la tabla 4. Por tanto, el complementario de la diagonal no puede ser el vector característico de
ninguna máquina de Turing.
73
Demostración de que no es recursivamente enumerable. Siguiendo la intuición anterior acerca de los
vectores característicos y la diagonal, se demuestra formalmente un resultado fundamental sobre las máquinas de
Turing: no existe ninguna máquina de Turing que acepte el lenguaje . Ver anexo Teorema 16.
Un problema indecidible recursivamente enumerable. Hasta aquí, se ha examinado un problema (el lenguaje
de diagonalización ) que no es aceptado por una máquina de Turing. El siguiente objetivo es depurar la
estructura de los lenguajes recursivamente enumerables (aquellos que son aceptados por las ) y
clasificarlos dentro de dos clases. Una clase, la que corresponde a lo que normalmente se denomina algoritmo,
dispone de una que no sólo reconoce el lenguaje, sino que también informa de si una cadena de entrada no
pertenece al lenguaje. Una máquina de (Turing, 1936) así siempre termina parándose, independientemente de si
llega a alcanzar o no un estado de aceptación.
La segunda clase de lenguajes está formada por aquellos lenguajes que no son aceptados por ninguna máquina
de Turing que garantice la parada en todos los casos. Estos lenguajes son aceptados de una forma poco adecuada;
si la entrada pertenece al lenguaje, terminará aceptándola, pero si la entrada no pertenece al lenguaje, entonces la
máquina de Turing continuará ejecutándose indefinidamente y nunca se podrá estar seguro de que dicha entrada
no será finalmente aceptada. Este tipo de lenguaje es el conjunto de pares codificados tales que la
acepta la entrada .
Máquinas de Turing que aceptan el lenguaje vacío. Como casos de reducciones que implican máquinas de
Turing, se va a examinar dos lenguajes denominados y . Cada uno de ellos consta de cadenas binarias. Si
es una cadena binaria, entonces representa a una cierta , de la enumeración de las máquinas de Turing.
Si , es decir, no acepta ninguna entrada, entonces pertenece a . Por tanto, es el lenguaje
formado por todas aquellas codificaciones de cuyo lenguaje es el lenguaje vacío. Por el contrario, si no
es el lenguaje vacío, entonces pertenece a . Por tanto, es el lenguaje que consta de todos los códigos de
las máquinas de Turing que aceptan al menos una cadena de entrada.
De aquí en adelante, resultará conveniente interpretar las cadenas como las máquinas de Turing que representan.
Así, se puede definir los dos lenguajes mencionados como sigue:
Observe que y son lenguajes sobre el alfabeto binario y que son complementarios entre sí. Veremos
que es el más “sencillo” de los dos y es pero no recursivo. Por el contrario, es .
74
es recursivamente enumerable. Demostración. Hay que demostrar que existe una que acepta . Para
ello, lo más sencillo es describir una no determinista , cuyo esquema se muestra en la figura 19. De acuerdo
con el teorema, puede convertirse en una determinista.
Figura 2. Construcción de un MT no determinística que acepta
Aceptar Aceptar
Cadena
w
Mi
M para Lne
U
Fuente: Autor
El funcionamiento de es el siguiente.
1. toma como entrada el código de una .
2. Utilizando su capacidad no determinista, prueba con una entrada que podría aceptar.
3. comprueba si acepta . Para esta parte del proceso, puede simular a la universal que acepta
Lu.
4. Si acepta w, entonces acepta su propia entrada, que es .
De esta forma, si acepta aunque sea una sola cadena, terminaría encontrándola (entre otras muchas, por
supuesto), y aceptaría . Sin embargo, si entonces ninguna cadena sería aceptada por , por lo que
no aceptará . Por tanto .
El siguiente paso consiste en demostrar que no es recursivo. Para ello, se reduce a . Es decir, describir
un algoritmo que transforme una entrada en una salida , el código de otra máquina de Turing, tal que
pertenezca a si y sólo si no es el lenguaje vacío. Es decir, acepta si y sólo si acepta al menos
una cadena. El truco está en que ignora su entrada, en lugar de simular para la entrada . Si acepta,
entonces acepta su propia entrada; por tanto, la aceptación de por parte de es equivalente a que no
sea el lenguaje vacío. Si fuera recursivo, entonces se tendría un algoritmo para determinar si acepta o no la
cadena w: construir y ver si
no es recursivo.
Figura 3. Esquema de construida a partir de : acepta una entrada arbitraria si y sólo si acepta .
75
Aceptar Aceptar
w
M’
U
Fuente: Autor
Se seguirá la misma línea que en la demostración anterior. Al diseñar un algoritmo que convierta una entrada, que
es un par codificado en binario en una tal que si y sólo si acepta la entrada . La
construcción de se muestra en la figura 20. Como veremos, si no acepta , entonces no acepta ninguna de
sus entradas; es decir . Sin embargo, si acepta , entonces acepta todas las entradas y, por tanto,
no será .
se diseña como sigue: ignora su propia entrada . En su lugar, reemplaza su entrada por la cadena que
representa la y la cadena de entrada Puesto que está diseñada para un par específico cuya
longitud será , se puede construir para disponer de una secuencia de estados , donde es el
estado inicial.
En el estado para escribe el -ésimo bit del código de pasa al estado y se
mueve hacia la derecha.
En el estado , se mueve hacia la derecha, si fuera necesario, reemplazando los símbolos no blancos (que
corresponderán a la cola de , si dicha entrada a tiene una longitud mayor que ) por espacios en blanco.
Cuando encuentra un espacio en blanco estando en el estado , utiliza una colección similar de estados para
volver a posicionar su cabeza en el extremo izquierdo de la cinta. Ahora, utilizando estados adicionales, simula
una universal en su cinta actual. Si acepta, entonces acepta. Si nunca acepta, entonces tampoco
aceptará nunca.
La anterior descripción de debería bastar para convencerse de que se podría diseñar una máquina de Turing que
transformara el código de y la cadena en el código correspondiente a . Es decir, existe un algoritmo que
permite llevar a cabo la reducción de a . Ver también que si acepta , entonces aceptará cualquier
entrada que estuviera originalmente en su cinta. El hecho de que sea ignorada es irrelevante; la descripción de
aceptación por una establece que lo que la acepta es lo que haya en su cinta antes de comenzar a operar.
Por tanto, si acepta , entonces el código correspondiente a pertenece a
76
Inversamente, si no acepta , entonces nunca acepta, independientemente de cuál sea su entrada. Por tanto,
en este caso, el código para no pertenece a . Al reducir satisfactoriamente a aplicando el algoritmo
que construye a partir de y; se puede concluir que, dado que no es recursivo, tampoco lo es.
La existencia de esta reducción es suficiente para completar la demostración. Sin embargo, para ilustrar la
influencia de esta reducción, se va a llevar este argumento un paso más allá. Si fuera recursivo, entonces se
podría desarrollar un algoritmo para de la forma siguiente:
Al convertir en la como anteriormente. Se utiliza un algoritmo hipotético para para determinar si
resulta o no que ,. En caso afirmativo, decir que no acepta ; y si , entonces decir que
acepta .
Según el teorema, saber que no existe tal algoritmo para , y se ha llegado a una contradicción de la hipótesis
que establecía que era recursivo, y concluir que no es recursivo. Ahora ya se conoce el estado de . Si Le
fuera , entonces por el teorema, tanto él como serían recursivos. De acuerdo con el teorema, no es
recursivo, se puede concluir que: no es
77
ANEXO 9. Lenguajes recursivamente numerables y recursivos
Un lenguaje es recursivamente numerable si y sólo si existe una que lo reconoce. Es decir, si es el conjunto de
todos los lenguajes (cada uno integrado por cadenas finitas de símbolos pertenecientes a un alfabeto universal ),
sólo los lenguajes recursivamente numerables de son reconocibles por una (por esto es que a los problemas de
decisión asociados se los conoce como computables). La clase de los lenguajes recursivamente numerables se
denomina (por recursively enumerables languages). El nombre se debe a que las cadenas de estos lenguajes se
pueden enumerar. De esta manera, dado , si es una tal que , se cumple para toda cadena
de que:
a. Si , entonces a partir de se detiene en su estado .
b. Si , entonces a partir de se detiene en su estado o no se detiene.
Se va a probar después que no todos los lenguajes son recursivamente numerables, y que sólo algunos tienen la
propiedad de que las que los reconocen se detienen siempre. Considerando este último caso, se define que un
lenguaje es recursivo si y sólo si existe una que lo reconoce y que se detiene cualquiera sea su entrada. La
clase de los lenguajes recursivos se denomina . A los problemas de decisión asociados se los conoce como
decidibles, porque las que los resuelven pueden justamente decidir, cualquiera sea la instancia, si es positiva o
negativa. Ahora, dado , si es una tal que , se cumple para toda cadena de que:
a. Si , entonces a partir de se detiene en su estado .
b. Si , entonces a partir de se detiene en su estado .
Se cumple que . Al probar entre esta clase y la que viene que , es decir que no todos
los problemas computables son decidibles, y que no todos los problemas son computables (las fronteras de y
determinan los límites de la decidibilidad y la computabilidad, respectivamente). Esto se ilustra en la siguiente
figura 74, que presenta una primera versión de la jerarquía de la computabilidad:
Figura 4. Jerarquia de computabilidad
R
RE
78
Fuente: Autor
En los dos teoremas, se presentan algunas propiedades de clausura de las clases y Algunos de estos
resultados se utilizan en la prueba de correctitud de la jerarquía planteada, al tiempo que sus demostraciones
permiten continuar con la ejercitación en la construcción de , ahora utilizando notación algorítmica en lugar de
funciones de transición, e incorporando casos de composición de , técnica que se seguirá empleando en las
próximas clases.
Algunas propiedades de clausura de la clase . Considerando las operaciones de complemento, intersección,
unión y concatenación de lenguajes, se cumple que la clase es cerrada con respecto a todas ellas. Al probar
primeramente que la clase es cerrada con respecto al complemento. Dado un lenguaje , su lenguaje
complemento es Se demuestra a continuación que si , entonces también
.
Dado un lenguaje recursivo , sea una que lo acepta y se detiene siempre, es decir a partir de cualquier
entrada. Se va a construir una que acepta y se detiene siempre, de la siguiente manera: dada una
entrada , si se detiene en , entonces se detiene en , y viceversa. La figura 75 siguiente ilustra esta idea:
Figura 5. que acepta
Mw Si
No
Si
No
M c
Fuente: Autor
Construcción de la Si Γ δ , , ), entonces con y idénticas
salvo en la aceptación y rechazo. Para todo estado de , todo par de símbolos y de , y todo movimiento
del conjunto se define:
a. Si entonces
b. Si d), entonces
Prueba de que se detiene siempre.
a. con entrada , se detiene en con entrada , se detiene en .
79
b. con entrada , se detiene en con entrada , se detiene en .
Prueba de
con entrada se detiene en con entrada , se detiene en
Esta es una típica prueba por construcción de que un lenguaje es recursivo. Se construye una , y se prueba
que se detiene siempre y acepta . La prueba por construcción de que un lenguaje es recursivamente
numerable, en cambio, requiere solamente la construcción de una y la prueba de que acepta .
La clase también es cerrada con respecto a las operaciones de intersección y unión de lenguajes. Es decir, si
entonces . Al probar el caso de la intersección. El caso de la unión
queda como ejercicio.
Sean una que acepta y se detiene siempre, y una que acepta y se detiene siempre. Se va a
construir una que acepta y se detiene siempre, con las siguientes características. simula primero
y luego . Dada una entrada , si se detiene en su estado , entonces directamente se detiene en su
estado .
En cambio, si se detiene en su estado , entonces con la misma entrada , la simula , y se detiene en
su estado (respectivamente ) si se detiene en su estado (respectivamente ). La figura 76 ilustra esta
idea:
Figura 6. que acepta
Mw Si
No
No
1MSi
No
M
2
Fuente: Autor
Construcción de la tiene dos cintas. Dada una entrada en la cinta 1, hace:
1. Copia en la cinta 2.
2. Simula a partir de en la cinta 2. Si se detiene en su estado , entonces se detiene en su estado
.
3. Borra el contenido de la cinta 2.
4. Copia en la cinta 2.
80
5. Simula a partir de en la cinta 2. Si se detiene en su estado (respectivamente ), entonces se
detiene en su estado (respectivamente ).
Queda probar que se detiene siempre, y que . Notar que a diferencia de las simulaciones
presentadas en la clase anterior, ahora de lo que se trata es de ejecutar directamente una por parte de otra
“invoca a la subrutina” , o en otras palabras, la función de transición de incluye un fragmento
que no es sino la función de transición de . En la clase siguiente, en que se trata la máquina de Turing universal,
este concepto se formaliza.
Otra propiedad de la clase que se demuestra a continuación es que es cerrada con respecto a la concatenación de
lenguajes, es decir que si entonces también ⦁ , siendo ⦁
Sean una que acepta y se detiene siempre, y una que acepta y se detiene siempre. Se va a
construir una que acepta ⦁ y se detiene siempre, con las siguientes características. Dada una entrada ,
con simula a partir de los primeros 0 símbolos de , y a partir de los últimos símbolos de ,
y si en ambos casos hay aceptación, entonces acepta . En caso contrario, hace lo mismo pero ahora con el
primer símbolo de y los últimos – símbolos de . Mientras no se detenga por aceptación, repite el
proceso con 2 y – símbolos de – símbolos, y así siguiendo hasta llegar a los y 0 símbolos, en cuyo
caso rechaza .
Construcción de la . tiene cinco cintas. A partir de una entrada en su cinta 1, tal que , hace:
1. Escribe el número 0 en la cinta 2. Sea i dicho número.
2. Escribe el número n en la cinta 3. Sea dicho número.
3. Escribe los primeros símbolos de en la cinta 4.
4. Escribe los últimos símbolos de en la cinta 5.
5. Simula en la cinta 4 a partir del contenido de dicha cinta, y simula en la cinta 5 a partir del
contenido de dicha cinta. Si ambas simulaciones se detienen en , entonces se detiene en .
6. Si , se detiene en .
7. Hace en la cinta – en la cinta 3, borra los contenidos de las cintas 4 y 5, y vuelve al
paso 3.
Algunas propiedades de clausura de la clase . Considerando las operaciones de intersección, unión y
concatenación de lenguajes, se cumple que también la clase es cerrada con respecto a ellas. En cambio, a
81
diferencia de la clase no es cerrada con respecto al complemento, lo que se probará más adelante. Al
demostrar primero que es cerrada con respecto a la unión de lenguajes, es decir que si
entonces . La prueba de que es cerrada con respecto a la intersección queda como ejercicio.
Sean una que acepta y una que acepta (ahora sólo se puede asegurar que estas se detienen
en los casos de aceptación). Se va a construir una que acepta . No sirve que la simule primero
y luego , porque de esta manera no acepta las cadenas de a partir de las que no se detiene. El
mismo problema ocurre simulando primero y después . La solución es otra: se simulan “en paralelo” las
y , y se acepta si alguna de las dos acepta. La figura 77 siguiente ilustra esta idea:
Figura 7. Simulación “en paralelo” las y
wSi
1M
M2
Si
Si
M
Fuente: Autor
Construcción de la . Sea la siguiente con cuatro cintas. Dada una entrada en la cinta 1, hace:
1. Copia en las cintas 2 y 3.
2. Escribe el número 1 en la cinta 4. Dicho número se va a referenciar como i en lo que sigue.
3. Simula, a partir de a lo sumo i pasos de la en la cinta 2, y a lo sumo i pasos de la en la
cinta 3. Si o se detienen en , entonces se detiene en .
4. Borra el contenido de las cintas 2 y 3.
5. Copia en las cintas 2 y 3.
6. Suma 1 al número i de la cinta 4.
7. Vuelve al paso 3.
Notar que la se detiene en su estado o no se detiene. Podría modificarse la construcción, haciendo que se
detenga en cuando detecta que tanto como se detienen en sus estados . Otra mejora en cuanto al
tiempo de trabajo de es no simular cada vez las dos desde el principio. En el paso 3 se indica que se simulan
a lo sumo i pasos porque y pueden detenerse antes. La implementación de estas simulaciones en términos
de la función de transición de podría consistir, asumiendo una representación en base unaria del contador i, en
82
avanzar sobre él a la derecha un dígito por cada paso simulado de y . Queda como ejercicio probar que
Una construcción alternativa, valiéndonos de las no determinísticas descriptas en la clase anterior, es
la siguiente. Si y son dos determinísticas
que aceptan los lenguajes y , respectivamente, se puede construir una que acepta a partir de
y Sea un estado que no está en ni en . La es la tupla
tal que , considerando todos los de
Es decir, al comienzo la pasa no determinísticamente a la configuración inicial de la MTD o a la
configuración inicial de la MTD , y después se comporta determinísticamente como ellas.
Al igual que la clase , es cerrada con respecto a la concatenación de lenguajes, es decir que si RE y
RE, entonces también ⦁ RE, lo que se prueba a continuación. Como en el caso de la unión de lenguajes
recursivamente numerables visto recién, debe tenerse en cuenta que las consideradas pueden no detenerse en
caso de rechazo.
Tal como se hizo con los lenguajes recursivos, se va a construir una que reconozca ⦁ simulando y
(las que reconocen y , respectivamente), primero a partir de 0 y símbolos de la entrada , después
a partir de 1 y – símbolos, y así siguiendo hasta llegar a y 0 símbolos, aceptando eventualmente. La
diferencia con el caso de los lenguajes recursivos está en que ahora, teniendo en cuenta las posibles no
detenciones de y , debe simularlas “en paralelo”. La primero hace simulaciones de un paso de y
con todas las posibles particiones de la entrada posibilidades), luego hace simulaciones de a lo
sumo dos pasos, y así siguiendo hasta eventualmente aceptar (éste es el caso en que al cabo de a lo sumo un
determinado número de pasos, , acepta los primeros símbolos de y acepta los últimos – símbolos
de ).
Construcción de la . Sea la siguiente con seis cintas, que a partir de una entrada en su cinta 1, tal
que hace:
1. Escribe el número 1 en la cinta 2. Sea dicho número.
2. Escribe el número 0 en la cinta 3. Sea dicho número.
3. Escribe el número en la cinta 4. Sea dicho número.
4. Escribe los primeros símbolos de en la cinta 5.
5. Escribe los últimos símbolos de en la cinta 6.
83
6. Simula a lo sumo pasos de en la cinta 5 a partir del contenido de dicha cinta, y simula a lo sumo
pasos de en la cinta 6 a partir del contenido de dicha cinta. Si ambas simulaciones se detienen en ,
entonces se detiene en .
7. Si , hace en la cinta 2, borra los contenidos de las cintas 3, 4, 5 y
8. 6, y vuelve al paso 2.
9. Hace en la cinta 3, – en la cinta 4, borra los contenidos de las cintas 5 y 6, y vuelve al
paso 4.
Al justificar formalmente la estructura de la jerarquía de la computabilidad presentada.
Sea la clase de los lenguajes complemento, con respecto a , de los lenguajes recursivamente
numerables. Formalmente: .
Considerando la siguiente figura 78 muestra una versión más detallada de la jerarquía de la
computabilidad:
Figura 8. versión más detallada de la jerarquía de la computabilidad
R
RE
CO-RE
Fuente: Autor
De la figura 78 se desprende que un lenguaje es recursivo si y sólo si tanto como son recursivamente
numerables, lo que se prueba a continuación.
. Se prueba fácilmente que La inclusión se cumple. También
vale porque . También se cumple la inversa, es
decir,
Sean y dos que aceptan los lenguajes y , respectivamente. Se va a construir una que se
detiene siempre y acepta , de la siguiente manera.
1. simula “en paralelo” las y .
2. Si se detiene en , entonces se detiene en su estado .
84
3. Y si se detiene en , entonces se detiene en su estado .
La figura 79 ilustra esta idea:
Figura 9. y dos que aceptan los lenguajes y
wSi
1M
Si
Si
M
M c No
Fuente: Autor
Se cumple que se detiene siempre porque para toda entrada , vale que , y por lo tanto o
aceptan . Queda la construcción de y la prueba de que .
En la última figura 78 que ilustra la jerarquía de la computabilidad, se distinguen cuatro categorías de lenguajes.
Enumeradas de acuerdo a su dificultad creciente, son:
1.
2. –
3. –
4. –
En este contexto, dado un par cualquiera de lenguajes y , se cumple alternativamente que:
Tanto como pertenecen a .
pertenece a – , y pertenece a – .
Tanto como pertenecen a –
Por el teorema, si está en también lo está . Dos lenguajes recursivos, los lenguajes {
y es un palíndrome}.
El lenguaje en – , con lo que se probara que , o en otras palabras, que hay problemas computables
que no son decidibles. En este caso pertenece a – , de acuerdo también al teorema. Notar que con la
existencia de se prueba además que , de acuerdo al teorema, o en otras palabras, que hay problemas que
no son computables. Adelantándonos, el primer lenguaje de – que corresponde al problema de la detención
de las , o directamente el problema de la detención (también conocido como halting problem). Este problema
85
computable no decidible aparece en la ya referida publicación de A. Turing en la que presenta las máquinas que
llevan su nombre. (Ricardo Rosenfeld, 2013)
El problema de la validez en la lógica de primer orden (o cálculo de predicados), es decir el problema de
determinar si una fórmula de la lógica de primer orden es válida, o lo que es lo mismo, si es un teorema (el trabajo
mencionado de Turing se relaciona con este problema).
El problema de correspondencia de Post, definido de la siguiente manera: dada una secuencia de pares de cadenas
de unos y ceros no vacías determinar si existe una secuencia de índices con tal
que las cadenas sean iguales.
El problema de determinar si una ecuación diofántica (ecuación algebraica con coeficientes y soluciones enteras)
tiene solución. El problema de teselación del plano: dado un conjunto finito de formas poligonales, determinar si
con ellas se puede cubrir el plano.
El problema de las palabras para semigrupos: dadas dos cadenas y un conjunto finito de igualdades entre
cadenas del tipo determinar si de la cadena se puede llegar a la cadena por medio de
sustituciones de subcadenas empleando las igualdades definidas.
Nos queda tratar el caso en que tanto como pertenecen a – lo que prueba que
. Un lenguaje de estas características, un tanto artificial. Luego los lenguajes más naturales de este tipo. A
modo de ilustración, un caso clásico de lenguaje no recursivamente numerable tal que su complemento tampoco
lo es, es el de los enunciados verdaderos de la teoría de números (o aritmética), de acuerdo al Teorema de
Incompletitud de Gödel3, que se referirá más adelante.
Las diferencias en el grado de dificultad de los lenguajes de las cuatro categorías señaladas se perciben a veces
mejor cuando se trata con restringidas, es decir con con restricciones en sus movimientos, sus cintas, etc.
Esto se analizará con cierto detalle en la Clase 5. Dado un conjunto de problemas indecidibles en el
marco de las generales, cuando se consideran con restringidas determinados problemas se mantienen
indecidibles mientras que otros pasan a ser decidibles. En el caso de estos últimos problemas, además, se pueden
destacar entre ellos diferencias en el costo de resolución (tiempo de ejecución de las ).
9.1 Problemas que las computadoras no pueden resolver : indecibilidad
3El teorema de incompletitud afirma que, bajo ciertas condiciones, ninguna teoría matemática formal capaz de describir los números naturales y la aritmética
con suficiente expresividad, es a la vez consistente y completa. Es decir, si los axiomas de dicha teoría no se contradicen entre sí, entonces existen
enunciados que no pueden probarse ni refutarse a partir de ellos. En particular, la conclusión del teorema se aplica siempre que la teoría aritmética en
cuestión sea recursiva, esto es, una teoría en la que el proceso de deducción pueda llevarse a cabo mediante un algoritmo.
86
El contenido de esta investigación se centra en los problemas indecidibles, es decir en los problemas de decisión
asociados a los lenguajes no recursivos, los lenguajes de – . Centrarse en los problemas decidibles, cuando se
analiza su complejidad computacional temporal.
Inicialmente se presenta el primer lenguaje recursivamente numerable que no es recursivo, que completa la
formalización de la jerarquía de la computabilidad definida en la clase anterior. Para ello se vale de la técnica de
diagonalización. Se muestra luego distintos casos de aplicación de esta técnica, y a partir de algunos de ellos se
obtiene otros lenguajes no recursivos. (John, 2008)
En el siguiente apartado hay representantes del conjunto – pero con otra técnica, la reducción de problemas.
Habiendo logrado probar la existencia de algunos primeros lenguajes de esta naturaleza con cierto esfuerzo
usando diagonalización, luego la obtención a partir de los mismos de nuevos representantes será más sencilla
empleando reducciones de problemas.
Para los desarrollos de esta clase se introduce antes que nada el concepto de máquina de Turing universal, el cual
se utilizara en las diagonalizaciones y reducciones. Hasta ahora se ha trabajado con que tratan, cada una, un
problema particular. Pero como modelo adecuado de una computadora la máquina de Turing puede ser también
“programable”, capaz de ejecutar cualquier a partir de cualquier entrada . En este caso, identificando con
a la universal, cumple que: Sus entradas son pares de la forma , siendo la codificación
de una , y una entrada, también codificada, de .
Dada la entrada , su ejecución consiste en simular a partir de .
La universal es como toda una tupla con sus propios estados y símbolos, y una
función de transición que establece cómo simular la cuyo código forma parte de su entrada. Una posible
manera de codificar una es la siguiente (para simplificar se consideran con una sola cinta; la codificación
se puede generalizar fácilmente a varias cintas). Dada
Los estados del conjunto se representan por los números , en notación binaria. Además,
y se representan en binario por los números , respectivamente.
Los símbolos del alfabeto se representan por los números , en notación binaria.
Los movimientos y se representan, respectivamente, por los números 1, 2 y 3, en notación binaria.
Finalmente, la función de transición se representa por una secuencia de 5- tuplas. Las tuplas se separan por el
símbolo numeral, es decir #, y sus componentes por medio de una coma.
87
Con estas consideraciones, la codificación de una consiste en la cadena formada por , en notación
binaria, seguida por el separador # y luego por la representación de la función de transición . Se antepone para
que se puedan identificar los estados y .
Si y la función de transición se define con
entonces el código de la es
La cadena en en realidad debe entenderse como la representación de , con sus símbolos
representados en notación binaria y separados entre sí por una coma. Para separar de se utilizan dos
numerales consecutivos.
Codificar las permite que las mismas se puedan enumerar, utilizando el orden canónico. La siguiente
computa, dado un número natural , el código de la -ésima según el orden canónico:
1. Hace
2. Crea la siguiente cadena w según el orden canónico.
3. Verifica si es un código válido de . Si no, vuelve al paso 2.
4. Si , escribe en la cinta de salida y se detiene en
5. Hace
6. Vuelve al paso 2.
En el paso 2 se generan cadenas en orden canónico con los símbolos que pueden formar parte del código de una
a partir de un ordenamiento establecido entre los símbolos.
En el paso 3 se verifica que las cadenas generadas tengan la forma , que los componentes y
respeten la codificación establecida, que ningún código de estado en supere el valor , etc.
Cuando en el paso 4 se cumple la igualdad , significa que se obtuvo el código .
Notar que en la enumeración canónica obtenida de las puede darse, para índices distintos
que Con estos elementos preparatorios ya se está en condiciones de probar la existencia de
primer lenguaje de –
El problema de la detención es computable no decidible. El problema de la detención (de las ), también
conocido como (por halting problem), es un problema clásico de la literatura, que se enuncia de la siguiente
manera: dada una y una cadena , ¿ se detiene a partir de ?. El lenguaje que lo representa es
se detiene a partir de
Al probar a continuación que – primero que , y luego que
88
Prueba de que . Sea la siguiente , que a partir de una entrada hace:
Si no es un código válido , rechaza. Simula a partir de . Si se detiene, acepta. La figura 80
ilustra el comportamiento de
Figura 10. El problema de la detención (de las ), también conocido como
M
HP
Si
No
M
Si
Fuente: Autor
Se cumple que acepta y se detiene a partir de
Prueba de que .
Al suponer que la siguiente tabla infinita de unos y ceros describe el comportamiento de todas las
con respecto a todas las cadenas de en lo que hace a la detención, considerando el orden canónico. El
valor de es 1 o 0, según la se detiene o no se detiene a partir de la cadena respectivamente.
Sea el lenguaje D = { | se detiene a partir de . Es decir, los elementos de son las cadenas tales que
. Probar que si entonces , y que , por lo que se cumplirá que .
Prueba de que Si el lenguaje fuera recursivo, también lo sería el lenguaje , dado que es
un caso particular de , que en lugar de considerar todos los pares sólo considera los pares
. Más precisamente, si entonces existe una que se detiene siempre y reconoce . Para
probar que , se va a construir una que se detiene siempre y reconoce .
A partir de una entrada trabaja de la siguiente manera: Encuentra el índice tal que según el orden
canónico. Genera . Simula a partir de y acepta (respectivamente rechaza) si acepta
(respectivamente rechaza).
En el paso genera canónicamente todas las cadenas hasta que encuentra la -ésima. Como se
detiene siempre, entonces se detiene siempre. Además se cumple se detiene a
partir de acepta acepta
Prueba de que
89
Al suponer que . Sea una que se detiene siempre y reconoce el lenguaje . A partir de se
construye la siguiente . Dada una entrada hace: Simula a partir de Si acepta, entra en
un loop. Y si rechaza, acepta (en realidad da lo mismo si rechaza). La figura 81 ilustra el comportamiento
de la
Figura 11. Comportamiento de la
wSi
No Si/No
M c
DM
Fuente: Autor
La descripción del fragmento de la función de transición de correspondiente al loop no tiene mayores
complicaciones: se puede reemplazar por un estado nuevo y definir una 5-tupla por cada símbolo
del alfabeto. En el paso 2 da lo mismo que acepte o rechace, si rechaza; lo importante es que se detenga.
La idea es que “le lleve la contra” a , en lo que respecta al comportamiento de la a partir de la
entrada si establece que se detiene a partir de (es decir si acepta), entonces no se detiene a
partir de y si establece que no se detiene a partir de (es decir si rechaza), entonces se detiene a
partir de Como la diagonal de la tabla representa el comportamiento de las respecto de las cadenas ,
entonces “el complemento a dos” de la diagonal (se permutan unos por ceros y ceros por unos), que difiere de
todas las filas de , representa el comportamiento de respecto de las cadenas . Esto entonces va a implicar
que no es ninguna de las , lo que se formaliza a continuación. Dado que la tabla incluye a todas las
tiene que ser alguna de ellas, denominada
Tabla 8. Comportamiento de las respecto de las cadenas
… … …
1 0 1 … 1 … 1 0 …
1 0 0 … 0 … 0 0 …
0 0 1 … 1 … 0 0 …
… … … … … … … … … … … … … … … … … … … …
1 1 0 … 0 … 1 1 …
… … … … … … … … … … 0 0 0 … 0 … 1 0 …
0 0 1 … 0 … 1 1 …
… … … … … … … … … …
90
Qué sucede al considerar la y la entrada
a. Si acepta wm, entonces por cómo se construyó se cumple que no se detiene a partir de . Pero
, así que vale que no se detiene a partir de . Por lo tanto, se cumple que rechaza
, lo que contradice la hipótesis.
b. Si en cambio rechaza , entonces por cómo se construyó se cumple que se detiene a partir de
. Pero como entonces se detiene a partir de . Dada la aclaración de queda que
acepta , lo que otra vez contradice la hipótesis.
De esta manera no puede existir la O dicho en otras palabras, es distinta de todas las enumeradas
en , lo que es absurdo porque en están todas las Y como la se construyó a partir de la
entonces tampoco puede existir Esto significa que .
La técnica empleada en el teorema anterior se denomina diagonalización. Es muy útil para probar que dos
conjuntos difieren en al menos un elemento, al que se lo suele denominar separador. En el caso anterior, el
separador que se encuentra entre las clases y es el lenguaje (en realidad también el lenguaje ). La idea
de la diagonalización es muy sencilla. En una de sus variantes, se toma como base una tabla de unos y ceros
y se utiliza el hecho de que “el complemento a dos” de su diagonal difiere de todas las filas: difiere de la primera
fila en el primer elemento, de la segunda fila en el segundo elemento, y así sucesivamente.
Otro lenguaje que no es recursivamente numerable. Se puede probar por diagonalización que de una
manera muy similar a cómo se probó que . En la siguiente tabla infinita de unos y ceros,
o 0 según la acepta o rechaza la cadena respectivamente.
De esta manera, acepta . Si y E
acepta , se cumple que
porque
porque
porque y así sucesivamente.
Es decir, no es ninguno de los lenguajes y como los lenguajes son todos los lenguajes recursivamente
numerables dado que en la tabla están todas las , entonces se cumple que . En términos de la tabla
, “el complemento a dos” de su diagonal, que representa el lenguaje , difiere de todas las filas de que
representan todos los lenguajes recursivamente numerables.
91
Notar que con lo desarrollado hasta este momento se cuenta con distintos caminos para formalizar los límites de la
computabilidad, es decir para probar la inclusión estricta . , porque de lo contrario sería
recursivo. Otro camino es recurrir directamente al lenguaje artificial que se presenta en la clase anterior, que
no pertenece a (ni siquiera pertenece a .
Una tercera alternativa es la diagonalización empleada en el caso anterior, con la que se encontró el lenguaje
separador entre y . Hay aún otra manera de probar que no todos los lenguajes son recursivamente
numerables, basada en la cardinalidad de los conjuntos infinitos: no puede haber más , y así lenguajes
recursivamente numerables, que ; la cantidad de lenguajes de es y como entonces
El caso aporta también un camino alternativo al del teorema del problema de la detención para probar que
. Claramente, el lenguaje acepta es recursivamente numerable, y como se vio que no es
recursivamente numerable, entonces se cumple que no es recursivo.
Otro lenguaje clásico de – es acepta . Claramente, el lenguaje es
recursivamente numerable, y no es recursivo porque de lo contrario el lenguaje sería recursivo (la prueba queda
como ejercicio). representa el problema de la pertenencia de una cadena a un lenguaje, o directamente el
problema de la pertenencia. Se lo conoce como lenguaje universal. En la clase siguiente se utilizara muy a
menudo para aplicar la técnica de reducción de problemas.
Al concluir con una apreciación sobre el significado de la indecidibilidad del problema de la detención,
generalizándola a todos los problemas indecidibles. Se ha demostrado la insolubilidad algorítmica del problema
general de la detención, es decir, se ha probado que no existe ninguna que lo resuelve sistemáticamente,
considerando las infinitas instancias . De todos modos ciertamente existe un algoritmo que resuelve
el problema cuando se considera una instancia particular uno que acepta o uno que rechaza. Para la
elección del algoritmo adecuado en cada caso habrá que apelar al ingenio, sin una técnica estándar en principio.
En otras palabras, un problema con una sola instancia siempre es decidible (obviamente nuestro interés radica en
los problemas con infinitas instancias).
Otro caso que ilustra esta dualidad de lo general y lo particular es el problema, ya mencionado, relacionado con
las ecuaciones diofánticas: dada una ecuación algebraica con distintas variables y coeficientes enteros, ¿existe una
solución con números enteros?
Dada la ecuación ¿existen valores enteros de que la resuelven? Se prueba que este
problema es indecidible. Por otro lado, ecuaciones diofánticas particulares son las que consideró P. de Fermat
cuando planteó su famoso teorema, conocido como último Teorema de Fermat, en el siglo XVII: dado , la
ecuación , siendo e mayores que , no tiene solución entera (Fermat no mostró la prueba del
92
teorema justificándose por lo pequeño del margen del libro en que lo publicó; el teorema se demostró recién en
1995). El problema de Fermat tiene una sola instancia, y como tal es decidible.
Un último caso de este tipo es el de la Conjetura de Goldbach, que establece que todo número natural par mayor
que 2 puede expresarse como la suma de dos números primos. Por tener una sola instancia, este problema es
decidible (al día de hoy sigue sin demostrarse). Naturalmente, y al igual que el problema de Fermat, la conjetura
de Goldbach se probaría fácilmente si el problema de la detención fuese decidible.
9.2 Reducción de problemas
Se completa el análisis de los problemas indecidibles, ahora con foco en la técnica de reducción de problemas,
que nos permitirá encontrar lenguajes no recursivos y no recursivamente numerables de una manera en general
mucho más sencilla que por medio de la diagonalización. Al considerar en su gran mayoría problemas
relacionados con . Al final, a partir de un teorema probado con una reducción de problemas, se presenta una
técnica que facilita aún más la demostración de la no recursividad, para un determinado tipo de lenguajes. La
noción de reducción de problemas es muy simple: para resolver un problema se lo relaciona con otro, que se sabe
cómo resolverlo; a partir de este conocimiento se resuelve el problema original.
Sean y dos lenguajes incluidos en . Existe una reducción del lenguaje al lenguaje , si y sólo si existe
una función total computable tal que La función se denomina
función de reducción. Que sea total computable significa, como se indicó previamente, que existe una que a
partir de cualquier cadena w computa en su cinta de salida y se detiene. En general, se identifica con a la
que computa . La figura 82 ilustra de reducción de problemas. Que haya una reducción de a significa,
entonces, que existe una que transforma toda cadena de en una cadena de , y toda cadena no
perteneciente a en una cadena no perteneciente a .
Figura 12. función se denomina función de reducción
*
1L
1w
2w
*
1L
1w
2w
f
f ( )
f ( )
Fuente: Autor
93
Se utiliza la notación para expresar que existe una reducción del lenguaje (o problema) al lenguaje (o
problema) .
El siguiente trabajo de investigación se aplica la reducción del problemas ya que se relaciona con un problema
clásico de la lógica, ya referido, y parte de un problema sobre cadenas de símbolos, también mencionado
previamente, que es el problema de correspondencia de Post (también conocido como ): dada una secuencia de
pares de cadenas de unos y ceros no vacías ¿existe una secuencia de índices con
, tal que las cadenas … y … sean iguales? Para los pares (1, 111), (10111, 10), (10, 0), se cumple que
(2, 1, 1, 3) es solución: en ambos casos se obtiene la cadena 101111110. En cambio, para los pares (10, 101),
(011, 11), (101, 011), se puede comprobar que no existe solución. Las soluciones pueden repetir índices; esto
significa que el espacio de búsqueda con el que se trata es infinito, lo que es un indicio de la indecidibilidad del
problema. Efectivamente, se prueba que existe una reducción de a PCP, por lo que PCP es indecidible. No se
construye esta reducción, sino que se utilizara PCP en otra reducción para probar, a continuación, que el problema
de la validez en la lógica de primer orden (también conocido como VAL) es indecidible.
Reducción de PCP a VAL. Sea es una fórmula válida de la lógica de primer orden}. Al construir
una reducción de a . Como no es recursivo, entonces se demuestra que tampoco lo es.
Dada una secuencia de pares de cadenas de unos y ceros no vacías , la función de reducción le
asignará a una fórmula de la lógica de primer orden válida si y sólo si tiene solución, en el sentido del
problema de correspondencia de Post.
Como símbolos de función se utiliza , de aridad 0 (es una constante), y y , de aridad 1. La idea es que
represente la cadena vacía, y y la concatenación, al final de una cadena, del dígito 0 o 1, respectivamente. De
este modo, la cadena de dígitos binarios se puede representar por el término , que para
facilitar la notación lo abreviaremos con (e).
Y como símbolo de predicado se utiliza , de aridad 2; el significado entendido para es que existe una
secuencia de índices , tal que el término s representa una cadena con subcadenas si de unos y ceros de la
forma , y el término representa una cadena con subcadenas de unos y ceros de la forma .
Definición de la función de reducción. La fórmula que se asigna, por la función de reducción a una secuencia
(sintácticamente correcta) de pares , es
con:
=
94
La función es total computable. Claramente, existe una que dada una secuencia sintácticamente
correcta genera la fórmula descripta previamente (en otro caso genera la cadena 1).
Se cumple . Se supone primero que es válida, lo que se denota con . Al probar
que tiene solución. Más específicamente, al encontrar un modelo para que establezca la existencia de una
secuencia de índices que soluciona .
El dominio de contiene todas las cadenas finitas de unos y ceros, incluyendo la cadena vacía . La
interpretación de e es , lo que se denota con . La interpretación de es la concatenación de un 0 al final
de una cadena, lo que se denota con . De la misma manera se define
Finalmente, la interpretación de es la siguiente: se cumple cuando existe una secuencia de índices
tal que y y son cadenas e unos y ceros de .
Como vale se cumple en particular . Claramente vale , porque se cumple para
. También vale , que establece que cuando el par está en , también lo está el par
, para Si , entonces existe una secuencia de índices , tal que y
. Definiendo una nueva secuencia de índices , vale si y = ti, por lo
que se cumple De esta manera, como se cumple por hipótesis y se ha demostrado
recién vale . Finalmente, y existe una solución para
Al suponer ahora que tiene solución, la secuencia de índices . Al probar que cualquiera sea el modelo ,
con una constante , dos funciones unarias y
, y un predicado binario , entonces satisface , es
decir . Dada la fórmula , se va a asumir y demostrar .
Para la interpretación de las cadenas finitas de unos y ceros en el dominio de se define inductivamente una
función denominada interpret, de la siguiente manera: interpret( ) = , interpret( ) = (interpret( )),
interpret( ) = (interpret(s)).
Por ejemplo, a la cadena 110 se le asigna
Más genéricamente, si una cadena s de dígitos
binarios tiene la forma , entonces interpret( ) =
( abreviado con
cómo se indico antes. Entonces, como vale , se cumple (interpret( ), (interpret( , para
. Como también vale , entonces para todo par se cumple (interpret( ), interpret( ))
95
, para . De esta manera, comenzando con si se considera repetidamente la última
observación se obtiene (interpret( ), interpret( , y dado que las cadenas y son
iguales porque es una solución de , entonces interpret( ) = interpret( ). De este modo se
cumple la fórmula y así .
Como una fórmula es insatisfactible si y sólo si su negación es válida, del caso anterior se desprende que el
lenguaje de las fórmulas satisfactibles de la lógica de primer orden también es indecidible (la prueba queda como
ejercicio). Lo mismo sucede con el lenguaje de los teoremas, porque por la sensatez y completitud de la lógica de
primer orden dicho lenguaje coincide con el de las fórmulas válidas. Por otra parte, el lenguaje de los teoremas (y
de las fórmulas válidas) es recursivamente numerable: a partir de axiomas y reglas de inferencia se puede
construir fácilmente una que lo reconoce (la prueba queda como ejercicio).
La indecidibilidad en la lógica de primer orden contrasta con la decidibilidad en la lógica proposicional, en la que
la satisfactibilidad y validez de las fórmulas se determinan mediante las tablas de verdad.
Por su parte, mientras el lenguaje de los teoremas de la teoría de números es recursivamente numerable, el de las
fórmulas verdaderas no lo es: por el Teorema de Incompletitud de Gödel, toda teoría recursiva y consistente que
contenga “suficiente” aritmética es incompleta. En particular, la indecidibilidad en la teoría de números se puede
probar mediante una reducción a partir del problema de pertenencia de la cadena vacía en un lenguaje
recursivamente numerable, que se demuestra es indecidible. La idea de la reducción es la siguiente. El lenguaje de
la teoría de números, si cuenta con las operaciones de suma y multiplicación (“suficiente” aritmética o
expresividad), como es el caso de la aritmética de Peano, permite expresar las configuraciones y computaciones
de las mediante números. Si una acepta , lo hace con una computación en la que ninguna
configuración mide, naturalmente, más que un número determinado . La reducción asigna entonces a cada
código una fórmula , que es verdadera si y sólo si representa una computación de que
acepta con configuraciones que no miden más que
Máquinas de turing restringidas. Los lenguajes regulares, libres de contexto y sensibles al contexto, se pueden
reconocer por restringidas en lo que hace a su poder computacional comparado con el de las sin
restricciones. Se analiza a continuación con cierto detalle.
Un autómata finito (abreviado con ) es una que tiene una sola cinta, la cinta de entrada, que es de sólo
lectura, y sobre la cual el cabezal se mueve solamente a la derecha desde el primer símbolo de la entrada. Cuando
el cabezal lee un blanco se detiene (acepta si y sólo si se detiene en un estado final). De este modo, los no
tienen memoria, salvo la que pueden proveer los estados. No existe un alfabeto dado que la única cinta es de
sólo lectura. Por lo tanto, la función de transición está compuesta por ternas del conjunto .
96
El autómata finito constituye un tipo de algoritmo ampliamente utilizado. Dos aplicaciones clásicas se relacionan
con la implementación del analizador lexicográfico de los compiladores, y la verificación automática de
programas utilizando modelos de transición de estados y lógica temporal (lo que se conoce como model
checking). Dado un , existe una gramática regular tal que Y dada una gramática regular ,
existe un tal que En otras palabras, el poder computacional de los alcanza para reconocer
todos los lenguajes regulares y sólo ellos.
97
ANEXO 10. Ordenamiento y búsqueda
Aunque el lenguaje común en ocasiones es adecuado para especificar un algoritmo, la mayoría de los matemáticos
y los especialistas en ciencias de la computación prefieren el seudocódigo por su precisión, estructura y
universalidad. El seudocódigo recibe este nombre porque se parece a un código real en lenguaje de computadora,
como C++ y Java. A diferencia de los lenguajes para computadora que deben preocuparse por puntos y comas,
mayúsculas y minúsculas, palabras reservadas y otros elementos, cualquier versión de seudocódigo es aceptable
siempre y cuando sus instrucciones no sean ambiguas. Nuestro seudocódigo se describe con operaciones y
funciones booleanas que representan identifica el lenguaje de la computadora con el cual el algoritmo funcionara
y se ejecuta directamente sobre la máquina de Turing.
Los algoritmos consisten en un título, una breve descripción del algoritmo, la entrada y la salida del algoritmo, y
las funciones que contienen las instrucciones del algoritmo. El algoritmo consta de una sola función. Para hacer
más conveniente la referencia a las líneas individuales dentro de una función, en ocasiones se numeran algunas de
ellas. La función del algoritmo en menor número de líneas numeradas.
Los algoritmos tienen las siguientes características:
a. Entrada. El algoritmo recibe datos de entrada.
b. Salida. El algoritmo produce una salida.
c. Precisión. Los pasos se establecen con precisión.
d. Determinismo. Los resultados intermedios de cada paso de ejecución son únicos y están determinados
sólo por las entradas y los resultados de los pasos anteriores.
e. Carácter finito. El algoritmo termina; es decir, se detiene después de ejecutar un número finito de
instrucciones.
f. Corrección La salida producida por el algoritmo es correcta; es decir, el algoritmo resuelve el
problema sin errores.
g. Generalidad El algoritmo se aplica a un conjunto de entradas.
Un programa de computadora, aun cuando se derive de un algoritmo correcto, puede ser inútil para cierto tipo de
entrada ya sea porque el tiempo necesario para correrlo o el espacio requerido para almacenar los datos, las
variables del programa, etcétera, son demasiado grandes. El análisis de un algoritmo se refiere al proceso de
derivar estimaciones del tiempo y el espacio necesarios para ejecutarlo. El problema de estimar el tiempo
requerido para ejecutar el algoritmo dependerá del lenguaje con el cual se esté operando, y en este caso es código
es binario.
98
En particular en el diseño y verificación del algoritmo, la lógica satisfactibilidad y otras propiedades de una
fórmula proposicional a veces se decidió sobre la base de una representación de la fórmula como un diagrama de
decisión binario . La satisfactibilidad proposicional tiene varias generalizaciones,
incluyendo satisfactibilidad al problema de la fórmula booleana cuantificados para la lógica clásica de primer y
segundo orden ( y , respectivamente), a los problemas de la satisfacción de las limitaciones para la
programación de enteros y el problema de la satisfactibilidad máximo. Muchos otros problemas de la
decisión, como los problemas de planificación y programación de problemas, pueden ser codificados en .
Suponga que se tiene un conjunto de trabajos, algunos etiquetados con “1” y otros etiquetados con “0”, y se
quiere encontrar el número de subconjuntos de que contienen al menos un trabajo “1”. Se construye un
algoritmo que examina todos los subconjuntos de y cuenta los que contienen al menos un trabajo “1” y después
se implementa este algoritmo como una secuencia en la máquina de Turing. Como un conjunto que tiene
elementos tiene subconjuntos, el programa requerirá al menos unidades de tiempo para la ejecución. No
importa cuáles sean esas unidades de tiempo, crece con tanta rapidez cuando se incrementa que, excepto por
los valores pequeños de , sería impráctico correr el programa.
Se planteara un algoritmos para ordenar, es decir, acomodar en orden los elementos de un conjunto. El problema
de ordenar un conjunto de objetos fue uno de los primeros problemas que se analizaron intensamente en las
ciencias de la computación. Muchas de las aplicaciones más conocidas del paradigma de diseño de algoritmos
Divide y Vencerás son algoritmos de ordenamiento. Durante los años sesenta, cuando el procesamiento comercial
de datos se automatizó en gran escala, el programa de ordenamiento era el que se ejecutaba con mayor frecuencia
en muchas instalaciones de cómputo. Una compañía de software se mantuvo operando durante años gracias a que
tenía un programa de ordenamiento mejor. Con el hardware actual, los aspectos de desempeño del ordenamiento
han cambiado un poco. En los años sesenta, la transferencia de datos entre almacenamiento lento (cinta o disco) y
la memoria principal era un importante cuello de botella del desempeño. La memoria principal era del orden de
100,000 bytes y los archivos a procesar eran varios órdenes de magnitud mayores. La atención se concentraba en
los algoritmos para efectuar este tipo de ordenamiento. Hoy, las memorias principales 1,000 veces mayores (o sea,
de 100 megabytes) son cosa común, y las hay 10,000 veces mayores (de unos cuantos gigabytes), de modo que la
mayor parte de los archivos cabe en la memoria principal.
Hay varias razones de peso para aplicar los algoritmos de ordenamiento. La primera es que tienen utilidad práctica
para el ordenamiento de los trabajo en la planta de producción una vez se estén seleccionando aquellas que
satisfagan las expresiones lógicas en cada nivel. El trabajo con conjuntos grandes de datos en las computadoras
(en nuestro caso MT máquina de Turing) se facilita si los datos están ordenados. La segunda es que se han ideado
99
una buena cantidad de algoritmos para ordenar (más de los que se cubren aquí), y nos convencerá del hecho de
que es posible enfocar un problema dado desde muchos puntos de vista distintos. El tratamiento de los algoritmos
suministrara algunas ideas acerca de cómo se puede mejorar un algoritmo dado y cómo escoger entre varios
algoritmos. La tercera es que el ordenamiento es uno de los pocos problemas para los que es fácil deducir cotas
inferiores firmes del comportamiento en el peor caso y en el caso promedio. Las cotas son firmes en el sentido de
que existen algoritmos que efectúan aproximadamente la cantidad mínima de trabajo especificada. Por ello, se
tienen algoritmos de ordenamiento prácticamente óptimos.
Al describir la mayor parte de los algoritmos, se supone que el conjunto a ordenar está almacenado en forma de
arreglo, de modo que se pueda acceder en cualquier momento a un elemento en cualquier posición; esto se
denomina acceso aleatorio. Si el acceso al conjunto es exclusivamente secuencial, se emplea el término sucesión
para hacer hincapié en que la estructura podría ser una lista ligada o un archivo secuencial, no sólo un arreglo. Se
define un arreglo dentro del intervalo de índices , un intervalo o subintervalo de ese arreglo será una
sucesión continua de elementos que está entre dos índices dados, primero y último, tales que 0 primero y
ultimo . Si ultimo primero, se dice que el intervalo está vacío.
Al suponer que cada elemento del conjunto a ordenar contiene un identificador, llamado clave, que es un elemento
de algún conjunto linealmente ordenado y que es posible comparar dos claves para determinar cuál es mayor o
que son iguales. Siempre se ordenan las claves en orden no decreciente. Cada elemento del conjunto podría
contener otra información además de la clave.
Si las claves se reacomodan durante el proceso de ordenamiento, la información asociada también se reacomodará
de manera acorde, pero a veces sólo se hablara de las claves sin mencionar explícitamente el resto del elemento.
Todos los algoritmos que consideraremos pertenecen a la clase de algoritmos de ordenamiento que podrían
comparar claves (y copiarlas) pero no deben aplicar otras operaciones a las claves. Estos son “algoritmos que
ordenan comparando claves”, o “algoritmos basados en comparación”. La medida primordial del trabajo que se
usa para analizar algoritmos de esta clase es el número de comparaciones de claves. Se establecen cotas inferiores
para el número de comparaciones que efectúa este tipo de algoritmos. Se tratan algoritmos de ordenamiento que
pueden efectuar operaciones distintas de la comparación de claves, y para los cuales son apropiadas otras medidas
del trabajo.
Los algoritmos de esta metodología se denominan ordenamientos internos porque se supone que los datos están
en la memoria de acceso aleatorio de alta velocidad de la computadora. Surgen diferentes aspectos de desempeño
cuando se desea ordenar conjuntos de datos tan grandes que no caben en la memoria. Los algoritmos para ordenar
100
grandes conjuntos de datos almacenados en dispositivos de almacenamiento externos más lentos, con restricciones
sobre la forma de acceder a los datos, se denominan ordenamientos externos. (John, 2008)
Al analizar algoritmos de ordenamiento, se considera qué tanto espacio adicional emplean (además del que
ocupan las entradas). Si la cantidad de espacio extra es constante con respecto al tamaño de las entradas, se
expresa que el algoritmo opera en su lugar.
A fin de que los algoritmos sean lo más claros posible, se usa Elemento y Clave como identificadores de tipo,
pero se tratara a Clave como un tipo numérico en cuanto a que usaran los operadores relacionales “ etc. Si
aparece una expresión de comparación de claves, como “E[i].clave,x” ,y los tipos reales no son numéricos
(String, por ejemplo), la sintaxis de Java requerirá una invocación de método, como “menor(E[i].clave, )”.
Esto también es necesario en muchos otros lenguajes.
Detalle de Java: Empleando la interfaz Comparable de Java, es posible escribir un procedimiento capaz de
comparar una amplia variedad de tipos de claves. El nombre de tipo Clave se sustituiría por la palabra reservada
Comparable. Un arreglo con elementos de tipo Elemento se declara como Elemento[] nombreArreglo; en
Java.
10.1 Ordenamiento por inserción.
Ordenamiento por inserción es un buen algoritmo de ordenamiento para comenzar porque la idea en la que se basa
es natural y general, sus análisis de peor caso y comportamiento promedio son fáciles de efectuar. También se usa
como parte de un algoritmo de ordenamiento más rápido.
La estrategia. Se parte de la sucesión de elementos en orden arbitrario (Ordenamiento por inserción se puede
usar con claves de cualquier conjunto ordenado linealmente, pero en el caso de las ilustraciones de palitos se
puede pensar que las claves son las alturas de los palitos, que son los elementos). La sucesión está establecida
como el lenguaje que ingresa en la a través de la cinta.
El procesamiento de cada trabajo es una medida normal en función del tiempo de terminación en el programa, en
la que se busca que sea el mínimo. Supongo que se ha ordenado algún segmento inicial de la sucesión. La figura
90 muestra una instantánea de la sucesión una vez que se han ordenado los cinco elementos del extremo
izquierdo. El paso general consiste en incrementar la longitud del segmento ordenado insertando el siguiente
elemento en el lugar correcto.
101
Sea el siguiente elemento a insertar en el segmento ordenado, es decir, es al elemento de la extrema izquierda
del segmento que todavía no se examina. Primero “se hace a un lado” a (es decir, se copia en una variable
local), dejando una vacante en su antigua posición. Luego se compara repetidamente con el elemento que está
inmediatamente a la izquierda de la vacante y, mientras sea menor, se pasara ese elemento a la vacante, dejando
una vacante en el lugar donde estaba; es decir, la vacante se desplaza una posición hacia la izquierda. Este proceso
se detiene cuando se acaban los elementos a la izquierda de la vacante actual, o cuando el elemento que está a la
izquierda de la vacante actual es menor o igual que .
En ese momento, se inserta en la vacante, como se muestra en la figura 90. Para poner en marcha el algoritmo,
basta con observar que el primer elemento sólo se puede considerar como un segmento ordenado. Al formalizar
esto para tener un procedimiento, se supone que la sucesión es un arreglo; sin embargo, la idea funciona también
con listas y otras estructuras secuenciales.
Figura 13. Inserción de en el orden correcto
Elementos en desorden
Ordenados Sin examinar
Insercion de x en el orden correctox =
Fuente: Autor
int desplaVac(Elemento[] E, int vacante, Clave x)
Condición previa: vacante no es negativa.
Condiciones posteriores: Sea posX el valor devuelto al invocador. Entonces:
102
1. Los elementos de cuyos índices son menores que posX están en sus posiciones originales y sus claves
son menores o iguales que .
2. Los elementos de que están en las posiciones posX+1, . . . , vacante son mayores que y se
desplazaron una posición a la izquierda respecto a la posición que ocupaban cuando se invocó
desplaVac.
El algoritmo y su análisis. Ahora se presenta los pormenores del procedimiento para ordenar. La tarea de la
subrutina desplaVac( , vacante, ) es desplazar elementos hasta que la vacante esté en la posición correcta para
colocar entre los elementos ordenados. El procedimiento devuelve el índice de la vacante, digamos posX, al
invocador. Las condiciones previas y posteriores se plantean en la figura 90. En otras palabras, desplaVac efectúa
la transición de la figura 90. Ahora ordenInsercion sólo tiene que invocar repetidamente a desplaVac,
formando un segmento ordenado cada vez más largo en el extremo izquierdo, hasta que todos los elementos estén
en ese segmento.
El procedimiento desplaVac adopta la forma representativa de las rutinas de búsqueda generalizada. Si no hay
más datos que examinar, fracasar; si hay más datos, examinar uno, y si es el que se está buscando, tener éxito; en
caso contrario, continuar con los datos no examinados. Puesto que hay dos casos para terminar, no sería
conveniente usar un ciclo while, a menos que se usara un break con uno o más de los casos para terminar. La
formulación recursiva es sencilla.
int desplaVacRec(Elemento[] E, int vacante, Clave x)
int posX;
1. if (vacante 0)
2. posX vacante;
3. else if (E[vacante1].clave x)
4. posX vacante;
5. else
6. E[vacante] E[vacante1];
7. posX desplaVacRec(E, vacante1, x);
8. return posX;
Para verificar que se está usando recursión correctamente en la línea 7, se observa que la invocación recursiva
está operando con un intervalo más pequeño, y que su segundo argumento no es negativo, con lo que se satisface
la condición previa (¿Verificar la cadena de razonamiento que nos dice que vacante-1 no es negativa; ¿por qué
no puede ser negativa?) Ahora es sencillo demostrar la corrección al recordar que se puede suponer que la
invocación recursiva de la línea 7 logra su objetivo.
103
Aunque el procedimiento para desplaVacRec es muy sencillo, si al visualizar el rastreo de activación para el -
ésimo elemento de a insertar, se da cuenta que la profundidad de la recursión, o la pila de marcos, podría crecer
hasta un tamaño . Esto podría ser indeseable si es grande. Por tanto, éste es un caso en que conviene convertir
la recursión en una iteración, una vez que se haya constatado que todo funciona correctamente. (Tratar de optimar
un programa que no funciona ciertamente sería útil.) El objetivo no es tanto ahorrar tiempo como ahorrar espacio.
En realidad muchos compiladores, si se les pide optimar a desplaVacRec, efectuarán la transformación
automáticamente. El algoritmo completo que sigue incluye la versión de desplaVac codificada iterativamente.
Ordenamiento por inserción.
Entradas: , un arreglo de elementos, y , el número de elementos. El intervalo de los índices es
Salidas: , con los elementos en orden no decreciente según sus claves.
Comentario: Las especificaciones de la subrutina desplaVac se da a continuación:
void ordenInsercion(Elemento[] E, int n)
int indicex;
for (indicex 1; indicex n; indicex )
Elemento actual E[indicex];
Clave x actual.clave;
int posX desplaVac(E, indicex, x);
E[posX] actual;
return;
int desplaVac(Elemento[] E, int indicex, Clave x)
int vacante, posX;
vacante indicex;
posX 0; // Suponemos fracaso.
while (vacante 0)
if (E[vacante1].clave x)
posX vacante; // Éxito.
break;
E[vacante] E[vacante1];
vacante ––; // Seguir buscando.
return posX;
Complejidad de peor caso. Para el análisis, se usa en lugar de índicex. Para cada valor de , el número
máximo de comparaciones que pueden efectuarse (en una invocación de la rutina iterativa desplaVac o en una
invocación de nivel más alto de la rutina recursiva desplaVacRec) es Por tanto, el total es
104
Se ha establecido una cota superior para el comportamiento de peor caso; hay que pensar un momento para
verificar que en verdad existen entradas con las que se efectúan comparaciones. Uno de esos peores
casos es cuando las claves están en orden inverso (es decir, decreciente). Así,
Comportamiento promedio. Al suponer que todas las permutaciones de las claves son entradas igualmente
verosímiles. Primero se determina cuántas comparaciones de claves se efectúan en promedio para insertar un
elemento nuevo en el segmento ordenado, es decir, en una invocación de desplaVac con cualquier valor
específico de (que se usa en vez de índicex). Para simplificar el análisis, se supone que todas las claves son
distintas.
Hay posiciones en las que puede colocarse . La figura muestra cuántas comparaciones se efectúan
dependiendo de la posición. La probabilidad de que vaya en cualquier posición específica es . (Esto
depende del hecho de que el algoritmo todavía no ha examinado a . Si el algoritmo hubiera tomado antes alguna
decisión con base en el valor de , no se podría suponer por fuerza que es uniformemente aleatorio con respecto
a las primeras claves.) Así pues, el número medio de comparaciones que se efectúan en desplaVac para
encontrar la posición del -ésimo elemento es
Ahora se obtiene la sumatoria para las inserciones:
donde se sustituye para obtener la última sumatoria. Ya vimos, por la ecuación que , se
puede incorporar el 1 que está antes de la sumatoria para hacer que el límite inferior . Olvidándonos de los
términos de orden inferior, tenemos:
Es evidente que Ordenamiento por inserción es un ordenamiento en su lugar si se usa la versión iterativa de
desplaVac. Con la versión recursiva, la pila de marcos puede crecer hasta
105
Cotas inferiores para el comportamiento de ciertos algoritmos de ordenamiento. Al pensar que el elemento
cuya clave es el cual ocupa la posición “vacante” del arreglo, mientras Ordenamiento por inserción compara
con la clave que está a su izquierda. Entonces, después de cada comparación, Ordenamiento por inserción no
cambiará de lugar ningún elemento o simplemente intercambiará dos elementos adyacentes. Se demuestra que
todos los algoritmos de ordenamiento que efectúan semejante traslado “local” limitado de elementos, después de
cada comparación, deben efectuar aproximadamente la misma cantidad de trabajo que Ordenamiento por
inserción. (Pinedo, 1995)
Una permutación de elementos se puede describir con una función uno a uno del conjunto sobre
sí mismo. Existen permutaciones distintas de elementos. Sean los elementos de la sucesión no
ordenada . A fin de simplificar la notación en este análisis, supóngase que los elementos a ordenar están en las
posiciones de no en . Existe una permutación tal que, para 1 es la posición
correcta de una vez que la sucesión está ordenada. Sin perder generalidad, se puede suponer que las claves son
los enteros , ya que se puede usar 1 en lugar de la clave más pequeña, 2 en lugar de la clave más pequeña
de las restantes y así sucesivamente, sin tener que modificar las instrucciones ejecutadas por el algoritmo.
Entonces, la entrada sin ordenar es Al considerar la sucesión de entrada
implica que la primera clave, 2, debe ir en la segunda posición, lo cual es obvio. π (2) = 4 porque la segunda clave,
4, debe ir en la cuarta posición, y así sucesivamente. Identificar la permutación con la sucesión
Una inversión de la permutación es un par tal que y . Si es una inversión,
las claves -ésima y -ésima de la sucesión están en desorden una respecto a la otra. La permutación 2, 4, 1, 5, 3
tiene cuatro inversiones: (2, 1), (4, 1), (4, 3) y (5, 3). Si un algoritmo de ordenamiento elimina cuando más una
inversión después de cada comparación de claves (al intercambiar elementos adyacentes, como hace
ordenamiento por inserción), entonces el número de comparaciones efectuadas con la entrada
será por lo menos el número de inversiones de . Por ello, se investigaran las inversiones.
Es fácil demostrar que existe una permutación con inversiones. (¿Cuál permutación?) Por tanto, el
comportamiento de peor caso de cualquier algoritmo de ordenamiento que elimina cuando más una inversión en
cada comparación de claves deberá estar en .
Para obtener una cota inferior del número medio de comparaciones efectuadas por tales algoritmos de
ordenamiento, se calcula el número medio de inversiones que hay en las permutaciones. Cada permutación se
puede aparear con su permutación transpuesta
106
La transpuesta de 2, 4, 1, 5, 3 es 3, 5, 1, 4, 2. Cada permutación tiene una transpuesta única y es distinta de su
transpuesta (para ). Sean y enteros entre 1 y , y supóngase que . Entonces es una inversión en
una y sólo una de las permutaciones y transpuesta de . Existen pares de enteros semejantes. Por
tanto, cada par de permutaciones tiene permutaciones en conjunto, y por ende un promedio de
Así, en total, el número medio de inversiones que hay en una permutación es de se ha
demostrado el teorema siguiente. Ver anexo Teorema 15.
Puesto que ordenamiento por inserción efectúa comparaciones de claves en el peor caso y
aproximadamente en promedio, es prácticamente lo mejor que se pueden lograr con cualquier algoritmo que
opere “localmente”, intercambiando sólo elementos adyacentes. Desde luego, a estas alturas no es obvio que
alguna otra estrategia pueda funcionar mejor, pero si existen algoritmos significativamente más rápidos deberán
trasladar elementos más de una posición a la vez. (Sara Baase, 2002)
10.2 Divide y vencerás.
El principio en que se basa el paradigma de diseño de algoritmos divide y vencerás es que (a menudo) es más fácil
resolver varios casos pequeños de un problema que uno grande. Los algoritmos emplean el enfoque de Divide y
vencerás: dividen el problema en ejemplares más pequeños del mismo problema (en este caso, conjuntos más
pequeños a ordenar), luego resuelven (vencen) los ejemplares más pequeños de forma recursiva (o sea, empleando
el mismo método) y por último combinan las soluciones para obtener la solución correspondiente a la entrada
original. Para escapar de la recursión, al resolver directamente algunos casos pequeños del problema. En
contraste, Ordenamiento por inserción se limitó a “recortar” un elemento para crear un subproblema. (Cormen &
Leiserson, 2010)
Al ver un caso excelente de divide y vencerás: busqueda binaria. El problema principal se dividió en dos
subproblemas, uno de los cuales ni siquiera se tenía que resolver. En general, se puede describir divide y vencerás
con el esqueleto de procedimiento de la algoritmo descrito a en la figura 91.
Para diseñar un algoritmo de divide y vencerás específico, se debe especificar las subrutinas
resolverDirectamente, dividir y combinar. El número de casos más pequeños en los que se divide la entrada es
Con una entrada de tamaño sea el número de pasos efectuados por resolverDirectamente, sea el
número de pasos efectuados por dividir, y sea el número de pasos efectuados por combinar. Entonces, la
forma general de la ecuación de recurrencia que describe la cantidad de trabajo efectuada por el algoritmo es
107
para pequeño
Figura 14. El esqueleto de divide y vencerás
resolver(I)
n tamaño(I);
if (n pequeño)
solucion resolverDirectamente(I);
else
dividir en .
para cada
resolver( );
solucion combinar( , . . . , );
return solucion;
El esqueleto de divide y vencerás con los casos base para pequeño. En muchos algoritmos
divide y vencerás, el paso de dividir o bien el paso de combinar es muy sencillo, y la ecuación de recurrencia
para es más simple que la forma general. El teorema maestro da soluciones para una amplia gama de ecuaciones
de recurrencia de divide y vencerás.
Quicksort y Mergesort, los algoritmos de ordenamiento, difieren en la forma en que dividen el problema y luego
combinan las soluciones, o subconjuntos ordenados. Quicksort se caracteriza como “división difícil, combinación
fácil”, mientras que Mergesort se caracteriza como “división fácil, combinación difícil”. Fuera del procesamiento
que requieren las invocaciones de procedimientos, se vera que el “trabajo real” se efectúa en la sección “difícil”.
Ambos procedimientos de ordenamiento tienen subrutinas para realizar su sección “difícil”, y tales subrutinas son
útiles por derecho propio. En el caso de Quicksort, el “caballito de batalla” es partir, y es el paso dividir del
esqueleto general; el paso combinar no hace nada. En el caso de Mergesort, el “caballito de batalla” es fusionar, y
es el paso combinar; el paso dividir sólo efectúa un cálculo sencillo. Ambos algoritmos dividen el problema en
dos subproblemas. Sin embargo, en Mergesort los problemas son de tamaño comparable (más o menos un
elemento), mientras que en Quicksort no se garantiza una división pareja. Esta diferencia da pie a características
de desempeño muy distintas, que se descubrira durante el análisis de los respectivos algoritmos. (Sara Baase,
2002). En el nivel más alto, HeapSort no es un algoritmo divide y vencerás, pero usa operaciones de montón que
pertenecen a la categoría Divide y vencerás. La forma acelerada de Heapsort emplea un algoritmo Divide y
vencerás más avanzado. (John, 2008)
En las limitaciones de la investigación reaparecera en una forma un poco distinta para la computación en paralelo.
108
ANEXO 11. Sistemas Secuenciales Biestables
Biestable con reloj. El biestable básico, tal como esta, es un sistema secuencial asíncrono. Por la adición de
compuertas a las entradas del sistema básico, puede haberse que el biestable responda a niveles de entrada durante
la ocurrencia de un pulso de reloj. EL biestable RS con reloj que se muestra en la figura 51 consta de un biestable
básico NOR y dos compuertas . Las salidas de las dos compuertas permanecen en 0 en tanto que el pulso de
reloj (agreviado , de las iniciales en ingles de clock pulse) sea 0, sin importar los valores de entrada y .
Cuando el pulso de reloj va a 1, se permite que la información de las entradas alcancen al biestable básico.
El estado de ajuste se alcanza con . Para cambiara al estado despejado, las entradas deben
ser . Tanto con la ocurrencia de un pulso de reloj provoca que ambas salidas
momentáneamente a 0. Cuando se elimina el pulso, el estado del biestable es indeterminado, esto es, puede
resultar cualquier estado, dependiendo de si la entrada de ajuste o la de restaurar del sistema biestable básico
permanezca en 1 durante un tiempo más prolongado antes de la transmisión a 0 al fin del pulso.
El símbolo grafico para el biestable S con reloj se muestra en la figura 51. Tiene tres entradas: . La
entrada no está indicada dentro de la caja, debido a que se reconoce por el triangulo pequeño marcado. El
triangulo es un símbolo para un indicador dinámico y denota el hecho de que el biestable responde a una
transición de reloj en una señal bajo nivel (binario 0) a un alto nivel (binario 1).
La salida del biestable están marcadas con y dentro de la caja. Pueden asignarse al biestable una variable con
nombre diferente aunque este escrita dentro de la caja. En ese caso, la letra que se elige para la variable del
biestable se marca fuera de la caja junto a la línea de salida. El estado del biestable está determinado por el valor
de su salida normal . Si se desea obtener el complemento de la salida normal, no es necesario insertar un
inventor, ya que el valor complementado está disponible directamente mediante la salida .
Figura 15. (Árbol sintáctico) Biestable con pulso de reloj
&0
0
0
&0
0
0
R
S
Q
Q'
&0
0
0
0
&0
0
0
0
CP
Fuente: Autor
109
La tabla característica para el biestable se muestra en la figura. En esta tabla se resume la operación del biestable
en una forma tabular. es el estado binario del biestable en un momento dado (referido como estado presente),
las columnas y dan los valores posibles de las entradas es el estado del biestable después de la
ocurrencia de un pulso de reloj (referida como estado siguiente).
La ecuación característica del biestable se deriva en el mapa. Esta ecuación especifica el valor del estado siguiente
como una función del estado presente y las entradas. La ecuación característica es una expresión algebraica para
la información binaria de la tabla característica. Los dos estados indeterminados están marcados con en el mapa,
ya que pueden resultar en 1 o bien en 0. Sin embargo, la relación debe incluirse como parte de la ecuación
característica para especificar que tanto como no pueden ser iguales a 1 en forma simultánea.
Biestable . El biestable que se muestra en la figura 52 es una modificación del biestable con reloj. Las
compuertas 1 y 2 forman un biestable básico y las compuertas 3 y 4 modifican para formar un biestable con
reloj. La entrada va en forma directa a la entrada , y su complemento, a través de la compuerta 5, se aplica a la
entrada . En tanto que el pulso de reloj en la entrada este en 0, las compuertas 3 y 4 tienen un 1 en sus salidas,
sin importar el valor de las otras entradas. Esto se apega al requisito de que las dos entradas de un biestable básico
permanezcan inicialmente en el nivel 1. La salida se muestra durante la ocurrencia de un pulso de reloj. Si el
1, la salida de la compuerta 3 pasa a 0, cambiando el biestable al estado de ajuste (a menos que ya este puesto ), si
es 0, la salida de la compuerta 4 va a 0, cambiando el biestable al estado despejado.
El biestable recibe su denominación debido a su capacidad de transferir datos en el biestable. En forma básica
es un biestable con un inversor en la salida . El inversor agregado reduce el número de entradas de dos a una.
Este tipo de biestable algunas veces se denomina un seguro –D con compuertas. La entrada con frecuencia
recibe designación variable (de la inicial en ingles de compuertas, es decir gate) para indicar que esta entrada
habilita el seguro con compuertas para hacer posible la entrada de información dentro del biestable.
El símbolo para un biestable temporizado se muestra en la figura 52. La tabla característica se lista en la parte
y se deriva la ecuación características en la parte d. La ecuación característica muestra el estado siguiente del
biestable es el mismo de la entrada y es independiente del valor del estado presente.
Figura 16. (Árbol sintáctico) Biestable con pulso de reloj
110
&0
0
0
&0
0
0
D
Q
Q'
&0
0
0
&0
0
0
C
Fuente: Autor
Biestable . Un biestable es un refinamiento del biestable ya que el estado indeterminado del tipo se
define ene el tipo . Las entradas y se comportan como las entradas y para ajustar y despejar el biestable
(obsérvese que en un biestable , la letra es para ajustar y la letra es para el despeje). Cuando se aplican
señales de entrada en forma simultánea a como , el biestable cambia a su estado complementario, esto es, si
cambia a y viceversa.
Un biestable temporizado se muestra en la figura 53. La salida opera con las entradas y de modo que
el biestable se despeja durante un pulso de reloj solo si era previamente 1. En forma similar, la salida opera
con las entradas y de modo que el biestable se ajusta con un pulso de reloj solo si era previamente 1.
Como se muestra en la tabla característica en la figura el biestable se comporta como un biestable excepto
cuando tanto como son iguales a 1. Cuando y son 1, el pulso de reloj se transmite solo a través de una
compuerta (la que tenga conectada su entrada a la salida del biestable que al presente sea igual a 1).
Por tanto, si la salida de la compuerta superior llega a ser 1 bajo la aplicación de un pulso de reloj, y el
biestable se despeja. Si , la salida de la compuerta inferior llega a ser un 1 y el biestable se ajusta. En
cualquier caso, el estado de la salida del biestable se complementa.
Las entradas en el símbolo grafico para el biestable deben marcarse con una (bajo ) y (bajo ). La
ecuación característica se da en la figura y se deriva mediante el mapa de la tabla característica.
Obsérvese que debido a la conexión de retroalimentación en el biestable , una señal que permanece en 1 (en
tanto ) una vez que las salidas se han complementado provocara transiciones repetidas y continuas de las
salidas. Para evitar esta operación indeseable, los pulsos de reloj deben tener una dirección más corta que el
111
retardo de propagación a través del biestable. Este es un requisito de restricción, ya que la operación del sistema
depende del ancho de los pulsos. Por esta razón, los biestable nunca se construyen como se muestra en la
figura. La restricción en el ancho del pulso puede eliminarse con una construcción de maestro-esclavo o de
disparo en borde. El mismo razonamiento se aplica al biestable que se presenta a continuación.
Figura 17. (Árbol sintáctico) Biestable con pulso de reloj
>=10
0
0
>=10
0
0
KQ
Q'
&0
0
0 0
&0
0
0 0
C
K
0
0
Fuente: Autor
Biestable . El biestable es una versión de una sola entrada del biestable . Como se muestra en la figura 54,
el biestable se obtiene mediante un tipo si ambas entradas se ligan. La denominación proviene de la
capacidad del biestable para conmutar (de la inicial del término ingles: toggle), o cambiar de estado. Sin importar
el estado presente del biestable, asume el estado complementario cuando ocurre el pulso de reloj mientras la
entrada es lógica 1. El símbolo, la tabla característica y la ecuación característica del biestable se muestra en
la figura, respectivamente.
Figura 18. (Árbol sintáctico) Biestable con pulso de reloj
112
>=10
0
0
>=10
0
0
Q
Q'
&0
0
0 0
&0
0
0 0
0
0
Fuente: Autor
Los biestable que se introducen los tipos disponibles más comunes en el comercio. Los procedimientos de análisis
y diseño que se desarrollan en este apartado son aplicables para cualquier biestable temporizado una vez que se
define su tabla característica.
Disparo del biestable. El estado de un biestable se cambia por una modificación momentánea en la señal de
entrada. Este cambio momentáneo se denomina gatillo y la transición que provoca se dice que dispara al biestable.
Los biestable asincrónicos, como los sistemas lógicos básicos, requieren una entrada de gatillo definida por un
cambio de nivel de señal. Este nivel debe volver a su valor inicial (0 en el biestable NOR y 1 en el ) antes de que
aplique un segundo gatillo. Los biestables temporizados se disparan por pulsos. Un pulso comienza desde un valor
inicial de 0, pasa en forma momentánea a 1 y después de un corto tiempo, regresa a su valor inicial de 0, pasa en
forma momentánea a 1 y después de un corto tiempo, regresa a su valor 0 inicial. El intervalo de tiempo desde la
aplicación del pulso hasta que ocurre la transición de la salida es un factor crítico que requiere más investigación.
Como se observo en el diagrama de bloques en la figura 54, un sistema secuencial tiene una trayectoria de
retroalimentación entre el sistema combinacional y los elementos de memoria. Esta trayectoria puede producir
inestabilidad y las salidas de los elementos de memoria (biestables) se cambian, mientras las salidas del sistema
combinacional que van a las entradas de los biestables se muestran por el pulso de reloj. Este problema de
temporizado puede evitarse si las salidas de los biestables no inician el cambio sino hasta que el pulso de entrada
ha regresado a 0. Para asegurar tal operación, un biestable debe tener un retardo de propagación de señal desde la
entrada a la salida que exceda la duración del pulso. Este retardo por lo común es muy difícil de controlar so el
diseñador depende por completo del retardo de propagación de las compuertas lógicas. Una forma de asegurar el
retardo apropiado es incluir dentro del sistema biestable una unidad de retardo física que tenga un retardo igual o
113
mayor que la duración del pulso. Una manera adecuada de resolver el problema del temporizado de la
retroalimentación es hacer sensitivo al biestable a la transición del pulso más que a la duración del pulso.
Un pulso de reloj puede ser positivo o bien negativo. Una fuente positiva de reloj permanece en 0 durante el
intervalo entre pulsos y pasa a 1 al ocurrir un pulso. El pulso pasa a través de dos transiciones de señal: desde 0 a
1 y el regreso de 1 a 0. La transición positiva se define como el borde positivo y la transición negativa como el
borde negativo. Esta explicación también se aplica a los pulsos negativos.
Los biestable temporizados se disparan durante el borde positivo del pulso, y la transición de estado principia tan
pronto el pulso alcanza el nivel lógico 1. El nuevo estado del biestable puede aparecer en las terminales de salida
mientras el pulso de entrada todavía este en 1. Si las otras entradas del biestable cambian mientras el reloj todavía
este en 1, el biestable iniciara la respuesta a esos nuevos valores y puede ocurrir un nuevo estado de salida.
Cuando esto sucede, la salida de un biestable no puede aplicarse a las entradas de otro biestable cuando el mismo
pulso de reloj los dispara a ambos. Sin embargo, si puede hacerse que el biestable responda a la transición de
borde positiva (o negativa) solamente, en lugar de la duración completa del pulso, entonces puede eliminarse el
problema de transición múltiple.
Una forma de hacer que el biestable responda solo a una transición del pulso es utilizar un acoplamiento capacitor.
En esta configuración, un sistema (resistor-capacitor) se inserta en la salida de reloj del biestable. Este sistema
genera un pico como respuesta a un cambio momentáneo de la señal de entrada. Un borde positivo emerge de
dicho sistema con un pico positivo, y un borde negativo emerge con un pico negativo. El disparo por bordes se
logra diseñando el biestable de modo que desprecie un pico y dispare una ocurrencia de otro pico. Una forma para
lograr el disparo por borde es utilizar un biestable maestro-esclavo o disparando por borde como se expone a
continuación.
Biestable maestro-esclavo. Un biestable maestro-esclavo se construye mediante dos biestable separados. Un
sistema sirve como un maestro y el otro como un esclavo, y el sistema global se conoce como un biestable
maestro-esclavo. El diagrama lógico de un biestable maestro-esclavo se muestra en la figura 55. Consta de un
biestable maestro, un biestable esclavo y un inversor. Cuando el pulso de reloj es 0, la salida del inversor es 1.
Ya que la entrada de reloj del esclavo es 1, el biestable está habilitado si la salida es igual a , en tanto que es
igual a . El biestable maestro se habilita porque Cuando el pulso llega a 1, entonces la información en
las entradas externas y se transmite al biestable maestro. Sin embargo, el biestable esclavo está aislado
mientras el pulso este en su nivel 1, ya que la salida del inversor es 0. Cuando el pulso regresa a 0, el biestable
114
maestro está aislado, lo cual evita que lo afecten las entradas externas. El biestable esclavo pasa entonces al
mismo estado que el del biestable maestro.
Figura 19. (Árbol sintáctico) Relaciones de tiempos en un biestable maestro-esclavo
Q
QSET
CLR
S
R Q
QSET
CLR
S
R
Q
Q'
S
R
C
Y
Y'
Fuente: Autor
Las relaciones de temporizados ilustran la secuencia de eventos que ocurren en un biestable maestro esclavo. Se
supone que el biestable está en el estado despejado antes de la ocurrencia de un pulso, de modo que y
. Las condiciones de entrada son y el siguiente pulso de reloj cambiara el biestable al estado ajustar
con . Mediante la transición de un pulso de 0 a 1, el biestable maestro esta restaurado y cambia a 1. El
biestable esclavo no es aceptado porque su entrada es 0. Ya que el biestable maestro es un sistema interno, su
cambio de estado no es obvio en las salida y . Cuando el pulsor regresa a 0, se permite que la información del
maestro pase al esclavo, haciendo que la salida externa sea . Obsérvese que la entrada externa debe
cambiarse al mismo tiempo que el pulso pasa a través de su transición de borde negativo. Este se debe a que una
vez que la entrada alcanza 0, el maestro está habilitado y sus entradas y no tienen influencia hasta que
ocurre el siguiente pulso de reloj. Por esto en un biestable maestro-esclavo es posible cambiar la salida del
biestable y su información de entrada con el mismo pulso de reloj. Debe tomarse en cuenta que la entrada puede
llegar mediante la salida de otro biestable maestro-esclavo que se cambio con el mismo pulso de reloj.
El comportamiento del biestable maestro-esclavo que acaba de describirse dicta que los cambios de estado en
todos los biestables coincidan con la transición de borde negativo del pulso. No obstante, algunos biestables
maestro-esclavo cambian los estados de salida en la transición de borde positivo de los pulsos de reloj. Esto
sucede en biestables que tienen un inversor adicional entre la terminal y la entrada del maestro. Tales biestable
se disparan con pulsos negativos, de modo que el borde negativo del pulso afecte al maestro y el borde positivo
afecte al esclavo y las terminales de salida.
115
La combinación maestro-esclavo puede construirse para cualquier tipo de biestable por la adición de un biestable
temporizado con un reloj invertido para formar el esclavo. Un biestable maestro-esclavo construido con
compuertas se muestra en la figura 56. Consta de dos biestable; las compuertas 1 a 4 forman el biestable
maestro, y las compuertas 5 a la 8 forman el biestable esclavo. La información presente en las entradas y se
transmite al biestable maestro en el borde positivo de un pulso de reloj y se sostiene hasta que ocurre el borde
negativo del pulso de reloj, después del cual se permite que pase a través del biestable esclavo. La entrada de reloj
normalmente es 0, lo cual mantiene las salidas de las compuertas 1 y 2 en el nivel. Esto evita que las entradas y
afecten el biestable maestro. El biestable esclavo es un tipo temporizado, con el biestable suministrado las
entradas y con la entrada de reloj invertida por la compuerta 9. Cuando el reloj es 0, la salida de la compuerta 9 es
1, de modo que la salida es igual a y es igual a .
Cuando ocurre el borde positivo de un pulso de reloj, el biestable maestro se afecta y puede cambiar estados. El
biestable esclavo está aislado mientras que el reloj este en el nivel 1, ya que la salida de la compuerta 9
proporciona un 1 a ambas entradas de las compuertas 7 y 8 biestable básico. Cuando la entrada de reloj regresa
a 0, el biestable maestro está aislado mediante las entradas y y el biestable esclavo pasa al mismo estado del
biestable maestro. Se considera ahora un sistema digital que contiene muchos biestable maestro-exclavo, con las
salidas de algunos biestable que van a las entradas de otros biestable.
Se supone que las entradas de pulso de reloj a todos los biestables están sincronizadas (ocurren al mismo tiempo).
Al principio de cada pulso de reloj, algunos de los elementos maestros cambian estado, pero todas las salidas
biestable permanecen en sus valores previos. Después de que el pulso de reloj regresa a 0, algunas de las salidas
cambian de estado maestro hasta el siguiente pulso de reloj. Así que, los estados de biestables en el sistema
pueden cambiarse en forma simultánea durante el mismo pulso de reloj, aun cuando las salidas de los biestables
estén conectadas a entradas de biestable.
Figura 20. (Árbol sintáctico) Biestable maestro-esclavo con pulsos de reloj
116
&0
0
0
&0
0
0
Q
Q'
&0
0
0
&0
0
0
&0
0
0
&0
0
0
K
J
&0
0
0 0
&0
0
0 0
1C
Y
Y'
Fuente: Autor
Se supone que las entradas de pulso de reloj a todos los biestables están sincronizadas (ocurren al mismo tiempo).
Al principio de cada pulso de reloj, algunos de los elementos maestros cambian estado, pero todas las salidas
biestable permanecen en sus valores previos. Después de que el pulso de reloj regresa a 0, algunas de las salidas
cambian de estado maestro hasta el siguiente pulso de reloj. Así que, los estados de biestables en el sistema
pueden cambiarse en forma simultánea durante el mismo pulso de reloj, aun cuando las salidas de los biestables
estén conectadas a entradas de biestable. Esto es posible ya que el nuevo estado aparece en las terminales de
salida solo después de que el pulso de reloj ha regresado a 0. En consecuencia, el contenido del segundo
transferirse al primero, y amabas transferencia pueden ocurrir durante el mismo pulso de reloj.
Biestable disparado por borde. Otro tipo de biestable que sincroniza los cambios de estado durante la transición
de pulsos de reloj es el biestable disparado por borde. En este tipo de biestable, las transiciones de salida ocurren
en un nivel específico del pulso de reloj. Cuando el nivel del pulso de entrada excede el nivel umbral, las entradas
están bloqueadas y, de este modo. El biestable no responde a cambios adicionales en las entradas hasta que el
pulso de reloj regresa a 0 y ocurre otro pulso. Algunos biestable disparados por borde provocan una transición en
el borde positivo del pulso, y otros causan una transición en el borde negativo del pulso.
El diagrama lógico de un biestable tipo disparado por borde positivo se muestra en la figura 57. Consta de tres
biestable básicos del tipo que se muestra. Las compuertas 1 y 2 conforman un biestable básico y las compuertas
3 y 4 conforman otro. El tercer tipo biestable básico que comprende las compuertas 5 y 6 proporciona las salidas
del sistema lógico. Las entradas y del tercer biestable básico deben mantenerse en lógica 1 para que las salidas
permanezcan en sus valores de estado estacionario. Cuando y la salida pasa al estado establecido con
. Cuando y , la salida pasa al estado despejado con . Las entradas y están determinadas
117
mediante los estados de los otros dos biestables básicos. Estos dos biestable básicos responden a las entradas
externas (datos) y (pulso de reloj).
La operación del sistema se explica en la figura 57, donde las compuertas 1-4 vuelven a dibujarse para mostrar
todas sus transiciones posibles. Las salidas y de las compuertas 2 y 3 van a las compuertas 5 y 6 como se
muestra en la figura 57, para proporcionar las salidas reales del biestable. En la figura 57 se muestran los valores
binarios en las salidas de las cuatro compuertas cuando . La entrada puede ser igual a 0 o 1. En
cualquier caso, un de 0 provoca que las salidas de las compuertas 2 y 3 pasen a 1, y asi hacen que ,
que es la condición para una salida de estado estacionario. Cuando , la compuerta 4 tiene una salida 1, la
cual causa que la salida de la compuerta 1 pase a 1. Estas son las dos condiciones posibles cuando el terminal,
que es 0, inhabilita cualesquiera cambios en la salida del biestable, sin importar cuál es el valor de .
Hay un tiempo definido, llamado tiempo de disposición, en el cual la entrada debe mantenerse en un valor
constante antes de la aplicación del pulso. El tiempo de disposición es igual al retardo de propagación a través de
las compuertas 4 y 1, ya que un cambio de provoca un cambio en las salidas de esas dos compuertas. Ahora se
supone que no cambia durante el tiempo de disposición y que la entrada llega a ser 1. Si cuando el
llega a ser 1, entonces permanece en 1 pero cambia a 0. Esto causa que la salida del biestable vaya a 0. Si
ahora mientras hay un cambio en la entrada , la salida de la compuerta 4 permanecerá en 1 (incluso si
va a 1), ya que una de las entradas de compuerta viene de la cual se mantiene en 0. Solo cuando el regresa a
0 puede cambiar la salida de la compuerta 4; pero entonces tanto como vuelven 1, inhabilitando cualquier
cambio en la salida del biestable. Sin embargo, hay un tiempo definido, llamado el tiempo de conservación, en el
que la entrada no debe cambiar después de la aplicación de la transición que va a positivo del pulso. El tiempo
de conservación es igual al retardo de propagación de la compuerta 3, ya que debe asegurarse que se vuelva 0
con objeto de mantener la salida de la compuerta 4 en 1 con independencia del valor de .
Si x cuando entonces cambia a 0, pero permanece en 1, lo cual provoca que las salidas del
biestable vayan a 1. Un cambio de mientras no altera y porque la compuerta 1 se mantiene en 1
por la señal 0 de . Cuando el va a 0, tanto como van a 1 para evitar que la salida tenga cambios.
En resumen, cuando el pulso de reloj de entrada realiza una transición que va a positivo, el valor de se transfiere
a . Los cambios en cuando se mantiene en un valor sostenido de, no afectan . Por otra parte, una
transición del pulso a negativa no afecta la salida, y tampoco cuando .
118
Figura 21. (Árbol sintáctico) Biestable tipo con disparo en borde positivo
&0
0
0
&0
0
0
Q
&0
0
0
&0
0
0
Q
Q'
&0
0
0 0
&0
0
0
D
C
S
R
Fuente: Autor
Siendo así, el biestable disparado por borde elimina cualquier problema de retroalimentación en los sistemas
lógicos secuenciales precisamente como lo hace un biestable maestro-esclavo. El tiempo de disposición y el
tiempo de conservación deben tomarse en consideración cuando se usa este tipo de biestable.
Cuando se usan tipos diferentes de biestable en el mismo sistema secuencial, debe tenerse la seguridad de que
todas las salidas de los biestables hacen sus transiciones al mismo tiempo, esto es, durante ya sea el borde
negativo o el positivo del pulso. Los biestables que se comportan en forma opuesta respecto a la transición de
polaridad adoptada pueden cambiarse con facilidad por la adición de inversores en sus entradas de reloj. Un
procedimiento alterno es proporcionar pulsos positivos y negativos (mediante un inversor), y aplicar entonces
pulsos positivos a los biestables que disparan durante el borde negativo y pulsos negativos a los biestables que
disparan durante el borde positivo, o viceversa.
Entradas directas. Los biestables disponibles en paquetes IC algunas veces proporcionan entradas especiales
para ajustar o despejar el biestable en forma asincrónica. Estas entradas por lo común se llaman preajuste directo y
despeje directo. Afectan el biestable en un valor positivo (o negativo) de la señal de entrada sin la necesidad de un
pulso de reloj. Estas entradas son útiles para producir todos los biestables a un estado inicial antes de su operación
temporizada. Después que se conecta la potencia en un sistema digital, los estados de sus biestables son
119
indeterminados. Un interruptor de despeje limpia todos los biestables a un estado inicial despejado y un
interruptor de inicio principia la operación temporizada del sistema. El interruptor de despeje debe limpiar todos
los biestables en forma asincrónica sin la necesidad de un pulso.
Tabla 9. Biestable con despeje directo
Entradas Salidas Tabla de función
Despeje Reloj
0 0 1
J
Q
Q
K
SET
CLR
C
1 0 0 Sin cambio
1 0 1 0 1
1 1 0 1 0
1 1 1 Lengueta
El símbolo grafico de un biestable maestro-esclavo con despeje directo se muestra en la tabla 22. El reloj o la
entrada tiene un circulo bajo el triangulo pequeño para indicar que las salidas cambian durante la transición
negativa del pulso ( la ausencia de un circulo pequeño indicaría un biestable disparado por borde positivo). La
entrada de despeje directo también tiene un pequeño círculo para indica que, en forma normal, esta entrada debe
mantenerse en 1. Si la entrada de despeje se mantiene en 0, el biestable permanece limpio, independiente de las
otras entradas o del pulso de reloj. La tabla de función específica la operación del sistema lógico. Las son
condiciones no importa que indican que un 0 en la entrada de despeje directo inhabilita todas las demás entradas.
Solo cuando la entrada de despeje es 1 puede tener efecto un transición negativa del reloj en las salidas. Las
salida no cambian si . El biestable cambia o completa cuando . Algunas biestables es posible
que también tengan una entrada de preajuste directo, la cual establece la salida en 1 (y en 0) en forma
asincrónica.
Cuando están disponibles entradas directas asincrónicas en un biestable maestro-esclavo, deben conectarse tanto
al maestro como al esclavo con el objeto de sobrepasar las otras entradas y el reloj. Un despeje directo en al
biestable maestro-esclavo en la figura se conecta a las entradas de las compuertas 1,4 y 8. Un despeje directo
en el biestable disparado en borde en la figura se conecta a las entradas de las compuertas 2 y 6.
Tablas de excitación biestable. Las tablas características de los diversos biestables se presentaron anteriormente.
Una tabla característica define la propiedad lógica del biestable y caracteriza por completo su operación. Los
sistemas lógicos integrados biestables algunas veces se definen por una tabla característica tabulada en forma un
poco diferente. Esta segunda forma de las tablas características para los biestables y se muestra en la
tabla. Representa la misma información que las tablas características en la tabla.
120
En la tabla se define el estado de cada biestable como una función de sus entradas y su estado previo. se
refiere al estado presente al siguiente estado después de la ocurrencia de un pulso de reloj. La tabla
característica para los biestables muestra que el estado siguiente es igual al estado presente cuando tanto la
entrada como la con 0. Cuando la entrada es igual a 1, el siguiente pulso de reloj el biestable. Cuando la
entrada es igual a 1, el siguiente pulso de reloj establece el biestable. El signo de interrogación para el siguiente
estado cuando tanto como son iguales a 1 en forma simultánea designa para el siguiente estado cuando tanto
como son iguales a 1 en forma simultánea designa un estado siguiente indeterminado.
La tabla para el biestable es la misma que para el cuando y se reemplazan por y respectivamente,
excepto para el caso indeterminado. Cuando tanto como son iguales a 1, el estado siguiente es igual al
complemento del estado presente, esto es, = . El estado siguiente del biestable depende por
completo de la entrada y es independiente del estado presente. El siguiente estado del biestable es el mismo
que el estado presente si y se complementa si .
La tabla característica es útil para análisis y para definir la operación del biestable. Especifica el estado siguiente
cuando las entradas del estado presente se conocen. Durante el proceso de diseño, por lo común se conoce la
transición del estado presente al estado siguiente y se desea encontrar las condiciones de entrada del biestable,
que provocaran la transición requerida. Por esta razón, se necesita una tabla que liste las entradas requeridas para
un cambio dado de estado. Dicha lista se denomina tabal de excitación.
En la tabla se presentan las tablas de excitación para los cuatro biestables. Cada tabla consta de dos columnas
y una para cada entrada para mostrar cómo se logra la transición requerida. Hay cuatro transiciones
posibles desde el estado presente al estado siguiente. Las condiciones requeridas de entrada para cada una de las
cuatro transiciones se derivan la información disponible en la tabla característica. El símbolo en las tablas
representa condiciones no importa, esto es, no importa si la entrada es 1 o 0.
Biestable . La tabla de excitación para el biestable se muestra en la tabla. En el primer renglón se muestra
el biestable en el estado 1 en el tiempo Se desea dejarlo en el estado 0 después de la ocurrencia del pulso.
Mediante la tabla característica, se encuentra que si al igual que son 0, el biestable no cambiara de estado. En
consecuencia, tanto la entrada como la deben 0. Sin embargo, en realidad no importa si se hace un 1,
cuando ocurre el pulso, ya que resulta en que deja el biestable en el estado, 0. Por eso puede ser 1 o 0 y el
biestable permanecerá en el estado 0 en . Así, la entrada bajo se marca como condición no importa.
121
Si el biestable está en el estado 0 y se desea que pase al estado 1, entonces mediante la tabla característica, se
encuentra que la única forma de hacer igual a 1 es hacer y . Si el biestable va a tener una
transición del estado 1 al estado 0, debe tenerse y .
La última condición que puede ocurrir es para que el biestable este en el estado 1 y permanezca es el estado 1. Por
supuesto debe ser 0; no se desea despejar el biestable.
Sin embargo, puede ser ya sea un 0 o un 1. Si es 0, el biestable no cambia y permanece en el estado 1; si es un 1,
se establece el biestable en el estado 1, como se desea. Así que, se lista como una condición no importa.
Biestable . La tabla de excitación para el biestable se muestra en la tabla. Cuando tanto el estado presente
como el estado siguiente son 0, la entrada deberá permanecer en 0 y la entrada podrá ser 0 o bien 1. En forma
similar, cuando tanto el estado presente como el siguiente son 1, la entrada debe permanecer en 0 mientras la
entrada puede ser 0 o 1. Si el biestable va a tener una transición del estado 0 al estado 1, debe ser igual a 1 ya
que la entrada establece el biestable. No obstante, la entrada puede ser 0 o en un 1. Si condición la
establece el biestable cuando se requiere; si y el biestable esta complementado y pasa del estado 0 al
estado 1 cuando se requiere. En este caso, la entrada se marca con una condición no importa para la transición
de 0 a 1. Para una transición del estado 1 al estado 0, debe tenerse , ya que la entrada despeja el biestable.
Sin embargo la entrada puede ser 0 o bien 1, ya que no tiene efecto junto con complementa el
biestable con una transición resultante del estado 1 al estado 0.
La tabla de excitación para el biestable ilustra la ventaja de usar este tipo cuando se diseña en sistemas lógicos
secuenciales. El hecho de que tiene muchas condiciones no importa indica que los sistemas lógicos
combinacionales para las funciones de entrada son susceptibles de ser más simples debido a que los términos no
importa por lo común simplifican a una función.
Biestable . La tabla de excitación para el biestable se muestra en la tabla. Mediante la tabla característica, se
observa que el estado siguiente siempre es igual a la entrada y es independiente del estado presente. De este
modo, debe ser 0 si ha de ser 0, y 1 si tiene que ser 1, sin importar el valor de .
Biestable . La tabla de excitación para el biestable se muestra en la tabla. Mediante la tabla características,
tabla, se encuentra que cuando la entrada , el estado del biestable se complementa; cuando el estado
del biestable permanece sin cambio. En consecuencia, cuando el estado del biestable debe permanecer igual, el
requisito es que . Cuando el estado del biestable tiene que complementarse, debe ser igual a 1.
122
Tabla 10. Tablas de excitación biestable
0 0 0 X
0 1 1 0
1 0 0 1
1 1 X 0
0 0 0
0 1 1
1 0 0
1 1 1
0 0 0 X
0 1 1 X
1 0 X 1
1 1 X 0
0 0 0
0 1 1
1 0 1
1 1 0
Otros biestables. El procedimiento de diseño que se describe en este apartado puede usarse con cualquier
biestable. Es necesario conocer la tabla característica del biestable de la cual es posible desarrollar una nueva tabla
de excitación. La tabla de excitación se utiliza entonces para determinas las funciones de entrada del biestable,
como se explica a continuación.
123
ANEXO 12. Lógica Proposicional
12.1 Proposiciones y variables lógicas
La lógica es la herramienta que usan las matemáticas para desarrollarse. El objetivo del mismo es describir en qué
consiste una teoría matemática. Para lograrlo, primero hay que exponer sucintamente las reglas de la lógica de
proposiciones, definir con precisión que es un razonamiento lógico y, por último, explicar en qué consiste su
aplicación en el desarrollo del trabajo de investigación (brevemente, una serie de axiomas, definiciones y
teoremas relacionados entre sí mediante argumentos lógicos usados para sustentar la hipótesis propuesta).
La lógica es un esquema de reglas que permite deducir verdades a partir de otras verdades. El medio que lleva de
las primeras verdades a las otras deducidas se llama razonamiento lógico. La lógica analiza, los razonamientos
lógicos, estableciendo cuando un razonamiento es válido, independientemente del contenido de las verdades que
se enuncien. Solo le interesan las manipulaciones que se hacen con los enunciados, no su contenido.
Todos los resultados mostrados en se prueban rigurosamente. Sin embargo, no se usa para ello el razonamiento
lógico, sino el simple y eficaz camino de las tablas introducidas. Por supuesto, algunos resultados sí se podrían
demostrar a partir de otros anteriores mediante las leyes del algebra de proposiciones, que se exponen. Se prefiere
dejar todo en manos de las tablas, pues en el resto de la investigación son los argumentos lógicos los
protagonistas. Por contra, aunque no se habla de axiomas, definiciones y teoremas en las teorías matemáticas,
desde el principio llamados teoremas a los resultados que se obtuvieren y se podrán visualizar en el anexo
Teoremas.
Proposiciones y variables lógicas. Puesto que la lógica busca deducir verdades a partir de otras verdades, su
materia prima son los enunciados de esas verdades. Eso es lo que se llama proposiciones: un enunciado que se
puede juzgar como verdadero o falso.
Los siguientes enunciados “la máquina está disponible”, “el inventario es suficiente” y “el operario está libre”
son proposiciones, pues se puede juzgar objetivamente que son falsas o verdaderas. Deliberadamente no se escribe
una definición formal del concepto de proposición en nuestra teoría por dos razones. Primero, en muchos casos es
cuestión de opinión si un enunciado se puede juzgar como verdadero o falso, o simplemente, el juicio no será
unánime. La segunda razón es que las proposiciones no son parte de la lógica. Son los ladrillos con los que se
construyen los razonamientos lógicos. La lógica se ocupa de las relaciones entre las proposiciones, no de su
contenido.
124
Es de interés particular, pues, asignar a cada proposición un valor binario, previa validación de la variable de
estado. Por ello se debe usar símbolos que representen proposiciones cualesquiera y examinar las relaciones entre
estos símbolos independientemente de corroborar su registro particular.
Se utilizara letras latinas minúsculas, especialmente . ., para representar proposiciones cualesquiera. La
única característica que nos recuerda que representan proposiciones es que estos símbolos pueden tener dos
valores: verdadero (representado por ) o falso (representado por ). Y como representan proposiciones
cualesquiera, pueden tomar cualquiera de los dos. Estos símbolos no son proposiciones sino variables discretas,
que comúnmente construyen recursivamente las formulas atómicas usadas en la lógica proposicional. Entre estas
variables lógicas discretas para una planta de producción, se definen las materias primas y proceso ( ), equipos
( ), la mano de obra ( ), pertenecientes a cada a centros de trabajo ( ) y productos ( ).
Sin embargo, una vez aclarada la diferencia entre proposiciones y variables lógicas, y puesto que una variable
lógica representa una proposición cualquiera, se empleara los dos términos indistintamente. El análisis utilizando
la lógica va a consistir en analizar variables lógicas y describir las relaciones entre ellas. La relación más sencilla
es la de variables dependientes e independientes. Dos variables lógicas son dependientes si el valor que tome una
condiciona el valor que puede tomar la otra. Son independientes si no son dependientes.
Al representar las variables lógicas por letras como . . Si en una expresión aparecen las variables y
ambas pueden tomar los valores y , y se tiene un total de cuatro combinaciones posibles de los valores de y
. Al tener tres variables, hay ocho posibilidades Una tabla de verdad, o simplemente tabla en este contexto,
es una representación en filas y columnas de los valores de algunas variables lógicas. Cada columna representa
una variable, y cada fila una posible combinación de los valores de las mismas. En la tabla 5 se muestran todas las
posibles combinaciones de los valores y para tres variables.
Una variable lógica puede, en principio, tomar los valores 0 o . Sin embargo, es posible que una variable
dependiente de otras, cuyo valor queda condicionado por estas, tome siempre el valor 1 (verdadero) para cualquier
situación de las variables de las que depende. O bien, otra variable que tome siempre el valor 0 (falso). Las
variables con este comportamiento reciben un nombre. Se llama tautología a la variable lógica, dependiente de
otras, la cual toma el valor 1 independientemente del valor de las variables de las que depende. Análogamente se
llama contradicción a la variable lógica cuyo valor es 0 en cualquier situación.
Tabla 11. Combinaciones de los valores y
p q r
0 0 0
0 0 1
125
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
12.2 Conectivos lógicos
Los conectores permiten construir nuevas proposiciones a partir de unas dadas. La nueva proposición es
dependiente de las proposiciones con las que se construye. Un conector monario llamado negación el cual, a partir
de una proposición, construye otra. También varios conectores binarios, que a partir de dos proposiciones dan
otra: conjunción, disyunción, implicación y doble implicación. En los cinco casos se dará una explicación intuitiva
seguida de una descripción formal.
La descripción formal consiste en describir exactamente como depende la nueva proposición de las proposiciones
con que se construye. La descripción se hace mediante tablas en las que aparecen todas las combinaciones
posibles de valores que toman las variables independientes. Inicialmente la negación de una proposición, que es
otra proposición con valor opuesto a la primera. Si la primera es cierta, su negación es falsa y viceversa.
En términos de variables lógicas, la negación de una variable es otra variable dependiente de la primera porque su
valor está determinado por el de ella.
La negación de una proposición , denotada , es la proposición cuyo valor es el opuesto al de . Se puede
definir la negación mediante la tabla 6. En ella se indica, para cada valor de la proposición , el valor que toma la
proposición
Tabla 12. Negación de una proposición
0 1
1 0
La conjunción es un conector binario que funciona como la conjunción copulativa “ ” del español. La conjunción
de dos proposiciones, entonces, es una proposición que es cierta si ambas son ciertas, y es falsa si alguna de ellas
es falsa. La conjunción de dos proposiciones denotada es la proposición que solo es cierta si ambas
son ciertas. En un proceso de producción donde las maquinas están dispuestas en serie se podrá expresar en
126
términos de la conjunción. La descripción mediante la tabla 7 consiste ahora en ilustrar, para cada valor que
pueden tomar las proposiciones y el valor que resulta en la proposición
Tabla 13. Conjunción de dos proposiciones denotada
0 0 0
0 1 0
1 0 0
1 1 1
La disyunción es el conector que opera de forma parecida a la conjunción disyuntiva “ ” del español. La
disyunción de dos proposiciones es otra proposición que es cierta si alguna de las dos originales es cierta. Es
decir, basta que una de ellas sea cierta para que la disyunción lo sea. Sin embargo en lógica se emplea en sentido
inclusivo como se aprecia en la tabla que la define. En un proceso de producción donde las maquinas están
dispuestas en paralelo se podrá expresar en términos de la disyunción. La disyunción de dos proposiciones ,
denotada , es la proposición que solo es falsa si ambas son falsas. En forma de tabla 8.
Tabla 14. disyunción de dos proposiciones , denotada
0 0 0
0 1 1
1 0 1
1 1 1
El siguiente conector que se introduce es la implicación, que tiene gran importancia en la lógica pues es la base
del razonamiento deductivo. Requiere un poco de atención para entender bien su descripción formal que, al
principio, no parece responder a la intuición. Cuando se afirma que una proposición implica otra se quiere
expresar el hecho de que si la primera es cierta, entonces la segunda debe ser cierta también.
En el lenguaje corriente se usa la expresión “Si . . . entonces . . . ”. Las dos proposiciones que aparecen en la
implicación se llaman antecedentes y consecuentes. El antecedente es la condición que, si es cierta, asegura que se
cumple el consecuente. Base del lenguaje PWL, la setencia if... Then.. en cualquier lenguaje de
programación.
Decir qué valor tiene la implicación en cada caso de los posibles valores de antecedente y consecuente. Es claro
que quiero decir que una implicación es cierta si el antecedente es cierto y el consecuente también. Por todo ello
127
se define la implicación del siguiente modo. La implicación de dos proposiciones denotada es la
proposición que solo es falsa si es verdadera y es falsa. La tabla 9 correspondiente es:
Tabla 15. La implicación de dos proposiciones denotada
0 0 1
0 1 1
1 0 0
1 1 1
Es fácil convencerse de que la proposición no es la misma que . Esta observación es suficientemente
importante como para asignar nombres a cada una de estas implicaciones.
Dada una implicación , se otorgan nombres a las siguientes implicaciones:
implicación directa,
implicación inversa,
implicación reciproca,
implicación contrapositiva.
El último conector que se introduce es el de doble implicación o bicondiciónal. Como su nombre indica, si dos
proposiciones están relacionadas con el conector doble implicación, significa que una implica la otra y la otra la
una. Entonces, si una de ellas es cierta, la otra debe serlo también, que es lo mismo que decir que si una es falsa la
otra también. La doble implicación de dos proposiciones denotada es la proposición que solo es
verdadera si ambas coinciden en su valor. De la tabla 10 resulta :
Tabla 16. La doble implicación de dos proposiciones denotada
0 0 1
0 1 0
1 0 0
1 1 1
Una explicación que se enuncia a partir de la doble implicación es la de variables lógicas equivalentes. Dos
variables son equivalentes si son dependientes de modo que siempre toman el mismo valor. Si una es verdadera,
entonces la otra también y viceversa. Es claro que el conector de doble implicación puede ayudar a expresar esta
idea. Una forma de hacerlo es decir que la doble implicación entre dos proposiciones equivalentes es siempre
cierta. Dos variables y son equivalentes, y se denota , si es una tautologıa. (Barnes, 1978)
128
Es claro que en cualquier expresión puedo sustituir una proposición por otra equivalente, y la nueva expresión que
obtengo es equivalente a la original pues los valores son los mismos. De ahí que el concepto de proposiciones
equivalentes sea importante y muy utilizado en lógica. Ahora se puede enunciar un primer resultado sencillo pero
muy útil en la teoría y en la práctica de la lógica. Es la relación entre las implicaciones directa, inversa, reciproca
y contrapositiva. Ver anexo Teorema 19.
Otro teorema relacionado con el concepto de equivalencia es la que dice que el conector doble implicación es
equivalente a la implicación directa junto con la implicación inversa. Es la formulación precisa de lo que el
símbolo ↔ expresa abiertamente. Ver anexo Teorema 20.
En las expresiones que incluyen algunos o todos los operadores , en la ausencia de paréntesis, primero se
evalúa después y luego . Esta convención se conoce como precedencia del operador. En álgebra, la
precedencia del operador indica que se evalúan y antes que y –.
12.3 Leyes del algebra proposicional
Los conectores entre proposiciones (negación, conjunción, disyunción, etc.) se pueden ver, desde un punto de
vista algebraico, como operaciones definidas en el conjunto de las proposiciones. Se toma una proposición (en el
caso de la negación) o dos proposiciones (en los otros casos) y se operan, obteniendo como resultado otra
proposición. Resulta imperativo analizar algunas propiedades algebraicas de estas operaciones como son la
aplicación reiterada, asociatividad, conmutatividad, existencia de elemento neutro, etc. (Badesa C, 1998)
Como primer paso se observa que los conectores de implicación y doble implicación se pueden escribir en
términos de la negación, conjunción y disyunción solamente. Entonces bastara con analizar las propiedades
algebraicas de estas tres operaciones. (En realidad, también el conector de disyunción se puede expresar en
función del de conjunción y el de negación, pero estos tres en conjunto tienen más y mejores propiedades
algebraicas. Ver anexo Teorema 21.
Puesto que en el teorema que la doble implicación es equivalente a la implicación directa y la inversa, entonces la
doble implicación también se puede expresar solo con negación, conjunción y disyunción. En definitiva, se darán
uso a las propiedades de la negación, la conjunción y la disyunción.
Propiedades de la negación. Debido a que la negación es una operación monaría, la única propiedad que en este
caso puede analizarse es la aplicación reiterada. El resultado es muy evidente por estar trabajando con
129
proposiciones que solo pueden tomar dos valores. La negación es cambiar el valor de una proposición, y como
solo hay dos posibilidades, si se cambia dos veces se regresa al valor original. Ver anexo Teorema 22.
Propiedades de la conjunción. La conjunción es una operación binaria y en ella sí procede analizar más
propiedades. La idempotencia, da el resultado de operar una proposición consigo misma. La asociatividad nos
indica cómo se puede efectuar la conjunción de tres proposiciones. La conmutatividad muestra que el orden de las
proposiciones en una conjunción es irrelevante. Existe un elemento neutro (la proposición con valor 1, que se
denota simplemente como 1) que al operarlo con cualquier proposición da como resultado la misma proposición.
Existe también un elemento dominante (la proposición con valor 0, que se denota simplemente como 0) que
operado con cualquier proposición arroja el resultado 0. Ver anexo Teorema 23.
La presencia de la propiedad asociativa permite definir el símbolo , sin paréntesis, como o bien
puesto que son iguales. El resultado en ambos casos es que solo es cierto si las tres
proposiciones y son ciertas. Generalizando esta idea se define la conjunción de las variables
denotada como la variable que solo es cierta si todas las variables
son ciertas. Las
propiedades asociativa y conmutativa aseguran que la descripción es coherente con la anterior.
Propiedades de la disyunción. El análisis de la disyunción sigue los mismos pasos que el de la conjunción pues
las propiedades que satisfacen son las mismas. La única diferencia es que los papeles de y , como elementos
neutro y dominante respectivamente, se invierten ahora. Ver anexo Teorema 24.
Las propiedades asociativa y conmutativa aseguran que la explicación es coherente con la descripción de la
disyunción de dos variables.
Propiedades de las operaciones combinadas. Ahora se estudian algunas propiedades que surgen al considerar
expresiones con dos o las tres operaciones combinadas. Ver anexo Teorema 25.
La simplificación de una proposición mediante manipulaciones algebraicas. Cada proposición es equivalente a la
anterior por la ley algebraica que se indica a su lado.
proposición a simplificar
segunda ley de De Morgan
doble negación y conmutatividad
distributividad
complementariedad de la negación
1 neutro de .
130
Prueba algebraica de la ley de absorción (suponiendo probadas las leyes algebraicas anteriores). Partiendo de la
proposición mediante pasos algebraicos se llega a que es equivalente a la proposición .
0 neutro de _
comp. de negación
distributividad
distributividad
idemp. y complemento
distrib., idemp. y dominación
complemento y 1 neutro de ^
0 neutro de .
Cuantificadores. Se introducen los enunciados abiertos y, tras ellos, los cuantificadores. Son elementos muy
habituales en la formulación de definiciones y resultados en matemáticas en expresiones de la forma “para todo
numero entero. . . ” o “existe una función tal que . . . ”.
Se llama abierto a un enunciado que contiene variables que toman valores en un conjunto dado, llamado universo,
de forma que para cada valor que tomen las variables, el enunciado se convierte en una proposición.
Un enunciado abierto no es una proposición por sí mismo, sino que se convierte en una cuando las variables
toman un valor. En el caso anterior, el enunciado puede ser verdadero o falso según los valores que tome la
variable.
Puesto que las proposiciones se representan por letras , los enunciados abiertos se representan por
símbolos como donde son las variables que contiene el enunciado.
Los cuantificadores son unos prefijos que, antepuestos a enunciados abiertos los convierten en proposiciones. Se
utilizan dos: el cuantificador universal y el cuantificador existencial. El primero se simboliza por , y se suele
leer “para todo”. Indica que el enunciado que le sigue debe ser cierto para todos los posibles valores de la
variable. El segundo se simboliza por , y se lee “existe algún”.
Indica que el enunciado que sigue es cierto para, al menos, uno de los valores que puede tomar la variable.
Tomar su propiedad de convertir enunciados abiertos en proposiciones como base para dar una aclaración.
Si es un enunciado abierto que depende de la variable , la cual toma valores en un conjunto universo dado,
definir el símbolo como la proposición que es cierta solo si el enunciado abierto es verdadero para todos
los valores que la variable puede tomar en su universo.
131
c. Se define el símbolo como la proposición que es cierta si el enunciado abierto es verdadero para
algún valor de los que la variable toma en su universo.
d. La proposición no es en realidad otra cosa que una conjunción, mientras que se trata de
una disyunción como se aprecia a continuación.
La necesidad de introducir los cuantificadores aparece cuando los posibles valores de la variable no se pueden
enlistar como en el caso anterior: si ahora toma valores en los numeros reales, no se puede escribir de
otro modo. Para usar cuantificadores basta recordar que un cuantificador junto a un enunciado abierto es una
proposición y, a partir de ahí, se maneja como cualquier otra proposición. Sin embargo hay algunas reglas que
simplifican el uso de proposiciones que contienen cuantificadores. En concreto se analizara dos de ellas: la
negación de proposiciones con cuantificadores y la combinación de cuantificadores. (Enderton, 1972)
Una proposición que comienza con el cuantificador universal necesita que el enunciado abierto sea cierto para
todos los valores de la variable, por tanto basta con que en un valor sea falso para que toda la proposición sea
falsa. Por ello, la negación con un cuantificador universal nos lleva a un cuantificador existencial y viceversa. Al
recordar que es una conjunción y es una disyunción, esto no es otra cosa que las leyes de De
Morgan vistas en el teorema. El resultado preciso se recoge en el siguiente teorema. Ver anexo Teorema 26.
Las primera y segunda reglas nos dicen que combinar cuantificadores universales y combinar cuantificadores
existenciales es conmutativo. Ver anexo Teorema 27.
Gracias a este resultado se puede escribir sin ambigüedad , y o en lugar de , ası como y o
en lugar de , y el orden de las variables e es irrelevante. Sin embargo hay que tener cuidado pues el
orden si es importante cuando se combinan cuantificadores de ambos tipos. (Ershov, 1990)
Para terminar se define el cuantificador de existencia y unicidad, simbolizado . Como su nombre indica este
símbolo contiene dos afirmaciones: primero, la existencia de un elemento que cumple el enunciado; segundo, que
dicho elemento es el único que lo cumple. La forma de enunciar la unicidad es diciendo que si hay dos elementos
que cumplen la propiedad, entonces son iguales. Si es un enunciado abierto, el símbolo es la
proposición definida por
132
TEOREMAS
Teorema 1. Dos conjuntos son iguales si, y solo si, cada uno es subconjunto del otro
Demostración. Primero, la implicación directa. Si entonces, por el axioma todo elemento de es elemento de y
viceversa. Pero, según la definición anterior, esto qué es lo mismo que decir
Segundo, la implicación inversa. Si , entonces todo elemento de esta en y todo elemento de esta
en , lo cual se puede escribir . Pero esta proposición es precisamente el antecedente del axioma, por
lo cual En particular, todo conjunto es subconjunto de sí mismo: .
Teorema 2. El conjunto vacío es subconjunto de cualquier conjunto.
Esto es, si es un conjunto arbitrario,
Demostración. Queremos probar la proposición Pero el antecedente es siempre falso pues, por
definición del conjunto vacío, Entonces la implicación es siempre cierta, independientemente del consecuente,
y el teorema queda probado.
Teorema 3. Dado un conjunto y subconjuntos del mismo
Demostración. Para probar la primera igualdad escribimos la definición de cada miembro y comprobamos que son
iguales:
donde se ha sustituido por su proposición equivalente . Para probar la segunda igualdad basta usar la
definición de diferencia simétrica.
Teorema 4. Sea un conjunto y subconjuntos arbitrarios de el.
Entonces se cumple:
1. Ley del doble complemento:
2. Leyes de idempotencia:
3. Leyes conmutativas:
4. Leyes asociativas:
5. Elementos neutros de la unión y la intersección: el vacío es neutro de la unión y el conjunto E es neutro de la
intersección:
133
6. Elementos dominantes de la unión y la intersección: el conjunto E es dominante en la unión y el vacío lo es en la
intersección:
7. Leyes del complemento:
8. Leyes distributivas:
9. Leyes de absorción:
10. Leyes de De Morgan:
Demostración. Las diecinueve propiedades enunciadas se demuestran similarmente y se pueden trazar hasta las
propiedades equivalentes de proposiciones del apartado anterior. La propiedad del doble complemento no es más que la
propiedad de la doble negación, las propiedades que afectan solo a la unión son exactamente las mismas que las de la
disyunción y las de la intersección aquellas de la conjunción.
Teorema 5. La relación inversa de una equivalencia es ella misma.
equivalencia ⇒
Demostración. En realidad es un resultado más general, pues vale para cualquier relación simétrica. Por ser simétrica,
y para cada pareja también y, por tanto, ambas están en
.
Teorema 6. Sea una equivalencia definida en un conjunto entonces cada elemento del conjunto está en la clase que
representa.
Es decir dos elementos están relacionados si, y solo si, están en la misma clase de equivalencia, es
decir
Demostración. El primer punto es consecuencia inmediata de que toda equivalencia es reflexiva y la definición de clase de
equivalencia. Para el segundo punto, separamos en dos la doble implicación.
Primero veamos que ⇒ demostrando la igualdad de por una doble contención. Si un elemento
c esta en es porque .
Ahora bien, por ser la relación transitiva y tener por hipótesis, entonces se cumple , con lo cual .
Hemos probado Como, además, la relación es simétrica, entonces y el mismo argumento nos lleva a
Por tanto
Teorema 7. Si es una equivalencia en el conjunto , sus clases de equivalencia constituyen una partición de .
Demostración. Debemos probar que las clases de equivalencia verifican las tres condiciones de la definición de partición.
Las clases de equivalencia son, obviamente por su definición, subconjuntos de .
Todo elemento de esta en alguna clase de equivalencia pues, por el teorema anterior, Entonces, es claro que la
union de todas las clases de equivalencia contiene todos los elementos de , y no mas, por el punto anterior.
134
Para probar que clases de equivalencia diferentes son disjuntas nos fijamos en la contrapositiva: si tienen un elemento en
común, entonces son iguales.
Teorema 8. Dada una partición de un conjunto, existe una equivalencia definida en dicho conjunto cuyas clases de
equivalencia son los subconjuntos que constituyen la partición.
Demostración. Sea el conjunto en el que hay definida una partición. Definamos en la relación de modo que dados
dos elementos , a esta relacionado con si a esta en el mismo subconjunto de la partición que .
Primero veamos que esta relación es una equivalencia. Es reflexiva, pues, obviamente, cualquier elemento esta en el
mismo subconjunto que el mismo. Es simétrica, pues si a esta en el mismo subconjunto que , entonces esta en el
mismo subconjunto que a. Es transitiva, pues si significa que tanto a como c están en el mismo subconjunto
que solo puede estar en uno, ya que los subconjuntos de una partición son disjuntos. Entonces están en el
mismo subconjunto y por tanto .
Teorema 9. La relación inversa de un orden es también un orden, denominado orden inverso.
Demostración. Sea un orden. Por ser asimétrica es claro que también lo es. Veamos que también es transitiva. Si
y es porque . Entonces, por ser R transitiva, , luego
.
La estructura que impone un orden en un conjunto hace destacar algunos elementos del mismo, un elemento que sea
mayor que todos los demás, un máximo; o un elemento que, aunque no sea mayor que todos los demás, no tenga a nadie
por encima de él, un maximal. Veamos con detalle todos estos elementos destacados. En las siguientes definiciones
asumimos que es un conjunto ordenado.
Teorema 10. Todo elemento máximo es maximal y, si existe, el máximo es único.
Análogamente, todo elemento mínimo es minimal y, si existe, es único.
Demostración. Probamos la parte del máximo, pues la del mínimo es similar.
Si es máximo entonces para cualquier en el conjunto.
Si se da la primera instancia, es claro que , por la propiedad asimétrica del orden.
Si se da la segunda, de nuevo tenemos a , pues de lo contrario también se violaría la propiedad asimétrica. Por
tanto es maximal.
Teorema 11. Un subconjunto acotado superiormente tiene máximo si, y solo si, tiene supremo y este pertenece a dicho
subconjunto.
Un subconjunto acotado inferiormente tiene mínimo si, y solo si, tiene ínfimo y este pertenece a dicho subconjunto.
Demostración. Probamos la relación entre máximo y supremo, pues la otra es similar. Primero la implicación directa. Sea
el máximo de . Entonces para todo elemento en , por tanto, b es una cota superior de . Ahora sea c otra
cota superior de . Entonces, como b esta en tenemos , luego es mínimo del conjunto de cotas superiores, es
decir, b es el supremo de .
Ahora la implicación inversa. Sea el supremo de B, el cual cumple además . Por ser supremo es cota superior,
luego todo elemento de cumple . Entonces b cumple la definición de máximo de
Teorema 12. En un orden total todo maximal es máximo y, por tanto, único y todo minimal es mínimo y, por tanto, único.
Demostración. Sea a un elemento maximal, y sea x un elemento arbitrario. Por ser a maximal tenemos a pero, por
ser el orden total, son comparables, luego debe ser , de donde a es máximo.
135
Los cuatro conjuntos numéricos aludidos, a pesar de ser todos órdenes totales, tienen propiedades que diferencian sus
estructuras de orden. En los próximos párrafos vamos a describir las propiedades que diferencian cada uno de los cuatro
órdenes (algunas de estas propiedades no son exclusivas de los órdenes totales, pero hemos preferido enunciarlas aquí
para aplicarlas directamente al caso de los conjuntos numéricos).
La primera propiedad es la del buen orden, y diferencia a los naturales de los otros conjuntos.
Teorema 13. En un conjunto con más de un elemento, si un orden total es lineal, entonces no verifica las propiedades del
inmediato sucesor ni del inmediato antecesor.
Demostración. Probamos su contrapositiva, que es equivalente: si se cumple la propiedad del inmediato sucesor o del
inmediato antecesor, entonces no es lineal.
Efectivamente, sea un elemento que no es máximo (existe porque el conjunto tiene más de un elemento) y sea y su
inmediato sucesor (con el antecesor es similar). Por definición de inmediato sucesor no existe un tal que ,
luego el orden no es lineal.
Teorema 14. Un orden total verifica la propiedad del supremo si, y solo si, verifica la propiedad del ínfimo.
Demostración. Supongamos que un orden total satisface la propiedad del supremo.
Sea un subconjunto acotado inferiormente y consideremos el conjunto de las cotas inferiores de dicho subconjunto.
Claramente este conjunto esta acotado superiormente y, por hipótesis, tiene supremo. Es fácil ver que el supremo de las
cotas inferiores es el ínfimo del subconjunto original. Por tanto se satisface la propiedad del ínfimo. Igualmente se razona
a la inversa probando así la equivalencia.
Teorema 15. Ordenación por comparación
Cualquier algoritmo que ordena por comparación de claves y elimina cuando más una inversión después de cada
comparación deberá efectuar al menos comparaciones en el peor caso y al menos comparaciones
en promedio (con elementos).
Teorema 16. no es un lenguaje recursivamente enumerable.
Es decir, no existe ninguna máquina de Turing que acepte .
Demostración. Supongamos que fuera para alguna . Dado que es un lenguaje sobre el alfabeto
debería estar en la lista de máquinas de Turing que hemos construido, dado que incluye todas las cuyo alfabeto de
entrada es Por tanto, existe al menos un código para , por ejemplo ; es decir,
Ahora veamos si pertenece a .
Si pertenece a , entonces acepta Pero entonces, por definición de , wi no pertenece a , porque
sólo contiene aquellas wj tales que no acepta .
De manera similar, si no pertenece a , entonces no acepta . Por tanto, por definición de , pertenece a .
Dado que no puede simultáneamente pertenecer a y no pertenecer a , concluimos que existe una contradicción en
la suposición de que existe Es decir, no es un lenguaje recursivamente enumerable.
Teorema 17. Si es un lenguaje recursivo, entonces también lo es.
Demostración. Sea para alguna que siempre se para. Construimos una tal que de
acuerdo con la construcción sugerida. Es decir, : se comporta igual que . Sin embargo, se modifica como sigue
para crear :
Los estados de aceptación de se convierten en los estados de no aceptación de sin transiciones; es decir, en estos
estados, se parará sin aceptar.
136
tiene un nuevo estado de aceptación . Desde no existen transiciones.
Para cada combinación de un estado de no aceptación de y un símbolo de cinta de tal que no tiene transiciones (es
decir, se para sin aceptar), se añade una transición al estado de aceptación .
Dado que está garantizado que siempre se para, sabemos que también está garantizado que se parará.
Además, acepta exactamente aquellas cadenas que no acepta. Por tanto, acepta
Teorema 18. Si existe una reducción de a
Entonces:
a. Si es indecidible, entonces también lo es.
xxxxxxxxxxx
b. Si es , entonces también lo es.
Demostración. En primer lugar, suponemos que es indecidible. Si es posible decidir sobre , entonces podemos
combinar la reducción de a con el algoritmo que decide sobre para construir un algoritmo que decida sobre .
Más detalladamente, suponemos que disponemos de un caso de . Aplicamos a el algoritmo que convierte en un
caso de . A continuación aplicamos el algoritmo que decide sobre a . Si dicho algoritmo da como respuesta “sí”,
entonces x está en . Dado que hemos reducido a , sabemos que la respuesta de a es “sí”; es decir,
pertenece a . Igualmente, si no forma parte de entonces no forma parte de , y lo que responda a la cuestión
“¿está x en ?” será también la respuesta correcta a “¿está en ?”
Por tanto, hemos llegado a una contradicción de la suposición de que es indecidible. La conclusión es que si es
indecidible, entonces , también es lo es.
Consideremos ahora el apartado (b). Supongamos que es , pero es . Ahora tenemos un algoritmo para
reducir a , pero sólo disponemos de un procedimiento para reconocer ; es decir, existe una que da como
respuesta “sí” si su entrada pertenece a , pero puede no pararse si su entrada no pertenece a . Como en el apartado
(a), partimos de una instancia de , la convertimos mediante el algoritmo de reducción en una instancia de . Luego
aplicamos la para a . Si se acepta, entonces se acepta.
Teorema 19. Las implicaciones directa y contrapositiva son equivalentes, y las implicaciones inversa y reciproca son
equivalentes.
Simbólicamente
Demostración. Probamos la primera equivalencia, pues la otra es similar. Para ello basta con elaborar una tabla con todos
los casos posibles y ver que, efectivamente, en todos ellos las proposiciones directa y contrapositiva toman el mismo
valor. Obsérvese que las columnas y son auxiliares en esta tabla, pues el objetivo es comparar las columnas
etiquetadas como
0 0 1 1 1 1
0 1 1 0 1 1
1 0 0 1 0 0
1 1 0 0 1 1
Por tanto, de la tabla anterior construimos la siguiente
Tabla 17. Relación entre las implicaciones directa, inversa, reciproca y contrapositiva.
137
0 0 1
0 1 1
1 0 1
1 1 1
donde se ve que la bicondiciónal es una tautología, pues en cualquiera de los cuatro casos el resultado es la constante .
Teorema 20. La doble implicación es equivalente a la conjunción de las implicaciones directa e inversa.
Es decir,
Demostración. Como antes, basta elaborar las tablas de ambas proposiciones y comprobar que sus resultados son iguales
para todos los valores posibles de y . En este caso las dos últimas columnas deben ser iguales, mientras que las
columnas son auxiliares.
Tabla 18. La doble implicación
0 0 1 1 1 1
0 1 1 0 0 0
1 0 0 1 0 0
1 1 1 1 1 1
Por ser la doble implicación como dos implicaciones, se acostumbra a leer también con la formula “ si, y solo
si, ” .
Teorema 21. La implicación de dos proposiciones es equivalente a la disyunción de la negación de la primera con la
segunda.
Demostración. Construimos las tablas de ambas con la columna auxiliar
Tabla 19. La implicación de dos proposiciones
0 0 1 1 1
0 1 1 1 1
1 0 0 0 0
1 1 0 1 1
La coincidencia de las dos últimas columnas en todos los casos demuestra que ambas proposiciones son equivalentes. Por
tanto, en cualquier expresión podemos sustituir por y viceversa.
Teorema 22. La negación de la negación es equivalente a la proposición original.
138
Es decir,
Demostración. Construimos una tabla
Tabla 20. La negación de la negación
0 1 0
1 0 1
Puesto que la primera y la última columna son iguales, las variables que representan son equivalentes.
Teorema 23. Conjunción de proposiciones satisface las propiedades de idempotencia, asociatividad, conmutatividad,
existencia de un elemento neutro y de un elemento dominante
Simbólicamente, si y son proposiciones cualesquiera se cumple
1. Idempotencia:
2. Asociatividad:
3. Conmutatividad:
4. Elemento neutro (1):
5. Dominación (por 0):
Demostración. La idempotencia está demostrada en la misma definición de la operación , (definición 1.8) pues en ella se
aprecia que 1
En la tabla también se prueba la conmutatividad. Asimismo se ve que 1 sirve como neutro y que 0 operado con cualquier
otro valor resulta en 0. Entonces solo resta probar la propiedad asociativa. Construimos una tabla de las proposiciones
La igualdad de las dos últimas columnas prueba que ambas proposiciones son equivalentes.
Teorema 24. La disyunción de proposiciones satisface las propiedades de idempotencia, asociatividad, conmutatividad,
existencia de un elemento neutro y de un elemento dominante.
Es decir, si y son proposiciones cualesquiera, se cumple
1. Idempotencia:
139
2. Asociatividad:
3. Conmutatividad:
4. Elemento neutro (0):
5. Dominación (por 1):
Demostración. La idempotencia está demostrada en la misma definición de la operación , (definición 1.10) pues en ella
se aprecia que 1 En la tabla también se prueba la conmutatividad. Asimismo se ve que la
constante 0 sirve como neutro y que la constante 1 operada con cualquier otro valor resulta en 1. Entonces solo resta
probar la propiedad asociativa. Construimos una tabla de las proposiciones
Como en el caso de la conjunción podemos definir el símbolo como o bien puesto que son
iguales. El resultado es que es cierta si alguna de las tres es cierta, o bien, es falsa solo si todas son falsas.
Generalizando esta idea definimos la disyunción de las variables denotada como la
variable que solo es falsa si todas las variables son falsas.
Teorema 25. Las siguientes relaciones son validas para cualesquiera proposiciones
1. Complementariedad de la negación:
2. Leyes distributivas:
3. Absorción:
4. Leyes de De Morgan:
Demostración. La complementariedad de la negación se prueba en la siguiente tabla.
La prueba de las propiedades distributivas sigue en una tabla de ocho filas.
La igualdad de la cuarta y quinta columnas es la prueba de la distribución de respecto a _, mientras que la sexta y
séptima columnas prueban la otra distribución.
140
En una ultima tabla se prueban las propiedades de absorción (tercera y cuarta columnas que son iguales a la primera) y las
leyes de De Morgan (quinta y sexta columnas, primera ley, séptima y octava, segunda ley).
Las leyes demostradas permiten hacer manipulaciones algebraicas con las proposiciones y probar algunos resultados sin
necesidad de recurrir a las tablas.
Teorema 26. Si es un enunciado abierto, con una variable, entonces se cumplen las equivalencias
Demostración. Como se ha dicho, se trata de las leyes de De Morgan. Razonemos una de ellas como muestra. La negación
de la proposición es cierta si el enunciado no se cumple en algun valor de la variable. Pero eso es
precisamente lo que dice la proposición
Si un enunciado abierto contiene varias variables, se necesita un cuantificador para cada una. Así, si es un
enunciado abierto con las variables e , entonces son enunciados abiertos con una variable: y.
Pero son proposiciones. La combinación de varios cuantificadores tiene algunas reglas que
permiten simplificar su escritura, pero requiere atención pues no todos los casos son simplificables.
Teorema 27. Si es un enunciado abierto que depende de dos variables, se cumplen las siguientes equivalencias
entre proposiciones.
Demostración. La proposición solo es verdadera si dado cualquier , puedo elegir cualquier y obtengo
que es verdadero. Pero en tal caso el valor de y elegido es independiente de , y puedo escogerlo primero.
Entonces, dado cualquier y, puedo elegir cualquier y tendré verdadero, lo cual es la proposición
Con esto se ha probado que cuando la primera es cierta, la segunda también. El mismo razonamiento pero a la inversa
muestra que cuando la segunda es cierta la primera también. En total ambas tienen siempre el mismo valor y, por tanto,
son equivalentes.
Análogamente la proposición afirma que existe algún de modo que puedo encontrar una y tal que
es verdadero. Puedo tomar los valores en orden inverso: escoger primero el valor de y encontrado antes, luego
cierta, entonces también lo es. El mismo razonamiento se aplica a la inversa y llegamos a que ambas son
equivalentes.
Teorema 28. Para proposiciones cualesquiera los siguientes son razonamientos lógicos
1. Modus ponendo ponens:
141
2. Modus tollendo tollens:
3. Silogismo:
4. Demostración por contradicción:
5. Demostración por casos:
6. Silogismo disyuntivo:
7. Conjunción:
8. Simplificación conjuntiva:
9. Amplificación disyuntiva:
10. Especificación universal: con a un elemento cualquiera del universo de
11. Generalización universal: (p(a) (a es arbitrario)) )
12. Especificación existencial: con a el elemento al que se refiere la existencia.
Demostración. Todas estas reglas de inferencia se pueden probar elaborando la tabla correspondiente, pero también
mediante manipulaciones algebraicas. En cualquier caso son todas muy similares, por lo cual expondremos la prueba de
tres de ellas con todo detalle, a modo de muestra, dejando el resto como ejercicio.
Prueba del modus ponendo ponens mediante una tabla. Para probar debemos probar que
es una tautologıa. Construimos la tabla con todos los ingredientes de esta última expresión.
La última columna muestra que, efectivamente, la implicación es una tautología y por tanto el razonamiento es válido.
Prueba del razonamiento por contradicción mediante manipulaciones algebraicas.
Para probar que la implicación es un razonamiento, debo probar que es equivalente a la proposición 1
(tautología) mediante una cadena de proposiciones equivalentes entre sí. En cada paso se da la razón que lo justifica.
(por la equivalencia )
(doble negación)
(0 neutro de )
(complementariedad de la negación).
Por último, la prueba de uno de los razonamientos que involucran cuantificadores y enunciados abiertos. Probamos el
razonamiento de especificación universal usando uno de los razonamientos lógicos de este mismo teorema, supuesto ya
demostrado. La proposición es equivalente a la conjunción de la proposición cuando x toma todos los
valores posibles. Entonces, por la regla de simplificación conjuntiva, de la premisa deducimos que cualquiera de las
proposiciones es cierta, en particular, si a es un valor posible de es cierta.
142
GLOSARIO
Autómatas finitos. Los autómatas finitos utilizan estados y transiciones entre estados en respuesta a las entradas. Resultan
útiles para construir diversos tipos de software, incluyendo el componente de análisis léxico de un compilador y los
sistemas que permiten verificar la corrección de, sistemas lógicos o protocolos.
Autómata finito determinista. Un AFDtiene un conjunto finito de estados y un conjunto finito de símbolos de entrada. Un
estado se diseña para que sea el estado inicial, y cero o más estados para que sean estados de aceptación. Una función de
transición determina cómo cambia el estado cada vez que se procesa un símbolo de entrada.
Diagramas de transiciones. Son adecuados para representar autómatas mediante un grafo en el que los nodos son los estados
y los arcos se etiquetan con los símbolos de entrada, indicando las transiciones de dicho autómata. El estado inicial se
designa mediante una flecha y los estados de aceptación mediante círculos dobles.
Lenguaje de un autómata. El autómata acepta cadenas. Una cadena es aceptada si, comenzando por el estado inicial, la
transición causada por el procesamiento de los símbolos de dicha cadena, uno cada vez, lleva a un estado de aceptación.
En términos del diagrama de transiciones, una cadena es aceptada si sus símbolos son las etiquetas de un camino que va
desde el estado inicial hasta algún estado de aceptación.
Autómata finito no determinista. El AFN difiere del AFD en que el primero puede tener cualquier número de transiciones
(incluyendo cero) a los estados siguientes desde un estado dado para un determinado símbolo de entrada.
Construcción de subconjuntos. Si se tratan los conjuntos de un AFN como estados de un AFD, es posible convertir
cualquier AFN en un AFD que acepta el mismo lenguaje.
Transiciones-ε . Podemos extender el AFN permitiendo transiciones para una entrada vacía, es decir, para ningún símbolo de
entrada. Estos AFN extendidos puede convertirse en autómatas AFD que aceptan el mismo lenguaje.
Aplicaciones de búsquedas en texto. Los autómatas finitos no deterministas son una forma útil de representar reconocedores
de patrones que exploran un texto largo para localizar una o más palabras clave. Estos autómatas pueden simularse
directamente por software o pueden convertirse primero en un AFD, que a continuación se simula.
Alfabetos. Un alfabeto es cualquier conjunto finito de símbolos.
Cadenas de caracteres. Una cadena es una secuencia de símbolos de longitud finita.
Lenguajes y problemas. Un lenguaje es un conjunto (posiblemente infinito) de cadenas, donde los símbolos símbolo de
todas ellas se han seleccionado de un determinado alfabeto. Cuando las cadenas de un lenguaje se interpretan de alguna
manera, la cuestión de si una cadena pertenece o no al lenguaje se dice, en ocasiones, que es un problema.
Máquina de Turing. La máquina de Turing es una máquina de computación abstracta con la potencia tanto de las
computadoras reales como de otras definiciones matemáticas de lo que se puede calcular. La MT consta de una unidad de
control y de una cinta infinita dividida en casillas. Cada casilla almacena uno de los símbolos del conjunto finito de
símbolos de cinta y una casilla corresponde a la posición actual de la cabeza de la cinta. La MT realiza movimientos
basados en su estado actual y en el símbolo de cinta de la casilla a la que apunta la cabeza de la cinta. En un movimiento,
cambia el estado, sobreescribe la celda señalada por la cabeza con algún símbolo de cinta y mueve la cabeza una celda
hacia la izquierda o hacia la derecha.
Son autómatas que modelan la potencia de las computadoras reales. Nos permiten analizar la decidibilidad, es decir, el
problema de qué puede o no puede hacer una computadora. También nos permiten distinguir los problemas tratables
(aquellos que pueden resolverse en un tiempo polinómico) de los problemas intratables (los que no se pueden resolver en
un tiempo polinómico).
Aceptación en una máquina de Turing. Inicialmente, la MT tiene en la cinta su entrada, una cadena de longitud finita de
símbolos de cinta, y el resto de las casillas contienen un espacio en blanco. Este último es uno de los símbolos de cinta y
la entrada se selecciona de un subconjunto de los símbolos de cinta que no incluye el espacio en blanco, y se conocen
como símbolos de entrada. La MT acepta su entrada si llega a un estado de aceptación.
143
Lenguajes recursivamente enumerables. Los lenguajes aceptados por la MT son los denominados lenguajes
recursivamente enumerables (RE). Por tanto, los lenguajes RE son aquellos lenguajes que pueden ser reconocidos o
aceptados por cualquier clase de dispositivos de computación.
Máquinas de Turing no deterministas. La MTN tiene un número finito de posibilidades para realizar el siguiente
movimiento (estado, nuevo símbolo y movimiento de la cabeza) para cada estado y símbolo señalado. Acepta una entrada
si cualquier secuencia de elecciones lleva a una configuración que corresponde a un estado de aceptación. Aunque
aparentemente más potente que la MT determinista, la MTN no es capaz de reconocer ningún lenguaje que no sea
recursivamente enumerable.
Simulación de una máquina de Turing mediante una computadora real. En principio, es posible, simular una máquina de
Turing mediante una computadora real si aceptamos que existe un suministro potencialmente infinito de un dispositivo de
almacenamiento extraíble, un disco, para simular la parte en que no hay espacios en blanco de la cinta de la MT. Puesto
que los recursos físicos con los que se construyen los discos no son infinitos, este argumento es cuestionable. Sin
embargo, dado que la cantidad de dispositivos de almacenamiento que existe en el universo es desconocida y, sin duda,
muy grande, la suposición de que existen recursos infinitos, como en una cinta de una MT, es realista en la práctica y
generalmente se acepta.
Simulación de una computadora mediante una máquina de Turing. Una máquina de Turing puede simular el
almacenamiento y la unidad de control de una computadora real empleando una cinta para almacenar todas las posiciones
y los contenidos correspondientes a los registros, la memoria principal, los discos y otros dispositivos de almacenamiento.
Por tanto, podemos estar seguros de que algo que una máquina de Turing no pueda hacer, tampoco lo podrá hacer una
computadora real.
Lenguajes recursivos y recursivamente enumerables. Los lenguajes aceptados por lasmáquinas de Turing son
recursivamente enumerables (RE) y el subconjunto de los lenguajes RE que son aceptados por una MT que siempre se
para se denominan lenguajes recursivos.
Decidibilidad e indecidibilidad. “Decidible” es sinónimo de “recursivo”, aunque se suele decir que los lenguajes son
“recursivos” y los problemas (que son lenguajes interpretados como una cuestión) son “decidibles”. Si un lenguaje no es
recursivo, entonces decimos que el problema expresado por dicho lenguaje es “indecidible”.
El lenguaje . Este lenguaje es el conjunto de cadenas de ceros y unos que, cuando se interpretan como una MT, no forman
parte del lenguaje de dicha MT. El lenguaje es un buen caso de un lenguaje que no es RE; es decir, que ninguna
máquina de Turing acepta.
El lenguaje universal. El lenguaje Lu está formado por cadenas que se interpretan como la codificación de una MT seguida
de una entrada para dicha MT. La cadena pertenece a si la MT acepta dicha entrada. es un buen caso de un
lenguaje que es RE pero no recursivo.
Reduccciones en tiempo polinómico. Si podemos transformar casos de un problema en tiempo polinómico en casos de un
segundo problema que proporciona la misma respuesta (sí o no), entonces decimos que el primer problema es reducible
en tiempo polinómico al segundo.
Problemas NP-completos. Un lenguaje es NP-completo si pertenece a NP, y existe una reducción en tiempo polinómico de
cada uno de los lenguajes de NP al lenguaje en cuestión. Estamos casi seguros de que ninguno de los problemas NP-
completos pertenece a P, y el hecho de que nadie haya encontrado un algoritmo en tiempo polinómico para ninguno de los
miles de problemas NP-completos conocidos refuerza la evidencia de que ninguno de ellos está en P.
Problemas de satisfacibilidad NP-completos. El teorema de Cook demostró el primer problema NPcompleto (si una expresión booleana
es satisfacible) reduciendo todos los problemas en NP al problema SAT en tiempo polinómico. Además, el problema sigue siendo NP-
completo incluso aunque la expresión se restrinja a un producto de cláusulas, estando cada una de estas cláusulas formada sólo por tres
literales: el problema 3SAT.
top related