| % |
| % This file contains the source code for the second optimization, |
| % which implements the algorithm for query compilation |
| % |
| :- import updat/1 from updates. |
| :- import append/3 from basics. |
| % define directive opt2_trans |
| opt2_trans(File_ctr) :- |
| in_opt2(File_ctr,File1), |
| see(File1), |
| remove_upd1, |
| insert_upd1(Preds), |
| remove_graph1, |
| remove_db_pred, |
| opt_read_and_create_graph1(File1), |
| seen, |
| see(File1), |
| out_opt2(File_ctr,FileOut2), |
| unix('rm -f FileOut2 2>/dev/null', R1), |
| tell(FileOut2), |
| opt_read_and_compile2(File1,FileOut2), |
| seen, told, |
| opt_insert_file(FileOut2), |
| see(File1), |
| out_db(File_ctr,FileOut), |
| unix('rm -f FileOut 2>/dev/null', R1), |
| tell(FileOut), |
| opt_read_and_compile1(File1,FileOut), |
| seen, told, |
| opt_insert_file(FileOut). |
| % parse transaction base rules repeatedly |
| % to create dependency graph |
| opt_read_and_create_graph1(FileIn) :- |
| read(Term), |
| ( |
| (Term == end_of_file) -> true |
| ; |
| opt_read_rule1(Term,FileIn), |
| opt_read_and_create_graph1(FileIn) ). |
| % read transaction base object file and write |
| % optimized object database file |
| opt_read_and_compile1(FileIn,FileOut) :- |
| read(Term), |
| ( |
| (Term == end_of_file) -> true |
| ; |
| opt_read_and_write_rule1(Term,FileIn,FileOut), |
| opt_read_and_compile1(FileIn,FileOut) ). |
| % read transaction base object file and write |
| % optimized transaction-base object file |
| opt_read_and_compile2(FileIn,FileOut) :- |
| read(Term), |
| ( |
| (Term == end_of_file) -> true |
| ; |
| opt_read_and_write_rule2(Term,FileIn,FileOut), |
| opt_read_and_compile2(FileIn,FileOut) ). |
| % determine edges from transaction base rules |
| opt_read_rule1(':-'(trans(Lhs),Rhs),_) :- |
| Lhs =..Lname, |
| Lname = [Name|_], |
| insert_edge1(Name, Rhs). |
| opt_read_rule1(':-'(Lhs,Rhs),_). |
| % write optimized rules in database file |
| opt_read_and_write_rule1(':-'(trans(Lhs),Rhs),_,_) :- |
| Lhs =..LLhs, |
| LLhs = [Name|_], |
| check_pred(Name), |
| opt(Lhs, Rhs, PRhs), |
| create_trans_db(Lhs, NLhs), |
| write(NLhs), |
| write(' :- '), |
| (islist(PRhs), |
| write_list(PRhs) |
| ; |
| create_trans_db(PRhs, NPRhs), |
| write(NPRhs), |
| write('.')), |
| nl, |
| write(NLhs), |
| write(' :- '), |
| write(Lhs), |
| write('.'), |
| nl, |
| (islist(PRhs), |
| write_list_pred_rules(PRhs) |
| ; |
| (updat(PRhs), |
| create_trans_db(PRhs, NRhs), |
| write(NRhs), |
| write(' :- '), |
| write(PRhs), |
| write('.'), nl |
| ; |
| not(updat(PRhs)))). |
| opt_read_and_write_rule1(':-'(Lhs,Rhs),_,_). |
| % write optimized rules in transaction base file |
| opt_read_and_write_rule2(':-'(trans(Lhs),Rhs),_,_) :- |
| check_ref(Lhs), |
| write(trans(Lhs)), |
| write(' :- '), |
| optT(Rhs, PR, PRhs), |
| write(PRhs), |
| write('.'), nl, |
| (islist(PR), |
| write_list_pred_trans(PR) |
| ; |
| (updat(PR), |
| create_trans_db(PR, NR), |
| write(trans(NR)), |
| write(' :- '), |
| write(PR), |
| write('.'), nl |
| ; |
| not(updat(PR)))). |
| opt_read_and_write_rule2(':-'(trans(Lhs),Rhs),_,_) :- |
| write(trans(Lhs)), |
| write(' :- '), |
| optT(Rhs, PR, PRhs), |
| write(PRhs), |
| write('.'), nl. |
| opt_read_and_write_rule2(':-'(Lhs,Rhs),_,_) :- |
| write(Lhs), |
| write(' :- '), |
| write(Rhs), |
| write('.'), nl. |
| opt(Lhs, Rhs, PRhs) :- not(iref1(Lhs,_)), |
| not(dref1(Lhs,_)), |
| remove_op(Rhs, PRhs). |
| % translate CTR terms into Prolog terms |
| optT(isolate(P), PR, R) :- not(iref1(P,_)), |
| not(dref1(P,_)), |
| remove_op(isolate(P), PR), |
| (islist(PR), |
| create_ctr_list(PR, NPR), |
| conv(NPR, R, ',') |
| ; |
| PR =..LPR, |
| LPR = [Name|_], |
| assert(db_pred(Name)), |
| create_trans_db(PR, NPR), |
| conv_one([NPR], R, '')). |
| optT(isolate(P), PR, isolate(R)) :- optT(P, PR, R). |
| optT(isolate1(P), PR, R) :- not(iref1(P,_)), |
| not(dref1(P,_)), |
| remove_op(isolate1(P), PR), |
| (islist(PR), |
| create_ctr_list(PR, NPR), |
| conv(NPR, R, ',') |
| ; |
| PR =..LPR, |
| LPR = [Name|_], |
| assert(db_pred(Name)), |
| create_trans_db(PR, NPR), |
| conv_one([NPR], R, 'call')). |
| optT(isolate1(P), PR, isolate1(R)) :- optT(P, PR, R). |
| optT(seq(L), PR, seq(L1)) :- optT_list(L, PR, L1). |
| optT(conc(L), PR, conc(L1)) :- optT_list(L, PR, L1). |
| optT(conc1(L), PR, conc1(L1)) :- optT_list(L, PR, L1). |
| optT(P, PR, P). |
| optT_list([], PR, []). |
| optT_list(L, PR, L1) :- L = [H0|Tail0], |
| L1 = [H1|Tail1], |
| optT(H0, PR, H1), |
| optT_list(Tail0, PR, Tail1). |
| % create translated clauses |
| remove_op(isolate(P), R) :- remove_op(P, R). |
| remove_op(isolate1(P), R) :- remove_op(P, R). |
| remove_op(seq(L), R) :- proc_list(L, R). |
| remove_op(conc(L), R) :- proc_list(L, R). |
| remove_op(conc1(L), R) :- proc_list(L, R). |
| remove_op(P, P). |
| proc_list([], []). |
| proc_list(L, L1) :- L = [H0|Tail0], |
| L1 = [H1|Tail1], |
| remove_op(H0, H1), |
| proc_list(Tail0, Tail1). |
| % build dependency graph |
| insert_edge1(Name, Rhs) :- appears(Rhs, X), |
| not(edge1(Name, X)), |
| not(Name = X), |
| assert(edge1(Name, X)), |
| fail. |
| insert_edge1(Name, Rhs). |
| insert_upd1(Preds) :- updat(Preds), |
| Preds =..Lpreds, |
| Lpreds = [Name|_], |
| assert(upd(Name)), fail. |
| insert_upd1(Preds). |
| % determine nodes for dependency graph |
| appears(conc(L), X) :- L = [Head|_], |
| appears(Head, X). |
| appears(conc(L), X) :- L = [_|Tail], |
| appears(conc(Tail), X). |
| appears(conc1(L), X) :- L = [Head|_], |
| appears(Head, X). |
| appears(conc1(L), X) :- L = [_|Tail], |
| appears(conc1(Tail), X). |
| appears(seq(L), X) :- L = [Head|_], |
| appears(Head, X). |
| appears(seq(L), X) :- L = [_|Tail], |
| appears(seq(Tail), X). |
| appears(isolate1(E), X) :- !, appears(E, X). |
| appears(isolate(E), X) :- !, appears(E, X). |
| appears(ins(X), Y) :- !, X =..Pred, |
| Pred = [Name|_], |
| Y = ins(Name). |
| appears(del(X), Y) :- !, X =..Pred, |
| Pred = [Name|_], |
| Y = del(Name). |
| appears(P, Y) :- P =..Pred, |
| Pred = [Name|_], |
| not(Name = conc), |
| not(Name = conc1), |
| not(Name = seq), |
| not(Name = isolate), |
| not(Name = isolate1), |
| atom(Name), |
| Y = Name. |
| % find connected nodes in dependency graph |
| reachable1(P, P). |
| reachable1(P, Q) :- edge1(P, Q). |
| reachable1(P, Q) :- edge1(P, R), reachable1(R, Q). |
| % query sets definition |
| qref1(Q, Q) :- Q =..Pred, |
| Pred = [Name|_], |
| upd(Name). |
| qref1(E, Q) :- appears(E, P), reachable1(P, Q), upd(Q). |
| qref2(E, Q) :- appears(E, P), reachable1(P, Q). |
| % insert sets definition |
| iref1(ins(Q), Q). |
| iref1(E, Q) :- appears(E, P), reachable1(P, ins(Q)). |
| % delete sets definition |
| dref1(del(Q), Q). |
| dref1(E, Q) :- appears(E, P), reachable1(P, del(Q)). |
| % cleanup before the algorithm begins |
| remove_upd1 :- retract(upd(X)), fail. |
| remove_upd1. |
| remove_db_pred :- retract(db_pred(X)), fail. |
| remove_db_pred. |
| % delete any previously created dependency graph |
| remove_graph1 :- retract(edge1(X, Y)), fail. |
| remove_graph1. |
| remove_dep1 :- retract(dep(1)). |
| remove_dep1. |
| remove(K) :- retract(dep(K)). |
| remove(K). |
| % create file names for input object files |
| in_opt2(FileIn,FileOut) :- |
| name(FileIn,NameIn), |
| append(NameIn,".opt1.o",NameOut), |
| name(FileOut,NameOut). |
| % create file names for output optimized files |
| out_db(FileIn,FileOut) :- |
| name(FileIn,NameIn), |
| append(NameIn,".opt2.db",NameOut), |
| name(FileOut,NameOut). |
| out_opt2(FileIn,FileOut) :- |
| name(FileIn,NameIn), |
| append(NameIn,".opt2.o",NameOut), |
| name(FileOut,NameOut). |
| % load optimized rules in database |
| opt_insert_file(FileName) :- |
| seeing(X), |
| see(FileName), |
| opt_read_and_add_line, |
| see(X). |
| opt_read_and_add_line :- |
| read(Line), |
| ( |
| (Line == end_of_file) -> true |
| ; |
| assert(Line), |
| opt_read_and_add_line ). |
| % build new predicate names for database optimized file |
| create_trans_db(monitor(Lhs), monitor(NLhs)) :- |
| not(islist(Lhs)), |
| Lhs =..X, |
| X = [Head|Tail], |
| not(Head = conc), |
| not(Head = conc1), |
| not(Head = seq), |
| not(Head = isolate), |
| not(Head = isolate1), |
| name(Head, NameHead), |
| append(NameHead,"_ctr_db", OutHead), |
| name(NewName, OutHead), |
| Y = [NewName|Tail], |
| NLhs =..Y. |
| create_trans_db(Lhs, NLhs) :- |
| not(islist(Lhs)), |
| Lhs =..X, |
| X = [Head|Tail], |
| not(Head = conc), |
| not(Head = conc1), |
| not(Head = seq), |
| not(Head = isolate), |
| not(Head = isolate1), |
| name(Head, NameHead), |
| append(NameHead,"_ctr_db", OutHead), |
| name(NewName, OutHead), |
| Y = [NewName|Tail], |
| NLhs =..Y. |
| % translate rules for database optimized file |
| create_ctr_list([], []). |
| create_ctr_list(PR, NPR) :- flatten(PR, LR), |
| LR = [Head|Tail], |
| assert(db_pred(Head)), |
| NPR = [Head1|Tail1], |
| create_trans_db(Head, Head1), |
| create_ctr_list(Tail, Tail1). |
| write_list([]). |
| write_list(L) :- L = [Head|Tail], |
| create_trans_db(Head, NHead), |
| write(NHead), |
| (Tail = [], |
| write('.') |
| ; |
| write(',')), |
| L1 = Tail, |
| write_list(L1). |
| %write new rules in optimized database file |
| write_list_pred_rules([]). |
| write_list_pred_rules(L) :- L = [Head|Tail], |
| updat(Head), |
| create_trans_db(Head, NHead), |
| write(NHead), |
| write(' :- '), |
| write(Head), |
| write('.'), |
| nl, |
| L1 = Tail, |
| write_list_pred_rules(L1). |
| write_list_pred_rules(L) :- L = [Head|Tail], |
| not(updat(Head)), |
| L1 = Tail, |
| write_list_pred_rules(L1). |
| write_list_pred_trans([]). |
| write_list_pred_trans(L) :- L = [Head|Tail], |
| updat(Head), |
| create_trans_db(Head, NHead), |
| write(trans(NHead)), |
| write(' :- '), |
| write(Head), |
| write('.'), |
| nl, |
| L1 = Tail, |
| write_list_pred_trans(L1). |
| write_list_pred_trans(L) :- L = [Head|Tail], |
| not(updat(Head)), |
| L1 = Tail, |
| write_list_pred_trans(L1). |
| islist([]). |
| islist([_|_]). |
| conv([], [],_). |
| conv([First|Tail], NewList, Functor) :- |
| (not(Tail = []), |
| NewList =..[Functor, First, NewTail] |
| ; |
| NewList = First, |
| NewTail = []), |
| conv(Tail, NewTail, Functor). |
| conv_one([El], NewEl, F1) :- |
| NewEl =..[F1, El]. |
| flatten([], []). |
| flatten([Head|Tail], FlatList) :- flatten(Head, FlatHead), |
| flatten(Tail, FlatTail), |
| append(FlatHead, FlatTail, FlatList), !. |
| flatten(X, [X]). |
| check_ref(Lhs) :- iref1(Lhs,_). |
| check_ref(Lhs) :- dref1(Lhs,_). |
| check_pred(Name) :- db_pred(Name). |
| check_pred(Name) :- db_pred(Y), |
| qref2(Y, Name). |
| edge1(dummy, dummy) :- fail. |
| modifiable(dummy) :- fail. |
| upd(dummy) :- fail. |
| dep(dummy) :- fail. |
| db_pred(dummy) :- fail. |