Tabla de Contenidos

Práctica Nro.: 1

Enunciados

  1. Ingresar a la base de conocimientos, los datos (hechos) correspondientes a un árbol genealógico, mediante los predicados Padre_de y Madre_de.
  2. Utilizando los hechos anteriores, definir los siguientes predicados: Hijo_de, Abuelo_de, Primo_de, Tío_de, Sobrino_de, Nieto_de, Ancestro_de, etc.
  3. Efectuar consultas a la base de conocimientos anterior.
  4. Definir un predicado que calcule el factorial de un número.
  5. Definir un predicado que calcule la sumatoria de todos los números enteros desde 1 hasta un número dado(pasado como parámetro).
  6. Definir un predicado para calcular un término de la sucesión de Fibonacci (cada término es igual a la suma de los dos anteriores).
  7. Definir un predicado que calcule el producto de dos números por medio de sumas sucesivas.
  8. Ingresar a al base de conocimientos las distancias entre diferentes ciudades adyacentes de la siguiente forma:
    Distancia(Ciudad1,Ciudad2,Distancia)
    y definir un predicado, que permita calcular la distancia entre dos ciudades cualesquiera.
  9. Hacer un predicado que calcule la sumatoria de los dígitos de un número.
  10. Hacer un predicado que calcule la potencia enésima de un número.
  11. Se cuenta en la base de conocimientos con hechos de la siguiente forma :
    PRODUCTO(Nro_Prod,Nro_sub_Prod) Definir un predicado que permita obtener todos los Sub-productos de un producto dado.
    1. En el primer nivel
    2. En todos los niveles

Resueltos

Ej 1, 2 y 3

% Los hago en base a algo que encontré en internet sobre la familia Simpson.
domains
	personaje = symbol
predicates
	% El primer personaje es padre del segundo.
	nondeterm padre_de(personaje, personaje).
	% El primer personaje es madre del segundo.
	nondeterm madre_de(personaje, personaje).
	
	nondeterm hijo_de(personaje, personaje).
	nondeterm abuelo_de(personaje, personaje).
	nondeterm abuela_de(personaje, personaje).
	nondeterm primo_de(personaje, personaje).
	nondeterm tio_de(personaje, personaje).
	nondeterm sobrino_de(personaje, personaje).
	nondeterm nieto_de(personaje, personaje).
	nondeterm ancestro_de(personaje, personaje).
	
clauses
% Ej 1
% Ingresar a la base de conocimientos, los datos (hechos) correspondientes a un árbol genealógico, mediante los predicados de Padre_de y Madre_de.

	% Prolog pide que las clausulas estén agrupadas.

	% Abuelos de Homero
	padre_de("Orville Simpson", "Abraham Simpson").
	% Padres de Homero y su hermano Herb Powell (Adoptado)
	padre_de("Abraham Simpson","Homero Simpson").
	padre_de("Abraham Simpson","Herb Powell").
	% Hijos de Homero.
	padre_de("Homero Simpson","Bart Simpson").
	padre_de("Homero Simpson","Lisa Simpson").
	padre_de("Homero Simpson","Maggie Simpson").
	% Padres de Marge
	padre_de("Clancy Bouvier", "Marge Bouvier").
	% Hermanas de Marge
	padre_de("Clancy Bouvier", "Patty Bouvier").
	padre_de("Clancy Bouvier", "Selma Bouvier").


	% Abuelos de Homero
	madre_de("Yuma Hickman", "Abraham Simpson").	
	% Padres de Homero y su hermano Herb Powell (Adoptado)
	madre_de("Penelope Olsen","Homero Simpson").
	madre_de("Penelope Olsen","Herb Powell").

	% Hijos de Marge
	madre_de("Marge Bouvier","Bart Simpson").
	madre_de("Marge Bouvier","Lisa Simpson").
	madre_de("Marge Bouvier","Maggie Simpson").
	
	% Padres de Marge
	madre_de("Jacqueline Bouvier", "Marge Bouvier").
	
	% Hermanas de Marge
	madre_de("Jacqueline Bouvier", "Patty Bouvier").
	madre_de("Jacqueline Bouvier", "Selma Bouvier").
	
% Ej 2
% Utilizando los hechos anteriores, definir los siguientes predicados: Hijo_de, Abuelo_de, Primo_de, Tío_de, Sobrino_de, Nieto_de, Ancestro_de, etc.

	hijo_de(Hijo, Padre) :- padre_de(Padre, Hijo).
	hijo_de(Hijo, Madre) :- madre_de(Madre, Hijo).
	
	abuelo_de(Abuelo, Nieto) :- padre_de(Padre, Nieto), padre_de(Abuelo, Padre).
	abuelo_de(Abuelo, Nieto) :- madre_de(Madre, Nieto), padre_de(Abuelo, Madre).
	
	abuela_de(Abuela, Nieto) :- padre_de(Padre, Nieto), madre_de(Abuela, Padre).
	abuela_de(Abuela, Nieto) :- madre_de(Madre, Nieto), madre_de(Abuela, Madre).
	% Son primos si tienen solo un abuelo en común.
	primo_de(Primo1, Primo2) :- abuelo_de(Abuelo1, Primo1), abuelo_de(Abuelo1, Primo2), abuelo_de(Abuelo2, Primo2), not (abuelo_de(Abuelo2, Primo1)).
	primo_de(Primo1, Primo2) :- abuela_de(Abuela1, Primo1), abuela_de(Abuela1, Primo2), abuela_de(Abuela2, Primo2), not (abuela_de(Abuela2, Primo1)).
	
	tio_de(Tio, Sobrino) :- padre_de(Padre, Sobrino), Padre<>Tio, padre_de(Abuelo, Padre), padre_de(Abuelo, Tio).
	tio_de(Tio, Sobrino) :- padre_de(Padre, Sobrino), Padre<>Tio, madre_de(Abuela, Padre), madre_de(Abuela, Tio).
	tio_de(Tio, Sobrino) :- madre_de(Madre, Sobrino), Madre<>Tio, padre_de(Abuelo, Madre), padre_de(Abuelo, Tio).
	tio_de(Tio, Sobrino) :- madre_de(Madre, Sobrino), Madre<>Tio, madre_de(Abuela, Madre), madre_de(Abuela, Tio).

	
	% Si el padre y el tío tienen el mismo padre, y no son el mismo personaje, entonces es el tío.
	sobrino_de(Sobrino, Tio) :- padre_de(Padre,Sobrino), padre_de(Abuelo, Padre), padre_de(Abuelo, Tio), Tio<>Padre.
	% Si la madre y el tío tienen el mismo padre, y no son el mismo personaje, entonces es el tío.
	sobrino_de(Sobrino, Tio) :- madre_de(Madre,Sobrino), padre_de(Abuelo, Madre), padre_de(Abuelo, Tio), Tio<>Madre.
% Si habilito las siguientes opciones acepta como tíos a meidos tíos y medias tías, pero me los tira 4 veces a cada uno.
	% Si el padre y la tía tienen el mismo padre, y no son el mismo personaje, entonces es la tía.
%	sobrino_de(Sobrino, Tia) :- padre_de(Padre,Sobrino), padre_de(Abuelo, Padre), padre_de(Abuelo, Tia), Tia<>Padre.
	% Si la madre y la tía tienen el mismo padre, y no son el mismo personaje, entonces es la tía.
%	sobrino_de(Sobrino, Tia) :- madre_de(Madre,Sobrino), padre_de(Abuelo, Madre), padre_de(Abuelo, Tia), Tia<>Madre.
	
	% Si el padre y el tío tienen la misma madre, y no son el mismo personaje, entonces es el tío.
%	sobrino_de(Sobrino, Tio) :- padre_de(Padre,Sobrino), madre_de(Abuela, Padre), madre_de(Abuela, Tio), Tio<>Padre.
	% Si la madre y el tío tienen la misma madre, y no son el mismo personaje, entonces es el tío.
%	sobrino_de(Sobrino, Tio) :- madre_de(Madre,Sobrino), madre_de(Abuela, Madre), madre_de(Abuela, Tio), Tio<>Madre.
	% Si el padre y la tía tienen la misma madre, y no son el mismo personaje, entonces es la tía.
%	sobrino_de(Sobrino, Tia) :- padre_de(Padre,Sobrino), madre_de(Abuela, Padre), madre_de(Abuela, Tia), Tia<>Padre.
	% Si la madre y la tía tienen la misma madre, y no son el mismo personaje, entonces es la tía.
%	sobrino_de(Sobrino, Tia) :- madre_de(Madre,Sobrino), madre_de(Abuela, Madre), madre_de(Abuela, Tia), Tia<>Madre.
	
	nieto_de(Nieto, Abuelo) :- abuelo_de(Abuelo, Nieto).
	nieto_de(Nieto, Abuela) :- abuela_de(Abuela, Nieto).
	
	ancestro_de(Ancestro, Descendiente) :- padre_de(Ancestro, Descendiente).
	ancestro_de(Ancestro, Descendiente) :- padre_de(Padre, Descendiente), ancestro_de(Ancestro, Padre).
	
	ancestro_de(Ancestro, Descendiente) :- madre_de(Ancestro, Descendiente).
	ancestro_de(Ancestro, Descendiente) :- madre_de(Padre, Descendiente), ancestro_de(Ancestro, Padre).
	
% Ej 3
% Efectuar consultas a la base de conocimientos anterior.

goal
%	write("Bart Simpson es hijo de: "), hijo_de("Bart Simpson", Sol),
%	write("Bart Simpson es sobrino de: "), sobrino_de("Bart Simpson", Tio),
%	write("Homero Simpson es padre de: "), padre_de("Homero Simpson", Hijo),
%	write("Homro Simpson es nieto de: "), nieto_de("Homero Simpson", Abuelo),
%	write("Abraham Simpson es abuelo de: "), abuelo_de("Abraham Simpson", Nieto),
	padre_de(Padre, Hijo),
%	ancestro_de(Ancestro, "Bart Simpson"),
%	ancestro_de("Orville Simpson", Descendiente),
%	ancestro_de(Ancestro, Descendiente),
	write().

Ej 4

%Ej 4.
% Definir un predicado que calcule el factorial.

domains
	entero = integer
predicates
	nondeterm factorial(entero,entero).

clauses
	factorial(0,1).
	factorial(N,M) :- N>0, N2=N-1, factorial(N2,M2), M=M2*N.

goal
	factorial(4,Salida), write(Salida).

Ej 5

%Ej 5.
%Definir un predicado que calcule la sumatoria de todos los números enteros desde 1 hasta un número dado (pasado como parámetro).
domains
	entero=integer
	
	
predicates
	nondeterm sumar(entero, entero).
	
clauses
	sumar(N,M) :- N=0, M=0.
	% Si N es mayor a cero, le resto uno y sigo sumando.
	sumar(N,M) :- N>0, N2=N-1, sumar(N2,M2), M=M2+N.

goal
	sumar(2, Salida).

Ej 6

% Ej 6.
% Definir un predicado para calcular un término de la sucesión de Fibanacci (cada término es igual a la suma de los dos anteriores).
domains
	entero=integer
predicates
	nondeterm fibonacci(entero, entero, entero, entero).
clauses
	% Si el N que quieren averiguar es negativo o 0 => el resultado es 0.
	fibonacci(_,_, N, Resultado) :- N<0, Resultado=0.

	% Si N es 1, => Resultado=N1.
	fibonacci(N1,_, N, Resultado) :- N=1, Resultado=N1.

	% Si N es 2, => Resultado=N2.
	fibonacci(_,N2, N, Resultado) :- N=2, Resultado=N2.
	
	% Si N es mayor a 2 calculo la serie de fibonacci.
	fibonacci(N1, N2, N, Resultado) :- N>2, M1=N-1, fibonacci(N1, N2, M1, Res1), M2=N-2, fibonacci(N1,N2,M2,Res2), Resultado = Res1+Res2.

goal
	% Calculo la serie de Fibonacci de 9 con raíces 1 y 2.
	fibonacci(1,2,9,Salida).

Ej 7

% Ej 7.
% Definir un predicado que calcule el producto de dos números por medio de sumas sucesivas.
domains
	entero = integer
predicates
	% Suma el primer entero con el segundo y lo guarda en el tercero.
	nondeterm sumas(entero, entero, entero).
clauses
	% Si el segundo número es 0, el resultado es igual al primer número pasado.
	sumas (N,1,Res) :- Res=N.
	
	% Si el primer número es 0, el resultado es igual al segundo número pasado.
	sumas (1,N,Res) :- Res=N.
	
	sumas(N,M,Resultado) :- N>1, M>1, N2=N-1, sumas(N2,M,Res2), Resultado=Res2+M.

goal
	sumas(2,5,Salida).

Ej 8

% Ej 8.
% Ingresar a la base de conocimientos las distancias entre diferentes ciudades adyacentes de la siguiente forma:
%	Distancia(Ciudad1,Ciudad2,Distancia)
% y definir un predicado, que permita calcular la distancia entre dos ciudades cualesquiera.

domains
	ciudad = symbol
	listaCiudades = ciudad*
predicates
	nondeterm distancia(ciudad, ciudad, integer).
	nondeterm recorrido(ciudad, ciudad, integer, listaCiudades).
	nondeterm calcularDistancia(ciudad, ciudad, integer).
	nondeterm perte(ciudad, listaCiudades).
	nondeterm agregar(ciudad, listaCiudades, listaCiudades).
	nondeterm imprimirLista(listaCiudades).
clauses
	perte(Ciudad, [Ciudad|_]).
	perte(Ciudad, [Ca|Co]) :- Ciudad<>Ca, perte(Ciudad, Co).
	
	imprimirLista([]).
	imprimirLista([Ca|Co]) :- imprimirLista(Co), write(Ca,"-").
	
	agregar(Ciudad, ListaOriginal, ListaFinal) :- ListaFinal=[Ciudad|ListaOriginal].
	
	% Cargando la base del conocimiento.
	distancia("Trenque Lauquen","Pehuajo",82).
	distancia("Pehuajo","Trenque Lauquen",82).
	distancia("Trenque Lauquen","Rivadavia",67).
	distancia("Rivadavia","Trenque Lauquen",67).
	distancia("Trenque Lauquen","Pellegrini",46).
	distancia("Pellegrini","Trenque Lauquen",46).
	distancia("Trenque Lauquen","Tres Lomas",58).
	distancia("Tres Lomas","Trenque Lauquen",58).
	distancia("Trenque Lauquen","Guamini",123).
	distancia("Guamini","Trenque Lauquen",123).
	distancia("Guamini","Pigüe",71).
	distancia("Pigüe","Guamini",71).
	distancia("Pigüe","Tornquis",61).
	distancia("Tornquis","Pigüe",61).
	distancia("Tornquis","Bahía Blanca",70).
	distancia("Bahía Blanca","Tornquis",70).
	distancia("Carlos Casares","Pehuajo",57).
	distancia("Pehuajo","Carlos Casares",57).
	distancia("Pehuajo","Carlos Tejedor",70).
	distancia("Carlos Tejedor","Pehuajo",70).
	distancia("Pehuajo","Bolivar",57).
	distancia("Bolivar","Pehuajo",57).
	distancia("Pehuajo","Daireaux",86).
	distancia("Daireaux","Pehuajo",86).
	distancia("9 de Julio","Los Toldos",64).
	distancia("9 de Julio","Bolivar",96).
	distancia("Bolivar","9 de Julio",96).
	distancia("Bolivar","Daireaux",80).
	distancia("Daireaux","Bolivar",80).
	distancia("Daireaux","Guamini",80).
	distancia("Guamini","Daireaux",80).
	distancia("Los Toldos","9 de Julio",64).
	distancia("Carlos Casares","9 de Julio",42).
	distancia("9 de Julio","Carlos Casares",42).
	distancia("Bragado","9 de Julio",59).
	distancia("9 de Julio","Bragado",59).
	distancia("Bragado","Alberti",20).
	distancia("Alberti","Bragado",20).
	distancia("Alberti","Chivilcoy",29).
	distancia("Chivilcoy","Alberti",29).
	distancia("Chivilcoy","Suipacha",34).
	distancia("Suipacha","Chivilcoy",34).
	distancia("Suipacha","Mercedes",23).
	distancia("Mercedes","Suipacha",23).
	distancia("Mercedes","Luján",37).
	distancia("Luján","Mercedes",37).
	distancia("Los Toldos","Junín",43).
	distancia("Junín","Los Toldos",43).
	distancia("Bragado","Junín",79).
	distancia("Junín","Bragado",79).
	distancia("Rivadavia","Villegas",49).
	distancia("Villegas","Rivadavia",49).
	distancia("Villegas","Ameghino",53).
	distancia("Ameghino","Villegas",53).
	distancia("Ameghino","General Pinto",54).
	distancia("General Pinto","Ameghino",54).
	distancia("General Pinto","Lincoln",32).
	distancia("Lincoln","General Pinto",32).
	distancia("Lincoln","Junín",54).
	distancia("Junín","Lincoln",54).
	distancia("Junín","O' Higgins",16).
	distancia("O' Higgins","Junín",16).
	distancia("O' Higgins","Chacabuco",35).
	distancia("Chacabuco","O' Higgins",35).
	distancia("Chacabuco","Carmen de Areco",68).
	distancia("Carmen de Areco","Chacabuco",68).
	distancia("Carmen de Areco","San Andrés de Giles",35).
	distancia("San Andrés de Giles","Carmen de Areco",35).
	distancia("San Andrés de Giles","Luján",34).
	distancia("Luján","San Andrés de Giles",34).
	distancia("Luján","General Rodriguez",11).
	distancia("General Rodriguez","Luján",11).
	distancia("Buenos Aires","General Rodriguez",50).
	distancia("General Rodriguez","Buenos Aires",50).
	distancia("Capital Federal","General Rodriguez",50).
	distancia("General Rodriguez","Capital Federal",50).
	distancia(Origen, Origen, Distancia) :- Distancia=0.
	
	% Si Origen es igual a Destino Acumulado es igual 0.
	recorrido(Origen, Destino, Acumulado, _) :- Origen=Destino, Acumulado=0.
	% Si Origen y Destino son vecinos, la distancia es la que hay entre ellos.
	recorrido(Origen, Destino, Distancia, Lista) :- distancia(Origen, Destino, Distancia), imprimirLista(Lista).%, write(" La distancia entre ",Origen," y ",Destino," es de ", Distancia).
	% Si Intermedia y Destino son vecinos eso es el acumulado
	% recorrido(Origen, Destino, Acumulado, Lista) :- distancia(Origen, Intermedia, Acum1), not (perte(Intermedia, Lista)), agregar(Intermedia,Lista, L2),, write(" La distancia entre ",Origen," y ",Intermedia," es de ", Acum1), recorrido(Intermedia, Destino,Acum2, L2),Acumulado=Acum1+Acum2.
	recorrido(Origen, Destino, Acumulado, Lista) :- distancia(Origen, Intermedia, Acum1), not (perte(Intermedia, Lista)), agregar(Intermedia,Lista, L2), recorrido(Intermedia, Destino,Acum2, L2),Acumulado=Acum1+Acum2.
	calcularDistancia(Origen, Destino, Distancia) :- L1=[], agregar(Origen, L1, L2), agregar(Destino, L2, L3), recorrido(Origen, Destino, Distancia, L3).
	calcularDistancia(Origen, Origen, 0) :- write("Estas a donde queres ir."),!.
	
goal
	calcularDistancia("Trenque Lauquen","Trenque Lauquen",Salida).

Ej 9

% Ej 10.
% Hacer un predicado que calcule la sumatoria de los dígitos de un número.
domains
	entero = integer
predicates
	nondeterm mod10(entero, entero).
	nondeterm resta(entero, entero, entero).
	nondeterm dividir(entero, entero, entero).
	nondeterm suma(entero, entero, entero).
	
	nondeterm sumatoriaDigitos(entero, entero).
clauses
	resta (N,M, Resultado) :- Resultado=N-M.
	suma (N,M,Resultado) :- Resultado = N+M.
	
	mod10(N, Resultado) :- N>=10, resta(N,10,Res2), mod10(Res2, Resultado).
	mod10(N, Resultado) :- N>=0, N<10,Resultado=N.
	mod10(N, Resultado) :- N<0, M=-N, mod10(M, Res2), Resultado=-Res2.
	
	dividir (N,M,Resultado) :- M<>0, Resultado=N/M, write("Resultado de la división: ",Resultado).
	
	sumatoriaDigitos(N,Resultado) :- N<0, M=-N, sumatoriaDigitos(M,Resultado).
	sumatoriaDigitos(0,Resultado) :- Resultado=0.
	sumatoriaDigitos(N,Res) :- N>0, mod10(N,M), M2=N-M, M3=M2/10, sumatoriaDigitos(M3,Res2), Res=Res2+M.

goal
	sumatoriaDigitos(,Resultado).

Ej 10

% Ej 11.
% Hacer un predicado que calcule la potencia enésima de un número.
domains
	entero = integer
predicates
	nondeterm potencia(entero, entero, real).
clauses
	% Cualquier número, distinto de 0, a la 0 es 1.
	potencia(Base, 0, Resultado) :- Base<>0, Resultado=1.
	% Cero a la cualquier cosa, distinta de 0, es 0.
	potencia(0, Exponente, Resultado) :- Exponente<>0, Resultado=0.
	
	% Si el Exponente es mayor a 0, le resto uno y vuelvo a llamar a la función para después multiplicarlo.
	potencia(Base, Exponente, Resultado) :- Exponente>0, Expo2=Exponente-1, potencia(Base, Expo2, Res2), Resultado = Res2*Base.
	% Si el Exponente es menor a 0, le cambio el signo y calculo la base al Exponente positivo y después hago 1/Resultado.
	potencia(Base, Exponente, Resultado) :- Exponente<0, Expo2=-Exponente, potencia(Base, Expo2, Res2), Resultado = 1/Res2.
goal
	% 2 a la -3?.
	potencia(2,-3, Resultado).