/* APPENDIX A Section A.2 An Execution Monitor */ /***********************************************************************/ /* The execution monitor calls a recovering procedure */ /* to counter-balance external disturbances. */ /* The recovery procedure uses a simple planner. */ /***********************************************************************/ /* :- nodbgcomp. */ :- pragma(debug). /* We allow EXOs be arbitrary Golog programs; hence, if Exo happens in S, then S1 is the situation resulting after termination of Exo */ monitor(DeltaOld,S,DeltaNew,S1) :- printMessages(DeltaOld,S), sense(Exo,S), ( Exo=noOp -> (S1=S, DeltaNew=DeltaOld); /*No exogenous disturbances */ /* Otherwise, simulate execution of exogenous */ offline(Exo,S,S1), /* Exogenous program cannot be redone */ !, ( relevant(DeltaOld,S,S1) -> ( write('Start recovering...'), nl, recover(1,4,DeltaOld,S1,DeltaNew) ); /* otherwise, continue */ nl, write(' No recovery is necessary. '), write('Proceeding with the next step of program. '), nl, DeltaNew=DeltaOld ) ). /* Determine whether the remainder of the program will terminate in the goal situation */ relevant(DeltaOld,S,S1) :- not offline(DeltaOld,S1,Sg). printMessages(Delta,S) :- nl, write(' Program state = '), write(Delta), nl, write(' Current situation: '), write(S), nl. sense(E,S):- nl, write('>Enter: an exogenous program or noOp if none occurs.'), nl, read(E1), /* IF an exogenous is noOp, or a terminating (hence, legal) Golog program THEN this simulator will consider it as just happened. */ ( (E1 = noOp; offline(E1,S,Sres)) -> E=E1 ; /* ELSE print error message, and try again. */ write(">> Your program is not possible. Try again."), nl, sense(E,S)). recover(M,N,PrOld,S,PrNew) :- M =< N, straightLineProgram(Plan,S,M), offline(Plan : PrOld, S, Sg), /* Can we recover using Plan? */ PrNew=(Plan : PrOld), /* Yes: prefix old program by Plan */ nl, write(' New program = '), write(PrNew), nl; /* Otherwise, try to find a longer sequence of actions */ M < N, /* Complexity bound is not exceeded yet */ M_inc is M+1, recover(M_inc,N,PrOld,S,PrNew). recover(M,N,PrOld,S,PrNew) :- M > N, nl, write('-------------------------'), write('| Recovery procedure FAILED |'), write('-------------------------'),nl, PrNew=nil. straightLineProgram(Plan,S,K) :- K >= 1, primitive_action(A), poss(A,S), goodAction(Plan,A), ( K =:= 1 -> Plan=A ; K_dec is K -1, straightLineProgram(TailPlan,do(A,S),K_dec), Plan=(A : TailPlan) ). /* Elaborate in the future: A is a good action to perform after Plan if A does not undo the results of the last action in Plan. Otherwise, A is futile. */ goodAction(Plan,A). /*--------------------- An execution example ---------------------- Example below demonstrates that exos can be counterbalanced up to the moment when ?(goal) was not yet performed. >Enter: an exogenous program or noOp if none occurs. move(s7,r1). Start recovering... New program = moveToTable(s7) : nil : ?(goal) Program state = nil : nil : ?(goal) Current situation: do(moveToTable(s7), do(move(s7, r1), do(move(r1, o1), do(moveToTable(r1), do(move(r1, o1), do(move(o1, m1), do(move(m1, e1), do(move(f, r2), do(move(r2, n), do(moveToTable(n), do(moveToTable(s7), do(moveToTable(r2), do(move(r2, s7), do(move(s7, n), do(move(n, e1), s0))))))))))))))) >Enter: an exogenous program or noOp if none occurs. noOp. Program state = nil Current situation: do(moveToTable(s7), do(move(s7, r1), do(move(r1, o1), do(moveToTable(r1), do(move(r1, o1), do(move(o1, m1), do(move(m1, e1), do(move(f, r2), do(move(r2, n), do(moveToTable(n), do(moveToTable(s7), do(moveToTable(r2), do(move(r2, s7), do(move(s7, n), do(move(n, e1), s0))))))))))))))) >Enter: an exogenous program or noOp if none occurs. moveToTable(r1). No recovery is necessary. Proceeding with the next step of program. yes. */