Documentos de Académico
Documentos de Profesional
Documentos de Cultura
3. Realizando consultas
Respuestas: Sı́ o no.
Tras compilar un programa desde el intérprete, se pueden realizar consultas
relacionadas con el programa. En la subventana superior introduce:
progenitor(juan, luis).
El la inferior se obtiene:
?- progenitor(juan, luis).
Success
Si se repite el proceso con
progenitor(juan, laura).
Se obtiene:
?- progenitor(juan, laura).
Failure
Consultas y variables
Si alguno de los atributos es una variable, el intérprete retornará los valo-
res que puede tomar para ser satisfecha. El nombre de una variable ha de
comenzar con mayúscula, o con guión bajo:
Si realizas la consulta
progenitor(juan,X).
El interface gráfico del interprete puede responder de varias formas: Pulsan-
do el botón ‘Once’ responde:
?- progenitor(juan,X).
X = luis
Pulsando el botón ‘First’ y a continuación pulsamos ‘Next’ dos veces se
obtiene
?-progenitor(juan,X)
Soln: 1
X = luis
;
Soln: 2
X = maria
;
No More Solutions.
4. Reglas
Si tenemos una formula conteniendo variables libres que describen un domi-
nio finito, podemos considerar la tuplas que satisfacen dicha fórmula. Por
otro lado una fórmula implica otra si cada tupla que satisface la primera,
también satisface la segunda.
El el programa familia podrı́amos introducir todos los hechos inversos acerca
de quién es hijo de quién:
hijo(luis,juan).
hijo(maria,juan).
Una manera más sencilla serı́a introducir una regla:
Para todo X e Y, si X es progenitor de Y, entonces Y es hijo de X .
Que se formula como
∀X∀Y (progenitor(X, Y ) →hijo(Y, X)) .
En la sintaxis de prolog, lo que se hace es considerar la siguiente regla
asociada
hijo(Y,X):-progenitor(X,Y).
Notemos, que este tipo de programas prolog las variables toman finitos va-
lores buscando en la base de datos formada por los hechos.
Ahora tenemos dos opciones o ampliar nuestro documento familia con la
lı́nea anterior o crear un nuevo programa con la linea adicional. Si quieres
crea un nuevo documento ampliacion.pl con la regla anterior. Si consultas
ambos documentos familia.pl y apliacion.pl tendrás a tu disposición los he-
chos y reglas que contienen ambos. Por ejemplo, puedes consultar
hijo(X,juan).
Varios antecedentes
Si quieres distinguir hijo de hija lo puedes hacer utilizando la conjuncion de
varios antecedentes. Borra la lı́nea anterior de ampliacion.pl e introduce las
dos siguientes:
hija(Y,X) :- progenitor(X,Y),mujer(Y).
hijo(Y,X) :- progenitor(X,Y),hombre(Y).
Salva el documento y ahora realiza la consulta
hijo(X,juan).
La respuesta es
?- hijo(X,juan).
Success
X = luis
Es posible que obtengas otra respuesta. Puede deberse a que anteriormente
hijo(Y,X) estaba definido de otro modo. Si has (re) consultado el docu-
mento amplicacion.pl obtendrás la respuesta correcta, en otro caso seguirás
obteniendo la que tenı́as con la regla antigua.
Es interesante que te fijes si en la ventana ‘Evaluate Query ...’ esta activado
o no el botón ‘Consult Changes Before Evaluating ...’ . Si está activado XGP
se encarga de (re) consultar las reglas y hechos por si ha habido cambios.
Volviendo a la sintaxis de prolog, hay que observar que la conjunción de
predicados se expresa mediante comas y que los caracteres ‘:-’ corresponden
al conector condicional ← .
Por ejemplo, ahora puedes introducir el predicado binario (2-ario) hermano
mediante
hermano(X,Y) :- progenitor(Z,X), progenitor(Z,Y).
Ejercicios
Escribe en prolog: Todo aquel que tiene un hijo es feliz.
Define las relaciones “abuelo” y “nieto”
Describe (informalmente) cómo modificarı́as el predicado hermano para que
no saliera uno hermano de sı́ mismo.
En vez de conjunción de predicados se puede trabajar con disyunción de
predicados. Si queremos averiguar el universo que describen las variables,
podemos buscar los hechos descritos por predicados monádicos (1-arios) y
hacer la reunión de los dominios de cada predicado monádico (1-ario).
universo(X):-hombre(X); mujer(X).
Si en algún otro lugar de los documentos consultados o predicados predefi-
nidos en el sistema existe otra regla con cabeza (consecuente), universo(X),
el universo puede hacerse aún mayor de lo que permite la regla anterior.
Por ejemplo podemos considerar las dos reglas
trozouniverso(X):-hombre(X).
trozouniverso(X):-mujer(X).
Ahora la consultas
universo(X).
trozouniverso(X).
obendran idéntica respuesta.
| ? fd_domain(VariableFD,5,25).
VariableFD = _#3(5..25)
(En la invocación al fd domain VariableFD era una variable normal, que
finalmente se mapea a una variable #3 con un dominio finito [5..25]. Aunque
ponga (5..25), los valores 5 y 25 forman parte del dominio.)
En el siguiente ejemplo vemos que fd domain establece restricciones sobre el
dominio y que su acción es consistente con otras restricciones que hayamos
podido definir antes.
Ejemplo: Definimos una restricción sobre la variable X, no puede tomar el
valor 5, con ello implı́citamente hemos declarado una variable FD con domi-
nio [0..4,6..127]. Para a continuación, agregar otra restricción con fd domain,
reduciendo el dominio de X a [0..4,6..10].
| ?X#\=5, fd_domain(X,1,10).
X = _#2(1..4:6..10)
fd domain/2
Este predicado se utilizará para definir variables con un dominio finito for-
mado por un conjunto de valores arbitrarios que se representarán por una
lista.
fd domain(A,B)
A – variable FD
B – lista de valores que representa el dominio
Ejemplo: Queremos definir una variable con un dominio finito que es el rango
[2..4]. Algo, que podı́amos tambien haber hecho con fd domain(VariableFD,2,4).
| ?fd_domain(VariableFD,[2,3,4]).
VariableFD = _#2(2..4)
| ?fd_domain(VariableFD,[2,4,3]).
VariableFD = _#2(2..4)
| ?fd_domain([A,B],1,3),A#\=B.
A = _#3(1..3)
B = _#25(1..3)
| ?fd_domain([A,B],1,3),A#\=B, fd_labeling([A,B]).
A = 1
B = 2 ? ;
A = 1
B = 3 ? ;
A = 2
B = 1 ? ;
A = 2
B = 3 ? ;
A = 3
B = 1 ? ;
A = 3
B = 2
| ?fd_domain([A,B,C],1,3),fd_all_different([A,B,C]),
fd_labeling([A,B,C]).
A = 1
B = 2
C = 3 ? ;
A = 1
B = 3
C = 2 ? ;
A = 2
B = 1
C = 3 ? ;
A = 2
B = 3
C = 1 ? ;
A = 3
B = 1
C = 2 ? ;
A = 3
B = 2
C = 1
Restricciones Aritméticas:
Son expresiones que representan funciones aritméticas compuestas por va-
riables o enteros y los operadores. Se pueden utilizar los siguientes, siendo
Exp$ donde $ es el número de la expresión FD que se utiliza:
“+ Exp1”: El mismo valor.
“- Exp1”: El valor opuesto.
“Exp1 + Exp2”: La suma de las 2 expresiones.
“Exp1 – Exp2”: La resta de las 2 expresiones.
“Exp1 * Exp2”: El producto de las 2 expresiones.
“Exp1 / Exp2”: El cociente de las 2 expresiones, solo se cumple si el resto
es 0.
“Exp1 ** Exp2”: La Exp1 elevada a Exp2, una de las 2 debe ser entera.
“min(Exp1, Exp2)”: El mı́nimo de las 2 expresiones.
“max(Exp1, Exp2)”: El máximo de las 2 expresiones.
“dist(Exp1, Exp2)”: La distancia entre las 2 expresiones, |Exp1–Exp2|.
“Exp1 // Exp2”: El cociente de la división entera de las expresiones.
“Exp1 rem Exp2”: El resto de la división entera de las expresiones.
“quot rem(Exp1,Exp2,R)”: Cociente de la división entera de las expresiones
devolviendo el resto en la variable R.
Las siguientes restricciones pueden utilizarse con arco consistencia completa
o parcial, se puede utilizar la parcial para reducir el dominio de las va-
riables complejas. Hay una menor propagación de las variables en la arco
consistencia parcial, pero aumenta la eficiencia y es mejor para las variables
aritméticas. Cuando se utiliza una arco consistencia completa es a la inver-
sa. Estos operadores se colocan entre las 2 expresiones como los operadores
aritméticos anteriores.
Ejemplos:
| ?A#\= 5, B#>=6, A#>=B+7.
A = _#2(13..127@)
B = _#27(6..120)
% Sudoku
%
% (para GNU Prolog)
%
% versión en castellano de un program prolog realizado de Jerome Cornet
%
% --------------------------------------
%-------------------------
%| 1 2 3 | 5 6 7 | 8 4 9 |
%| 4 6 7 | 1 9 8 | 3 5 2 |
%| 5 9 8 | 2 3 4 | 6 7 1 |
%-------------------------
%| 2 1 4 | 3 7 9 | 5 6 8 |
%| 3 8 5 | 4 1 6 | 9 2 7 |
%| 6 7 9 | 8 2 5 | 4 1 3 |
%-------------------------
%| 9 3 6 | 7 4 2 | 1 8 5 |
%| 7 5 1 | 6 8 3 | 2 9 4 |
%| 8 4 2 | 9 5 1 | 7 3 6 |
%-------------------------
% X es una variable con dominio finito (fd) que toma valores enteros del 1 al 9.
%Comprueba que dos elementos cualquiera de la lista L son distinto entre sı́.
todosdistintos(L) :- fd_all_different(L).
%---------------------------------------
% fila toma una lista de nueve términos y los escribe
%en una fila separados de tres en tres.
nl,
lineahorizontal,
fila(A1, A2, A3, A4, A5, A6, A7, A8, A9),
fila(B1, B2, B3, B4, B5, B6, B7, B8, B9),
fila(C1, C2, C3, C4, C5, C6, C7, C8, C9),
lineahorizontal,
fila(D1, D2, D3, D4, D5, D6, D7, D8, D9),
fila(E1, E2, E3, E4, E5, E6, E7, E8, E9),
fila(F1, F2, F3, F4, F5, F6, F7, F8, F9),
lineahorizontal,
fila(G1, G2, G3, G4, G5, G6, G7, G8, G9),
fila(H1, H2, H3, H4, H5, H6, H7, H8, H9),
fila(I1, I2, I3, I4, I5, I6, I7, I8, I9),
lineahorizontal.
%---------------------------------------
%sudoku: Primero hace que las 81 variables tengan dominio finito de enteros entre 1 y 9.
%El predicado fd_labeling/1 recibe como primer parámetro la lista con las variables
%con dominio finito y prueba a asignar a cada variable un valor dentro de su
%dominio y realiza backtracking sobre esas asignaciones permitiendo encontrar
%todas las posibles soluciones. Una vez encontrada la solución
%la visualiza en un cuadrado de sudoku
Resolución
complementario(no A,A):- !.
complementario(A, no A).
resolvente(C1,C2,C):- pertenece(L1,C1),
complementario(L1,L2), pertenece(L2,C2),
delete(C1, L1, C1P), delete(C2, L2, C2P),
concatena(C1P, C2P, C3), sort(C3,C).
apply(Termino,Lista) :- Termino =..[Pred|Arg1],
concatena(Arg1,Lista,Arg2),
Atomo =.. [Pred|Arg2], Atomo.
maplist( ,[],[]).
maplist(R,[X1|L1],[X2|L2]) :- apply(R,[X1,X2]), maplist(R,L1,L2).
refutacion(S,R):- maplist(sort,S,S1), refutacion aux(S1,R).
refutacion aux(S,R) :-pertenece([],S), !, reverse(S,R).
refutacion aux(S,R) :-pertenece(C1,S), pertenece(C2,S),
resolvente(C1,C2,C), \+ pertenece(C, S),
%format(’ N w resolvente de w y w n’,[C,C1,C2]),
refutacion aux([C|S],R).
Prácticas de Lógica en aula informática (Curso 2010-11) — Práctica 4
P ¬ ∧ Q, P ∧ Q ∨ R, P ∧ ¬Q, P ∧ (¬Q).
(P → ¬(Q ∧ R)) ∨ ¬R ∧ (P → Q).
P → (Q → R) (P ∧ Q) → R P
a) b) c) (RI¬¬)
(P ∧ Q) → R P → (Q → R) ¬¬P
¬P 1 ∨ ¬Q1
P ∨Q P ∨ Q1
P → P1
d) ¬P (RE∨) e) f) ¬P ∨ Q2
Q → Q1
Q Q1 ∨ Q2
¬P ∨ ¬Q
(RR)
P →Q
g)
¬(P ∧ ¬Q
(L1) P → (Q → P )
(L2) (P → (Q → R)) → ((P → Q) → (P → R))
(L3) (¬P → ¬Q) → (Q → P )
P P → (Q → R)
(RL1) (RL2) (RL3)
Q→P (P → Q) → (P → R)
¬P → ¬Q
Q→P
1.— Las expresiones P (x), R(x, y), etc. son siempre fórmulas atómicas.
Sin embargo ADN no permite introducir fórmulas con variables libres.
En los apuntes de teorı́a se suele utilizar expresiones del tipo (∀x)P (x) ,
no obstante, ADN prefiere la expresión ∀xP (x) .
y también su recı́proco.
∀x(P → Q(x))
P → ∀xQ(x)