sldnf.1.2.pl
sldnf.1.2.pl — text/x-perl, 10 kB (10722 bytes)
Contenuto del file
% TODO: % stop when 1st solution found % stop negation when 1st solution found % CLP? Minimize?s % Version 1.2: stops at a given depth % Deals with cut. % prints infixed operators % Note that it does not handle correctly the cut in the resolvent, but only % in a clause. Please, no do write ?- p,!. but define e new predicate % callp:- p,!. % Given a clause a:-b,!,c, we have that: % 1.the scope of the cut is a:-b, in the sense that it will cut the % alternatives to a and b. This is represented with the list % of OpenCuts: it contains all the cuts that are in a clause that % has been selected. % 2.The cut has an effect when it is reached, and its effect lasts % until the backtracking goes back to a. Thus, the information about % reaching a cut is saved with assert(reached(Cut)). % Each cut has a unique name, given by a counter. :- dynamic begin_resolvent/1, end_resolvent/1, begin_binding/1, end_binding/1, counter/1. draw_goal(G,FileName):- open(FileName,write,File), term_length(G,Length), conv_sq_list(G,GSq), init_cuts, (draw(GSq,File,Length) ; true), close(File). draw(R,F,Longest):- draw(R,F,Longest,30,[]). % Default Max depth: 30 % draw(+Resolvent,+Stream,MaxLenghtOfResolvent,MaxDepth,OpenCuts) draw([],F,Longest,_,_):- print_string_spaces(F,Longest,"true"), fail. draw(_,F,Longest,0,_):- !, print_string_spaces(F,Longest,"..."), fail. draw([not G|R],F,LongestIn,Depth,OpenCuts):- Depth1 is Depth-1, write(F,"\\begin{bundle}{"), print_resolvent(F,[not G|R]), writeln(F,"}\n\\chunk{"), % NOTA: forse in questo caso non conviene metterlo, cosi` il box diventa giusto. % pero` non si assicura che sia giusto il figlio del box... % Compute the maximum length term_length([not G|R],ResLen), Length is max(LongestIn,ResLen), write(F,"\\begin{bundle}{\\framebox{"), (draw([G],F,0,Depth1,[]) ; true), write(F,"}}"), (vanilla(G) -> print_fail(F,ResLen) ; write(F,"\\chunk{"), (draw(R,F,Length,Depth1,OpenCuts); true), write(F,"}") ), writeln(F,"\\end{bundle}}\\end{bundle}"), fail. % Cut ! draw([!|R],F,LongestIn,Depth,[LastCut|OpenCuts]):- !, Depth1 is Depth-1, term_length([!|R],ResLen), Length is max(LongestIn,ResLen), write(F,"\\begin{bundle}{"), print_resolvent(F,[!|R]), writeln(F,"}"), assert(reached(LastCut)), (print_builtin_children(true,R,F,Length,Depth1,OpenCuts); writeln(F,"\\end{bundle}")), fail. % Built-in Predicate draw([G|R],F,LongestIn,Depth,OpenCuts):- Depth1 is Depth-1, not(G = not(_)), built_in(G), term_length([G|R],ResLen), Length is max(LongestIn,ResLen), write(F,"\\begin{bundle}{"), print_resolvent(F,[G|R]), writeln(F,"}"), (print_builtin_children(G,R,F,Length,Depth1,OpenCuts); writeln(F,"\\end{bundle}")), fail. % User defined predicate draw([G|R],F,LongestIn,Depth,OpenCuts):- Depth1 is Depth-1, not(G = not(_)), not(built_in(G)), term_length([G|R],ResLen), Length is max(LongestIn,ResLen), write(F,"\\begin{bundle}{"), print_resolvent(F,[G|R]), writeln(F,"}"), (print_children(G,R,F,Length,Depth1,OpenCuts); writeln(F,"\\end{bundle}")), fail. print_children(G,R,F,Length,Depth,OpenCuts):- Depth1 is Depth-1, term_variables(G,Vars), vars_names(Vars,VarNames), count_children(G,NumChildren), (NumChildren = 1 -> Len = Length ; Len=0), increase_counter, get_counter(C), % Unique name for the node: if a cut is reached, it will have this name % First part: the cut may cut the alternatives for the clause retract_cut_on_backtracking(C), clausola(G,B), (clause_is_not_cut(C) -> true ; write(F,"\\chunk{(cut)}"), fail), (check_body_contains_cut(B,OpenCuts,NewCuts,_AddedCut,C) -> % retract_cut_on_backtracking(AddedCut) true ; NewCuts=OpenCuts), % Second part: takes care of the alternatives of the predicates % in the body ( (member(Cut,OpenCuts),reached(Cut)) -> write(F,"\\chunk{(cut)}"), fail ; write(F,"\\chunk"), print_binding(F,VarNames), write(F,"{"), append(B,R,Ris), (draw(Ris,F,Len,Depth1,NewCuts) ; write(F,"}"), fail) ). print_children(G,_,F,Length,_Depth,_):- not(clausola(G,_)), print_fail(F,Length), fail. print_builtin_children(G,R,F,Length,Depth,OpenCuts):- Depth1 is Depth-1, term_variables(G,Vars), vars_names(Vars,VarNames), findall(G,call(G),L),length(L,NumChildren), (NumChildren = 1 -> Len = Length ; Len=0), call(G), write(F,"\\chunk"), print_binding(F,VarNames), write(F,"{"), (draw(R,F,Len,Depth1,OpenCuts) ; write(F,"}"), fail). print_builtin_children(G,_,F,Length,_Depth,_OpenCuts):- not(call(G)), print_fail(F,Length), %write(F,"\\chunk{fail}"), fail. %%%%%%%%%%%%%%%% Predicates fot cut handling %%%%%%%%%%%%%%%%% %check_body_contains_cut(+Body,++OpenCuts,-NewCuts,-AddedCut,++Counter) check_body_contains_cut(B,OpenCuts,NewCuts,AddedCut,Counter):- memberchk(!,B),push_cut(OpenCuts,NewCuts,AddedCut,Counter). % A clause is not cut if there exists no reached cut after % the last open cut. %clause_is_not_cut([]):-!, % not(reached(_)). %clause_is_not_cut(OpenCuts):- % OpenCuts = [_|_], % last_cut(OpenCuts,Last), % not( % (reached(Cut), follows(Cut,Last)) % ). % With counters: the clause is not cut if the cut of the current % node has not been reached. clause_is_not_cut(C):- not reached(cut(C)). %push_cut([],[cut(C)],cut(C),C). %push_cut([cut(N)|T],[cut(N1),cut(N)|T],cut(N1)):- % N1 is N+1. push_cut(L,[cut(C)|L],cut(C),C). % On backtracking, remove the information about the reached cuts % that are not open retract_cut_on_backtracking(_). retract_cut_on_backtracking(C):- retract(reached(C)), fail. %retract_cut_on_backtracking([]):- % retract(reached(_)), fail. %retract_cut_on_backtracking(OpenCuts):- % OpenCuts = [_|_], % last_cut(OpenCuts,Last), % reached(Cut), follows(Cut,Last), % retract(reached(Cut)), fail. follows(cut(N),cut(N1)):- N>N1. last_cut([C],C):-!. last_cut([Cut|Cuts],C):- last_cut(Cuts,LastSoFar), (follows(LastSoFar,Cut) -> C=LastSoFar ; C=Cut). init_cuts:- retract_all(reached(_)), reset_counter. increase_counter:- counter(C), retract(counter(C)), C1 is C+1, assert(counter(C1)). get_counter(C):- counter(C). reset_counter:- retract_all(counter(_)), assert(counter(0)). %%%%%%%%%%%%%%% End predicates for cut handling %%%%%%%%%%%%%% count_children(G,NumChildren):- findall(B,clausola(G,B),L), length(L,NumChildren). vars_names([],[]). vars_names([X|T],[b(X,N)|TN]):- var_name(X,N), vars_names(T,TN). var_name(X,N):- open(string(""),write,Stream), write(Stream,X), get_stream_info(Stream, name, N), close(Stream). print_binding(F,X):- write(F,"["), (begin_binding(S) -> write(F,S); true), print_binding1(F,X), (end_binding(Send) -> write(F,Send) ; true), write(F,"]"). print_binding1(_F,[]). print_binding1(F,[b(A,B)|T]):- var_name(A,Name), Name = B, !, % Avoid writing "X=X" as a binding... print_binding1(F,T). print_binding1(F,[b(A,B)|T]):- write(F,B), write(F,"/"), write_term_no_sqbrack(F,A), (T=[] -> true ; write(F,", "), print_binding1(F,T)). % Writes a term replacing the symbols "[" and "]" % with \lbrack and \rbrack, because you cannot use "[" % inside a label of an arc. write_term_no_sqbrack(F,A):- var(A), !, write(F,A). write_term_no_sqbrack(F,[]):- !, write(F,"\\lbrack\\rbrack "). write_term_no_sqbrack(F,[H|T]):- !, write(F,"\\lbrack "), print_list_no_sqbrack(F,[H|T]), write(F,"\\rbrack "). write_term_no_sqbrack(F,T):- T =.. [Fun], !, write(F,Fun). % infixed operators write_term_no_sqbrack(F,T):- T =.. [Fun,ArgX,ArgY], current_op(_,Associativity,Fun), (Associativity = xfy ; Associativity = yfx ; Associativity = xfx),!, write_term_no_sqbrack(F,ArgX), pretty_write_op(F,Fun), write_term_no_sqbrack(F,ArgY). write_term_no_sqbrack(F,T):- !, T =.. [Fun|Arg], write(F,Fun), write(F,"("), print_list_no_sqbrack(F,Arg), write(F,")"). % If the list is a difference list, we also have the % case in which the rest is a variable. print_list_no_sqbrack(F,V):- var(V), !, write_term_no_sqbrack(F,V). print_list_no_sqbrack(F,[H|T]):- var(T),!, write_term_no_sqbrack(F,H), write(F,"$|$"), write_term_no_sqbrack(F,T). print_list_no_sqbrack(F,[H]):- !, write_term_no_sqbrack(F,H). print_list_no_sqbrack(F,[H1,H2|T]):- write_term_no_sqbrack(F,H1),write(F,","), print_list_no_sqbrack(F,[H2|T]). pretty_write_op(F,<):- !, write(F,$<$). pretty_write_op(F,>):- !, write(F,$>$). pretty_write_op(F,Op):- !, write(F,Op). print_resolvent(F,X):- (begin_resolvent(S) -> write(F,S); true), print_list(F,X), (end_resolvent(Send) -> write(F,Send) ; true). print_list(F,[H]):- !, write_term_no_sqbrack(F,H). print_list(F,[H1,H2|T]):- write_term_no_sqbrack(F,H1),write(F,","), print_list(F,[H2|T]). print_fail(F,Longest):- write(F,"\\chunk{"), print_string_spaces(F,Longest,"false"), write(F,"}"). % Prints a string adding "Longest" spaces. print_string_spaces(F,Longest,String):- NumSpace is Longest//2, print_n_spaces(F,NumSpace), write(F,String), writeln(F,"\n"), print_n_spaces(F,NumSpace). print_n_spaces(_,0):- !. print_n_spaces(F,N):- number(N), N>0, write(F,"~"), N1 is N-1, print_n_spaces(F,N1). vanilla([]). vanilla([A|B]) :- !, vanilla(A), vanilla(B). vanilla(not X) :- !, (vanilla(X) -> fail ; true). vanilla(X) :- built_in(X), call(X). vanilla(X) :- clausola(X,Body), vanilla(Body). term_length(G,Length):- term_string(G,S), string_length(S,Length). clausola(H,BSq):- functor(H,F,A), current_predicate(F/A), clause(H,B), conv_sq_list(B,BSq). clausola(H,BSq):- my_clause(H,BSq). conv_sq_list((A,B),[A|Bsq]):- !, conv_sq_list(B,Bsq). conv_sq_list(true,[]):- !. conv_sq_list(X,[X]). built_in(G):- functor(G,F,A), current_built_in(F/A).