%% Son Tran's translator program - b2s.pl %% %% input: a Prolog program representing a domain %% description in Language B %% output: a domain description and a domain problem %% which will be used as input to Smodels %% %% The b2s translator is currently capable of handling %% the following features: %% %% a. Dynamic Causal Laws of the form: %% causes(A,F,P) iff action A causes fluent literal F %% to be true if preconditions P hold. %% %& b. Static Causal Laws: %% caused(F,G) iff set of fluent literals G causes fluent %% literal F to be true. %% %% c. Defaults: %% default(F,G) - normally fluent literal F holds in any state %% which satisfies G. %% %% d. Executability conditions: %% impossible(A,G) iff it is not possible to execute %% action A if set of fluent literals G hold. %% %% e. Constraints: %% constraint(L) iff list L is satisfied in any state. %% %% f. Serialization of actions: %% Concurrent actions are not allowed. %% %% g. Initial state: %% initially(F) iff fluent literal F holds in the initial state. %% %% h. Goal state: %% goal(F) iff fluent literal F holds in the final state. %% %% Program b2s.pl will separate the above rules into two different files %% which will be used as input to Smodels: %% 1. (a) through (f) will be used to generate the domain description file, %% 2. (g) and (h) will be used to generate the domain problem file. %% %% Notice that b2s will only work correctly if the following %% predicates are defined in the domain description input file: %% 1. fluent(F) iff F is a fluent. %% 2. action(A) iff A is an action. %% %%-------------------------------------------------------------------------- %% To use the b2s program: %% 1. Compile b2s.pl using SICStus Prolog %% 2. At the SICStus Prolog prompt, type: gen. %% and press %% 3. Enter the name of input/output files ended by a period when requested. %%-------------------------------------------------------------------------- user_module(library(files)). user_module(library(lineio)). user_module(library(strings)). user_module(library(lists)). unknown_predicate_handler(_,_,fail). %%% %%% Collecting static causal laws %%% and translating them into rules suitable for SMODELS %%% pr_static_causal(Id):- findall((X,Y), caused(X,Y), Z), nl(Id), write(Id, '%%% Section: static causal laws %%%%'), nl(Id), nl(Id), pr_static_causal(Z, Id). pr_static_causal([], Id):- nl(Id), write(Id, '%%% End section: static causal laws %%%%'), nl(Id). pr_static_causal([(L,C)|T], Id):- add_time(L, 'T', Id), write(Id, ' :- time(T), '), add_time_list(C, 'T', Id), write(Id, '.'), nl(Id), pr_static_causal(T, Id). %%% %%% Collecting default laws %%% and translating them into rules suitable for SMODELS %%% pr_default(Id):- findall((X,Y), default(X,Y), Z), nl(Id), write(Id, '%%% Section: default laws %%%%'), nl(Id), nl(Id), pr_default(Z, Id). pr_default([], Id):- nl(Id), write(Id, '%%% End section: default laws %%%%'), nl(Id). pr_default([(L,C)|T], Id):- add_time(L, 'T', Id), write(Id, ' :- time(T), '), add_time_list(C, 'T', Id), length(C,N), ( eq(N,0) -> write(Id, ' not '), add_time_contrary(L, Id) | write(Id, ', not '), add_time_contrary(L, Id) ), write(Id, '.'), nl(Id), pr_default(T, Id). add_time_contrary(L, Id):- fluent(L), add_time(neg(L), 'T', Id). add_time_contrary(neg(L), Id):- fluent(L), add_time(L, 'T', Id). %%% %%% Collecting dynamic causal laws %%% and translating them into rules suitable for SMODELS %%% pr_dynamic_causal(Id) :- findall((A,X,Y), causes(A,X,Y), Z), nl(Id), write(Id, '%%% Section: dynamic causal laws %%%%'), nl(Id), pr_dynamic_causal(Z, Id). pr_dynamic_causal([], Id):- nl(Id), write(Id, '%%% End section: dynamic causal laws %%%%'), nl(Id). pr_dynamic_causal([(A,L,C)|T], Id):- add_time(L, 'T1', Id), write(Id, ' :- '), write(Id, ' next(T,T1),'), add_time(A, 'T', Id), length(C,N), ( eq(N,0) -> write(Id, '.'), nl(Id) | write(Id, ','), add_time_list(C, 'T', Id), write(Id, '.'), nl(Id) ), pr_dynamic_causal(T, Id). %%% %%% Generating inertial rules for fluent literals %%% one rule per fluent literal %%% non_inertial(L):- fluent(L), default(L,_). non_inertial(L):- fluent(L), default(neg(L),_). is_inertial(L):- fluent(L), \+ non_inertial(L). pr_inertial(Id):- findall(X, (fluent(X),is_inertial(X)), Y), % remove_dups(Y1, Y), nl(Id), write(Id, '%%% Section: inertial %%%%'), nl(Id), pr_inertial(Y, Id). pr_inertial([], Id):- nl(Id), write(Id, '%%% End section: inertial %%%%'), nl(Id). pr_inertial([H|T], Id):- pr_line(H, Id), nl(Id), pr_line(neg(H), Id), nl(Id), pr_inertial(T, Id). pr_line(H, Id):- fluent(H), add_time(H, 'T1', Id), write(Id, ' :- next(T,T1),'), add_time(H, 'T', Id), write(Id, ', not '), add_time(neg(H), 'T1', Id), write(Id, '.'). pr_line(neg(H), Id):- fluent(H), add_time(neg(H),'T1', Id), write(Id, ' :- next(T,T1),'), add_time(neg(H), 'T', Id), write(Id, ', not '), add_time(H, 'T1', Id), write(Id, '.'). %%% %%% Generating initial rules for fluent literals %%% one rule per fluent literal %%% pr_initial(Id) :- findall(X, (fluent(X),is_inertial(X)), Z), % remove_dups(Z1, Z), nl(Id), write(Id, '%%% Section: initial conditions are exogenous %%%%'), nl(Id), pr_initial(Z, Id). pr_initial([], Id):- nl(Id), write(Id, '%%% End section: initial conditions are exogenous %%%%'), nl(Id). pr_initial([L|T], Id):- pri_line(L, Id), nl(Id), pri_line(neg(L), Id),nl(Id), pr_initial(T, Id). pri_line(H, Id):- fluent(H), add_time(H, '0', Id), write(Id, ' :- not '), add_time(neg(H), '0', Id), write(Id, '.'). pri_line(neg(H), Id):- fluent(H), add_time(neg(H),'0', Id), write(Id, ' :- not '), add_time(H, '0', Id), write(Id, '.'). %%% %%% Generating rules for 'actions are exogenous' %%% two rules for each action %%% pr_ex_action(Id):- findall(A, action(A), Z), nl(Id), write(Id, '%%% Section: actions are exogenous %%%%'), nl(Id), pr_ex_action(Z, Id). pr_ex_action([], Id):- nl(Id), write(Id, '%%% End of section: actions are exogenous %%%%'), nl(Id). pr_ex_action([A|T], Id):- add_time(A, 'T', Id), write(Id, ' :- time(T), not '), add_time(neg(A), 'T', Id), write(Id, '.'), nl(Id), add_time(neg(A), 'T', Id), write(Id, ' :- time(T), not '), add_time(A, 'T', Id), write(Id, '.'), nl(Id), pr_ex_action(T, Id). %%% %%% Generating rules for section 'no actions are executed at last time' %%% one per action %%% pr_no_action(Id):- findall(A, action(A), Z), nl(Id), write(Id, '%%% Section: no actions are executed at last time %%'), nl(Id), pr_no_action(Z, Id). pr_no_action([], Id):- nl(Id), write(Id, '%%% End of section: no actions are executed at last time %%%%'), nl(Id). pr_no_action([A|T], Id):- write(Id, ':- '), add_time(A, 'lasttime', Id), write(Id, '.'), nl(Id), pr_no_action(T, Id). %%% %%% Adding the two auxiliary predicates to the domain file %%% pr_auxiliary(Id):- write(Id, '%%% Auxiliary predicates '), nl(Id), nl(Id), write(Id, 'time(0..lasttime).'), nl(Id), write(Id, 'next(T,T1):- time(T), time(T1), T1 = T + 1.'), nl(Id). %%% %%% Generating rules for each constraint %%% %%% pr_constraint(Id):- findall(X, constraint(X), Z), nl(Id), write(Id, '%%% Section: Constraints %%'), nl(Id), pr_constraint(Z,Id). pr_constraint([],Id):- nl(Id), write(Id, '%%% End of section: Constraints %%%%'), nl(Id). pr_constraint([A|T],Id):- write(Id, ':- time(T), '), add_time_list(A, 'T',Id), write(Id, '.'), nl(Id), pr_constraint(T,Id). %%% %%% Generating rules for each executability condition %%% %%% pr_impossible(Id):- findall((X,Y), impossible(X,Y), Z), nl(Id), write(Id, '%%% Section: Executability Conditions %%'), nl(Id), pr_impossible(Z,Id). pr_impossible([],Id):- nl(Id), write(Id, '%%% End of section: Executability Conditions %%%%'), nl(Id). pr_impossible([(A,L)|T],Id):- write(Id, ':- time(T), '), add_time(A, 'T',Id), length(L,N), ( eq(N,0) -> write(Id, '.'), nl(id) | write(Id, ','), add_time_list(L, 'T',Id), write(Id, '.'), nl(Id) ), pr_impossible(T,Id). %%% %%% pr_serial %%% %%% pr_serial(Id):- findall(A, action(A), Z), nl(Id), write(Id, '%%% Section: Serialization of Actions %%%'), nl(Id), pr_serial(Z,Id). pr_serial([],Id):- nl(Id), write(Id, '%%% End of section: Serialtization of Actions %%%%'), nl(Id). pr_serial([A|T],Id):- pr_serial_list(A,T,Id), pr_serial(T,Id). pr_serial_list(_,[],Id). pr_serial_list(A,[H|T],Id):- write(Id, ':- time(T), '), add_time(A, 'T',Id), write(Id, ', '), add_time(H, 'T',Id), write(Id, '. '), nl(Id), pr_serial_list(A,T,Id). %%% %%% Generating problem output file which includes %%% the initial situation and the goal %%% pr_initsit_goal(Id) :- findall(I, initially(I), Z), findall(G, goal(G), Z1), nl(Id), write(Id, '%%% File with Initial Conditions and Goal for Smodels %%%'), nl(Id), nl(Id), write(Id, 'compute 1 {'), pr_initsituation(Z,Id), length(Z1,N), ( eq(N,0) -> write(Id,'}'), nl(Id), nl(Id), write(Id, '%%% End of file with Initial Conditions and Goal %%%%'), nl(Id) | write(Id,', '), pr_goal(Z1,Id) ). pr_initsituation([],Id). pr_initsituation([G|T],Id) :- add_lasttime(G, '0', Id), length(T,N), ( eq(N,0) -> pr_initsituation([],Id) | write(Id,', '), pr_initsituation(T,Id) ). pr_goal([],Id):- write(Id,'}'), nl(Id), nl(Id), write(Id, '%%% End of file with Initial Conditions and Goal %%%%'), nl(Id). pr_goal([G|T],Id) :- add_lasttime(G, 'lasttime', Id), length(T,N), ( eq(N,0) -> pr_goal([],Id) | write(Id,', '), pr_goal(T,Id) ). add_lasttime(Term, Y, Id) :- Term=..X, length(X,N), ( eq(N,1) -> write_first(X,Id), write(Id,'('), write(Id,Y), write(Id,')') | write_list(X, Y, Id) ). write_list([G|T], Y, Id) :- ( eq(neg,G) -> write(Id,'n'), add_list(T, Y, Id) | write(Id, G), write(Id,'('), write_args(T, Y, Id) ). add_list([H|T], Y, Id) :- H=..X, length(X,N), ( eq(N,1) -> write_first(X,Id), write(Id,'('), write(Id,Y), write(Id,')') | write_list(X, Y, Id) ). write_args([], Y, Id) :- write(Id, Y), write(Id, ')'). write_args([H|T], Y, Id) :- write(Id, H), write(Id, ','), write_args(T, Y, Id). %%% %%% add_time(Term, Y, Id) %%% inserting one parameter to Term %%% the parameter indicates the time point %%% Y can be: now (T), next (T1), last (lasttime), zero (0) %%% add_time(Term, Y, Id):- Term =.. X, length(X,N), ( eq(N,1) -> write_first(X, Id), write(Id, '('), write(Id, Y), write(Id, ')') | write_time(X, Y, Id) ). write_first([X|_], Id):- write(Id, X). write_time([A|T], Y, Id):- ( eq(neg,A) -> write(Id, 'n'), add_time_list(T, Y, Id) | write(Id, A), write_arg(T, Y, Id) ). write_arg(T, Y, Id):- write(Id, '('), write_next(T, Y, Id). write_next([], Y, Id):- write(Id, Y), write(Id, ')'). write_next([H|T], Y, Id):- write(Id, H), write(Id, ','), write_next(T, Y, Id). add_time_list([], _, Id). add_time_list([H|T], Y, Id):- add_time(H, Y, Id), length(T,N), ( eq(N,0) -> write(Id, '') | write(Id, ',') ), add_time_list(T, Y, Id). eq(X,X). %%% %%% for SICStus program %%% gen:- write(' Enter domain description file name: '), read(S), absolute_file_name(S, Source), %%% get the source file name consult(Source), write(' Enter domain description output file name: '), read(F), absolute_file_name(F, FileDescr), %%% get the domain output file name write(' Enter problem output file name: '), read(G), absolute_file_name(G, FileProbl), %%% get the problem output file name write(' Generating .... '), open(FileDescr, write, X), pr_dynamic_causal(X), pr_static_causal(X), pr_inertial(X), pr_initial(X), pr_ex_action(X), pr_no_action(X), pr_auxiliary(X), pr_constraint(X), pr_impossible(X), pr_serial(X), pr_default(X), close(X), open(FileProbl, write, Y), pr_initsit_goal(Y), close(Y).