Pregunta central

¿Cómo demostramos que un algoritmo funciona para todas sus entradas válidas y que siempre termina?

Idea central

La inducción permite pasar de un caso inicial a todos los siguientes. En un ciclo, demostramos que una propiedad útil —la invariante— se cumple antes de empezar y se conserva después de cada iteración. Al combinarla con la condición de salida obtenemos la corrección; para garantizar terminación, identificamos además una cantidad que disminuye y no puede disminuir indefinidamente.

← Clase anterior: implementación y tiempos · Clase siguiente: grafos →

Fuente: Diapositivas completas (33 páginas). La nota integra las revelaciones sucesivas de las diapositivas en explicaciones continuas. Los ejemplos adicionales, ejercicios y aclaraciones se añaden como apoyo de estudio.

Mapa de la clase

flowchart TD
    I["Inducción: base y paso inductivo"] --> V["Invariantes: propiedades entre iteraciones"]
    V --> G["Gale–Shapley: conservar un emparejamiento"]
    V --> M["Mínimo: resumir el prefijo recorrido"]
    V --> D["Dos punteros: descartar sin perder soluciones"]
    D --> T["Terminación: el intervalo se acorta"]
    D --> C["Corrección: toda solución permanece dentro"]
    T --> E["Costo: a lo más n − 1 iteraciones"]

1. Inducción matemática

Diapositivas 2–7.

1.1. La idea del dominó

Sea una afirmación sobre un entero . Para demostrarla para todo :

  1. Caso base: demostrar directamente.
  2. Hipótesis inductiva: tomar un arbitrario y suponer .
  3. Paso inductivo: usando esa hipótesis, demostrar .
  4. Conclusión: por inducción, vale para todo entero .
flowchart LR
    B["P(n₀): primera pieza"] --> C["P(n₀ + 1)"]
    C --> D["P(n₀ + 2)"]
    D --> E["…"]
    H["Regla general: P(k) implica P(k + 1)"] -.-> C
    H -.-> D

La base tira la primera pieza; el paso demuestra que cualquier pieza tira la siguiente. Probar solamente varios casos no garantiza que la cadena continúe.

💎 Gema: suponer no es concluir

Suponemos para demostrar la implicación . No podemos suponer : eso sería usar como premisa lo que queremos probar.

El inicio puede ser , u otro entero adecuado. También podemos probar solamente un rango finito ; en ese caso basta el paso para .

1.2. Ejemplo: suma de los primeros enteros

Queremos demostrar, para todo :

Base . La suma es y la fórmula da .

Hipótesis. Suponemos .

Paso. La suma nueva contiene la anterior y un término extra:

Esta es exactamente la fórmula de . Por inducción, se cumple para todo .

Ejemplo numérico: si sabemos que , agregar produce . Este ejemplo ilustra el paso general, pero no lo sustituye.

1.3. Ejemplo:

Base : .

Hipótesis: , para un arbitrario.

Paso:

La primera desigualdad usa la hipótesis y el hecho de multiplicar por un número positivo. La segunda equivale a . Por tanto, .

Si usamos , verificamos además por separado.

Precisión de las diapositivas 5–6

De no se obtiene directamente . El puente necesario es , que aparece anotado en la diapositiva 6.

2. Invariantes: inducción sobre la ejecución

Diapositiva 8 y estructura utilizada en los ejemplos siguientes.

Una invariante es una afirmación lógico-matemática que se cumple en un punto específico de la ejecución. En esta clase, ese punto será la cabecera del ciclo, antes de evaluar su condición, incluyendo la evaluación final que resulta falsa.

No exige que los valores permanezcan constantes. Por ejemplo, menor puede cambiar varias veces mientras sigue siendo el mínimo de la parte ya recorrida.

Inducción matemáticaPrueba de un ciclo
Variable Número de visitas a la cabecera
Caso baseLa inicialización establece la propiedad
Hipótesis La propiedad vale antes del cuerpo
Paso a Ejecutar el cuerpo conserva la propiedad
Aplicación finalInvariante y condición de salida implican el resultado
flowchart TD
    A["Inicialización"] --> B["Cabecera k: vale I"]
    B --> C{"¿Continúa el ciclo?"}
    C -->|Sí| D["Cuerpo k: cambia el estado"]
    D --> E["Cabecera k + 1: vuelve a valer I"]
    E --> C
    C -->|No| F["I y condición de salida ⇒ resultado correcto"]

Detalle de índices: al llegar por primera vez a la cabecera, y se han ejecutado cero cuerpos. Al llegar por vez , se han ejecutado cuerpos.

Corrección parcial, terminación y corrección total

  • Corrección parcial: si termina, devuelve una respuesta correcta.
  • Terminación: no puede ejecutar infinitas iteraciones.
  • Corrección total: corrección parcial más terminación.

Una variante es una medida de progreso, por ejemplo un entero no negativo que disminuye estrictamente en cada iteración que continúa. Su descenso prueba terminación.

💎 Gema: conservar y avanzar son obligaciones distintas

“ siempre es un emparejamiento” no impide que un programa repita eternamente el mismo estado. Una propiedad de seguridad explica qué se conserva; una medida de progreso explica por qué se termina.

No hay una receta universal para encontrar invariantes. Una estrategia útil es escribir primero qué queremos al salir y buscar una versión de esa propiedad que describa el progreso parcial.

3. Primer ejemplo: Gale–Shapley

Diapositivas 9–19. Modelo uno a uno: a lo más una pareja por hospital y estudiante.

3.1. Algoritmo y propiedad que queremos conservar

M ← conjunto vacío
mientras exista un hospital h libre con estudiantes pendientes:
    s ← primer estudiante de su lista al que h aún no ha propuesto
    registrar que h ya propuso a s
    si s está libre:
        agregar (h, s) a M
    si no, si s prefiere h a su pareja actual h':
        quitar (h', s) de M
        agregar (h, s) a M
    si no:
        mantener M sin cambios
devolver M

Invariante: en cada visita a la cabecera, es un emparejamiento: ningún hospital ni estudiante pertenece a más de una pareja.

3.2. Demostración por inducción en

Base . . No hay ninguna persona con dos parejas; la propiedad se cumple.

Hipótesis. Al inicio , es un emparejamiento.

Paso. Analizamos el cuerpo . El hospital proponente está libre por la condición de selección.

CasoActualizaciónPor qué conserva la invariante
está libreAmbos extremos estaban libres
prefiere a sobre Quitamos la pareja anterior antes de poner la nueva
rechaza a No cambia ninguna pareja

Los tres casos posibles conservan la propiedad; por inducción vale en todas las visitas.

flowchart TD
    H["Hospital h libre propone a s"] --> L{"¿s está libre?"}
    L -->|Sí| A["Agregar pareja h–s"]
    L -->|No| P{"¿s prefiere a h?"}
    P -->|Sí| R["Quitar h′–s y agregar h–s"]
    P -->|No| N["No cambiar M"]
    A --> I["Cada participante tiene a lo más una pareja"]
    R --> I
    N --> I

3.3. Ejemplo de las tres ramas

Supongamos que prefiere a , y ambos hospitales proponen primero a .

  1. . propone a , que está libre: .
  2. propone a , que prefiere cambiar: . Ahora queda libre.
  3. propone a , que está libre: .

Para ilustrar la rama de rechazo, si en el paso 2 prefiriera a , conservaría su pareja y seguiría libre. Esta es una alternativa al paso 2, no una propuesta repetida dentro de la misma ejecución.

💎 Gema: emparejamiento no significa estabilidad

La invariante probada garantiza a lo más una pareja. No demuestra por sí sola que todos tengan pareja ni que no exista una pareja bloqueante. Esas propiedades requieren argumentos adicionales; véanse 2026-08-18 ADA - Algoritmo_Gale–Shapley y 2026-08-20 ADA - GaleShapley-continuacion.

Complemento de terminación: con hospitales y estudiantes hay propuestas posibles. Cada iteración realiza una nueva; el número de propuestas pendientes disminuye. Por ello hay a lo más iteraciones.

4. Segundo ejemplo: mínimo de un arreglo

Diapositivas 20–22.

Entrada: arreglo no vacío , con . No necesita estar ordenado.

La versión siguiente explicita como while el for de las diapositivas para observar la cabecera final:

menor ← A[1]
c ← 2
mientras c ≤ n:
    si A[c] < menor:
        menor ← A[c]
    c ← c + 1
devolver menor

Invariante: en la visita a la cabecera,

Equivalentemente, menor es el mínimo de : lo ya procesado.

4.1. Prueba paso a paso

  1. Base: , y menor = A[1], el mínimo del prefijo de un elemento.
  2. Hipótesis: en la cabecera , menor es el mínimo de .
  3. Mantenimiento: se compara con . Si el nuevo elemento es menor, se reemplaza; si no, se conserva. Así obtenemos el mínimo de .
  4. Salida: al terminar, y . La invariante dice que menor es el mínimo de todo .
  5. Terminación: es no negativo en las cabeceras alcanzadas y disminuye en uno por cuerpo, hasta llegar a cero.

4.2. Traza de ejemplo

Para :

Visita Próximo índice Prefijo procesadomenor al llegarAcción
127Comparar con 3: actualizar
233Comparar con 8: conservar
343Comparar con 2: actualizar
452Condición falsa: devolver 2
flowchart LR
    A["Prefijo: 7 · mínimo 7"] --> B["Agregar 3 · mínimo 3"]
    B --> C["Agregar 8 · mínimo 3"]
    C --> D["Agregar 2 · mínimo 2"]

💎 Gema: una invariante describe lo ya ganado

Antes de comparar , ese elemento todavía no pertenece al prefijo procesado. Por eso escribimos , no .

Casos frontera: para , no se ejecuta el cuerpo y se devuelve . Para , acceder a es inválido; hay que rechazar la entrada o definir una salida especial. Con el modelo de costo constante, se hacen comparaciones: tiempo y espacio auxiliar .

5. Análisis de Target-Sum con dos punteros

Diapositivas 23–33.

5.1. Problema, condiciones y pseudocódigo

Dado un arreglo de enteros ordenado de manera no decreciente y un objetivo , devolver un par de índices distintos tal que , o indicar que no existe.

Se permiten negativos y valores repetidos. Índices distintos no significa valores distintos: en el par suma . Aunque el enunciado de la diapositiva usa “pares”, el pseudocódigo termina al encontrar el primero; no enumera todas las soluciones.

TARGET-SUM(A[1..n], T)
    lo ← 1
    hi ← n
    mientras lo < hi:
        suma ← A[lo] + A[hi]
        si suma = T:
            devolver (lo, hi)
        si suma > T:
            hi ← hi - 1
        si no:
            lo ← lo + 1
    devolver NO SE PUEDE

Para no entra al ciclo y devuelve correctamente NO SE PUEDE. Las fórmulas de cabeceras de las diapositivas se desarrollan suponiendo .

5.2. Por qué se mueve ese puntero

Si la suma es demasiado pequeña, descartamos lo: incluso combinado con el mayor valor del intervalo, no alcanza .

Si la suma es demasiado grande, descartamos hi: incluso combinado con el menor valor del intervalo, supera .

flowchart TD
    A["lo = 1; hi = n"] --> B{"¿lo menor que hi?"}
    B -->|No| N["No existe un par"]
    B -->|Sí| S["suma = A[lo] + A[hi]"]
    S --> C{"Comparar con T"}
    C -->|Igual| R["Devolver lo, hi"]
    C -->|Menor| L["Descartar lo: lo aumenta en 1"]
    C -->|Mayor| H["Descartar hi: hi disminuye en 1"]
    L --> B
    H --> B

💎 Gema: el orden justifica el descarte

No movemos un puntero por intuición solamente: descartamos de golpe todas las parejas que usan ese extremo dentro del intervalo. Sin orden, las desigualdades anteriores dejan de estar justificadas.

5.3. Ejemplo de las diapositivas, paso a paso

Visita lohiSumaDecisión
118Descartar índice 1
228Descartar índice 8
327Descartar índice 7
426Descartar índice 2
536Devolver

Explorador paso a paso

El intervalo activo conserva todas las soluciones posibles. Cada paso que no encuentra el objetivo elimina un extremo y reduce hi − lo en uno. El ejemplo sin solución permite observar la salida cuando ambos punteros coinciden.

5.4. Primera invariante: tamaño y terminación

En la visita a la cabecera:

Base: , , ; entonces .

Hipótesis: en la visita , .

Paso: si encontramos la suma, se retorna inmediatamente. Si hay una siguiente visita, exactamente un puntero se mueve una posición hacia el otro:

Terminación: a más tardar en la visita , , así que lo < hi es falso. Hay a lo más ejecuciones del cuerpo. La variante es .

💎 Gema: distancia y cantidad no son lo mismo

es la distancia entre punteros; el intervalo contiene posiciones. Cuando la distancia es cero queda un elemento, insuficiente para formar un par de índices distintos.

5.5. Segunda invariante: conservar todas las soluciones

Usaremos esta formulación precisa:

En palabras: si existe una pareja solución, sus dos índices siguen dentro del intervalo activo. Equivalentemente, ningún par que use al menos un índice descartado puede ser solución.

Base: el intervalo inicial contiene todos los índices. No hay índices descartados; la afirmación se cumple por vacuidad: no existe un elemento descartado que pueda violarla.

Hipótesis: en la cabecera , toda solución está dentro de .

Mantenimiento:

  1. Si la suma es menor que , para cada con tenemos . Ninguna solución del intervalo usa lo, así que lo podemos descartar. Los pares que ya tenían índices fuera estaban descartados por la hipótesis.
  2. Si la suma es mayor que , para cada con tenemos . Ninguna solución del intervalo usa hi, así que lo podemos descartar. La hipótesis cubre de nuevo los pares previamente descartados.
  3. Si la suma es igual, se retorna un par válido y no hay otra visita que demostrar.

Esto prueba la invariante por inducción.

Aclaración del enunciado en las diapositivas

La formulación literal es más débil

Las diapositivas 25 y 27–28 dicen que no hay una solución cuyos dos índices estén en el conjunto descartado . Eso no excluye una solución que combine un índice descartado con uno activo. Por sí sola, esa formulación no permite concluir que no hay solución al quedar un solo índice activo. La invariante reforzada de arriba cubre ambos tipos de pareja.

Por qué importa: en , , consideremos hipotéticamente lo = hi = 2. Entre los descartados no hay una pareja que sume , pero sí suma . Este estado no es alcanzable por el algoritmo correcto para esa entrada; muestra que la afirmación débil y lo = hi no bastan lógicamente.

5.6. El argumento por casos y contradicción de las diapositivas

Diapositivas 29–31, con índices aclarados. Antes de reducir hi, llamemos y ; después, hi vale . El índice recién descartado es y sabemos que .

La prueba de las diapositivas examina cómo se combina con lo descartado anteriormente:

  • Caso 1: índice derecho . Como , resulta .
  • Caso 2: índice izquierdo . Supongamos, para obtener una contradicción, que . Cuando se descartó en una iteración anterior, lo valía y hi tenía algún valor . Se movió lo porque . Como , concluimos , contradiciendo la supuesta igualdad.

Puede ocurrir si hi permaneció quieto mientras avanzaba lo; por eso aquí usamos , sin exigir .

Para cubrir además los índices activos , usamos . Así queda descartado cualquier compañero posible de .

Correcciones de lectura

El dibujo de las diapositivas 29–31 mezcla las etiquetas y ; aquí siempre designa al extremo que se elimina. En las diapositivas 30–31, la frase “Como hi avanzó” debe referirse a lo, porque el movimiento que se justifica con una suma menor que es lo ← lo + 1.

El caso de aumentar lo es simétrico. La demostración de la sección 5.5 evita reconstruir toda la historia porque guarda una hipótesis más fuerte.

5.7. Corrección total

Salida con un par: el cuerpo se ejecuta solamente si , así que los índices son distintos. El retorno exige además .

Salida NO SE PUEDE: para , queda . Por la segunda invariante toda solución tendría que estar dentro de un intervalo de un solo índice, que no contiene dos índices distintos. Por tanto, no existe solución. Para , tampoco hay dos índices y la salida es inmediata.

Terminación: ya fue demostrada con la primera invariante. En conjunto, esto establece corrección total.

Ejemplo sin solución: , . Primero , por lo que lo pasa a 2. Luego , por lo que hi pasa a 2. Al coincidir los punteros, devuelve NO SE PUEDE.

6. Tiempo de ejecución y espacio

Diapositivas 32–33. Para evitar confundir el objetivo con el tiempo , llamaremos al tiempo.

Suponiendo acceso al arreglo, suma y comparación de enteros de tamaño acotado en tiempo constante:

ParteCantidad máximaCosto por ejecución
Inicialización1
Evaluación de lo < hi
Cuerpo del ciclo
Retorno final11

Para , la cuenta de las diapositivas es:

Es una cota de peor caso, no necesariamente el tiempo exacto de todas las entradas: un retorno temprano realiza menos iteraciones y distintas ramas pueden tener distintos costos.

6.1. Demostración formal de

Para no depender del signo de , usamos, con constantes de costo no negativas y :

Así, y prueban .

Precisión sobre la última diapositiva

Su paso de a exige que esa constante sea no negativa. Como no se especifica esa relación entre costos, usamos la cota anterior, válida sin esa condición adicional.

Complementos: el peor caso es , porque existen entradas sin solución que ejecutan cuerpos. El mejor caso para es cuando los extremos iniciales ya suman . El espacio auxiliar es : solo se mantienen unos pocos índices y valores.

Si la entrada no está ordenada, ordenar primero mediante un algoritmo de y después buscar cuesta en total. Si se requieren los índices originales, hay que conservarlos junto a cada valor. Enumerar todas las parejas es un problema distinto y puede tener resultados.

💎 Gema: dos punteros, un solo presupuesto

No multiplicamos por : en cada iteración solo se consume una unidad de distancia entre los punteros. El presupuesto total es , aunque existan dos variables que cambian.

7. Guía para resolver una prueba de invariantes

  1. Especifica la entrada y la salida. ¿Hay orden? ¿Se permite arreglo vacío? ¿Los índices deben ser distintos?
  2. Fija el punto de observación. Por ejemplo, justo antes de evaluar la condición.
  3. Escribe la propiedad con índices precisos. ¿Describe lo procesado o las soluciones aún posibles?
  4. Prueba la base desde la inicialización. No uses una iteración que todavía no ocurre.
  5. Supón la propiedad en la cabecera . Analiza todas las ramas del cuerpo.
  6. Demuestra la propiedad en la cabecera . Aclara qué pasa si hay retorno anticipado.
  7. Usa la condición de salida para obtener el resultado. Si no alcanza, fortalece la invariante.
  8. Prueba terminación y cuenta operaciones. Una variante ayuda tanto a probar finitud como a acotar iteraciones.

8. Práctica con soluciones desplegables

A. Suma acumulada — ejemplo adicional

s ← 0
i ← 1
mientras i ≤ n:
    s ← s + i
    i ← i + 1
devolver s

¿Cuál es la invariante y por qué devuelve ?

B. Dos punteros con negativos

Ejecuta el algoritmo sobre con .

C. ¿Por qué no usar lo ≤ hi?

Considera y .

D. ¿Qué falla sin ordenar?

Ejecuta el algoritmo sobre y .

E. ¿Una invariante verdadera siempre es útil?

¿Basta “el arreglo no cambia” para demostrar que Target-Sum es correcto?

Conceptos para extraer

  • Inducción matemática: caso base, hipótesis y paso.
  • Invariante y variante de ciclo.
  • Corrección parcial y corrección total.
  • Vacuidad y demostración por contradicción.
  • Conservación de soluciones en algoritmos de dos punteros.

Resumen después de clase

La inducción demuestra propiedades generales a partir de una base y un paso que conserva la verdad. En algoritmos iterativos, las invariantes describen lo que sabemos en cada cabecera: Gale–Shapley conserva un emparejamiento y el algoritmo del mínimo resume el prefijo procesado. En Target-Sum, el orden permite descartar extremos sin perder soluciones y la distancia entre los punteros disminuye en cada paso. Esto prueba tanto corrección total como un tiempo lineal en el peor caso, conectando con el análisis asintótico de las clases anteriores.

Acciones de estudio

  • Rehacer las dos pruebas de inducción sin consultar la solución.
  • Explicar por qué la invariante del mínimo usa .
  • Reconstruir ambos casos de mantenimiento de Target-Sum.
  • Distinguir qué prueba cada invariante: seguridad, conservación de soluciones o progreso.
  • Revisar las aclaraciones de las diapositivas 25, 29–31 y 33 al repasar el material original.