Declaratieve Talen/oplossingenSluiting
Naar navigatie springen
Naar zoeken springen
% -- Deel 1 sluiting(Waar, Regels, Sluiting) :- select(Cond >> Cons, Regels, RemainingRegels), member2(Cond, Waar), !, append(Waar, Cons, NewWaar0), list_to_set(NewWaar0, NewWaar1), sluiting(NewWaar1, RemainingRegels, Sluiting). sluiting(X, _, X). member2(L1, L2) :- intersection(L1, L2, L1). % -- Deel 2 alleredundante(F, X) :- findall(Pad, ( select(Cond >> Cons, F, AndereRegels), isredundant(Cond, AndereRegels, Cons, Pad0), Pad = redundant(Cond >> Cons, Pad0) ), List), list_to_set(List, X). isredundant(From, Regels, To, Pad) :- select(Cond >> Cons, Regels, AndereRegels), ( member2(To, Cons) -> Pad = [Cond >> Cons], From = Cond ; isredundant(From0, AndereRegels, To, Pad0), ( member2(From0, Cons) -> Pad = [Cond >> Cons | Pad0], From = Cond ; Pad = Pad0, From = From0 ) ).
Andere oplossing, weliswaar veel lelijker maar het maakt gebruik van sluiting/3 in deel 2
%% Deel 1 %% sluiting(VarSet,F,Sluiting) :- findall(Gevolg, (member(A>>Gevolg,F), set_diff(A,VarSet,[])), Gevolgen), concat(Gevolgen,EenLijst), append(VarSet,EenLijst,NieuwLijst), list_to_set(NieuwLijst,Stap), ( set_equals(Stap,VarSet) -> % geen nieuwe variabelen toegevoegd in laatste stap; sluiting gevonden Sluiting = Stap, true ; sluiting(Stap,F,Sluiting)). % twee verzamelingen zijn gelijk als het wederzijds verschil de lege verzameling is set_equals(S1,S2) :- set_diff(S1,S2,[]), set_diff(S2,S1,[]). % Verschil tussen twee verzamelingen met eventueel dubbele elementen set_diff([],_,[]) :- !. set_diff(In1,[],In1) :- !. set_diff(In1,In2,Out) :- select(E,In2,In2Out), select(E,In1,In1Out), !, set_diff(In1Out,In2Out,Out). member2(L1,L2) :- intersection(L1,L2,L1). % Maak van een lijst van lijsten één lijst concat([],[]). concat(Lists,Out) :- concat(Lists,[],Out). concat([],Out,Out). concat([List],Acc,Out) :- concat([List,[]],Acc,Out). concat([List1,List2|Rest],Acc,Out) :- append(List1,List2,Concat), append(Concat,Acc,NewAcc), concat(Rest,NewAcc,Out). %% Deel 2 %% alleredundante(F,X) :- findall(redundant(Regel,Clause),zoekredundante(F,Regel,Clause),X). zoekredundante(F,Regel,X) :- select(Regel,F,AndereRegels), zoek_minimale_redundante(Regel,AndereRegels,X). zoek_minimale_redundante(Regel,AndereRegels,X) :- findall(Subset, subseq0(AndereRegels,Subset), Subsets), qsort(Subsets, SortedSubsets), member(Set,SortedSubsets), is_redundant(Regel,Set), !, length(Set,MinLengte), % het minimaal aantal regels dat redundantie veroorzaakt is gevonden: controller voor elk van de subsets van die lengte of ze redundantie veroorzaken gelijke_lengte(MinLengte,SortedSubsets,MinCandidates), member(X,MinCandidates), is_redundant(Regel,X). % alle lijsten in de lijst die lengte N hebben gelijke_lengte(N,Lijst,Uit) :- gelijke_lengte(N,Lijst,[],Uit). gelijke_lengte(_N,[],Acc,Acc). gelijke_lengte(N,[L|Rest],Acc,Uit) :- length(L,Lengte), (N == Lengte -> NewAcc = [L | Acc], gelijke_lengte(N,Rest,NewAcc,Uit) ; gelijke_lengte(N,Rest,Acc,Uit)). % een regel is redundant ten opzichte van de andere regels als de sluiting van de gegeven head % de body van de regel omvat is_redundant(A >> B, Regels) :- sluiting(A,Regels,Sluiting), member2(B,Sluiting). % alle subsequenties van de gegeven verzameling subseq0(List, List). % triviaal geval subseq0(List, Rest) :- subseq1(List, Rest). subseq1([_|Tail], Rest) :- subseq0(Tail, Rest). % controleert of het tweede argument een echte subsequentie is van het eerste argument subseq1([Head|Tail], [Head|Rest]) :- subseq1(Tail, Rest). delete_first_N(N,List,Res) :- take(N,List,Smaller), set_diff(List,Smaller,Res). take(0,_,[]). take(N,[H|T],Res) :- NewN is N - 1, take(NewN,T,TRes), Res = [ H | TRes]. member_with_index(X,N,List) :- member_with_index(X,0,N,List). member_with_index(X,N,N,[X | _]). member_with_index(X,Acc,N,[_|List]) :- NewAcc is Acc + 1, member_with_index(X,NewAcc,N,List). % sorteer lijsten op lengte qsort(Lijst,Sorted) :- qsort(Lijst,[],Sorted). qsort([],L,L). qsort([Spil|R],Acc,Sorted) :- split(Spil,R,Kleiner,Groter), qsort(Groter,Acc,NewAcc), qsort(Kleiner,[Spil|NewAcc],Sorted). % de comparator is hier de lijstlengte split(_Spil,[],[],[]). split(Spil,[X|R],Kleiner,Groter) :- length(Spil,SpilLength), length(X,XLength), SpilLength > XLength, !, Kleiner = [X|RestK], split(Spil,R,RestK,Groter). split(Spil,[X|R],Kleiner,Groter) :- Groter = [X|RestG], split(Spil,R,Kleiner,RestG).