59. Validación de algoritmos mediante razonamiento lógico

Validar un algoritmo mediante razonamiento lógico significa analizar si sus pasos producen el resultado esperado para todos los casos relevantes.

59.1 Introducción

Probar un programa ejecutándolo es importante, pero no siempre alcanza. También necesitamos razonar sobre lo que el algoritmo promete hacer.

La lógica permite revisar condiciones, casos, resultados esperados y propiedades que deben mantenerse durante la ejecución.

59.2 Qué significa validar un algoritmo

Validar un algoritmo consiste en comprobar que resuelve el problema correcto y que lo hace bajo las condiciones previstas.

No se trata solo de que funcione con un ejemplo, sino de entender por qué debería funcionar con todos los casos que pertenecen al problema.

59.3 Precondiciones

Una precondición describe qué debe cumplirse antes de ejecutar un algoritmo.

Precondición: la lista no está vacía.

Si un algoritmo calcula el promedio de una lista, necesita que la lista tenga al menos un elemento para evitar una división por cero.

59.4 Postcondiciones

Una postcondición describe qué debe cumplirse después de ejecutar el algoritmo, si las precondiciones eran verdaderas.

Postcondición: el resultado es el promedio de todos los valores de la lista.

La postcondición expresa el objetivo lógico del algoritmo.

59.5 Ejemplo con promedio

function promedio(valores) {
  let suma = 0;

  for (const valor of valores) {
    suma += valor;
  }

  return suma / valores.length;
}

Para validar este algoritmo, debemos razonar que suma acumula todos los valores y que valores.length representa la cantidad de elementos.

59.6 Casos válidos e inválidos

Un algoritmo debe distinguir qué entradas acepta y qué entradas rechaza.

Entrada Situación Acción esperada
[4, 6, 8] Lista válida Calcular promedio
[] Lista vacía Rechazar o informar error
null No hay lista Rechazar o informar error

59.7 Invariantes

Un invariante es una propiedad que se mantiene verdadera durante una parte del algoritmo, especialmente dentro de un ciclo.

En el cálculo de una suma, después de cada iteración, la variable suma debe contener la suma de los elementos procesados hasta ese momento.

59.8 Invariante de un ciclo

let suma = 0;

for (const valor of valores) {
  suma += valor;
}

Invariante: al terminar cada vuelta, suma contiene la suma de todos los valores ya recorridos.

Si este invariante se mantiene hasta el final, entonces suma contiene la suma total de la lista.

59.9 Razonamiento por casos

El razonamiento por casos consiste en revisar cada situación posible por separado.

Por ejemplo, para validar una regla de acceso podemos analizar:

  • Usuario activo con permiso.
  • Usuario activo sin permiso.
  • Usuario inactivo con permiso.
  • Usuario inactivo sin permiso.

59.10 Tabla lógica de validación

Para la condición usuarioActivo && tienePermiso, la tabla permite verificar todos los casos.

Usuario activo Tiene permiso Puede acceder
false false false
false true false
true false false
true true true

59.11 Casos límite

Los casos límite son valores que están justo en el borde de una condición.

if (edad >= 18) {
  permitirIngreso();
}

Para validar esta regla, debemos revisar edades como 17, 18 y 19. El valor 18 es especialmente importante porque define el límite.

59.12 Razonamiento sobre terminación

Además de producir el resultado correcto, un algoritmo debe terminar.

En un ciclo, debe existir alguna condición que avance hacia el final.

while (contador < 10) {
  contador++;
}

La variable contador aumenta en cada vuelta, por lo que eventualmente dejará de cumplir la condición.

59.13 Corrección parcial y total

La corrección parcial significa: si el algoritmo termina, su resultado es correcto.

La corrección total agrega otra exigencia: además de ser correcto, el algoritmo debe terminar.

Ambas ideas son útiles para razonar con precisión sobre algoritmos.

59.14 Relación con pruebas

El razonamiento lógico no reemplaza las pruebas, pero ayuda a elegir mejores casos de prueba.

Una buena estrategia combina:

  • Casos normales.
  • Casos límite.
  • Casos inválidos.
  • Combinaciones importantes de condiciones.

59.15 Errores comunes

  • Validar solo con ejemplos favorables.
  • No definir precondiciones.
  • Olvidar casos límite.
  • No razonar sobre la terminación de ciclos.
  • Confundir que un algoritmo funcione una vez con que sea correcto en general.

59.16 Qué debes recordar de este tema

  • Validar un algoritmo implica razonar sobre su comportamiento esperado.
  • Las precondiciones indican qué debe cumplirse antes de ejecutar.
  • Las postcondiciones indican qué debe cumplirse al finalizar.
  • Los invariantes ayudan a razonar sobre ciclos.
  • Las tablas y los casos límite mejoran la calidad de la validación.

59.17 Conclusión

La validación de algoritmos mediante razonamiento lógico permite ir más allá de probar ejemplos aislados. Al analizar condiciones, invariantes, casos y resultados esperados, podemos construir programas más confiables.

En el próximo tema estudiaremos aplicaciones de la lógica en bases de datos, inteligencia artificial y sistemas expertos.