Declaratieve Talen/Oplossing Minimale Snede
Naar navigatie springen
Naar zoeken springen
Oplossing niet volledig maar het moeilijkste stuk is er:
boog(a,b,1). boog(a,c,1). boog(b,c,1). boog(c,z,3). boog(b,z,1). min_cut(Snede,Kost) :- findall((Snede,Kost),min_snede(Snede,Kost),R), min(R,Snede,Kost). min([(Snede,Kost)],KortsteSnede,LaagsteKost) :- KortsteSnede = Snede, LaagsteKost = Kost. min([(Snede,Kost)|Rest],KortsteSnede,LaagsteKost) :- KortsteSnede = Snede, LaagsteKost = Kost. min_rnd_snede(Snede, Kost) :- knopen(Knopen), permu(Knopen, [K|PKnopen]), min_snede_perm([K],PKnopen,Snede,Kost). %gegeven een zeker permutatie/volgorde van de knopen: ga alle snedes af min_snede_perm(X,[Y],KortsteSnede,Lengte) :- kost(snede(X,[Y]),Lengte), KortsteSnede = snede(X,[Y]). min_snede_perm([X1|X1rest],[X2|X2rest], KortsteSnede, LengteKortsteSnede) :- min_snede_perm([X2,X1|X1rest],X2rest,KortsteSubSnede,LengteKortsteSubSnede), kost(snede([X1|X1rest],[X2|X2rest]),Kost), (Kost < LengteKortsteSubSnede -> LengteKortsteSnede = Kost, KortsteSnede = snede([X1|X1rest],[X2|X2rest]); KortsteSnede = KortsteSubSnede, LengteKortsteSnede = LengteKortsteSubSnede ). %bereken de kost van een snede kost(snede([],_),Y) :- Y = 0. kost(snede([X|Xs],Y),Result) :- findall(Kost, ((boog(X,Z,Kost);boog(Z,X,Kost)),elementvan(Z,Y)),Kosten), sum(Kosten,TotaleKostX), kost(snede(Xs,Y),RecurResult), Result is RecurResult + TotaleKostX. %element van elementvan(X,[L|Lijst]) :- X == L; elementvan(X,Lijst). %bereken de som van een rij sum([],R) :- R = 0. sum([X],R) :- R = X. sum([L|List], R) :- sum(List, Recur), R is Recur + L. %alle knopen van de graaf knopen(Result) :- findall(X,(boog(_,X,_);boog(X,_,_)),Knopen), list_to_set(Knopen,Result). %permutates the list permu([],[]). permu(X,[Y|Ys]) :- del(Y,X,Rs), permu(Rs,Ys). %deletes X from the list del(X,[X|Xs],Xs). del(X,[Y|Ys],[Y|Zs]) :- del(X,Ys,Zs).
Een alternatief
boog(a,b,1). boog(a,c,1). boog(b,c,1). boog(c,z,3). boog(b,z,1). mincut(X,Y) :- findall((Opl,L),oplossingen([a],Opl,L),Rij), sort(Rij,Sorted), last(Sorted,Last), neem_minimum(Sorted,Last,(L,Y)), alle_knopen(All), vind_rechterdeel(All,L,[],R), X = (L,R). neem_minimum([],Res,Res). neem_minimum([(Links,Som)|Xs],(LL,SS),(Lres,Sres)) :- ( Som < SS -> neem_minimum(Xs,(Links,Som),(Lres,Sres)) ; neem_minimum(Xs,(LL,SS),(Lres,Sres))). is_bereikbaar(X,Rij,Return) :- findall(B,(boog(X,B),\+ member(B,Rij)),R), delete(R,z,Return). alle_knopen(Result) :- findall(X,boog(X,_,_),Rij1), findall(Y,boog(_,Y,_),Rij2), append(Rij1,Rij2,Rij), sort(Rij,Result). % Alle knopen, Linkerdeel, res en res vind_rechterdeel([],_,Res,Res). vind_rechterdeel([X|Rest],Rij,Res,Result) :- ( member(X,Rij) -> vind_rechterdeel(Rest,Rij,Res,Result) ; vind_rechterdeel(Rest,Rij,[X|Res],Result)). som_rij([],Res,Res). som_rij([X|Xs],SubRes,Res) :- NSubRes is SubRes + X, som_rij(Xs,NSubRes,Res). % Linkerdeel, rechterdeel, result bereken_som(Links,Rechts,Som) :- findall(L,(boog(X,Y,L),member(X,Links),member(Y,Rechts)),Rij), som_rij(Rij,0,Som). % Je zit in, linkerdeel, result oplossingen(Res,Res,Som) :- alle_knopen(Knopen), vind_rechterdeel(Knopen,Res,[],Rechts), bereken_som(Res,Rechts,Som). oplossingen(Rij,Result,L) :- member(M,Rij), boog(M,B,_), B \== z, \+ member(B,Rij), append(Rij,[B],Verder), oplossingen(Verder,Result,L).
--Beau 15 jun 2006 11:51 (CEST)
Een ander alternatief
Elfangor
buur(X,Y,N) :- (boog(X,Y,N) ; boog(Y,X,N)). find(X,Y,snede([X|Z],[Y|W])) :- findall(A,buur(A,_,_),L), list_to_set(L,La), permutation(La,R), append([[X,Y],Z,W],R). mincut(X,Y) :- findall(C-B,(find(a,b,B), capaciteit(B,C)),L), keysort(L,[Xs-_|R]), partition(gelijk(Xs),R,Gelijken,_), pairs_values(Gelijken,Values), findall(C-B,(member(B,Values), gesneden_bogen(B,C)),A), keysort(A,[X-Y|_]). gelijk(Xs,Xs-_). capaciteit(snede(Xs,Ys), C) :- findall(N, (member(X,Xs), member(Y,Ys), buur(X,Y,N)),L), sumlist(L,C). gesneden_bogen(snede(Xs,Ys), C) :- findall(N, (member(X,Xs), member(Y,Ys), buur(X,Y,N)),L), length(L,C).
Een alternatief dat gebruik maakt van een bekend universeel zoekalgoritme
--Nick.dewaele (overleg) 16 jan 2018 19:49 (CET)
boog(a,b,1). boog(a,c,1). boog(b,d,1). boog(c,d,1). boog(d,z,2). neighbor(X, Y) :- boog(X,Y,_); boog(Y, X, _). vertices(V) :- findall(X, neighbor(X, _), Xs), sort(Xs, V). edges(E) :- findall(e(X,Y,W), boog(X,Y,W), E). weight(e(_,_,W), W). % Dit predicaat vindt alle bogen tussen knopen uit V en knopen uit W edgesbetween(V, W, Res) :- findall(e(X,Y,Weight), ( (member(X, V), member(Y, W) ; member(Y,V), member(X, W) ), boog(X,Y,Weight) ), Res). sumWeightEdges(V, W, Sum) :- edgesbetween(V, W, E), maplist(weight, E, Weights), % dit is de "map" van Haskell sum_list(Weights, Sum). mincut(X,Y) :- vertices(Vert), findall(V, (member(V, Vert), \+member(V,[a,z])), InternalNodes), sumWeightEdges([a], [z], InitCost), dijkstra([InitCost-state([a], [z], InternalNodes)], X-Y). dijkstra([Cost-state(Left,Right,[V|Unassigned]) | Q], Res) :- % voeg eerst toe aan de linkerkant sumWeightEdges([V], Right, SL), CostL is Cost + SL, LeftChild = CostL-state([V|Left], Right, Unassigned), % en dan rechts sumWeightEdges([V], Left, SR), CostR is Cost + SR, RightChild = CostR-state(Left, [V|Right], Unassigned), insertPQ([LeftChild, RightChild], Q, NewQ), dijkstra(NewQ, Res). dijkstra([Cost-state(Left, Right, [])|Q], Cost-cut(L,R)) :- % De eerste op de wachtrij is nu optimaal. Als er andere doelen zijn met dezelfde kost, % dan staan die nu ook op de wachtrij. Dit is altijd het geval tenzij er bogen zijn met % gewicht 0. Ik veronderstel dat dit zich nooit voordoet. filterbest([Cost-state(Left, Right, [])|Q], OptStates), include(isGoal, OptStates, OptGoals), % dit is de "filter" van Haskell % geef 1 van de mogelijke resultaten terug. member(_-state(L,R,_), OptGoals). insertPQ(Elems, Q, NewQ) :- append(Elems, Q, Q_), sort(1, @=<, Q_, NewQ). isGoal(_-state(_,_,[])). % haal de knopen uit de (gesorteerde) wachtrij die evenveel kosten als de eerste filterbest([K-V | T], Res) :- filterbest([K-V|T], K, Res). filterbest([K-V | T], K, [K-V|Res]) :- filterbest(T, K, Res). filterbest([K-_ | _], X, []) :- K \= X. filterbest([], _, []). kleinste_mincut(X, Y) :- findall(NumEdges-Cost-cut(Left,Right), ( mincut(Cost, cut(Left,Right)), edgesbetween(Left, Right, E), length(E, NumEdges) ), MinCuts), sort(1, @=<, MinCuts, Sorted), filterbest(Sorted, Best), % kies 1 oplossing member(_-X-Y, Best).