Guest User

Untitled

a guest
Jul 26th, 2018
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Prolog 3.40 KB | None | 0 0
  1. :-use_module(library(sets)).
  2. main(FileName,RS) :-
  3. see(FileName),read(Deps),seen,unfold(Deps,FDs),
  4. getAttr(FDs,R0),
  5. splitAll(FDs,R0,RS),!.
  6.  
  7. % unfold finds all dependencies where one thing leads to two (or more) others,
  8. % splitting that dependency into two (or more) dependencies
  9. unfold([],[]).
  10. % removing trivial cases i.e. A>>A
  11. unfold([X>>X|Tail],New):- !,unfold(Tail,New).  
  12. % removing the trivial case [X,X,A]>>A. (The case [X,A,B]>>[A,B] unfolds into two of these cases)
  13. unfold([Y>>X|Tail],New):- member(X,Y),!,unfold(Tail,New).
  14. % biproduct of the row below, it might happen and if it does this predicate will catch it.
  15. unfold( [_>>[] |Tail],New):- !, unfold(Tail,New).
  16. % if splitting the dependecy works, then split it
  17. unfold( [D>>[H2|Tail2] |Tail],Rest):- !, unfold([D>>H2, D>>Tail2 |Tail],Rest).
  18. % otherwise, just add it as it is, assuming it's not splittable.
  19. unfold([ (D >> H2)|Tail],[D>>H2|Rest]):-unfold(Tail, Rest).
  20.  
  21. % determines whether all elements in L1 are in L2
  22. in([],_).
  23. in([H1|T1],L2) :- member(H1,L2), in(T1,L2).
  24.  
  25. % returns the closure of X
  26. % if X isn't a list and Y isn't a list
  27. closure(X,FDs,S) :-member(Y>>Z,FDs), \+member(Z,X), Y=X, \+X=[_|_],closure([Z|[X]],FDs,S),!.
  28. % closure(X,FDs,[Z|[X]]) :-member(Y>>Z,FDs), \+member(Z,X), Y=X, \+X=[_|_],!.
  29. % if X is a list and Y isn't a list
  30. closure(X,FDs,S) :-member(Y>>Z,FDs),\+member(Z,X), member(Y,X),closure([Z|X],FDs,S),!.
  31. % if X is a list and Y is a list
  32. closure(X,FDs,S):- member(Y>>Z,FDs), \+member(Z,X), in(Y,X),closure([Z|X],FDs,S),!.
  33. closure(X,_,X).
  34.  
  35. % gets a list of closures written as functional dependencies
  36. lClosures([],_,[]).
  37. lClosures([H|T],FDs,Cl):- Cl = [H>>C|Crest],closure(H,FDs,C),lClosures(T,FDs,Crest).
  38.  
  39. % Cl must be a one to one FD list
  40. proj(_,[],[]).
  41. proj(R1,[X>>Y|Ct],FDs1):- member(X,R1),member(Y,R1),FDs1 = [X>>Y|P],!,proj(R1,Ct,P).
  42. proj(R1,[_|Ct],FDs1):-!,proj(R1,Ct,FDs1).
  43.  
  44. % removes FD:s of the form a>>b b>>c a>>c where a>>c is unneccessary
  45. % Initially Ref and the first argument are identical
  46. purge([],_,[]).
  47. % purge([X>>Y|T],Ref,FDs1):- member(X>>Z,Ref),member(Z>>Y,Ref),!,purge(T,Ref,FDs1) .
  48. purge([X>>Y|T],Ref,FDs1):- leadsToInManySteps(X,Y,Ref),!,purge(T,Ref,FDs1) .
  49. purge([H|T],Ref,FDs1):- FDs1 = [H|T2], purge(T,Ref,T2).
  50.  
  51. % wrapper for leadsTo. Finds out if X leads to Y in any case other than the trivial.
  52. leadsToInManySteps(X,Y,Refs):-leadsTo(X,Y,Refs,[],N),N>1,!.
  53. % checks whether X leads to Y e.g. X>>A, A>>B, B>>Y
  54. % in at least ONE STEP
  55. % Refs is a list of dependencies
  56. % N is the number of steps to get to Y. N is at least 1
  57. leadsTo(X,Y,Refs,_,1) :- member(X>>Y,Refs).
  58. leadsTo(X,Y,Refs,Visited,N) :-write(Visited), \+member(X,Visited),member(X>>Z,Refs),V2 = [X|Visited],leadsTo(Z,Y,Refs,V2,N2),N is N2+1.
  59.  
  60. % the cases are one to one or many to one
  61. getAttr([],[]).
  62. % assuming that X is a list
  63. getAttr([X>>Y|T],Attr):- X = [_|_] ,getAttr(T,A),union([Y|X],A,R),Attr = R .
  64. getAttr([X>>Y|T],Attr):- getAttr(T,A),union([X,Y],A,R), Attr = R.
  65.  
  66. %checks if a given FD is a violation of the algorithm
  67. violates(X>>_,FDs,R):- closure(X,FDs,C), \+subtract(R,C,[]).
  68.  
  69. split(FDs,R,R1,R2,S1,S2) :- member(X>>Y,FDs),violates(X>>Y,FDs,R),closure(X,FDs,R1),subtract(R,R1,R21),
  70. (X=[_|_]->append(X,R21,R2);R2 = [X|R21]),
  71. proj(R1,FDs,S1),proj(R2,FDs,S2).
  72.  
  73. splitAll(FDs,R,RS):- split(FDs,R,R1,R2,S1,S2),!,splitAll(S1,R1,RS1),splitAll(S2,R2,RS2),append(RS1,RS2,RS).
  74. % if split didn't work, we're done.
  75. splitAll(_,R,[R]).
Add Comment
Please, Sign In to add comment