Grafuri

Numărul de componente conexe într-un graf.

Enunț:
Se dă un graf nedirecționat: se dă lista vârfurilor sale și pentru fiecare vârf se dă lista
vecinilor săi. Se cere un program Prolog care să afle și să afișeze numărul de componente conexe din graful dat.

prolog_logo
Cod Sursa PROLOG

 

% definirea grafurilor pentru teste
graf1:-abolish(nodes),abolish(vec),
asserta(nodes([a,b,c,d,e,f,g,h])),
asserta(vec(a,[b,c])),
asserta(vec(b,[a])),
asserta(vec(c,[a,d,e])),
asserta(vec(d,[c])),
asserta(vec(e,[c])),
asserta(vec(f,[g,h])),
asserta(vec(g,[f,h])),
asserta(vec(h,[f,g])).
graf2:-abolish(nodes),abolish(vec),
asserta(nodes([a,b,c,d,e,f,g,h,i,j,k,l,m])),
asserta(vec(a,[b,c,h])),
asserta(vec(b,[a])),
asserta(vec(c,[a])),
asserta(vec(d,[k,m])),
asserta(vec(e,[i,g])),
asserta(vec(f,[i,g])),
asserta(vec(g,[e,f])),
asserta(vec(h,[a])),
asserta(vec(i,[j,e,f])),
asserta(vec(j,[i,k])),
asserta(vec(k,[d,j])),
asserta(vec(l,[])),
asserta(vec(m,[d])).
% testele
test1:-graf1,comp.
test2:-graf2,comp.
% programul
comp:-clear,init,loop,write_res.
init:-nodes(L),init(L).
init(L):-assert(total(0)),list_noduri(L).
clear:-clear_coada,nodes(L),clear(L).
clear(L):-retract(total(X)),clear(L).
clear([X|L]):-retract(liber(X)),clear(L).
clear(L).
clear_coada:-retract(coada(X)),clear_coada.
clear_coada.
write_res:-retract(total(X)),write(X).
list_noduri([X]):-assert(liber(X)).
list_noduri([X|Y]):-assert(liber(X)),list_noduri(Y).
% simulam un ciclu
loop:-retract(liber(X)),push(X),parcurge,retract(total(T)),T1 is T+1,assert(total(T1)),loop.
loop.
parcurge:-pop(X),vec(X,V),get_free(V,L),push(L),parcurge.
parcurge.
get_free([],[]).
get_free([X|L],[X|K]):- retract(liber(X)),get_free(L,K).
get_free([X|L],K):- get_free(L,K).
get_free(X,[X|K]):- retract(liber(X)).
get_free(X,K).
% simulam coada de noduri atinse in componenta curenta
push([]).
push([X]):-push(X).
push([X|L]):-push(X),push(L).
push(X):-assert(coada(X)).
pop(X):-retract(coada(X)).

Interogări:

?- test1.
2
?- test2.
3

Cel mai scurt drum între 2 vârfuri într-un graf.

Enunț:
Se dă un graf nedirecționat: se dă lista vârfurilor sale și lista de muchii sub forma (a,b,c),
unde a și b sunt vârfurile muchiei și c este costul ei.
Se cere un program Prolog care să afle și să afișeze cel mai scurt drum de la un vârf S la
un vârf F în graful dat.

prolog_logo
Cod Sursa PROLOG

 

% definirea grafurilor utilizate
graf1:-abolish(nodes),abolish(vec),
assert(nodes([a,b,c,d,e])),
assert(vec(a,b,10)),
assert(vec(b,c,10)),
assert(vec(c,d,15)),
assert(vec(a,d,23)),
assert(vec(c,e,5)),
assert(vec(d,e,10)).
graf2:-abolish(nodes),abolish(vec),
assert(nodes([a,b,c,d,e,f,g,h])),
assert(vec(a,b,5)),
assert(vec(a,d,6)),
assert(vec(a,g,4)),
assert(vec(b,f,3)),
assert(vec(c,d,3)),
assert(vec(c,f,6)),
assert(vec(e,f,3)),
assert(vec(e,g,2)),
assert(vec(e,h,2)),
assert(vec(f,h,1)).
% testele
test1:-graf1,drum(a,c).
test2:-graf1,drum(d,b).
test3:-graf1,drum(a,e).
test4:-graf2,drum(b,e).
test5:-graf2,drum(h,b).
test6:-graf2,drum(d,e).
test7:-graf2,drum(a,h).
% functii pentru muchii
is_connect(X,Y):-vec(X,Y,_);vec(Y,X,_).
cost(X,Y,Z):-vec(X,Y,C),Z is C;vec(Y,X,C),Z is C.
% initializare
clear:-nodes(L),clear_vl(L),clear_prec,clear_best(L),(retract(dst(X))->true;true).
clear_vl([X|L]):-set_vl(X,0),clear_vl(L).
clear_vl([]).
clear_best([X|L]):-set_best(X,1000000),clear_best(L).
clear_best([]):-set_best(z,1000000).
clear_prec:-abolish(prec).
clear_prec.
init(S):-set_vl(S,1),set_best(S,0).
drum(S,F):-clear,init(S),loop(F),get_best(F,Res),afiseaza_drum(S,F),write(‘\nLungimea
drumului – ‘),write(Res).
loop(F):-get_min(F) ; get_min(X), ( get_best(X,1000000) ; set_vl(X,2), update(X) ,
loop(F) ) .
afiseaza_drum(S,S):-write(S).
afiseaza_drum(S,F):-get_prec(F,X),afiseaza_drum(S,X),write(-),write(F).
% —
get_min(X):-nodes(L),get_free_node(Y),get_min(Y,L,X).
get_min(X,[Y|L],X):-
get_vl(Y,C),C==1,get_best(Y,BY),get_best(X,BX),BY<BX,get_min(X,L,X).
get_min(X,[Y|L],Z):- get_min(X,L,Z).
get_min(X,[],X).
get_free_node(X):-nodes(L),get_free_node(X,L).
get_free_node(Y,[Y|L]):-get_vl(Y,V),V==1.
get_free_node(X,[Y|L]):-get_free_node(X,L).
% —
update(X):-nodes(L),update(X,L).
update(X,[Y|L]):- ( X\==Y, get_best(X,BX) , get_vl(Y,VY) , cost(X,Y,C) , CCost is
BX+C , get_best(Y,BY) , (VY==0 ; VY==1 , CCost<BY) , set_vl(Y,1),
set_best(Y,CCost), set_prec(Y,X) ; true ) , update(X,L).
update(X,[]).
% —
set_vl(X,Y):-retract(vl(X,Z)),assert(vl(X,Y));assert(vl(X,Y)).
get_vl(X,Y):-retract(vl(X,Y)),assert(vl(X,Y)).
set_best(X,Y):-retract(best(X,Z)),assert(best(X,Y));assert(best(X,Y)).
get_best(X,Y):-retract(best(X,Y)),assert(best(X,Y)).
% seteaza Y ca nodul precedent al lui X
set_prec(X,Y):-retract(prec(X,Z)),assert(prec(X,Y));assert(prec(X,Y)).
get_prec(X,Y):-retract(prec(X,Y)),assert(prec(X,Y)).

Interogări:

?- test1.
a-b-c
Lungimea drumului – 20
yes
?- test2.
d-a-b
Lungimea drumului – 33
yes
?- test3.
a-b-c-e
Lungimea drumului – 25
yes
?- test4.
b-f-e
Lungimea drumului – 6
yes
?- test5.
h-f-b
Lungimea drumului – 4
yes
?- test6.
d-c-f-e
Lungimea drumului – 12
yes

?- test7.
a-b-f-h
Lungimea drumului – 9
yes

Leave a comment