Uso de não determinismo Exemplo
Problema dos casamentos estáveis Existe um conjunto de N homens e um conjunto de N mulheres que querem casar. Cada homem tem associada uma lista com todas as mulheres por ordem decrescente das suas preferências para casamento. Idem para cada mulher (que tem uma lista de todos os homens por ordem decrescente das suas preferências). O problema é encontrar um conjunto de casamentos que sejam todos estáveis. Os casamentos são instáveis se existe um homem e uma mulher que se preferem mais entre eles que aos seus esposos.
Instabilidade Existe um conjunto de N homens e um conjunto de N mulheres que querem casar. Cada homem tem associada uma lista com todas as mulheres por ordem decrescente das suas preferências para casamento. Idem para cada mulher (que tem uma lista de todos os homens por ordem decrescente das suas preferências). O problema é encontrar um conjunto de casamentos que sejam todos estáveis. Os casamentos são instáveis se existe um homem e uma mulher que se preferem mais entre eles que aos seus esposos. Exemplo de par de casamentos instáveis: Manuel : Paula (Manuel preferia a Maria) Pedro : Maria (Maria preferia o Manuel)
N=3 Homens Preferências Mulheres Preferências Zé Ana, Rita, Inês Ana Rui, Zé, Ivo Rui Inês, Ana, Rita Rita Zé, Rui, Ivo Ivo Ana, Inês, Rita Inês Zé, Ivo, Rui Zé : Ana Rui : Inês Ivo : Rita Conjuntos estáveis? Zé : Ana Ivo : Inês Rui : Rita Rui : Ana Ivo : Inês Zé : Rita X X
Prolog O predicado deverá receber uma lista de homens com as suas preferências e uma lista de mulheres com as suas preferências e devolver uma lista de pares homem/mulher com os casamentos. Um exemplo duma chamada deste predicado poderá ser:?- casamentos( [h(pedro,[maria,paula]), h(manuel,[paula,maria])], [m(maria,[pedro,manuel]), m(paula,[pedro,manuel])], C). C = [c(pedro,maria), c(manuel,paula)] ; no
Aproveitar o não determinismo Ir (não deterministicamente) gerando casais Testando estabilidade com os já gerados Gerar casais: Para cada homem, escolher uma mulher solteira casamentos(homens,mulheres, Casais) :- acasala(homens,mulheres, [], Casais). acasala([],[],_,[]). acasala([h(homem,prefsh) HRest],Ms, Casados,[c(Homem,Mulher) Cs]) :- % escolher Mulher % testar estabilidade acasala(hrest,mrest, [c(homem:prefsh,mulher:prefsm) Casados],Cs).
Escolher uma mulher member/2? É preciso memorizar as que ainda ficam solteiras Solução: select/3 my_select(x, [X R], R). my_select(x, [H T], [H R]):- my_select(x, T, R). Ficaria: my_select(m(mulher,_), Ms, MRest) Com heurística (tentar 1º as mais preferidas): member(mulher, PrefsH), my_select(m(mulher,prefsm), Ms, MRest)
Acasalar acasala([],[],_,[]). acasala([h(homem,prefsh) HRest],Ms, Casados,[c(Homem,Mulher) Cs]) :- member(mulher,prefsh), %Heurística: tenta 1º as + preferidas my_select(m(mulher,prefsm), Ms, MRest), % testar estabilidade acasala(hrest,mrest, [c(homem:prefsh,mulher:prefsm) Casados],Cs). Teste de estabilidade \+ instavel(c(homem:prefsh,mulher:prefsm), Casados)
Instabilidade instáveis Cs, Prefs <h1,m1>,<h2,m2> Cs (preftrocar(h1, m2, Prefs) preftrocar(h2, m1, Prefs)) preftrocar h, m, Prefs (prefere(h, m, conjuge h, Prefs) prefere(m, h, conjuge(m), Prefs)) instavel(c(h1:prefsh1,m1:prefsm1), [c(h2:prefsh2,m2:prefsm2) _]):- preferem_trocar(h1,m1, H2,M2, PrefsH1,PrefsM2) ; preferem_trocar(h2,m2, H1,M1, PrefsH2,PrefsM1). instavel(casal, [_ Cs]):- instavel(casal, Cs).
Preferir trocar preftrocar h, m, Prefs (prefere(h, m, conjuge h, Prefs) prefere(m, h, conjuge(m), Prefs)) %H1 (casado com M1) e M2 (casada com H2) %preferem trocar entre eles preferem_trocar(h1,m1, H2,M2, PrefsH1,PrefsM2):- antes(prefsh1, M2,M1), antes(prefsm2, H1,H2). %antes(prefs, X,Y) :- X está antes de Y em Prefs. antes([x _], X,_):-!. antes([y _], _,Y):-!, fail. antes([_ L], X,Y):- antes(l, X,Y).
casamentos(homens,mulheres, Casais) :- acasala(homens,mulheres, [], Casais). acasala([],[],_,[]). acasala([h(homem,prefsh) HRest],Ms, Casados,[c(Homem,Mulher) Cs]) :- member(mulher,prefsh), %Heurística: tenta 1º as + preferidas my_select(m(mulher,prefsm), Ms, MRest), \+ instavel(c(homem:prefsh,mulher:prefsm), Casados), acasala(hrest,mrest, [c(homem:prefsh,mulher:prefsm) Casados],Cs). instavel(c(h1:prefsh1,m1:prefsm1), [c(h2:prefsh2,m2:prefsm2) _]):- preferem_trocar(h1,m1, H2,M2, PrefsH1,PrefsM2) ; preferem_trocar(h2,m2, H1,M1, PrefsH2,PrefsM1). instavel(casal, [_ Cs]):- instavel(casal, Cs). %H1 (casado com M1) e M2 (casada com H2) preferem trocar entre eles preferem_trocar(h1,m1, H2,M2, PrefsH1,PrefsM2):- antes(prefsh1, M2,M1), antes(prefsm2, H1,H2). %antes(prefs, X,Y) :- X está antes de Y em Prefs. antes([x _], X,_):-!. antes([y _], _,Y):-!, fail. antes([_ L], X,Y):- antes(l, X,Y). my_select(x, [X R], R). my_select(x, [H T], [H R]):- my_select(x, T, R).