Relational Database Design Programs
The following are some Prolog programs that are useful for Chapter 12 and 13 problems. To invoke cprolog on tinman, type
$cprologAfter entering cprolog, consult the program using the following command:
| ?- ['dbd.pro'].where dbd.pro is a file containing the programs. After this, you may ask any query based on the relations defined in the program. To exit cprolog environment, enter the following command:
| ?- halt.
The Prolog program follows:
% Input data: The relation scheme R and the set of FDs F
% are represented as follows:
% Suppose
% R = (A,B,C,G,H,I)
% F = { A --> B, A --> C, CG --> H, CG --> I, B --> H }
%
% Then, R and F are represented as Prolog lists as follows:
%
% R = [a,b,c,g,h,i]
% F = [ [[a],[b]], [[a],[c]], [[c,g],[h]], [[c,g],[i]], [[b],[h]] ]
%
% Note that all attributes are in lower case
%
%***************************************************************************
% xplus computes the closure of a set of attributes with respect to R and F
%
% xplus(R,F,X,XPLUS) is true iff XPLUS is the closure of X wrt R and F.
%
% input: R,F, and X
% output: XPLUS
%***************************************************************************
xplus(R,F,X,XPLUS) :- xph(R,F,X,X,[],XP),
mergesort(XP,XPLUS).
xph(R,F,X,T,T,T) :- !.
xph(R,F,X,Tnew,Told,XPLUS) :- onepass(R,F,X,Tnew,S),
xph(R,F,X,S,Tnew,XPLUS).
onepass(R,[],X,S,S) :- !.
onepass(R,[[U,V]|L],X,T,F) :- subset(T,U), !,
union(T,V,T1),
onepass(R,L,X,T1,F).
onepass(R,[[U,V]|L],X,T,F) :- onepass(R,L,X,T,F).
%***************************************************************************
% finfplus checks to see if a FD is in the closure of a set of FDs
%
% finfplus(R,F,[X,Y]) is true if FD, X --> Y belongs to the closure of
% F with respect to R. X and Y are lists of attributes.
%
% input: R, F, and [X,Y]
% output: Yes/No
%
%***************************************************************************
finfplus(R,F,[X,Y]) :- xplus(R,F,X,Z),
subset(Z,Y).
%***************************************************************************
%
% fplus(R,F,FPLUS) is true if FPLUS is the closure of F wrt R.
%
% input: R, F
% output: FPLUS
%
%**************************************************************************
fplus(R,F,FPLUS) :- setof(FD,onefinfplus(R,F,FD),FPLUS).
onefinfplus(R,F,[X,Y]) :- subset(R,X),
subset(R,Y),
not (subset(X,Y)),
finfplus(R,F,[X,Y]).
%***************************************************************************
%
% implies(R,F1,F2) is true if the set of FDs F1 logically implies
% the set of FDs F2.
%
% equiv(R,F1,F2) is true if the sets of FDs F1 and F2 are logically
% equivalent.
%
% input: R, F1, F2
% output: Yes/No
%
%***************************************************************************
implies(R,F,[]).
implies(R,F,[[X,Y]|L]) :- xplus(R,F,X,Z),
subset(Z,Y),
implies(R,F,L).
equiv(R,F1,F2) :- implies(R,F1,F2),
implies(R,F2,F1).
%***************************************************************************
%
% superkey(R,F,K) is true if K is a super key of R given FDS F.
% candkey(R,F,K) is true if K is a candidate key of R given FDs F
%
% could be used to generate super keys/candidate keys as well as
% test if K is a super key or a candidate key.
%
% input: R, F
% output: K
%***************************************************************************
superkey(R,F,K) :- subset(R,K),
xplus(R,F,K,R1),
mergesort(R,R1).
candkey(R,F,K) :- superkey(R,F,K),
setof(K1,(subset(K,K1),not(subset(K1,K))),S),
ckey_check(R,F,S).
ckey_check(R,F,[]).
ckey_check(R,F,[K1|L]) :- not(superkey(R,F,K1)),
ckey_check(R,F,L).
%***************************************************************************
%cancover(R,F,FC) :- .
%***************************************************************************
% dfd(R,F,[X,Y]) is true if X-->Y is derivable from F.
% can also be used to derive all FDs in closure of F
% Input: R, F, [X,Y]
% Output: yes if X-->Y is derivable from F; no otherwise
%***************************************************************************
dfd(R,F,X) :- member(X,F).
dfd(R,F,[X,Y]) :- subset(R,X),
subset(X,Y).
dfd(R,F,[U,V]) :- subset(R,W),
dfd(R,F,[X,Y]),
union(X,W,U),
union(Y,W,V).
dfd(R,F,[X,Z]) :- subset(R,Y),
dfd(R,F,[X,Y]),
dfd(R,F,[Y,Z]).
%***************************************************************************
%***************************************************************************
% Utility relations
%***************************************************************************
member(X,[X|_]).
member(X,[_|L]) :- member(X,L).
union([],A,A) :- !.
union([X|L],A,B) :- member(X,A), union(L,A,B).
union([X|L],A,[X|B]) :- not (member(X,A)), union(L,A,B).
reverse([],[]) :- !.
reverse([X|L],N) :- reverse(L,M), append(M,[X],N).
append([],X,X) :- !.
append([X|Y],Z,[X|W]) :- append(Y,Z,W).
subset(S,SS) :- var(SS), !, subset_gen(S,SS).
subset(S,SS) :- subset_test(SS,S).
subset_gen(L,L).
subset_gen(L,M) :- remove(L,M).
remove([A|L],L).
remove([A|L],M) :- remove(L,M).
remove([A|L],[A|M]) :- remove(L,M).
subset_test([],L).
subset_test([A|L],B) :- member(A,B), subset_test(L,B).
mergesort([],[]) :- !.
mergesort([X],[X]) :- !.
mergesort(X,Z) :- split(X,L1,L2),
mergesort(L1,M1),
mergesort(L2,M2),
merge(M1,M2,Z).
split([],[],[]) :- !.
split([X],[X],[]) :- !.
split([X,Y|Z],[X|L1],[Y|L2]) :- split(Z,L1,L2).
merge([],X,X) :- !.
merge(X,[],X) :- !.
merge([X|L],[Y|M],[X|N]) :- X @=< Y, !, merge(L,[Y|M],N).
merge([X|L],[Y|M],[Y|N]) :- Y @=< X, merge([X|L],M,N).
% ***********************************************************************