% A Reactive Elevator Controller with Interactively % Generated Exogenous Actions % Primitive action declarations. primitive_action(goUp). primitive_action(goDown). primitive_action(resetButton(N)). primitive_action(toggleFan). primitive_action(ringAlarm). primitive_action(wait). primitive_action(startFire). primitive_action(endFire). primitive_action(callElevator(N)). primitive_action(resetAlarm). primitive_action(changeTemp). % Golog Procedures proc(control, wait : while(some(n,buttonOn(n)), pi(n, ?(buttonOn(n)) : serveFloor(n)))). proc(serveFloor(N), while(-atFloor(N), if(aboveFloor(N), goDown, goUp)) : resetButton(N)). proc(rules, ?(fire & -alarmOn) : ringAlarm : while(alarmOn,wait) # ?(tooHot & -fan) : toggleFan # ?(tooCold & fan) : toggleFan # ?(-(fire & -alarmOn v tooHot & -fan v tooCold & fan))). % exoTransition under the assumption that at most one exogenous action % can occur after each control action. exoTransition(S1,S2) :- requestExogenousAction(E,S1), (E = nil, S2 = S1 ; not E = nil, S2 = do(E,S1)). requestExogenousAction(E,S) :- write("Enter an exogenous action, or nil."), read(E1), % IF exogenous action is nil, or is possible THEN no problem ((E1 = nil ; poss(E1,S)) -> E = E1 ; % ELSE print error message, and try again. write(">> Action not possible. Try again."), nl, requestExogenousAction(E,S)). % Preconditions for Primitive Actions poss(goUp,S) :- atFloor(N,S), topFloor(T), N < T. poss(goDown,S) :- atFloor(N,S), firstFloor(F), F < N. poss(resetButton(N),S) :- atFloor(N,S), buttonOn(N,S). poss(toggleFan,S). poss(ringAlarm,S) :- fire(S). poss(startFire,S) :- not fire(S). poss(endFire,S) :- fire(S). poss(callElevator(N),S) :- not buttonOn(N,S). poss(changeTemp,S). poss(resetAlarm,S) :- alarmOn(S). poss(wait,S). % Successor State Axioms for Primitive Fluents. buttonOn(N,do(A,S)) :- A = callElevator(N) ; buttonOn(N,S), not A = resetButton(N). fire(do(A,S)) :- A = startFire ; not A = endFire, fire(S). fan(do(A,S)) :- A = toggleFan, not fan(S) ; not A = toggleFan, fan(S). atFloor(N,do(A,S)) :- A = goDown, atFloor(M,S), N is M - 1 ; A = goUp, atFloor(M,S), N is M + 1 ; not A = goDown, not A = goUp, atFloor(N,S). alarmOn(do(A,S)) :- A = ringAlarm ; not A = resetAlarm, alarmOn(S). temp(T,do(A,S)) :- A = changeTemp, temp(T1,S), (not fan(S), T is T1 + 1 ; fan(S), T is T1 - 1) ; not A = changeTemp, temp(T,S). % Abbreviations tooHot(S) :- temp(T,S), T > 3. tooCold(S) :- temp(T,S), T < -3. aboveFloor(N,S) :- atFloor(M,S), N < M. % Initial Situation. atFloor(1,s0). temp(0,s0). topFloor(6). firstFloor(1). % Restore suppressed situation arguments. restoreSitArg(tooCold,S,tooCold(S)). restoreSitArg(fire,S,fire(S)). restoreSitArg(buttonOn(N),S,buttonOn(N,S)). restoreSitArg(fan,S,fan(S)). restoreSitArg(tooHot,S,tooHot(S)). restoreSitArg(atFloor(N),S,atFloor(N,S)). restoreSitArg(alarmOn,S,alarmOn(S)). restoreSitArg(temp(T),S,temp(T,S)). restoreSitArg(aboveFloor(N),S,aboveFloor(N,S)). restoreSitArg(requestExogenousAction(E),S,requestExogenousAction(E,S)). elevator :- doR(control,rules,s0,S), prettyPrintSituation(S). prettyPrintSituation(S) :- makeActionList(S,Alist), nl, write(Alist), nl. makeActionList(s0,[]). makeActionList(do(A,S),L) :- makeActionList(S,L1), append(L1,[A],L).