4. Modelo de programación lógica


Modelo de Programación Lógica – IT Tehuacán

Instituto Tecnológico de Tehuacán

Ingeniería en Sistemas Computacionales | Programación Lógica y Funcional

Unidad 2: Desarrollo Avanzado del Modelo de Programación Lógica
Importancia del Modelo de Programación Lógica

La Programación Lógica reemplaza el paradigma imperativo tradicional de «instrucciones paso a paso» por un modelo declarativo fundamentado en la lógica de predicados. En lugar de programar el control del flujo de ejecución, el desarrollador especifica la estructura del conocimiento mediante relaciones y reglas de inferencia, dejando que la máquina resuelva el problema de razonamiento automáticamente.

Inteligencia Artificial

Base esencial para la construcción de Motores de Inferencia, Sistemas Expertos y Razonamiento Automatizado.

Procesamiento de Lenguaje

Facilita la creación de parsing sintáctico y gramáticas de cláusulas definidas (DCG) de forma natural.

Búsqueda en Grafos

Automatización de consultas declarativas complejas y resolución de problemas de optimización combinatoria.

1. Introducción y Semántica de los Programas Lógicos

Un programa lógico consta de un conjunto de cláusulas de Horn. La semántica define el significado formal de dichas cláusulas a través de tres interpretaciones interconectadas:

Semántica Declarativa

Define el significado basándose en el valor de verdad lógico de las fórmulas. Determina qué consecuencias lógicas se derivan directamente del programa.

Semántica Operacional

Define cómo se ejecuta el programa paso a paso utilizando la regla de inferencia de Resolución SLD y la unificación de términos.

Semántica Punto Fijo

Interpreta el programa como un operador de punto fijo (Operador de Herbrand) que expande el conocimiento hasta alcanzar la máxima deducción posible.

2. Representación Clausada del Conocimiento y Consultas

El conocimiento en Prolog se almacena en la Base de Cláusulas (o Base de Conocimientos) compuesta de dos tipos fundamentales de sentencias y una forma especial de interacción:

Elemento Sintaxis Formal / Lógica Sintaxis Prolog Descripción
Hecho P (Literal positivo) humano(socrates). Afirmación incondicional que siempre es verdadera.
Regla P ← Q₁ ∧ Q₂ mortal(X) :- humano(X). Relación condicional (P es verdad si Q₁ y Q₂ son verdades).
Consulta (Goal) ← P (Literal negativo) ?- mortal(socrates). Pregunta que dispara la refutación del motor de inferencia.
3. Espacios de Búsqueda en Programación Lógica

Cuando se efectúa una consulta, el motor de inferencia construye implícitamente un Árbol de Búsqueda SLD. Prolog recorre este árbol usando una estrategia en **profundidad (Depth-First Search)** con **Backtracking** (retroceso sistemático).

?- abuelo(juan, Nieto).
├── [Regla: abuelo(X,Y) :- padre(X,Z), padre(Z,Y)]
│ ├── ?- padre(juan, Z), padre(Z, Nieto).
│ │ ├── [Hecho: padre(juan, pedro) -> Z = pedro]
│ │ │ ├── ?- padre(pedro, Nieto).
│ │ │ │ ├── [Hecho: padre(pedro, maria)] -> ÉXITO: Nieto = maria
│ │ │ │ └── [Hecho: padre(pedro, luis)] -> ÉXITO: Nieto = luis
│ │ └── [Hecho: padre(juan, carlos) -> Z = carlos]
│ │ └── ?- padre(carlos, Nieto). -> FALLO (Backtracking)
4. Números, Listas y Árboles

Para procesar estructuras de datos complejas, Prolog utiliza términos compuestos y recursión.

A. Aritmética con Números

En Prolog, las operaciones aritméticas no se evalúan automáticamente. Se requiere el operador especial is.

% Suma recursiva de los elementos de una lista
suma([], 0).
suma([Cabeza|Cola], Total) :-
    suma(Cola, SubTotal),
    Total is Cabeza + SubTotal.

B. Manipulación de Listas

Las listas se dividen estructuralmente mediante la notación de cabeza y cola: [Cabeza | Cola].

% Comprobar pertenencia en una lista
miembro(X, [X|_]).
miembro(X, [_|Cola]) :- miembro(X, Cola).

% Concatenación de listas
concatenar([], L, L).
concatenar([X|L1], L2, [X|L3]) :- concatenar(L1, L2, L3).

C. Estructura de Árboles Binarios

Los árboles se representan mediante términos functores como arbol(Valor, Izq, Der) o nil para hojas vacías.

% Recorrido In-Order de un Árbol Binario
inorder(nil, []).
inorder(arbol(V, Izq, Der), Recorrido) :-
    inorder(Izq, RecIzq),
    inorder(Der, RecDer),
    concatenar(RecIzq, [V|RecDer], Recorrido).
5. Control de Búsqueda y Predicados Mitológicos

A. Operador Corte (Cut: !)

El corte es una meta que siempre tiene éxito pero poda las ramas de búsqueda del árbol SLD, **impidiendo el backtracking** sobre las alternativas previas.

B. Predicados Meta-Lógicos / Mitológicos

Son predicados incorporados que permiten inspeccionar, alterar y manipular la estructura de los términos e interactuar con la base de conocimiento de forma dinámico-reflexiva.

var(X) / nonvar(X)

Verifica si una variable está libre (no instanciada) o si ya tiene un valor asignado.

functor(T, F, A)

Inspecciona o construye un término compuesto con nombre F y aridad A.

arg(N, T, A)

Accede al N-ésimo argumento A de un término estructurado T.

asserta/assertz/retract

Agrega o elimina reglas y hechos en tiempo de ejecución de la base de datos dinámica.

Ejercicios Prácticos Resueltos
Ejercicio 1 (Aritmética y Listas): Implementar un predicado en Prolog longitud(Lista, N) que calcule el número de elementos de una lista sin utilizar el predicado nativo length/2.
% Caso base: La lista vacía tiene longitud 0
longitud([], 0).

% Caso recursivo: La longitud es 1 + la longitud de la cola
longitud([_|Cola], N) :-
    longitud(Cola, NSub),
    N is NSub + 1.
Ejercicio 2 (Manipulación de Árboles): Escribir un predicado contar_hojas(Arbol, Hojas) que determine el número total de nodos hoja en un árbol binario.
% Caso base: Árbol vacío
contar_hojas(nil, 0).

% Caso base: Nodo hoja (subárboles nulos)
contar_hojas(arbol(_, nil, nil), 1) :- !.

% Caso recursivo: Nodo interno
contar_hojas(arbol(_, Izq, Der), Total) :-
    contar_hojas(Izq, HIzq),
    contar_hojas(Der, HDer),
    Total is HIzq + HDer.
Ejercicio 3 (Control de Búsqueda): Explicar el comportamiento del predicado de máximo entre dos números utilizando el corte !: maximo(A, B, Max).
% Si A >= B, la solución es A y no se evalúan otras alternativas
maximo(A, B, A) :- A >= B, !.
maximo(_, B, B).

Explicación: Si A >= B es verdadero, el corte ! destruye la opción de backtracking evitando ejecutar innecesariamente la segunda regla.

Examen de Conocimientos (15 Preguntas)

1. ¿En qué se diferencia el modelo de programación lógica del imperativo?

2. La semántica operadora de Prolog se basa en:

3. ¿Qué representa una regla en Prolog?

4. ¿Cuál es el orden de búsqueda predeterminado en el árbol SLD de Prolog?

5. ¿Para qué sirve el operador `is` en Prolog?

6. En la sintaxis de listas `[A | B]`, ¿qué representan `A` y `B` respectivamente?

7. ¿Cuál es el efecto directo del operador Corte `!`?

8. El predicado meta-lógico `var(X)` se evalúa como VERDADERO si:

9. ¿Cómo se representa habitualmente un nodo en un árbol binario en Prolog?

10. ¿Qué realiza el predicado dinámico `assertz(Clausula)`?

11. ¿Qué es el «Backtracking»?

12. ¿Qué ocurre si ejecutamos la consulta `?- 5 = 2 + 3.` en Prolog?

13. ¿Cuál es la función del predicado `functor(Término, Nombre, Aridad)`?

14. ¿Qué es la Unificación?

15. ¿Qué diferencia principal existe entre `asserta/1` y `assertz/1`?