1%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    2%%
    3%% Libraries
    4%%
    5%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
:- lib(fd).
   12:-include(swi_fd).   13
   14flux_version(3.1).
   19:- use_module(library(chr)).
   23:- ensure_loaded('fluent3.chr').   24
   25:- tell('fluent3.pl'),listing,told.   26
   27
   28%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   29%%
   30%% State Specifications and Update
   31%%
   32%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   39holds(F, [F|_]).
   40holds(F, Z) :- nonvar(Z), Z=[F1|Z1], F\==F1, holds(F, Z1).
   49holds(F, [F|Z], Z).
   50holds(F, Z, [F1|Zp]) :- nonvar(Z), Z=[F1|Z1], F\==F1, holds(F, Z1, Zp).
   58cancel(F,Z1,Z2) :-
   59   var(Z1)    -> cancel(F,Z1), cancelled(F,Z1), Z2=Z1 ;
   60   Z1 = [G|Z] -> ( F\=G -> cancel(F,Z,Z3), Z2=[G|Z3]
   61                         ; cancel(F,Z,Z2) ) ;
   62   Z1 = []    -> Z2 = [].
   69minus_(Z, [], Z).
   70minus_(Z, [F|Fs], Zp) :-
   71   ( \+ not_holds(F, Z) -> holds(F, Z, Z1) ;
   72     \+ holds(F, Z)     -> Z1 = Z
   73                         ; cancel(F, Z, Z1), not_holds(F, Z1) ),
   74   minus_(Z1, Fs, Zp).
   81plus_(Z, [], Z).
   82plus_(Z, [F|Fs], Zp) :-
   83   ( \+ holds(F, Z)     -> Z1=[F|Z] ;
   84     \+ not_holds(F, Z) -> Z1=Z
   85                         ; cancel(F, Z, Z2), not_holds(F, Z2), Z1=[F|Z2] ),
   86   plus_(Z1, Fs, Zp).
   94update(Z1, ThetaP, ThetaN, Z2) :-
   95   minus_(Z1, ThetaN, Z), plus_(Z, ThetaP, Z2).
   96
   97
   98%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   99%%
  100%% State Knowledge
  101%%
  102%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  109knows(F, Z) :- \+ not_holds(F, Z).
  116knows_not(F, Z) :- \+ holds(F, Z).
  132knows_val(X, F, Z) :- k_holds(F, Z), knows_val(X).
  133
  134k_holds(F, Z) :- nonvar(Z), Z=[F1|Z1],
  135                 ( instance(F1, F), F=F1 ; k_holds(F, Z1) ).
  136
  137:-local variable(known_val).
  138:-setval(known_val,[]).  139
  140knows_val(X) :- dom(X), \+ nonground(X), ambiguous(X) -> false.
  141knows_val(X) :- getval(known_val,X), X \== [], setval(known_val, []).
  142
  143dom([]).
  144dom([X|Xs]) :- dom(Xs), ( is_domain(X) -> indomain(X)
  145                                        ; true ).
  146
  147ambiguous(X) :- 
  148   ( getval(known_val, Val), 
  149     Val \== [] -> setval(known_val, [])
  150   ;
  151                    setval(known_val, X), 
  152                    false
  153   ).
  154
  155%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  156%%
  157%% Execution
  158%%
  159%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  192execute(A,Z1,Z2) :-
  193   is_predicate(perform/2),
  194   perform(A,Y)    -> ( is_predicate(ab_state_update/4) ->
  195                           ( Z1=[sit(S)|Z], ! ; S=[], Z=Z1 ),
  196                           ( state_update(Z,A,Z3,Y)
  197                             ; ab_res([[A,Y]|S],Z3) ),
  198                           !, Z2=[sit([[A,Y]|S])|Z3]
  199                        ;
  200			state_update(Z1,A,Z2,Y) ) ;
  201
  202   is_predicate(perform/3),
  203   perform(A,Y,E)  -> ( is_predicate(ab_state_update/4) ->
  204                           ( Z1=[sit(S)|Z], ! ; S=[], Z=Z1 ),
  205                           ( state_update(Z,A,Z3,Y), state_updates(Z3,E,Z4)
  206                             ; ab_res([[A,Y,E]|S],Z4) ),
  207                           !, Z2=[sit([[A,Y,E]|S])|Z4]
  208                        ;
  209			state_update(Z1,A,Z,Y), state_updates(Z,E,Z2) ) ;
  210
  211   A = [A1|A2]     ->
  212                      execute(A1,Z1,Z), execute(A2,Z,Z2) ;
  213
  214   A = if(F,A1,A2) ->
  215                      (holds(F,Z1) -> execute(A1,Z1,Z2)
  216                                    ; execute(A2,Z1,Z2)) ;
  217
  218   A = []          ->
  219                      Z1=Z2 ;
  220
  221   complex_action(A,Z1,Z2).
  222
  223ab_res([],Z) :- init(Z).
  224ab_res([S1|S],Z) :-
  225   ab_res(S,Z1),
  226   ( S1=[A,Y] -> ( state_update(Z1,A,Z,Y) ; ab_state_update(Z1,A,Z,Y) )
  227     ;
  228     S1=[A,Y,E], ( state_update(Z1,A,Z2,Y) ; ab_state_update(Z1,A,Z2,Y) ),
  229                 state_updates(Z2, E, Z) ).
  230
  231state_updates(Z, [], Z).
  232state_updates(Z1, [A|S], Z2) :-
  233   state_update(Z1, A, Z), state_updates(Z, S, Z2).
  234
  235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  236%%
  237%% Planning
  238%%
  239%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  240
  241%%
  242%% plan(PlanningProblemName,Z,P)
  243%%
  244%% P is an optimal plan for PlanningProblemName with starting state Z
  245%%
  246%% It assumes the definition of a predicate PlanningProblemName(Z0,P,Z)
  247%% describing the search space such that plan P executed in starting
  248%% state Z0 results in state Z which satisfies the planning goal,
  249%% and the definition of plan_cost(PlanningProblemName,P,Z,C) such that
  250%% C is the cost of plan P resulting in state Z; or
  251%%
  252%% the definition of a predicate is PlanningProblemName(Z0,P)
  253%% describing the search space such that conditional plan P executed in
  254%% starting state Z0 necessarily results in a state in which the planning
  255%% goal is satisfied, and the definition of plan_cost(PlanningProblemName,P,C)
  256%% such that C is the cost of plan P.
  257%%
  258%% For the definition of the search space, the predicates for knowledge
  259%% described below can be used.
  260%%
  261
  262:- local variable(plan_search_best).
  263
  264plan(Problem, Z, P) :-
  265   setval(plan_search_best(_ : -1)),
  266   plan_search(Problem, Z),
  267   getval(plan_search_best,P:C),
  268   C =\= -1.
  269
  270plan_search(Problem, Z) :-
  271    is_predicate(Problem/2) ->
  272       ( PlanningProblem =.. [Problem,Z,P],
  273         call(PlanningProblem),
  274         plan_cost(Problem, P, C),
  275         getval(plan_search_best,_:C1),
  276         ( C1 =< C, C1 =\= -1 -> false
  277                               ;
  278                               setval(plan_search_best,P:C), false )
  279         ;
  280         true ) ;
  281    PlanningProblem =.. [Problem,Z,P,Zn],
  282    call(PlanningProblem),
  283    plan_cost(Problem, P, Zn, C),
  284    getval(plan_search_best,_:C1),
  285    ( C1 =< C, C1 =\= -1 -> false
  286                              ;
  287                            setval(plan_search_best,P:C),
  288                            false
  289    )
  290    ;
  291    true.
  303knows(F, S, Z0) :- \+ ( res(S, Z0, Z), not_holds(F, Z) ).
  310knows_not(F, S, Z0) :- \+ ( res(S, Z0, Z), holds(F, Z) ).
  311
  312%%
  313%% knows_val(X,F,S,Z0)
  314%%
  315%% there is an instance of the variables in X for which
  316%% non-ground fluent F is known to hold after doing S in state Z0
  317%%
  318
  319:-local variable(known_vals).
  320
  321knows_val(X, F, S, Z0) :-
  322   setval(known_vals,[]),
  323   res(S, Z0, Z),
  324   findall(X, knows_val(X,F,Z), T),
  325   getval(known_vals,T1),
  326   ( T1=[] -> T2=T ; intersection(T,T1,T2) ),
  327   setval(known_vals, T2),
  328   false.
  329knows_val(X, _, _, _) :-
  330   getval(known_vals, T), 
  331   member(X, T),
  332   setval(known_vals, []).
  333
  334
  335res([], Z0, Z0).
  336res(do(A,S), Z0, Z) :-
  337   ( A = if_true(F)  -> res(S, Z0, Z), holds(F, Z) 
  338   ;
  339                        ( A = if_false(F) -> res(S, Z0, Z),
  340                                             not_holds(F, Z) 
  341                        ;
  342                                             res(S, Z0, Z1),
  343                                             state_update(Z1, A, Z, _)
  344                        )
  345   ).
  346
  347
  348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  349%%
  350%% Ramification Problem
  351%%
  352%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  366causes(Z,P,N,Z2) :-
  367   causes(Z,P,N,Z1,P1,N1) -> causes(Z1,P1,N1,Z2)
  368                           ; Z2=Z.
  377ramify(Z1,ThetaP,ThetaN,Z2) :-
  378   update(Z1,ThetaP,ThetaN,Z), causes(Z,ThetaP,ThetaN,Z2)