:- module(substitute,[subst/3,free/2,assignment/3]). :- use_module(signature,[fovar/1,newvar/1,newconst/1]). %const/1 :- [comsemOperators]. assignment([],_Constants,[]). assignment([V|Vars],Constants,[V:C|RestAssignment]) :- member(C,Constants), assignment(Vars,Constants,RestAssignment). subst(Ass,true(A),true(B)) :- !,subst(Ass,A,B). subst(Ass,false(A),false(B)) :- !,subst(Ass,A,B). subst(Ass,~A,~B) :- !,subst(Ass,A,B). subst(Ass,A&B,C&D) :- !,subst(Ass,A,C), subst(Ass,B,D). %% exists(X,P): %% 1. First, check if X is assigned a value. If so remove respective assignment. %% 2. Then check, if some variable is assigned the value X. Rename accordingly. %% 3. Substitute on scope. %% %% After checking (1), (2) may still be the case. Therefore, we have to go on with %% exists(X,Scope) in clause one and can only remove the exists in clause two. subst(Assignment,exists(X,Scope),Out) :- member(X:C,Assignment), !,delete(Assignment,X:C,NewAssignment), subst(NewAssignment,exists(X,Scope),Out). subst(Assignment,exists(X,Scope),exists(Y,OutScope)) :- captures(Assignment,X), !,gensym(fovar,Y), subst([Y:X],Scope,RenamedScope), subst(Assignment,RenamedScope,OutScope). % only reached if none of the above conditions holds. subst(Ass,exists(X,Scope), exists(X,OutScope)) :- !,subst(Ass,Scope,OutScope). subst(Assignment,forall(X,Scope),Out) :- member(X:C,Assignment), !,delete(Assignment,X:C,NewAssignment), subst(NewAssignment,forall(X,Scope),Out). subst(Assignment,exists(X,Scope),forall(Y,OutScope)) :- captures(Assignment,X), !,gensym(fovar,Y), subst([Y:X],Scope,RenamedScope), subst(Assignment,RenamedScope,OutScope). % only reached if none of the above conditions holds. subst(Ass,forall(X,Scope), forall(X,OutScope)) :- !,subst(Ass,Scope,OutScope). subst(Ass,X,C) :- member(X:C,Ass),!. % free variable in Dom(Ass) subst(Ass,In,Out) :- % atom or constant/unassigned variable (Args = []) In =.. [F|Args], substargs(Ass,Args,OutArgs), Out =.. [F|OutArgs]. % substargs/3 maps subst/3 over a list. substargs(_Ass,[],[]). substargs(Ass,[H1|R1],[H2|R2]) :- subst(Ass,H1,H2), substargs(Ass,R1,R2). /* was (less general, doesn't allow for complex terms as substitutes): substargs(_Ass,[],[]). substargs(Ass,[A1|R1],[A2|R2]) :- member(A1:A2, Ass),!, substargs(Ass,R1,R2). substargs(Ass,[A1|R1],[A1|R2]) :- substargs(Ass,R1,R2). */ free(Formula,Vars) :- findall(V,(fovar(V),freein(V,Formula)),Vs), list_to_set(Vs,Vars). captures([X:C|_],X) :- freein(X,C). captures([_|R],X) :- captures(R,X). freein(X,true(A)) :- !,freein(X,A). freein(X,false(A)) :- !,freein(X,A). freein(X,~A) :- !,freein(X,A). freein(X,A&B) :- !,(freein(X,A);freein(X,B)). freein(X,exists(X,_)) :- !,fail. freein(X,exists(_,A)) :- !,freein(X,A). % X=Y already covered above. freein(X,forall(X,_)) :- !,fail. freein(X,forall(_,A)) :- !,freein(X,A). % freein(X,A) :- \+ const(X), A =.. [_F|Args], member(X,Args). \+ can't be used for generating freein(X,A) :- fovar(X), A =.. [_F|Args], member(X,Args). freein(X,X) :- fovar(X).