¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Reglas y recursión en Prolog

Después de esta lección: Puedo escribir una regla que usa otros hechos, incluida una recursiva.

Lección de 55 min7 comandosLaboratorio de Prolog: programación lógica con hechos, reglas y preguntas, en el navegador

Definir abuelo sin escribir cada caso

Una regla de Prolog define una relación nueva, como abuelo o hermano, a partir de hechos que ya tienes. Con ella, Prolog contesta preguntas que nadie escribió como hecho, y una regla puede incluso usarse a sí misma.

Así se calcula quién es antepasado de quién en un árbol familiar con una sola regla, sea cual sea su tamaño.

Al final de esta lección

Nota

Puedo escribir una regla que usa otros hechos, incluida una recursiva.

Palabras clave

PalabraQué significaEjemplo
Reglaun hecho que es cierto si otros lo soncheap(I) :- price(I, P), P < 3.
Cabezalo que afirma la regla, a la izquierda de :-
Cuerpolo que debe cumplirse, a la derecha de :-
Recursiónuna regla que se usa a sí misma
Caso basela parte que no se usa a sí misma y que para la recursión

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una regla es un hecho con condiciones

Una regla tiene dos mitades unidas por :-, que se lee "si". A la izquierda está la cabeza: lo que afirmamos. A la derecha está el cuerpo: lo que debe cumplirse.

En el cuerpo, una coma significa "y". cheap(Item) :- price(Item, P), P < 3. dice: un artículo es barato si tiene un precio P y P es menor que 3.

Una regla sobre precios

Código: prolog
price(bread, 1).
price(milk, 2).
price(cheese, 7).

% Un artículo es barato si su precio es menor que 3.
cheap(Item) :- price(Item, P), P < 3.

% Preguntar cheap(X) da bread y milk.

Lee las reglas del laboratorio

Comando
docker exec prolog cat family.pl

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Una regla se pregunta como un hecho

Cuando preguntas por grandparent(tom, X), Prolog busca primero parent(tom, Y) y, con cada Y, busca parent(Y, X). Es el mismo trabajo que dos bucles uno dentro de otro.

Los Runs usan los hechos de la lección anterior. Recuerda que todo lo que Prolog escribe sale en inglés.

Los nietos de tom

Comando
docker exec prolog swipl -q -g "forall(grandparent(tom, X), (write(X), nl))" -t halt family.pl

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Quién es abuelo de eve

Comando
docker exec prolog swipl -q -g "forall(grandparent(X, eve), (write(X), nl))" -t halt family.pl

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Todas las parejas de hermanos

Comando
docker exec prolog swipl -q -g "forall(sibling(X, Y), (write(X-Y), nl))" -t halt family.pl

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Ejemplo: grandparent(tom, X) paso a paso

PasoQué busca PrologResultado
1parent(tom, Y)Y vale ann, y después ben
2Con Y = ann: parent(ann, X)X vale cat
3Con Y = ben: parent(ben, X)X vale dan, y después eve
4Respuestascat, dan y eve

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una regla recursiva se usa a sí misma

Un antepasado es un padre, o el antepasado de un padre. Esa frase se usa a sí misma, y por eso se escribe con recursión.

Hacen falta dos reglas. La primera, ancestor(X, Y) :- parent(X, Y)., es el caso base: no se llama a sí misma y para la búsqueda. La segunda, ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y)., sube un escalón y vuelve a preguntar.

Jefes y jefes de jefes

Código: prolog
boss(rosa, luis).
boss(luis, ines).
boss(ines, jorge).

% Caso base: un jefe directo.
above(X, Y) :- boss(X, Y).
% Caso recursivo: el jefe de alguien que está por encima.
above(X, Y) :- boss(X, Z), above(Z, Y).

Todos los antepasados de tom

Comando
docker exec prolog swipl -q -g "forall(ancestor(tom, X), (write(X), nl))" -t halt family.pl

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Quiénes son antepasados de eve

Comando
docker exec prolog swipl -q -g "forall(ancestor(X, eve), (write(X), nl))" -t halt family.pl

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Una pregunta que no se cumple

Comando
docker exec prolog swipl -q -g "(ancestor(cat, tom) -> write(yes) ; write(no)), nl" -t halt family.pl

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un error frecuente

Advertencia

Mucha gente cree que basta con la regla recursiva. Sin caso base, la recursión no tiene dónde parar y Prolog sigue hasta quedarse sin memoria. Escribe siempre primero el caso más simple, y después el que lo usa.

La regla abuelo, con dos bucles

Código: python
# Una regla de abuelo son dos búsquedas una dentro de otra.
facts = [["tom", "ann"], ["tom", "ben"], ["ann", "cat"], ["ben", "dan"], ["ben", "eve"]]


def children_of(person):
    found = []
    for pair in facts:
        if pair[0] == person:
            found.append(pair[1])
    return found


person = "tom"
for child in children_of(person):
    for grandchild in children_of(child):
        print(person, "es abuelo de", grandchild)
# Cambia "tom" por "ben" y vuelve a ejecutar.

Para ir más lejos

Piensa en dos cambios. ¿Qué pasaría si invirtieras el orden del cuerpo y escribieras primero ancestor(Z, Y) y después parent(X, Z)? Prolog podría quedarse dando vueltas.

Explica con tus palabras por qué la regla sibling lleva X \= Y al final, y qué pareja de hermanos aparecería de más sin esa condición.

Sobre este laboratorio y su código: Laboratorio de Prolog: programación lógica con hechos, reglas y preguntas, en el navegador

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.