Agradeço comentários, sugestões ou correccões. O meu endereço de correio electrónico é < delfim@mat.ua.pt > . Desde já obrigado.
São objectivos da aula:
O problema das 8 rainhas é um problema bem conhecido, muitas vezes usado para introduzir a ideia de retrocesso (backtracking). Consiste em colocar 8 rainhas num tabuleiro de xadrez (8 ×8) de tal modo que nenhuma rainha ataque outra. A abordagem habitual, para resolver este problema, consiste numa pesquisa exaustiva de todas as possibilidades de colocação das rainhas. Numerando as linhas e as colunas de 1 a 8, então cada uma dessas possibilidades pode ser representada por um óctuplo
|
onde [i,ci] denota a posição de uma rainha no quadrado da linha i e coluna ci. Podemos representar esta configuracão apenas por
|
convencionando que a i-esima posição denota, implicitamente, a linha i. Além disso, como duas rainhas na mesma coluna atacam-se mutuamente, apenas precisamos de considerar os óctuplos [ c1, ¼, c8 ] que sejam uma permutacão de [1, 2, 3, 4, 5, 6, 7, 8]. Para resolver este problema temos então, essencialmente, de:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Problema das 8 rainhas
% Delfim F. Marado Torres, 24/Maio/1999
%
% No livro do Bratko, pp. 108--118,
% pode encontrar outras resolucoes
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Predicado principal: rainhas(Solucao)
%
% Solucao sera' instanciada com uma
% lista da forma [ [1,Y1], ..., [8,Y8] ]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
rainhas(S) :-
permutacao([1,2,3,4,5,6,7,8],P),
formaPares(P,S),
naoAtaca(S).
formaPares(L,LP) :-
fp(1,L,LP).
fp(_,[],[]).
fp(N,[X|R],[[N,X]|RP]) :-
N1 is N + 1,
fp(N1,R,RP).
naoAtaca([]).
naoAtaca([P|RP]) :-
naoAtacaNenhuma(P,RP),
naoAtaca(RP).
naoAtacaNenhuma(_,[]).
naoAtacaNenhuma([X,Y],[[X1,Y1]|RP]) :-
not emLinha([X,Y],[X1,Y1]),
naoAtacaNenhuma([X,Y],RP).
emLinha([X,_],[X,_]).
emLinha([_,Y],[_,Y]).
emLinha([X1,Y1],[X2,Y2]) :-
D is abs(Y2 - Y1),
D is abs(X2 - X1).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Predicados ja realizados anteriormente
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
permutacao([],[]).
permutacao([X|R],P) :-
permutacao(R,RP),
adiciona(X,RP,P).
adiciona(X,R,[X|R]).
adiciona(X,[Y|R],[Y|A]) :-
adiciona(X,R,A).
Sabe quantas soluções diferentes existem para o problema das 8 rainhas? Nada mais nada menos que 92! Tal como eu, pode descobrir isso com o comando
?- tell('rainhas.txt'), rainhas(S), write(S), nl, fail.
No
told. % escrevi eu
Yes
?-
dando depois uma vista de olhos ao ficheiro rainhas.txt.
Pretende-se construir, e posteriormente consultar, uma Base de Conhecimento em Prolog com predicados profissao/2 e curso/2
profissao(Pessoa,Actividade).
curso(Pessoa,Curso).
através de um interface que use a língua portuguesa. Eis alguns exemplos do funcionamento pretendido:
profissao(xico,fotografo).
curso(ze,matematica).
Para o sistema Prolog reconhecer as frases acima e fazer, sozinho, as respectivas acções (acrescentar ou consultar conhecimento) vamos recorrer a uma DCG.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Gramatica 'BC'
%%
%% Delfim F. Marado Torres
%% 25/Maio/1999
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
gramBC -->
afirmacao(Tipo,Pess,Act),
{ acrescentaBC(Tipo,Pess,Act) }.
gramBC -->
questao(Pess),
{ daActividade(Pess) }.
afirmacao(profissao,P,A) -->
det(_),
[P, e, A, '.'].
afirmacao(curso,P,A) -->
det(_),
[P, estuda, A, '.'].
questao(Pess) -->
det(masculino),
[que, faz],
det(_),
[Pess, '?'].
det(masculino) --> [o] | ['O'].
det(feminino) --> [a] | ['A'].
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Accoes Semanticas da Gramatica
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
acrescentaBC(Tipo,Pess,Act) :-
C =..[Tipo,Pess,Act],
assertz(C),
write('A clausula '),
write(C),
write(' foi adicionada com sucesso.'),
nl.
daActividade(P) :-
profissao(P,A),
informa(' e ',P,A).
daActividade(P) :-
curso(P,A),
informa(' estuda ',P,A).
daActividade(P) :-
write(P),
write(' nao consta da BC!'),
nl.
informa(T,P,A) :-
write(P),
write(T),
write(A),
write('.'),
nl.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Predicado Principal: bc/1
%%
%% Recebe uma string em vez de uma lista
%%
%% EXEMPLOS:
%%
%% ?- bc('O xico e fotografo.').
%% A clausula profissao(xico,fotografo) foi adicionada com sucesso.
%%
%% ?- bc('A ze estuda matematica.').
%% A clausula curso(ze,matematica) foi adicionada com sucesso.
%%
%% ?- bc('O que faz o xico?').
%% xico e fotografo.
%% ?- bc('O que faz a ze?').
%% ze estuda matematica.
%%
%% ?- bc('O que faz o delfim?').
%% delfim nao consta da BC!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
bc(String) :-
converte(String,Lista),!,
gramBC(Lista,[]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Predicado ja' usado na teorica.
%%
%% Transforma uma string numa lista de palavras.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
converte(S,L) :-
name(S,LA1),
adicionaEspacos(LA1,LA2),
conv(LA2,L).
adicionaEspacos([],[]).
adicionaEspacos([X|R1],[32,X,32|R2]) :-
member(X,[58,59,44,46,33,63]),
adicionaEspacos(R1,R2).
adicionaEspacos([X|R1],[X|R2]) :-
adicionaEspacos(R1,R2).
conv([],[]).
conv(LA,[P|R]) :-
palavra(LA,PA,RA),
name(P,PA),
conv(RA,R).
palavra([],[],[]).
palavra([32|R],[],L) :-
desprezaEspacos(R,L).
palavra([X|R1],[X|R2],L) :-
palavra(R1,R2,L).
desprezaEspacos([32|R1],R) :-
desprezaEspacos(R1,R).
desprezaEspacos(L,L).