%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% SICStus Interpreter of BMAP %%% by Agostino Dovier, Andrea Formisano, Enrico Pontelli %%% Updated NOV 11th, 2010 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Changelog wrt 2009 (LPNMR) version: %%% - actocc multivalued (durable actions) %%% - durable effects %%% - implemented "++" %%% - added parameter for loop control %%% - used "minimum" and "maximum" fd built-in for %%% executability/precondition (plus base case) %%%%%%%% Nov, 19 2010 %%% - ADDED stampa_result option (for particular theories - eg soccer) %%% - ADDED set_increasingcost ("monotonic" on/off option) %%% - ADDED pair (useful for cartesian points - see soccer domain) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% :-use_module(library(clpfd)). :-use_module(library(lists)). :-prolog_flag(unknown,_,fail). :-prolog_flag(redefine_warnings,_,off). :-prolog_flag(discontiguous_warnings,_,off). :-use_module(library(terms)). %%% The following declarations could be removed if you work on %%% an unique action description in a single Prolog session %%% (in this case you can compile it) :- dynamic(agent/1). :- dynamic(fluent/2). :- dynamic(fluent/3). :- dynamic(causes/2). :- dynamic(executable/3). :- dynamic(action/2). :- dynamic(caused/2). :- dynamic(always/1). :- dynamic(concurrency_constraint/1). :- dynamic(holds/2). :- dynamic(time_constraint/1). :- dynamic(action_cost/3). :- dynamic(state_cost/1). :- dynamic(goal_cost/1). :- dynamic(plan_cost/1). :- dynamic(initially/1). :- dynamic(goal/1). %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% Infix operators for fluent constraints %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% :-op(600,xfx,eq). bin_fd_pred(eq). :-op(600,xfx,neq). bin_fd_pred(neq). :-op(600,xfx,leq). bin_fd_pred(leq). :-op(600,xfx,geq). bin_fd_pred(geq). :-op(600,xfx,lt). bin_fd_pred(lt). :-op(600,xfx,gt). bin_fd_pred(gt). :-op(500,xfx,@). :-op(300,xf,'++'). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % pretty syntax stuff: :-dynamic(fluent/1). :-dynamic(executable/1). :-dynamic(costs/2). :-dynamic(action/1). :-dynamic(causes/1). :-op(1120,xfx,by). :-op(1120,xfx,valued). :-op(1125,xfx,if). :-op(1125,xfx,costs). :-op(1130,fx,executable). :-op(1130,xfx,know). :-op(1130,xfx,executable_by). :-op(1130,fx,causes). :-op(1130,xfx,caused). :-op(1130,fx,concurrency_constraint). :-op(1130,fx,always). :-op(1130,xfx,costs). :-op(1130,fx,state_cost). :-op(1130,fx,plan_cost). :-op(1130,fx,goal_cost). :-op(1130,fx,initially). :-op(1130,fx,goal). :-op(1135,fx,agent). :-op(1135,fx,action). :-op(1135,fx,fluent). :-op(1135,xfx,holds). :-op(1135,fx,time_constraint). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% LOAD THE ACTION DESCRIPTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% :-include( %'test.txt' %'three_barrels.pl'). %'capracavolo.pl'). %'gas_diffusion.pl'). %'puzzle.pl'). %'peg_solitaire.pl'). %'social_game.pl'). %'philosophers.pl'). %'fuelcars.pl'). %'pumps_pipes.pl'). %'robot_table.pl'). %'reader_switcher.pl' %'15puzzle_BMAP.txt' 'soccer.txt' ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% SET THE LABELING STRATEGY: Choose exactly one of these options %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% strategy( %%left_ff leftmost %left_ffc %left_d left_ffcd %%%default ). %% and one of these: %%% loopcontrol( %on off ). monotonic( %%on off ). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% MAIN PREDICATE %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bmap(M) :- N is M + 1, bmap(N,_,_),!. bmap(_) :- statistics(runtime,[_,Time]), format("* No solutions: RunTime: ~d ms ~n",[Time]). bmap(N, Actionsocc,States):- my_clean, %profile_reset(_),!, add_con(build_states(N,States,Nf)), add_con(action_occs(N,Actionsocc,PlanCost,Na)), format("* There are ~q fluents per state and ~q possible actions~n",[Nf,Na]), !, %%%%%%%%%%%%%%%% ADD CONSTRAINTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% add_con(set_initial(States)), add_con(set_goal(States)), add_con(set_intermediate_constraints(N,Actionsocc,States)), %% They could be add_con(set_concurrency_constraints(N,Actionsocc,States)), %% merged write_ini_fi(States), add_con(set_transitions(N, Actionsocc, States)), add_con(set_executability(Actionsocc,States,N)), add_con(set_goalcost(States,GC)), add_con(set_plancost(PlanCost)), %%% NEW add_con(set_increasingcost(States,COSTS)), !, %%%%%%%%%%%%%% LABELING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% REMARK Observe that only action variables are labelled. %%% Fluent variables obtain their values by propagation %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% get_all_actions(Actionsocc, AllActions), length(AllActions,L), format("* Still to label ~d variables~n",[L]), statistics(runtime,[_,PT]), format("* Constraints added in ms: ~d ~n",[PT]),!, %standard labeling([ff,min],AllActions), %profile_reset(_), !, my_labeling(Actionsocc,States), %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%% write statistics %%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% statistics(runtime,[_,Time]), line, dump_result(Actionsocc,States),line, write('* State cost evolution: '), write(COSTS),nl, format("* Total Plan Cost = ~d ~n* Goal Cost = ~d ~n* Solution found in Time: ~dms ~n", [PlanCost,GC,Time] ), line. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% The domain of Each Fluent Variable is set here %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% build_states(N,States,Nf) :- findall([F,int(MinF,MaxF)],fluent(F,MinF,MaxF),L1), findall([F,set(Dom)],fluent(F,Dom),Lf,L1), %%% SICStus - findall with append length(Lf,Nf), make_states(N,Lf,States). make_states(0,_,[]). make_states(N,List,[S|STATES]) :- N>0, N1 is N-1, make_states(N1,List,STATES), make_one_state(List,S). make_one_state([],[]). make_one_state([[F,int(MinF,MaxF)]|Fluents],[fluent(F,VarF)|VarFluents]) :- make_one_state(Fluents,VarFluents), VarF in MinF..MaxF. %%% interval case make_one_state([[F,set(Dom)]|Fluents],[fluent(F,VarF)|VarFluents]) :- make_one_state(Fluents,VarFluents), VarF in Dom. %%% set case %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% The domain of each action (occurrence) variable is set to [0..N] %%% In each state transition exactly one action per agent occur %%% (sum constraint on reified action flags) %%% The default action duration is 1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% action_occs(N,Actionsocc,PlanCost,Na) :- setof([Agents,A,D],(action(Agents,A,D);action(Agents,A),D=1),La), length(La,Na), make_action_occurrences(N,La,Actionsocc,PlanCost,N), duration_constraints(1,N,Actionsocc). make_action_occurrences(1,_,[],0,_). make_action_occurrences(M,List,[Act|ActionsOcc],Cost,N) :- M>1, N1 is M-1, make_action_occurrences(N1,List,ActionsOcc,Cost1,N), make_one_action_occurrences(List,Act,Cost2,AGENTS,M,N), get_action_list(Act,AList), fd_gt_zero(AList), Cost #= Cost1 + Cost2 , check_columns(AGENTS). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% make_one_action_occurrences([],[],0,[],_,_). make_one_action_occurrences([[Ag,A,D] |Actions], [action(Ag,A,OccA,D)|OccActions],Cost, [ACTAG|AGENTS],M,N) :- make_one_action_occurrences(Actions,OccActions,Cost1,AGENTS,M,N), Bot is N-M+1, Top is min(Bot+D-1,N), OccA in {0} \/ (Bot..Top), (action_cost(Ag,A,CA),!; CA = 1), %%%Default action cost = 1 B #<=> OccA #> 0, Cost #= B*CA + Cost1, setof(G,agent(G),L), %%% Setting basic constraints fix_agents(L,Ag,ACTAG,OccA). %%% for agents %%% fix_agents(AllAgents,ActionAgents,AgentsConstrained,OccActions) %%% In case the Agent Ag is one of the agents executing the action %%% sets its value to the Action Value, Otherwise it is 0 fix_agents([],_,[],_). fix_agents([Ag|AllAgents],ActionAgents,[Flag|AgentsConstrained],OccA) :- member(Ag,ActionAgents),!, Flag #<=> OccA #>0, fix_agents(AllAgents,ActionAgents,AgentsConstrained,OccA). fix_agents([_Ag|AllAgents],ActionAgents,[0|AgentsConstrained],OccA) :- fix_agents(AllAgents,ActionAgents,AgentsConstrained,OccA). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% All the ActionsOcc related to a durable action %%%% are set to the correct timing %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% duration_constraints(N,N,_) :- !. duration_constraints(I,N,ActionsOcc) :- nth1(I,ActionsOcc,AccI), I1 is I + 1, add_duration_constraints_step(AccI,ActionsOcc,I,N), duration_constraints(I1,N,ActionsOcc). add_duration_constraints_step([],_,_,_). add_duration_constraints_step([action(_,_,_,1)|R],ActionsOcc,I,N) :- add_duration_constraints_step(R,ActionsOcc,I,N). add_duration_constraints_step([action(Ag,Act,VARI,D)|R],ActionsOcc,I,N) :- D > 1, next_vars(Ag,Act,I,D,N,ActionsOcc,VARS), (I = 1 -> VARI #> 0 #<=> Flag ; I > 1 -> I1 is I - 1, action_select(Ag,Act,I1,ActionsOcc, VARJ,_), VARI #> VARJ #<=> Flag), T is min(D+I-1,N), all_equal(VARS,T,Flag), %% Flag -> All VARS = T add_duration_constraints_step(R,ActionsOcc,I,N). %%% check_columns([AgentsAct1,...,AgentsActn]). %%% checks that each agents executes at most 1 action per time check_columns([]). check_columns([A|GENTS]) :- select_first_column([A|GENTS],FIRST,LAST), fd_atmost_one(FIRST), %%% <=== check_columns(LAST). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% constraints on TRANSITIONS are set here. First each tranisition %%% is selected. Then every fluent is analyzed and its new value %%% is constrained using its previous value and the dynamic and static %%% rules applied in that state transition. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_transitions(N, ActOccs, States) :- set_transitions(0,N,ActOccs,States). set_transitions(M,N, ActOccs, States) :- M < N - 1, !, M1 is M + 1, state_select(M, States, StateM), set_transition(StateM, M, ActOccs, States, N), set_transitions(M1, N, ActOccs, States). set_transitions(_,_,_,_). set_transition([],_,_,_,_). set_transition([Fluent|RStateM],M,ActOccs,States,N) :- set_one_fluent(Fluent, M, ActOccs, States,N), set_transition(RStateM, M, ActOccs, States,N). set_one_fluent(fluent(FluentName,IV), M, ActOccs,States,N) :- findall([OP,FE1,FE2,L,DUR], ((causes(FC,L,DUR);causes(FC,L),DUR=1), zero_subterm(FluentName,FC), ( FC =.. [OP,FE1,FE2],bin_fd_pred(OP) ; FC = ++(FluentName), FE1=FluentName,OP=eq, FE2=1+FluentName^(-1) %%% Fluent Increment )), Dyn), M1 is M + 1, state_select(M1,States, ToState), member(fluent(FluentName,EV),ToState), dynamic(Dyn, M, ActOccs, States,DynFormula,N), findall([OP,FE1,FE2,L], %%% OLD [without clustering - with ++] (orig_caused(L,FC),zero_subterm(FluentName,FC), (FC = ++(F),!, FE1 = F, OP = eq, FE2 = F^(-1) + 1; FC =..[OP,FE1,FE2]) ), %%% NEW [With clustering] % (( smart_cluster(FluentName,Fluents),!; % cluster([FluentName], Fluents), % assert( smart_cluster(FluentName,Fluents) )), % member(F,Fluents), orig_caused(L,FC), % zero_subterm_all(F,[L,FC]), FC =..[OP,FE1,FE2]), Stat), sort(Stat,Statord), static(Statord, ActOccs, States, M1, StatFormula), %%% write('STATIC: '),write(Stat), write(StatFormula),nl, bool_disj(DynFormula,StatFormula,Formula), %%% inertia #\ Formula #=> EV #= IV. dynamic([],_,_,_, [],_). %%% MOD14 le 2 righe sotto dynamic([[OP,FE1,FE2,Prec,DUR]|Rest], M , ActOccs, States, [ PFlag |PF1],N):- M1 is M + 1, get_all_precondition_vars(Prec,M,ActOccs,States,ListsPV), bool_and(ListsPV,PFlag), %%% The effect is in the next state (M1 = M + 1) rel_parsing(FE1,Val1,M1,States,ActOccs, dyn), rel_parsing(FE2,Val2,M1,States,ActOccs, dyn), exp_constraint(Val1,OP,Val2,C), %%%(VA #/\ PFlag) #<=> Flag, %%%% PFlag #=> C, %%% Assign the effect in the successive Dur-1 states assign_implication(2, DUR, M, OP, FE1,FE2, States,ActOccs,PFlag,N), dynamic(Rest, M, ActOccs, States, PF1,N). %%% DURABLE EFFECTS HERE: assign_implication(J,DUR,_, _,_,_, _,_,_,_) :- J > DUR,!. assign_implication(I,DUR,M,OP,FE1,FE2,States,ActOccs,PFlag,N) :- MI is M + I, J is I + 1, (MI > N - 1, !; rel_parsing(FE1,ValF1,MI,States,ActOccs, dyn), rel_parsing(FE2,ValF2,MI,States,ActOccs, dyn), exp_constraint(ValF1,OP,ValF2,C), PFlag #=> C, assign_implication(J,DUR,M,OP,FE1,FE2,States,ActOccs,PFlag,N)). %%%% RETRIEVE THE CONSTRAINTS ON PRECONDITIONS get_all_precondition_vars([],_,_,_,[]). get_all_precondition_vars([actocc(AGLIST,NAME)^K|R],M,ActOccs,States,[VA|ListsPV]) :- !, %%% DEFAULT HERE PREDICATE P is M + K, rel_parsing(rei(actocc(AGLIST,NAME)),VA,P,States,ActOccs,dyn), get_all_precondition_vars(R,M,ActOccs,States,ListsPV). get_all_precondition_vars([actocc(AGLIST,NAME)|R],M,ActOccs,States,[VA|ListsPV]) :- !, %%% DEFAULT HERE PREDICATE rel_parsing(rei(actocc(AGLIST,NAME)),VA,M,States,ActOccs,dyn), get_all_precondition_vars(R,M,ActOccs,States,ListsPV). get_all_precondition_vars([EXP|R],M,ActOccs,States,[F|ListsPV]) :- !, EXP =.. [OP,FE1,FE2], rel_parsing(FE1,Val1,M,States,ActOccs,dyn), rel_parsing(FE2,Val2,M,States,ActOccs,dyn), exp_constraint(Val1,OP,Val2,F), get_all_precondition_vars(R,M,ActOccs,States,ListsPV). static([],_,_,_,[]). static([[OP,FE1,FE2,Cond] | Others], ActOccs, States, M, [Flag |Fo] ) :- get_precondition_vars(M,Cond,States,List), % rel rel_parsing(FE1,Val1,M,States,ActOccs,stat), rel_parsing(FE2,Val2,M,States,ActOccs,stat), exp_constraint(Val1,OP,Val2,C), bool_and(List,Flag), Flag #=> C, static(Others,ActOccs, States, M,Fo). %%% fixpoint call cluster(A,B) :- collect_fluents_aux(A,C), (sort(A,X),sort(C,X), %%% A is equal to C !, B=C; cluster(C,B)). collect_fluents_aux([],[]). collect_fluents_aux([F|Fs],Fluents) :- findall(Fnext,( orig_caused(L,C), zero_subterm_all(F,[L,C]), fluent(Fnext,_,_),F \== Fnext, zero_subterm_all(Fnext,[L,C]) ), FNEXTS), collect_fluents_aux(Fs,Faux), union(Faux, [F|FNEXTS], Fluents). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% The executability of each action is then related to the %%% values of the fluents in the previous state. "formula" %%% store the disjunction of all executability conditions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_executability(ActionsOcc,States,N) :- findall([Agents,Act,C],executable(Agents,Act,C),Conds), group_cond(Conds,GroupedConds), set_executability(1,N,ActionsOcc,States,GroupedConds). set_executability(N,N,_,_,_) :- !. set_executability(M,N,ActionsOcc,States,Conds) :- set_executability_sub(Conds,M,ActionsOcc,States), M1 is M + 1, set_executability(M1,N,ActionsOcc,States,Conds). set_executability_sub([],_,_,_). set_executability_sub([[Agents,Act,C]|CA],M,ActionsOcc,States) :- action_select(Agents,Act,M,ActionsOcc,VA,DUR), M1 is M - 1, preconditions_flags(C, M1, States,Flags), bool_or(Flags,F), %%%% ((DUR=1;M=1) -> (VA #> 0) #=> F ; (DUR>1,M>1) -> action_select(Agents,Act,M1,ActionsOcc,VP,DUR), (VA #> VP) #=> F), set_executability_sub(CA,M,ActionsOcc,States). preconditions_flags([],_,_,[]). preconditions_flags([C|R],M,States,[Flag|Flags]) :- get_precondition_vars(M,C,States,Cs), bool_and(Cs,Flag), preconditions_flags(R,M,States,Flags). get_precondition_vars(_,[],_,[]). get_precondition_vars(M,[FC|Rest],States,[F|LR]) :- FC =.. [OP,FE1,FE2], get_precondition_vars(M,Rest,States,LR), rel_parsing(FE1,Val1,M,States,_,stat), rel_parsing(FE2,Val2,M,States,_,stat), exp_constraint(Val1,OP,Val2,F). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Initial state and goal info are set here. %%% In the first state static causal rules are applied by "complete_state" %%% (for the other states they are applied in set transition) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_initial([Initial|States]) :- findall(C, orig_initially(C), InitFC), add_stateorstep_constraints(InitFC,0,_,[Initial|States]), complete_state(Initial). set_goal(States) :- findall(C, orig_goal(C), GoalFC), length(States,N), M is N -1, add_stateorstep_constraints(GoalFC,M,_,States). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% intermediate constraints: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% always %%% holds %%% time %%% are set here %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Note the similarity .... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_intermediate_constraints(N,ActionsOccs,States) :- findall(C, orig_always(C), Always), rec_add_constraints(0,N,Always,ActionsOccs,States), findall(C1,(holds(C,No),C=..[OP,FE1,FE2],C1 =..[OP,FE1@No,FE2@No]), Holds), rec_add_constraints(0,N,Holds,ActionsOccs,States), findall(C,orig_time_constraint(C), Time_C), rec_add_constraints(0,N,Time_C,ActionsOccs,States). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% setting concurrency constraints %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_concurrency_constraints(N,ActionsOccs,States) :- findall(C,orig_concurrency_constraint(C),LC), rec_add_constraints(1,N,LC,ActionsOccs,States). %%% Notice 1..N %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% rec_add_constraints/5 %%% Forces the constraints [c1,...,cn] to the state/state transitions %%% from A to B %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% rec_add_constraints(N,N,_,_,_). rec_add_constraints(I,N,C,Actionsocc,States) :- I < N, I1 is I + 1, add_stateorstep_constraints(C,I,Actionsocc,States), rec_add_constraints(I1,N,C,Actionsocc,States). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% add_stateorstep_constraints/4 %%% Fixes the constraints [c1,...,cn] to the state/state transition "I" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% add_stateorstep_constraints([],_,_,_). add_stateorstep_constraints([C|Cs],I,Actionsocc,States) :- C =.. [OP,E1,E2], rel_parsing(E1,Val1,I,States,Actionsocc, stat), rel_parsing(E2,Val2,I,States,Actionsocc, stat), add_constraint(Val1,OP,Val2), add_stateorstep_constraints(Cs,I,Actionsocc,States). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%% Complete (initial) state by static laws %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% complete_state(State) :- complete_state(State,State). complete_state([],_). complete_state( [fluent(Fluent,_)| Fluents],InitialState) :- set_one_static_fluent(Fluent, InitialState), complete_state(Fluents ,InitialState). set_one_static_fluent(Name, State) :- %%% EXTENSIONS findall([OP,FE1,FE2,L], %%%% qui mettere i cluster ev. (orig_caused(L,FC),zero_subterm(Name,FC),FC =..[OP,FE1,FE2]), Stat), static(Stat,_,[State],0,_). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% set_goalcost(States, Val) :- length(States,N),M is N-1, state_select(M,States,FinalState), (state_cost(FE),!;FE=0), parsing(FE,Val,FinalState), (goal_cost(C), C =.. [OP,goal,Num], add_constraint(Val,OP,Num), !; write(' ** No goal cost given ')). set_plancost(PlanCost) :- (plan_cost(C),C =.. [OP,plan,Num], add_constraint(PlanCost,OP,Num),!; write(' ** Planning Cost Unconstrained ')). %%% NEW set_increasingcost(States,COSTS) :- length(States,N),M is N-1, set_increasingcost(0,M,States,COSTS). set_increasingcost(A,A,States,[Val]) :- state_select(A,States,StateA), (state_cost(FE),!;FE=1), parsing(FE,Val,StateA). set_increasingcost(A,B,States,[ValA|R]) :- A < B, A1 is A + 1, state_select(A,States,StateA), state_select(A1,States,StateB), (state_cost(FE),!;FE=1), parsing(FE,ValA,StateA), parsing(FE,ValB,StateB), (monotonic(on) -> add_constraint(ValA,lt,ValB); %ValA #< ValB, monotonic(off) -> true), set_increasingcost(A1,B,States,R). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% SYNTAX and PARSING OF FLUENT EXPRESSIONS: %%% FE ::= INTEGER | FD_VAR | FE1 * FE2 | FE1 + FE2 | FE1 - FE2 | FE1 / FE2 | FE1 mod FE2 %%% abs(FE) | rei( FE OP FE) --- reified constraint %%% actocc(LIST,ACT) %%% action_occurrence %%% FE ^ Time | FE @ Time %%% pair(FE,FE) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% parsing( Fluent, Val, State ) :- rel_parsing(Fluent,Val,0,[State],_,stat). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% rel_parsing( +FE1,-Val1,+M,+States,+Actionsocc,+Flag) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% rel_parsing( Num , Num , _, _ , _,_) :- integer(Num), !. rel_parsing(actocc(Ag,A), Val, M, _ , Actionsocc, stat) :- action_select(Ag,A,M,Actionsocc,Val,_), !. rel_parsing(actocc(_,_), 0, _, _ , _, stat) :- %%% Out of range -> Action !. %%% var = 0 rel_parsing(actocc(Ag,A), Val, M, _ , Actionsocc, dyn) :- nth0(M,Actionsocc,ACTLISTM), %%% nth0 check the range !, member(action(Ag,A,Val, _D),ACTLISTM). rel_parsing(actocc(_,_), 0, _, _ , _, dyn) :- %%% Out of range -> Action !. %%% var = 0 %%% NEW PG rel_parsing(pair(X,Y),Val,M,States,Actionsocc,Flag) :- !, rel_parsing( X, Val1, M, States, Actionsocc,Flag), rel_parsing( Y, Val2, M, States, Actionsocc,Flag), Val #= 8*Val1 + Val2. %%% rel_parsing( rei(actocc(Ag,A)), Val, M, States, Actionsocc,Flag) :- rel_parsing( actocc(Ag,A), Val1, M, States, Actionsocc,Flag), Val #<=> (Val1 #> 0), !. rel_parsing( rei(RC), Val, M, States, Actionsocc,Flag) :- RC =.. [OP,E1,E2], rel_parsing( E1, Val1, M, States, Actionsocc,Flag), rel_parsing( E2, Val2, M, States, Actionsocc,Flag), exp_constraint(Val1,OP,Val2,Val), !. rel_parsing( abs(FE), Val, M, States, Actionsocc,Flag) :- rel_parsing(FE, Val1, M, States, Actionsocc,Flag), Val #= abs(Val1), !. rel_parsing(FE^Delta, Val, M, States , Actionsocc,Flag) :- H is M + Delta, rel_parsing(FE, Val, H, States , Actionsocc,Flag), !. rel_parsing( FE @ Time, Val, _, States, Actionsocc, Flag ) :- rel_parsing(FE, Val, Time, States, Actionsocc, Flag), !. rel_parsing( FE, Val, M, States, Actionsocc, Flag ) :- FE =.. [OP,FE1,FE2], member(OP,[+,-,mod,/,*]), rel_parsing( FE1, Val1, M, States, Actionsocc ,Flag), rel_parsing( FE2, Val2, M, States, Actionsocc ,Flag), ( OP = + -> Val #= Val1 + Val2; OP = - -> Val #= Val1 - Val2; OP = * -> Val #= Val1 * Val2; OP = / -> Val #= Val1 / Val2; OP = mod -> Val #= Val1 mod Val2), !. rel_parsing( Fluent, Val, M, States , _ , _) :- ( state_select(M,States,State), member(fluent(Fluent,Val),State), !; M < 1 -> state_select(0,States,State0), member(fluent(Fluent,Val),State0); %%% underflow -> value in state 0 M > 0 -> length(States,N), state_select(N,[_|States],StateN), %%% <= CHANGED HERE member(fluent(Fluent,Val),StateN), %%% overflow -> value in final state write(Fluent@M),write('###===> delta warning')). %%% SYNTAX and BUILDING of a FLUENT CONSTRAINT %%% FE1 op FE2, where op in {eq,neq,leq,geq,lt,gt} %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% %%% exp_constraint(L,OP,R,C) :- (OP == eq -> C #<=> L #= R; OP == neq -> C #<=> L #\= R; OP == geq -> C #<=> L #>= R; OP == leq -> C #<=> L #=< R; OP == gt -> C #<=> L #> R; OP == lt -> C #<=> L #< R). add_constraint(L,OP,R) :- exp_constraint(L,OP,R,1). my_clean :- retractall(smart_cluster(_,_)), statistics(_,_). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%% AUXILIARY predicates %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% state_select(I,States,StateI) :- nth0(I,States,StateI). action_select(AG,ACT,I,ACTOCCS,VACT,DUR) :- nth1(I,ACTOCCS,ACTSTEP), member(action(AG,ACT,VACT,DUR),ACTSTEP). %%% Select the sets of consecutive "D" action variables next_vars(_,_,_,0,_, _, []) :- !. next_vars(_,_,N,_,N, _, []) :- !. next_vars(Ag,Act,M,D,N, ActionsOcc, [VARM|R]) :- action_select(Ag,Act,M,ActionsOcc,VARM,_), M1 is M + 1,D1 is D - 1, next_vars(Ag,Act,M1,D1,N, ActionsOcc, R). %%% Return the first column of a matrix and the %%% rest of the matrix select_first_column([],[],[]). select_first_column([[A]|AGS],[A|RA],[]) :- !, select_first_column(AGS,RA,_). select_first_column([[A|AG1]|AGS],[A|RA],[AG1|ARS]) :- select_first_column(AGS,RA,ARS). %%%%%%%%%%%%% get_all_actions(A,B) :- term_variables(A,C), reverse(C,B). get_action_list([],[]). get_action_list([action(_,_,V,_)|Rest],[V|MRest]) :- get_action_list(Rest,MRest). group_cond([],[]). group_cond([[Agents,Action,C]|R],[[Agents,Action,[C|Cs]]|S]) :- findall(L,(member([Agents,Action,L],R)),Cs), filter(Agents,Action,R,Others), group_cond(Others,S). filter(_,_,[],[]). filter(A,B,[[A,B,_]|R],S) :- !, filter(A,B,R,S). filter(A,B,[C|R],[C|S]) :- !, filter(A,B,R,S). %%%%%%%% it looks for a "current" fluent zero_subterm(A,B) :- A==B,!. zero_subterm(_,B) :- var(B),!,fail. zero_subterm(A,G) :- functor(G,B,_), %G =.. [B|_], A == B,!. zero_subterm(A,A^0) :- !. zero_subterm(A,A^_) :- !, fail. zero_subterm(A,G) :- G =.. [_|Args], zero_subterm_all(A,Args). zero_subterm_all(A,[B|_]) :- zero_subterm(A,B),!. zero_subterm_all(A,[_|R]) :- zero_subterm_all(A,R). %%% disjoint append union([],L,L). union([A|R],S,T) :- member(A,S),!, union(R,S,T). union([A|R],S,[A|T]) :- union(R,S,T). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% pretty syntax digestion %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %UNPRETTY FLUENT % fluent F valued V1,V2 ==> fluent(valued(F,','(V,V))) fluent(F,MinF,MaxF) :- fluent(valued(F,','(MinF,MaxF))). % fluent F valued Dom ==> fluent(valued(F,Dom)) fluent(F,Dom) :- fluent(valued(F,Dom)), \+functor(Dom,',',2). %UNPRETTY ACTION action(Agents,A) :- action(PrettyAc), unpretty_action(PrettyAc,Agents,A). %action(executable_by(X, [A,A,...])) unpretty_action(executable_by(X, [A|As]), [A|As], X). %action(executable_by(X, ','(A,','(A,...)))) unpretty_action(executable_by(X, As), LAs, X) :- (commatolist(As,Temp) -> (LAs=Temp) ; (LAs=[As]) ). %action(executable_by(X, A)) unpretty_action(executable_by(X, [A]), [A], X) :- \+is_list(A), \+functor(A,',',2). %UNPRETTY EXECUTABILITY executable(Agents,Act,C) :- unpretty_executable(Agents,Act,C). %executable(if(by(X, ','(A,','(A,...)) ), ','(C,','(C,...)))) %executable(if(by(X, [A,A,...]), [C,C,...])) %executable(if(by(X, A, [C,C,...])) unpretty_executable(Agents,Act,C):- executable(if(by(Act, As), Cs)), (commatolist(As,T1) -> (T1=Agents) ; (is_list(As) -> (As=Agents) ; ([As]=Agents))), (commatolist(Cs,T2) -> (T2=C) ; (Cs=C)). %UNPRETTY CAUSED RealL=>Constr orig_caused(RealL,Constr) :- caused(List,Constr), ( commatolist(List,LL) -> (LL=RealL) ; (List=RealL) ). %UNPRETTY CAUSES RealL=>Constr %causes( if(C, ','(C,','(C,...))) ) %causes( if(C, [C,C,...]) ) causes(Constr,RealL) :- causes(if(Constr,List)), ( commatolist(List,LL) -> (LL=RealL) ; (List=RealL) ). %UNPRETTY INITIALLY (works for lists and comma-separated lists of constraints) orig_initially(CoCL) :- initially(C), (is_list(C) -> member(CoCL,C) ; commatolist(C,LL) -> member(CoCL,LL) ; (CoCL = C)). %UNPRETTY GOAL (works for lists and comma-separated lists of constraints) orig_goal(CoCL) :- goal(C), (is_list(C) -> member(CoCL,C) ; commatolist(C,LL) -> member(CoCL,LL) ; (CoCL = C)). %UNPRETTY CONCURRENCY_CONSTRAINT (works for lists and comma-separated lists of constraints) orig_concurrency_constraint(CoCL) :- concurrency_constraint(C), (is_list(C) -> member(CoCL,C) ; commatolist(C,LL) -> member(CoCL,LL) ; (CoCL = C)). %UNPRETTY ALWAYS (works for lists and comma-separated lists of constraints) orig_always(CoCL) :- always(C), (is_list(C) -> member(CoCL,C) ; commatolist(C,LL) -> member(CoCL,LL) ; (CoCL = C)). %UNPRETTY TIME_CONSTRAINT (works for lists and comma-separated lists of constraints) orig_time_constraint(CoCL) :- time_constraint(C), (is_list(C) -> member(CoCL,C) ; commatolist(C,LL) -> member(CoCL,LL) ; (CoCL = C)). %UNPRETTY COSTS (=action_cost) action_cost(Ag,A,CA) :- unpretty_action_cost(Ag,A,CA). %costs(by(X, ','(A,','(A,...))), E) %costs(by(X, [A,A,...]), E) unpretty_action_cost(Agents,Act,E):- costs(by(Act, As), E), (commatolist(As,T1) -> (T1=Agents) ; (As=Agents)). %AUX %commatolist(CommaSep,List) commatolist(','(X,','(Y,Z)),[X|L]) :- commatolist(','(Y,Z),L). commatolist(','(X,Y),[X,Y]) :- \+functor(Y,',',2). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%% LABELING HEURISTICS %%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% my_labeling implements a leftmost strategy. %%% After a new state is reached, it is checked its %%% difference wrt the previous ones my_labeling(Actionsocc,States) :- term_variables_list(Actionsocc, ListOfVarLists), (strategy(leftmost) -> (Options = []); strategy(left_ff) -> (Options = [ff]); strategy(left_ffc) -> (Options = [ffc]); strategy(left_ffcd) -> (Options = [ffc,down]); true -> (Options = 'default')),!, my_labeling(Options,ListOfVarLists,States). my_labeling('default',ListOfVarLists,States) :- !, loopcontrol(ONOFF), no_loop_constraint(ONOFF,States), term_variables(ListOfVarLists,VARS), labeling([ffc,down],VARS). % my_labeling_varbyvar(ListOfVarLists,States,1). my_labeling(Options,ListOfVarLists,States) :- my_labeling_statebystate(ListOfVarLists,States,1,Options). my_labeling_statebystate([],_,_,_). my_labeling_statebystate([CurrVArs | CurrVArsList], States,I,Options) :- labeling(Options,CurrVArs), I1 is I + 1, my_labeling_statebystate(CurrVArsList,States,I1,Options). my_labeling_varbyvar([],_,_). my_labeling_varbyvar([CurrVArs | CurrVArsList], States,I) :- my_labeling_varbyvar_aux(CurrVArs), %loopcontrol(ONOFF), %no_loop(ONOFF,States,I), I1 is I + 1, my_labeling_varbyvar(CurrVArsList,States,I1). my_labeling_varbyvar_aux([]). my_labeling_varbyvar_aux([A|R]) :- %%% EXTENSIONS preferenze tra azioni indomain(A), %%% e euristica nei valori my_labeling_varbyvar_aux(R). term_variables_list([],[]). term_variables_list([ActionList|ListOfActionLists], [VarList|ListOfVarLists]):- term_variables(ActionList, VarList), term_variables_list(ListOfActionLists, ListOfVarLists). no_loop_constraint(on,States) :- no_loop_constraint(States,C), bool_or(C,0). no_loop_constraint(off,_). no_loop_constraint([],[]) :- !. no_loop_constraint([_],[]) :- !. no_loop_constraint([S|Tates],C) :- no_loop_constraint(S,Tates,C1), no_loop_constraint(Tates,C2), append(C1,C2,C). no_loop_constraint(_,[],[]). no_loop_constraint(S,[T|Ates],[Cflag|C2]) :- all_equal(S,T,C1), bool_and(C1,Cflag), no_loop_constraint(S,Ates,C2). all_equal([],[],[]). all_equal([fluent(A,V)|R],[fluent(A,W)|S],[C1|C]) :- C1 #<=> V #= W, %%% reified all_equal(R,S,C). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Metapredicates: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% meta_bmap(Flag,LIM,MIN) :- M is LIM//2, statistics(runtime,[Ts,_]), (Flag = bis -> bisect_min(0,M,LIM,unknown,MIN); Flag = up -> bmap_up(LIM,MIN)), statistics(runtime,[Te,_]), T is (Te-Ts)/1000, format("***Total time: ~2f s ~n",[T]). %%% Look (using bisection) for the minimum A < MIN <= B %%% such that there is a plan of length MIN bisect_min(A,A,B,known,B). %%% The flag "known" allow to bisect_min(A,A,B,unknown,B) :- %%% skip the last call to sicsplan(B) bmapfail(B),!. %%% bisect_min(A,A,_,unknown,0). %%% 0 means unsatisfiable bisect_min(A,N,B,Flag,MIN) :- %%% in the selected range A < N, (bmapfail(N),!, M is (A+N)//2, bisect_min(A,M,N,known,MIN); M is (B+N)//2, bisect_min(N,M,B,Flag,MIN)). %%% Look (incrementally) for the minimum MIN >= N %%% such that there is a plan of length MIN %%% Possibly looping (if unsat) bmap_up(N,MIN) :- (bmapfail(N),!,MIN=N; M is N + 1, bmap_up(M,MIN)). bmapfail(N) :- M is N + 1, main(M,_,_),!. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% AUXILIARY FD predicates %%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% sum(X,Res) :- sum(X,#=,Res). fd_domain_bool(X) :- X in 0..1. fd_atmost_one(X) :- sum(X,#=,AA), AA in 0..1. fd_only_one(X) :- sum(X,#=,1). fd_gt_zero(X) :- sum(X,#>,0). fd_one_or_two(X) :- sum(X,#=,AA), AA in 1..2. all_equal([],_,_). all_equal([A|R],B,Flag) :- Flag #=> A #=B, all_equal(R,B,Flag). bool_disj(A,B,Flag) :- append(A,B,C), bool_or(C,Flag). bool_or([],0). bool_or(List,Flag) :- %%% Flag <-> 1 in List maximum(Flag,List).%%% bool_and([],1). bool_and(List,Flag) :- %%% Flag <-> minimum(Flag,List).%%% Lists = [1,1,1...1] %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% AUXILIARY PREDICATES for ACTION LANGUAGES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% neq(A,B) :- A \== B. diff(A,B) :- A \== B. diff(A,B,C) :- A \== B, A \== C, C \== B. interval(A,A,_). interval(X,A,B) :- A < B, C is A + 1, interval(X,C,B). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% PRINT %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% add_con(P) :- functor(P,Name,_), format("#####Adding constraints ~w ... ",[Name]), once(P),!, format("DONE #####~n",[]). add_con(_) :- format("ERROR #####~n",[]), fail. write_ini_fi(States) :- write('Initial State:'),nl, States=[S|_],write_state(S),nl, write('Final State:'),nl, append(_,[Last],States),write_state(Last). dump_result(A,S) :- stampa_result(A,S), line, write('Plan in short:'),nl, state_plan(A),nl. %%% PRINT CHOICE stampa_result(A,B) :- dump_result(0,A,B). %stampa_result(_A,B) :- % soccer_result(0,B), nl. %%%%%%%% dump_result(N,[],[S]) :- write('Time '),write(N),write(': '), write_state(S). dump_result(N,[A|B],[S|Rest]) :- write('Time '),write(N),write(': '), write_state(S), write_actions(A), N1 is N + 1, dump_result(N1,B,Rest). write_state([]) :- nl. write_state([fluent(Name,Value)|Rest]) :- ( fd_var(Value),!, format("~q: <> ",[Name]); format("~q = ~q\t",[Name,Value]) ), write_state(Rest). write_actions(A) :- find_actions(A,Names),!, write(' ---->> '), write_flat_list(Names),nl. find_actions([],[]). find_actions([action(Agents,Name,Value,_)|Rest], [[Agents,Name,Value ] |S]) :- %%% [[Agents,Name ] |S]) :- Value > 0,!, find_actions(Rest,S) . find_actions([_|Rest], S) :- find_actions(Rest,S) . state_plan([]) :- write('stop.'),nl. state_plan([A|As]) :- find_actions(A,Names), write_flat_list(Names),write(' -> '), state_plan(As). line :- write('*****************************************************************************'), nl. write_list([]). write_list([A|R]) :- write(A),nl, write_list(R). write_flat_list([]). write_flat_list([[A,B,C]|R]) :- write(A),write(':'),write(B),write(' ('),write(C),write(') '), write_flat_list(R). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%% END CODE %%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%